zardus / preeny

Some helpful preload libraries for pwning stuff.
BSD 2-Clause "Simplified" License
1.56k stars 171 forks source link

desock assistance #35

Open Tim-Nosco opened 6 years ago

Tim-Nosco commented 6 years ago

Hey Zardus. I'm working on ftp from csaw2015: https://github.com/ctfs/write-ups-2015/tree/master/csaw-ctf-2015/reverse/ftp-300 [Uploading ftp.zip…]()

When I run: LD_PRELOAD=./desock.so:./defork.so ./ftp I can manually enter USER blankwall then PASS cookie to get the expected functionality. Quite awesome!

% LD_PRELOAD=./desock.so:./defork.so ./ftp         
[+] Creating Socket
[+] Binding
[+] Listening
[+] accept loop
[+] socket fd: 4
Welcome to FTP server
USER blankwall
Please send password for user blankwall
PASS cookie
logged in
^C

Unfortunately, if I make a file to emulate the way fuzzers interact with the binary and run the program that way, I do not get the expected functionality:

% cat ftp_in
USER blankwall
PASS cookie
% LD_PRELOAD=./desock.so:./defork.so ./ftp < ftp_in
[+] Creating Socket
[+] Binding
[+] Listening
[+] accept loop
[+] socket fd: 4
Welcome to FTP server
Please send password for user blankwall
PASS cookie
^C

I investigated a little and believe the first read(preeny_fd,65536) collects all of ftp_in and writes it to the socket. FTP only accepts the first line; this leaves PASS cookie on the dup socket. FTP then writes to STDOUT Please send password for user blankwall\nPASS cookie\n. Nothing remains for the next FTP read (that expects the password).

How can I mitigate this issue?

Thank you so much for your outstanding tool! I'm working on a universal way to communicate with ELF binaries through a single file (for fuzzing). The things I've done and will hopefully push to your project are: injecting argv/argc, redirecting file reads (simple to just LD_PRELOAD a custom read function).

zardus commented 6 years ago

Sorry for the laggy response. Super busy times lately.

The problem you’re describing is common with fuzzers (in fact, Driller suffers heavily from this, fully externally from preeny). Are you sure that the FTP server itself doesn’t suffer from this problem (i.e., reads as much as it can, instead of byte by byte)? In that case, there’s little that we can do.

Of course, you can try reducing that read() to 1 byte. Most network applications should be able to adapt to that and keep reading until they’ve read whatever they’re supposed to. That might be an easy solution.

On Tue, Nov 14, 2017 at 10:51 AM Tim Nosco notifications@github.com wrote:

Hey Zardus. I'm working on ftp from csaw2015: https://github.com/ctfs/write-ups-2015/tree/master/csaw-ctf-2015/reverse/ftp-300

When I run: LD_PRELOAD=./desock.so:./defork.so ./ftp I can manually enter USER blankwall then PASS cookie to get the expected functionality. Quite awesome!

[+] Creating Socket [+] Binding [+] Listening [+] accept loop [+] socket fd: 4 Welcome to FTP server USER blankwall Please send password for user blankwall PASS cookie logged in ^C```

Unfortunately, if I make a file to emulate the way fuzzers interact with the binary and run the program that way, I do not get the expected functionality:


USER blankwall
PASS cookie
% LD_PRELOAD=./desock.so:./defork.so ./ftp < ftp_in
[+] Creating Socket
[+] Binding
[+] Listening
[+] accept loop
[+] socket fd: 4
Welcome to FTP server
Please send password for user blankwall
PASS cookie
^C```

I investigated a little and believe the first `read(preeny_fd,65536)` collects all of `ftp_in` and writes it to the socket.
FTP only accepts the first line; this leaves `PASS cookie` on the dup socket.
FTP then writes to STDOUT "Please send password for user blankwall\nPASS cookie".
Nothing remains for the next FTP read (that expects the password).

How can I mitigate this issue?

Thank you so much for your outstanding tool!
I'm working on a universal way to communicate with ELF binaries through a single file (for fuzzing).
The things I've done and will hopefully push to your project are: injecting argv/argc, redirecting file reads (simple to just LD_PRELOAD a custom read function).

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<https://github.com/zardus/preeny/issues/35>, or mute the thread
<https://github.com/notifications/unsubscribe-auth/ADSzlwDPfi28EyFRrE1NgE9XngYqJ-vjks5s2dMogaJpZM4QdvXm>
.
Krace commented 6 years ago

I also meet this problems, any other ideas about how to solve it? :P

zardus commented 6 years ago

The only thing that pops into my mind is to change preeny in these cases to have recv always read a single byte. A well-written program should loop until it has the number of bytes it needs. This isn't a general solution, though, and will likely slow things down since the program will perform many more system calls than before.

Krace commented 6 years ago

Wow,thanks for your quick reply. Do you know the root cause of this problem?The souce code I need to patch is too complex,maybe we can find another way to solve it. :P

Krace commented 6 years ago

PS:I've tried it with the singe byte every time patch,it seems to be run correctly! But...why,I can't understand that.