2024CBCTF招新赛复盘

inside

根据 hint,去https://github.com/ergrelet/unlicense下载脱壳机,直接拖拽文件脱壳.

里面一看,是个被魔改的 base64,把 key 和密文 dump 出来,扔给 gpt 一把梭写脚本,即得到 flag.

def custom_base64_decrypt(encoded_bytes):
    # 映射表
    v11 = "BACDEFGHIJKLMNOPQRSTUVWXZYabcdefghijklmnopqrstuvwxyz01234567+/89"

    # 解密的逆向 XOR 操作值
    xor_values = [21, 0x55, 69, 51]

    # 逆向映射表
    reverse_v11 = {v: i for i, v in enumerate(v11)}

    decoded_bytes = []
    for i in range(0, len(encoded_bytes), 4):
        chunk = encoded_bytes[i:i+4]

        # 解密:先 XOR,然后通过映射表逆向查找
        indices = []
        for j, c in enumerate(chunk):
            decoded_char = chr(c ^ xor_values[j])
            if decoded_char in reverse_v11:
                indices.append(reverse_v11[decoded_char])
            else:
                indices.append(0)  # 防止异常字符

        # 将索引恢复为原始的三个字节
        if len(indices) == 4:
            b1 = (indices[0] << 2) | (indices[1] >> 4)
            b2 = ((indices[1] & 0xF) << 4) | (indices[2] >> 2)
            b3 = ((indices[2] & 0x3) << 6) | indices[3]
            decoded_bytes.extend([b1, b2, b3])

    # 移除填充的多余字节
    return bytes(decoded_bytes)

# 被加密的密文
encrypted_data = [
    0x44, 0x65, 0x0F, 0x77, 0x43, 0x10, 0x1C, 0x04, 0x71, 0x11, 0x29, 0x58, 0x4D, 0x66, 0x22, 0x01,
    0x76, 0x39, 0x6A, 0x5A, 0x58, 0x38, 0x03, 0x49, 0x58, 0x39, 0x6A, 0x40, 0x5B, 0x66, 0x17, 0x55,
    0x4C, 0x3F, 0x03, 0x55, 0x4C, 0x67, 0x6A, 0x1C
]

# 解密结果
plaintext = custom_base64_decrypt(encrypted_data)
print(plaintext.decode('utf-8', errors='ignore'))

in_inside

这题与其说是我自己做的,不如说早就被学长透完了.

不会用 dbg,也看不懂壳,没有工具.学长说这是 vmp,是强壳,不能脱,直接动调.于是就用着笨办法,一步一步调,看出了逻辑,本质上就是两个字节的四位互换,然后再异或 0x11,0x22(这里我把他们当成了十进制 😓).那么就可以写脚本了.

我自己的脚本不知道为什么出问题了,还是让 ai 修改了好久才成功.

void decrypt(unsigned char *data, size_t length)
{
	for (size_t i = 0; i < length; i += 2)
	{
		unsigned char x1 = data[i];
		unsigned char x2 = data[i + 1];

		// 反向异或操作
		x1 ^= 0x11; // 对应原始加密中使用的 22
		x2 ^= 0x22; // 对应原始加密中使用的 11

		// 反向移位
		unsigned char temp1 = (x1 >> 4) | (x2 << 4); // 交换两个字节的高低四位
		unsigned char temp2 = (x2 >> 4) | (x1 << 4); // 交换两个字节的高低四位

		// 反向位移
		x1 = temp1;
		x2 = temp2;

		// 更新数据
		data[i] = x1;
		data[i + 1] = x2;
	}
}

int main()
{
	size_t data_length = sizeof(encrypted_data);
	decrypt(encrypted_data, data_length);

	printf("Decrypted data:\n%s\n", encrypted_data);
	return 0;
}

让我康康

也基本是学长教的.

首先一眼平坦化,用 D-810 结果搞不出来,想了半天.去搜索到另一个工具 angr,利用符号执行(D-810 也是啊,用什么不同呢 🤔).然后去平坦化,但还是依托诗.

后面姑且看出了是个流加密,写了脚本,但由于不熟悉 RC4 和平坦化的依托诗.在学长提醒下才知道这是个魔改的 RC4,抄网上脚本,加上了魔改的随机数.(这是个考点,windows 下和 linux 下的rand()是不同的)

结果还是出不来,这时学长非常贱地说了一句话:"写不出来就对啦."这里 key 值被修改了(如果脚本发现无问题,应该想到这点,要么密文,要么 key,但我脑子太昏了,没想到),通过交叉应用看到main之前的修改函数,是根据有无调试而修改 key 值,利用学长教的方法,打断点,修改 ZF 值,手动 hook 过去,可以看到 key 值被修改成了"showmeyourpower!!"

然后修改 key 值,即可得 flag.

#include<stdio.h>

/*
RC4初始化函数
*/
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k)
{
	int i = 0, j = 0;
	char k[256] = { 0 };
	unsigned char tmp = 0;
	for (i = 0; i < 256; i++) {
		s[i] = i;
		k[i] = key[i % Len_k];
	}
	for (i = 0; i < 256; i++) {
		j = (j + s[i] + k[i]) % 256;
		tmp = s[i];
		s[i] = s[j];
		s[j] = tmp;
	}
}

/*
RC4加解密函数
unsigned char* Data     加解密的数据
unsigned long Len_D     加解密数据的长度
unsigned char* key      密钥
unsigned long Len_k     密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
	unsigned char s[256];
	rc4_init(s, key, Len_k);
	int i = 0, j = 0, t = 0;
	unsigned long k = 0;
	unsigned char tmp;
	for (k = 0; k < Len_D; k++) {
		i = (i + 1) % 256;
		j = (j + s[i]) % 256;
		tmp = s[i];
		s[i] = s[j];
		s[j] = tmp;
		t = (s[i] + s[j]) % 256;
        s[t] ^= rand();
		Data[k] = Data[k] ^ s[t];
	}
}
int main()
{
    srand(0x1BF52);
	//字符串密钥
	unsigned char key[] = 0x73, 0x68, 0x6F, 0x77, 0x5F, 0x6D, 0x65, 0x5F, 0x79, 0x6F,
  0x75, 0x72, 0x5F, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x21, 0x21;
	unsigned long key_len = sizeof(key);
	//数组密钥
	//unsigned char key[] = {};
	//unsigned long key_len = sizeof(key);

	//加解密数据
	unsigned char data[] = {0x21, 0xEE, 0x74, 0xF0, 0x2C, 0x76, 0xC4, 0x29, 0x33, 0x8F, 0xA2, 0xC2, 0x25, 0x18, 0x57, 0xA0, 0xAB, 0x42, 0x94, 0x76, 0x4F, 0x57, 0x47, 0x1B, 0x58, 0xE4, 0xD9, 0xE3, 0x1D, 0x35, 0x4E, 0xA4};
	//加解密
	rc4_crypt(data, sizeof(data), key, key_len);
	printf("%s",data);
	return;
}
posted @   T0fV404  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示