巅峰极客2024

Misc

Misc题搞得有点像re病毒分析,不过misc成分还是比较高

源文件有upx壳,脱完了获得的程序沙箱跑不出来

IDA分析一下发现有虚拟机检测,所以只能在本地运行

运行后释放了两个文件

图片其实在释放程序中能找到

file文件上传沙箱后显示是木马,释放了default程序

对file进行逆向分析,只发现了pupy这个字段

而且有大量python对象

但是直接搜这个项目没用,需要解码器项目

https://github.com/CaledoniaProject/pupyrat-config-decoder

配置python2环境,运行

28行报错

修改一下

运行时不要直接 ./,用 python2 main.py

IP地址就得到了

那图片有啥用呢,zsteg跑一下

看一下大小就知道和释放的file是一样的,实际上也确实如此

提取file的方式很多,就是分析需要你找到那个github项目的工具,难点主要在这里吧,当时也没找到

Re

伪代码很难看,动调翻一翻可以发现一些关键点

首先是239行

是最终密文比对的部分,238行也可以看到密文长度1280字节

然后是276行附近,明显是加密部分

出现大量sha256加密的API

之后就是大量的异或

513行,输入字符的限制

动调可以发现,整体逻辑大概是先113行scanf

然后飞到513附近验证输入字符

然后再飞到276行加密

加密完了还有一堆移动性的操作

哈希逆不起来,只能考虑爆破

动调看一下加密过程

加密部分断一下,看看phInput

看来是一次加密三个字节

注意要再循环一次

每次取三个字节,每个循环往后移动一个字节

然后找一下sha256加密的密文,应该在pbOutput里

&v107指向了第二个字节的地址

然后存到v14去异或

异或部分代码头尾参差不齐应该是反编译器分析的问题,if(v13)else也没什么影响,if和else的内容都一样。

加密的部分就是32字节的密文再去以后3字节循环的明文。

于是可以考虑三字节爆破

密文长1280字节,每一段sah256是32字节,就是64个hex字符

不过密文不是按明文顺序排列的,所以解密也不用考虑顺序,index能匹配到即可

爆出来乱序的三字节组,写个脚本进行排列即可

import hashlib
import itertools

enc = "EB74464F7924C56210CBFFC5A239BE0399ED2C8FB9542BA7C58A7E560F352CA03EE5E00A6EA938CF85F882C799D78BC682225428F4E556D047F15E5766855C04660DC72181954CF9976E5705CBAA483D2AAB5A69283D68E4F74C23CFA8C226D0F941E7F4FF9960F1DA677E9DBF9814B5B3E2D799074AC0120F212F3A52C37FE335D56DB4BD214600049F7F950C01FABD8625065607304F17AEF3C0F0177F9B3EBDE5663346606CB307F1645F006DB088F34F7D44BE9543A1393B29506D1D31814460FE7BAC48BDBB8E354128E7535CE73B1618C594D9D1B9BF7148A7D77077E9A7FFA0BE1CFA9800FE3364F9E7304557974045E0C950B8F3444432C16AB7DDEE371F6026FA2D6FC143598A9EE9E12736EABD515BAE24BB03E4C062DDC263F4A18C3E5C10A4CC88E19B04592B864AC883D8B994EEB2C46496B3416B000C9A344A4F3CF2C30DA6DD57B7D3701CDCB9418EAE8A0470C2AD2668ECF0E3AE6B6A29F6AE3C23E30F42571DFC507171D173F928718E2A5D18C43F7A5B20E125A6421EFBEFA5034BF44B5E66EF90124EE2CFFD9AACE7C49356A64ADFFBA0D44D29B125AB8E98386ED91129B0197AE9A642C173578EFD4784D1EE087CE765A714640F9AA867A4AD879229F1712037D522B5226B2DC7440EFCB753EC8A52C29CF1FB9BD85FA65FDA70B1261E143F9406D00D90AA0F55310652F3F908D7C1E5A841F77EBD3014FCA23CB223F8915D7730AFC7276F1C0FC7EA33A3083553D2684D964EC7E4A9205DEE6FCFEADA8B589CF48326AF2DEBF56DB42A4DFDF74BF9CB0A34BFD97B90B83E17E31FE0A48B54C94AC4175B46302D5E8B38D7CB42E618AEC9197D43B1B36891A18CDC5CA57F20284187FE6988D860ED46076F779B088D2FA78A798A55DCC6E657E8B101A23B9F8ADE02F696D905F63C626C3E07FD06002B2030B20FAFF02625D9B875A4B74DD421CCB5411CC309EBE7CC75BED408F9F486E6CFFF4F14AC36DFFB643C2721A3AD4CA95415D59CF3C3EE85FF75F2BC6FFD1FC09499544B7218F5937E8B73C7764DEBC840266B14F3D049AE9511AB135CC764C5C6F10C87C087BC8D3181D7470630D4A983FE401F46C99F4A52D81E8D4146211BFA28AE52C9D0E3974AFB2D830F443136F4464DDFEFA30688BE27A8A0158A85B8040C2C04598F2111751D296F862FFEBC2FB50D6530FE6C09D70F54664ED2F2C44365D647B3E6D5BB45707C8B18C8A248B153309605B34ED9CEF42172114F52AE47E8063131EFB2F1AD55868D648722111B00CFE2132463F9659AA1F8298ED2FBD1239071DC3ACF63661C77A5ACBB54410FF3F7CFA1701040BD2D2C8F721A37E310A84605845E7202DB021B2346A1BB920AE80DD0066F05A0524BC80339ED9932542883473FEFCA18C1C8B8C9B0E31B7169BAC1F1B9697B2799BDB869006C16C49B77525AB7546FE3345E5F01A5E248FB966B7592D2A0DA0BED3E27F6C789647FDE73F59258FFC6A638758661126FC03D24226DA7295EBDF50C52D96631B5804D02CDF2DC89FA6063CA2D00953200BED4BF734CEDBA0C56A185C46CB60ABCDD8C611E4203B4E0F217FA14389FB1A49C03180CC616C730FA48B1B96EB17D7B3BDFD9B6A7D646A57C976DD592A3F022A15399A1C37140E1897B231918DC2F2257DD2CC33FADEF99939CE9EB676674458ED487984E9F8D2C7DF23D8093940FEAB586D0E674B6B2416125DED9C2386A247F1D87BAD1CAB640579EAE3050FFD0A8AEDF52254AA5E9186F060C97150EC26626CC8451C47569764B281667A54428E096A20A5D81EB4D"
enc_list = [enc[i:i+64] for i in range(0, len(enc), 64)]  # 40

def encrypt(data):
    data_bytes = data.encode()
    sha256_hash = hashlib.sha256()
    sha256_hash.update(data_bytes)
    hash_bytes = sha256_hash.digest()
    result = bytearray()
    for i in range(len(hash_bytes)):
        result.append(data_bytes[i % len(data_bytes)] ^ hash_bytes[i % len(hash_bytes)])
    return result

flag_list = []
char_list = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-{}"
for data in itertools.product(char_list, repeat=3):
    data = ''.join(data)
    enc_result = encrypt(data)
    enc_result = enc_result.hex().upper()
    try:
        index = enc_list.index(enc_result)
        flag_list.append(data)
    except ValueError:
        pass

print(flag_list)

# 初始化 current 为 "fla"
current = "fla"

# 找到起始点 "fla" 的索引
start_index = flag_list.index('fla')

# 从起始点开始遍历
i = start_index
while i < len(flag_list):
    # 检查当前元素的前两个字符是否与 current 的后两个字符相同
    if flag_list[i][:2] == current[-2:]:
        # 将当前元素的第三个字符附加到 current 后面
        current += flag_list[i][2]
        # 重置索引,从头开始寻找下一个匹配的元素
        i = 0
    else:
        i += 1

# 输出最终结果
print(current)
#flag{194a39a4-7937-48fb-bfea-80bd17729f8a}

关于密文排列的乱序,可以猜测应该是密文按照二叉搜索树的数据结构进行了存储

GPT姥爷如是说:

用MLM优化也能看出一些端倪:

int main() {
    std::cout << "Input flag:";
    std::string flag;
    std::cin >> flag;
    std::list<std::string> list;
    for (int i = 0; i < flag.size() - 2; i++) {
        if (!((flag[i] >= '0' && flag[i] <= '9') ||
          (flag[i] >= 'a' && flag[i] <= 'z') || flag[i] == '-' ||
          flag[i] == '}')) {
            std::cout << "Error." << std::endl;
            return 0;
        }
    }
    for (int i = 0; i < flag.size() - 2; i++) {
        std::string str;
        get_hash(flag, str, i);
        BCRYPT_ALG_HANDLE phAlgorithm;
        BCRYPT_HASH_HANDLE phHash;
        UCHAR pbHash[32];
        BCryptOpenAlgorithmProvider(&phAlgorithm, BCRYPT_SHA256_ALGORITHM, NULL, 0);
        BCryptCreateHash(phAlgorithm, &phHash, NULL, 0, NULL, 0, 0);
        BCryptHashData(phHash, (PUCHAR)str.c_str(), str.size(), 0);
        BCryptFinishHash(phHash, pbHash, sizeof(pbHash), 0);
        BCryptDestroyHash(phHash);
        BCryptCloseAlgorithmProvider(phAlgorithm, 0);
        UCHAR pbHash2[32];
        for (int j = 0; j < 32; j++) {
            pbHash2[j] = pbHash[j];
        }
        for (int j = 2; j < 32; j++) {
            pbHash2[j] ^= str[j % str.size()];
        }
        for (int j = 2; j < 32; j++) {
            pbHash2[j] ^= pbHash[j % 32];
        }
        std::string hash = std::string((char*)pbHash2, 32);
        if (list.count(hash) != 0) {
            std::cout << "Error." << std::endl;
            return 0;
        }
        list.push_back(hash);
    }
    std::string result;
    std::list<std::string>::iterator it;
    for (it = list.begin(); it != list.end(); it++) {
        result += *it;
    }
    std::string flag2 = decrypt(result);
    if (flag2 ==
      "right,flag is your input!") {
        std::cout << "right,flag is your input!" << std::endl;
    } else {
        std::cout << "Error." << std::endl;
    }
    return 0;
}

it = list.begin(); it != list.end()这样的代码也有一定的参考意义

大致能看出这部分的代码是把新生成的哈希和已有的密文进行比对,小的放前面,大的放后面

二叉搜索树(BST,Binary Search Tree),也称二叉排序树或二叉查找树。
二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:

  1. 非空左子树的所有键值小于其根结点的键值。
  2. 非空右子树的所有键值大于其根结点的键值。
  3. 左、右子树都是二叉搜索树。

正好符合二叉搜索树的定义,不过还原树对这一题解密意义不大,因为有明显的特征可以直接拼接。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值