吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3810|回复: 15
收起左侧

[CTF] L3HCTF 部分RE WP

[复制链接]
zsky 发表于 2021-11-17 12:55
本帖最后由 zsky 于 2021-11-17 18:34 编辑

L3HCTF 部分RE WP

double-joy

IDA打开程序,找到main函数进行分析

image-20211116102232560.png

最关键的是enc_flag 函数, 经过调试,发现传入的参数有2套,都是固定的结构体

image-20211116103019789.png

typedef struct _struc_1
{
        BYTE* pKey;                //指向OPCODE
        _DWORD* pFlag;   //指向FLAG,主要这个FLAG前40个字节是用户输入的,后面一大部分要留给程序用
        int i;                    //指向OPCODE的索引
        int stack;            //指向了一些 “操作数”,在OPCODE 中存着,比如OPCODE是 \XE的话,后面4个字节就是一个“操作数”
}struc_1;

进入 enc_flag函数,F5,发现很乱,然后patch掉一些用于对齐的代码后,F5, 发现是个VM

调试,发现一共执行了0XCA次 enc_flag, 并且传入的参数是交替的

还原程序代码

#include <windows.h>
#include <basetsd.h>
#include <stdio.h>

typedef unsigned int uint32;
#define _DWORD uint32

typedef struct _struc_1
{
        BYTE* pKey;                         //指向OPCODE
        _DWORD* pFlag;           //指向FLAG,主要这个FLAG前40个字节是用户输入的,后面一大部分要留给程序用
        int i;                                //指向OPCODE的索引
        int stack;                         //指向了一些 “操作数”,在OPCODE 中存着,比如OPCODE是 \XE的话,后面4个字节就是一个“操作数”
}struc_1;

BYTE key1[] =
{
  0x11, 0x15, 0x00, 0x00, 0x00, 0x0E, 0x0A, 0x00, 0x00, 0x00,
  0x0E, 0x15, 0xCD, 0x5B, 0x07, 0x08, 0x0E, 0x0B, 0x00, 0x00,
  0x00, 0x0E, 0xB1, 0x68, 0xDE, 0x3A, 0x08, 0x0E, 0x12, 0x00,
  0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x13,
  0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E,
  0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x0A, 0x00, 0x00, 0x00,
  0x0C, 0x01, 0x0B, 0x0A, 0x10, 0x44, 0x00, 0x00, 0x00, 0x0E,
  0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x09, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x09,
  0x0E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x01, 0x01, 0x01,
  0x01, 0x02, 0x07, 0x08, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x0E,
  0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x01, 0x00, 0x00, 0x00,
  0x00, 0x08, 0x0F, 0xA8, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, 0x00,
  0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x4C,
  0x49, 0x00, 0x00, 0x08, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x0E,
  0x0E, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x76, 0x6F, 0x00, 0x00,
  0x08, 0x0E, 0x02, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00,
  0x00, 0x00, 0x0E, 0x20, 0x65, 0x00, 0x00, 0x08, 0x0E, 0x03,
  0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x0E,
  0x55, 0x43, 0x00, 0x00, 0x08, 0x0E, 0x13, 0x00, 0x00, 0x00,
  0x0E, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x13, 0x00, 0x00,
  0x00, 0x09, 0x0E, 0x0A, 0x00, 0x00, 0x00, 0x0C, 0x01, 0x0B,
  0x0A, 0x10, 0x56, 0x01, 0x00, 0x00, 0x0E, 0x14, 0x00, 0x00,
  0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x14, 0x00,
  0x00, 0x00, 0x09, 0x0E, 0x14, 0x00, 0x00, 0x00, 0x0C, 0x01,
  0x0B, 0x0A, 0x10, 0x20, 0x01, 0x00, 0x00, 0x0E, 0x0C, 0x00,
  0x00, 0x00, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x09, 0x08, 0x0E, 0x0D, 0x00, 0x00,
  0x00, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x01, 0x00,
  0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
  0x08, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x0E, 0x0C, 0x00, 0x00,
  0x00, 0x09, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x10,
  0x00, 0x00, 0x00, 0x02, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x09,
  0x0E, 0x20, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x07, 0x0E, 0x0D,
  0x00, 0x00, 0x00, 0x09, 0x00, 0x0E, 0x0B, 0x00, 0x00, 0x00,
  0x09, 0x0E, 0x0B, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x03, 0x00,
  0x00, 0x00, 0x05, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x09,
  0x00, 0x07, 0x00, 0x08, 0x0E, 0x0B, 0x00, 0x00, 0x00, 0x0E,
  0x0B, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x0A, 0x00, 0x00, 0x00,
  0x09, 0x00, 0x08, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x0D,
  0x00, 0x00, 0x00, 0x09, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x09,
  0x0E, 0x10, 0x00, 0x00, 0x00, 0x02, 0x0E, 0x0C, 0x00, 0x00,
  0x00, 0x09, 0x0E, 0x20, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x07,
  0x0E, 0x0C, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0E, 0x0B, 0x00,
  0x00, 0x00, 0x09, 0x0E, 0x0B, 0x00, 0x00, 0x00, 0x09, 0x0E,
  0x00, 0x08, 0x00, 0x00, 0x0C, 0x03, 0x0E, 0x03, 0x00, 0x00,
  0x00, 0x05, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
  0x07, 0x00, 0x08, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x09, 0x0E,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0C, 0x00, 0x00, 0x00,
  0x09, 0x08, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x0E, 0x0D, 0x00, 0x00, 0x00, 0x09, 0x08, 0x12, 0x01, 0x00,
  0x00, 0x00, 0x0E, 0x14, 0x00, 0x00, 0x00, 0x0E, 0x14, 0x00,
  0x00, 0x00, 0x09, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
  0x0F, 0xCC, 0xFE, 0xFF, 0xFF, 0x0E, 0x13, 0x00, 0x00, 0x00,
  0x0E, 0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x02, 0x00, 0x00,
  0x00, 0x00, 0x08, 0x0F, 0x96, 0xFE, 0xFF, 0xFF, 0x12, 0x00,
  0x00, 0x00, 0x00, 0x00
};

BYTE key2[] =
{
  0x11, 0x15, 0x00, 0x00, 0x00, 0x0E, 0x0A, 0x00, 0x00, 0x00,
  0x0E, 0xF7, 0xCB, 0x54, 0x01, 0x08, 0x0E, 0x0B, 0x00, 0x00,
  0x00, 0x0E, 0xAD, 0xDE, 0xED, 0x5E, 0x08, 0x0E, 0x12, 0x00,
  0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x13,
  0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E,
  0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x0A, 0x00, 0x00, 0x00,
  0x0C, 0x01, 0x0B, 0x0A, 0x10, 0x44, 0x00, 0x00, 0x00, 0x0E,
  0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x09, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x09,
  0x0E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x01, 0x01, 0x01,
  0x01, 0x02, 0x07, 0x08, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x0E,
  0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x01, 0x00, 0x00, 0x00,
  0x00, 0x08, 0x0F, 0xA8, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, 0x00,
  0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x54,
  0x53, 0x00, 0x00, 0x08, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x0E,
  0x0E, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x4D, 0x4F, 0x00, 0x00,
  0x08, 0x0E, 0x02, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00,
  0x00, 0x00, 0x0E, 0x74, 0x20, 0x00, 0x00, 0x08, 0x0E, 0x03,
  0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x0E,
  0x61, 0x65, 0x00, 0x00, 0x08, 0x0E, 0x13, 0x00, 0x00, 0x00,
  0x0E, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x13, 0x00, 0x00,
  0x00, 0x09, 0x0E, 0x0A, 0x00, 0x00, 0x00, 0x0C, 0x01, 0x0B,
  0x0A, 0x10, 0x5B, 0x01, 0x00, 0x00, 0x0E, 0x14, 0x00, 0x00,
  0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x14, 0x00,
  0x00, 0x00, 0x09, 0x0E, 0x14, 0x00, 0x00, 0x00, 0x0C, 0x01,
  0x0B, 0x0A, 0x10, 0x25, 0x01, 0x00, 0x00, 0x0E, 0x0C, 0x00,
  0x00, 0x00, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x09, 0x08, 0x0E, 0x0D, 0x00, 0x00,
  0x00, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x01, 0x00,
  0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
  0x08, 0x0E, 0x0B, 0x00, 0x00, 0x00, 0x0E, 0x0B, 0x00, 0x00,
  0x00, 0x09, 0x0E, 0x0A, 0x00, 0x00, 0x00, 0x09, 0x00, 0x08,
  0x0E, 0x0C, 0x00, 0x00, 0x00, 0x0E, 0x0C, 0x00, 0x00, 0x00,
  0x09, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x10, 0x00,
  0x00, 0x00, 0x02, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E,
  0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0E, 0x0D, 0x00, 0x00,
  0x00, 0x09, 0x0E, 0x0B, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0E,
  0x0D, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x20, 0x00, 0x00, 0x00,
  0x0C, 0x03, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00,
  0x00, 0x00, 0x00, 0x09, 0x00, 0x07, 0x07, 0x00, 0x08, 0x0E,
  0x0D, 0x00, 0x00, 0x00, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x09,
  0x0E, 0x0C, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x10, 0x00, 0x00,
  0x00, 0x02, 0x0E, 0x02, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00,
  0x00, 0x00, 0x00, 0x09, 0x00, 0x0E, 0x0C, 0x00, 0x00, 0x00,
  0x09, 0x0E, 0x0B, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0E, 0x0C,
  0x00, 0x00, 0x00, 0x09, 0x0E, 0x20, 0x00, 0x00, 0x00, 0x0C,
  0x03, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00,
  0x00, 0x00, 0x09, 0x00, 0x07, 0x07, 0x00, 0x08, 0x0E, 0x13,
  0x00, 0x00, 0x00, 0x09, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x0E, 0x0C, 0x00, 0x00, 0x00, 0x09, 0x08, 0x0E, 0x13, 0x00,
  0x00, 0x00, 0x09, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0E,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0D, 0x00, 0x00, 0x00,
  0x09, 0x08, 0x12, 0x01, 0x00, 0x00, 0x00, 0x0E, 0x14, 0x00,
  0x00, 0x00, 0x0E, 0x14, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x08, 0x0F, 0xC7, 0xFE, 0xFF, 0xFF,
  0x0E, 0x13, 0x00, 0x00, 0x00, 0x0E, 0x13, 0x00, 0x00, 0x00,
  0x09, 0x0E, 0x02, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0F, 0x91,
  0xFE, 0xFF, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void enc_flag(struc_1* st)
{
        BYTE* pKey = st->pKey;
        BYTE opcode = 0;
        _DWORD* pFlag = st->pFlag;
        int data1, data2, tmp, index;

        while (true)
        {
                opcode = pKey[st->i];        //取出对应的opcode
                st->i++;                                //每取出一个opcode, 索引就+1
                printf("------>OPCODE :%d\n", opcode);
                switch (opcode)
                {
                case 0:
                        st->stack--;
                        data1 = pFlag[st->stack];
                        data2 = pFlag[st->stack - 1];
                        pFlag[st->stack - 1] = data1 + data2;
                        printf("pFlag[%d] = pFlag[%d]:%#x + pFlag[%d]:%#x;\n", st->stack - 1, st->stack, data1, st->stack - 1, data2);
                        continue;
                case 1:
                        st->stack--;
                        data1 = pFlag[st->stack];
                        data2 = pFlag[st->stack - 1];
                        pFlag[st->stack - 1] = data1 - data2;
                        printf("pFlag[%d] = pFlag[%d]:%#x - pFlag[%d]:%#x;\n", st->stack - 1, st->stack, data1, st->stack - 1, data2);
                        continue;
                case 2:
                        st->stack--;
                        data1 = pFlag[st->stack];
                        data2 = pFlag[st->stack - 1];
                        pFlag[st->stack - 1] = data1 * data2;
                        printf("pFlag[%d] = pFlag[%d]:%#x * pFlag[%d]:%#x;\n", st->stack - 1, st->stack, data1, st->stack - 1, data2);
                        continue;
                case 3:
                        st->stack--;
                        data1 = pFlag[st->stack];
                        data2 = pFlag[st->stack - 1];
                        pFlag[st->stack - 1] = data1 / data2;
                        printf("pFlag[%d] = pFlag[%d]:%#x / pFlag[%d]:%#x;\n", st->stack - 1, st->stack, data1, st->stack - 1, data2);
                        continue;
                case 4:
                        st->stack--;
                        data1 = pFlag[st->stack];
                        data2 = pFlag[st->stack - 1];
                        pFlag[st->stack - 1] = data1 % data2;
                        printf("pFlag[%d] = pFlag[%d]:%#x %% pFlag[%d]:%#x;\n", st->stack - 1, st->stack, data1, st->stack - 1, data2);
                        continue;
                case 5:
                        st->stack--;
                        data1 = pFlag[st->stack];
                        data2 = pFlag[st->stack - 1];
                        pFlag[st->stack - 1] = data1 & data2;
                        printf("pFlag[%d] = pFlag[%d]:%#x & pFlag[%d]:%#x;\n", st->stack - 1, st->stack, data1, st->stack - 1, data2);
                        continue;
                case 6:
                        st->stack--;
                        data1 = pFlag[st->stack];
                        data2 = pFlag[st->stack - 1];
                        pFlag[st->stack - 1] = data1 | data2;
                        printf("pFlag[%d] = pFlag[%d]:%#x | pFlag[%d]:%#x;\n", st->stack - 1, st->stack, data1, st->stack - 1, data2);
                        continue;
                case 7:
                        st->stack--;
                        data1 = pFlag[st->stack];
                        data2 = pFlag[st->stack - 1];
                        pFlag[st->stack - 1] = data1 ^ data2;
                        printf("pFlag[%d] = pFlag[%d]:%#x ^ pFlag[%d]:%#x;\n", st->stack - 1, st->stack, data1, st->stack - 1, data2);
                        continue;
                case 8:
                        st->stack--;
                        tmp = pFlag[st->stack];
                        index = pFlag[st->stack - 1];
                        pFlag[index] = tmp;
                        printf("pFlag[%d] = %#x;\n", index, tmp);
                        st->stack--;
                        continue;
                case 9:
                        index = pFlag[st->stack - 1];
                        data1 = pFlag[index];
                        pFlag[st->stack - 1] = data1;
                        printf("pFlag[%d] = %#x;\n", st->stack -1, data1);
                        continue;
                case 10:
                        tmp = pFlag[st->stack - 1];
                        if (tmp == 0)
                        {
                                pFlag[st->stack - 1] = 1;
                                printf("pFlag[%d] = 1;\n", st->stack - 1);
                        }
                        else {
                                pFlag[st->stack - 1] = 0;
                                printf("pFlag[%d] = 0;\n", st->stack - 1);
                        }
                        continue;
                case 11:
                        tmp = pFlag[st->stack - 1];
                        if ((int)tmp < 0)
                        {
                                pFlag[st->stack - 1] = 1;
                                printf("pFlag[%d] = 1;\n", st->stack - 1);
                        }
                        else {
                                pFlag[st->stack - 1] = 0;
                                printf("pFlag[%d] = 0;\n", st->stack - 1);
                        }
                        continue;
                case 12:
                        data1 = pFlag[st->stack - 1];
                        data2 = pFlag[st->stack - 2];
                        pFlag[st->stack - 1] = data2;
                        pFlag[st->stack - 2] = data1;
                        printf("exchange pFlag[%d]:%#x, pFlag[%d]:%#x\n", st->stack - 1, data2, st->stack - 2, data1);
                        continue;
                case 13:
                        st->stack--;
                        continue;
                case 14:
                        tmp = *(_DWORD*)&pKey[st->i];
                        st->i += 4;
                        pFlag[st->stack++] = tmp;
                        printf("pFlag[%d] = %#x\n", st->stack-1, tmp);
                        continue;
                case 15:
                        tmp = *(_DWORD*)&pKey[st->i];
                        index = st->i + 4 + tmp;
                        st->i = index;
                        continue;
                case 16:
                        tmp = st->i + 4;
                        st->stack--;
                        if (pFlag[st->stack])
                                tmp += *(_DWORD*)&pKey[st->i];
                        st->i = tmp;
                        continue;
                case 17:
                        tmp = *(_DWORD*)&pKey[st->i];
                        st->stack += tmp;
                        st->i += 4;
                        continue;
                case 18:
                        st->i += 4;
                        return;
                default:
                        st->i++;
                }
        }
}

char flag1[4000] = { 0 };                //前40个字节使用户输入的flag,40往后是为了加密flag用到的数据
char flag2[4000] = { 0 };                //前40个字节使用户输入的flag,40往后是为了加密flag用到的数据

char compare_date[1000] = {
          0xE8, 0xFA, 0xE0, 0xAE, 0x01, 0x41, 0x3E, 0xFC, 0x92, 0xAD,
          0x7C, 0x16, 0xBE, 0x6C, 0xEA, 0x51, 0x00, 0x01, 0x2A, 0x24,
          0x1B, 0x1A, 0x51, 0x01, 0x94, 0x66, 0x4D, 0x51, 0xEB, 0xBF,
          0x5F, 0x2F, 0x98, 0x63, 0xD3, 0x46, 0xF0, 0xE3, 0xEE, 0x79,
        0
};

int main()
{
        struc_1 v12 = { 0 };
        struc_1 v13 = { 0 };

        memcpy(flag1, "111111111111222211111111111111111111111\0", 40);
        memcpy(flag2, "111111111111222211111111111111111111111\0", 40);

        v12.pFlag = (_DWORD *)flag1;
        v12.pKey = key1;
        v12.i = 0;
        v12.stack = 0;

        v13.pFlag = (_DWORD*)flag2;
        v13.pKey = key2;
        v13.i = 0;
        v13.stack = 0;

        for (int i = 0; i < 0XCA; i+=2)
        {
                enc_flag(&v12);
                memcpy(flag2, flag1, 40);
                enc_flag(&v13);
                memcpy(flag1, flag2, 40);
                printf("----------------------------------------------------------------------------");
        }

        return 0;        
}

调试发现,flag是分组进行加密的,每8个字符一组,共5组

第一组 L3HCTF{*, 只差1个字符, 暴力破解


char compare_date[] = {
          0xE8, 0xFA, 0xE0, 0xAE, 0x01, 0x41, 0x3E, 0xFC, 0x92, 0xAD,
          0x7C, 0x16, 0xBE, 0x6C, 0xEA, 0x51, 0x00, 0x01, 0x2A, 0x24,
          0x1B, 0x1A, 0x51, 0x01, 0x94, 0x66, 0x4D, 0x51, 0xEB, 0xBF,
          0x5F, 0x2F, 0x98, 0x63, 0xD3, 0x46, 0xF0, 0xE3, 0xEE, 0x79
};

int main()
{
        struc_1 v12 = { 0 };
        struc_1 v13 = { 0 };
        memcpy(flag1, "111111111111111111111111111111111111111\0", 40);
        memcpy(flag2, "111111111111111111111111111111111111111\0", 40);
        v12.pFlag = (_DWORD*)flag1;
        v12.pKey = key1;
        v12.i = 0;
        v12.kk = 0;

        v13.pFlag = (_DWORD*)flag2;
        v13.pKey = key2;
        v13.i = 0;
        v13.kk = 0;

        memcpy(flag1, "L3HCTF{1", 8);
        memcpy(flag2, "L3HCTF{1", 8);

        for (int j = 32; j < 127; j++)
        {

                v12.pFlag = (_DWORD*)flag1;
                v12.pKey = key1;
                v12.i = 0;
                v12.kk = 0;

                v13.pFlag = (_DWORD*)flag2;
                v13.pKey = key2;
                v13.i = 0;
                v13.kk = 0;

                memcpy(flag1, "L3HCTF{", 8);
                memcpy(flag2, "L3HCTF{", 8);
                flag1[7] = j;
                flag2[7] = j;

                for (int i = 0; i < 0XCA; i += 2)
                {
                        enc_flag(&v12);
                        memcpy(flag2, flag1, 40);
                        enc_flag(&v13);
                        memcpy(flag1, flag2, 40);
                }

                if (memcmp(flag1, compare_date, 8) == 0)
                {
                        printf("%c\n", j);
                        getchar();
                }

        }

        return 0;
}
//D

发现第一组是L3HCTF{D

然后下面开始还原VM,只需还原出加密每一组的第一个循环就OK

输入flag 为 L3HCTF{D1111222211111111111111111111111}

第二组为
Input:  31 31 31 31 32 32 32 32
enc后
Output: ec 9d 57 67 94 6a 7e a5

通过打印的日志,追踪Input,来分析如何得到的Output

加密flag的第二组的第一个循环的日志

输入:31 31 31 31 32 32 32 32
输出:ec 9d 57 67 94 6a 7e a5

======以下是打印的日志
OPCODE :14
pFlag[21] = 0x14
------>OPCODE :14
pFlag[22] = 0x14
------>OPCODE :9
pFlag[22] = 0x13;
------>OPCODE :14
pFlag[23] = 0x1
------>OPCODE :0
pFlag[22] = pFlag[23]:0x1 + pFlag[22]:0x13;
------>OPCODE :8
pFlag[20] = 0x14;
------>OPCODE :15
------>OPCODE :14
pFlag[21] = 0x14
------>OPCODE :9
pFlag[21] = 0x14;
------>OPCODE :14
pFlag[22] = 0x14
------>OPCODE :12
exchange pFlag[22]:0x14, pFlag[21]:0x14
------>OPCODE :1
pFlag[21] = pFlag[22]:0x14 - pFlag[21]:0x14;
------>OPCODE :11
pFlag[21] = 0;
------>OPCODE :10
pFlag[21] = 1;
------>OPCODE :16
------>OPCODE :14
pFlag[21] = 0x13
------>OPCODE :14
pFlag[22] = 0x13
------>OPCODE :9
pFlag[22] = 0;
------>OPCODE :14
pFlag[23] = 0x2
------>OPCODE :0
pFlag[22] = pFlag[23]:0x2 + pFlag[22]:0;
------>OPCODE :8
pFlag[19] = 0x2;
------>OPCODE :15
------>OPCODE :14
pFlag[21] = 0x13
------>OPCODE :9
pFlag[21] = 0x2;
------>OPCODE :14
pFlag[22] = 0xa
------>OPCODE :12
exchange pFlag[22]:0x2, pFlag[21]:0xa
------>OPCODE :1
pFlag[21] = pFlag[22]:0x2 - pFlag[21]:0xa;
------>OPCODE :11
pFlag[21] = 1;
------>OPCODE :10
pFlag[21] = 0;
------>OPCODE :16
------>OPCODE :14
pFlag[21] = 0x14
------>OPCODE :14
pFlag[22] = 0
------>OPCODE :8
pFlag[20] = 0;
------>OPCODE :14
pFlag[21] = 0x14
------>OPCODE :9
pFlag[21] = 0;
------>OPCODE :14
pFlag[22] = 0x14
------>OPCODE :12
exchange pFlag[22]:0, pFlag[21]:0x14
------>OPCODE :1
pFlag[21] = pFlag[22]:0 - pFlag[21]:0x14;
------>OPCODE :11
pFlag[21] = 1;
------>OPCODE :10
pFlag[21] = 0;
------>OPCODE :16
------>OPCODE :14
pFlag[21] = 0xc
------>OPCODE :14
pFlag[22] = 0x13
------>OPCODE :9
pFlag[22] = 0x2;
------>OPCODE :14
pFlag[23] = 0
------>OPCODE :0
pFlag[22] = pFlag[23]:0 + pFlag[22]:0x2;
------>OPCODE :9
pFlag[22] = 0x31313131;
------>OPCODE :8
pFlag[12] = 0x31313131;
------>OPCODE :14
pFlag[21] = 0xd
------>OPCODE :14
pFlag[22] = 0x13
------>OPCODE :9
pFlag[22] = 0x2;
------>OPCODE :14
pFlag[23] = 0x1
------>OPCODE :0
pFlag[22] = pFlag[23]:0x1 + pFlag[22]:0x2;
------>OPCODE :14
pFlag[23] = 0
------>OPCODE :0
pFlag[22] = pFlag[23]:0 + pFlag[22]:0x3;
------>OPCODE :9
pFlag[22] = 0x32323232;
------>OPCODE :8
pFlag[13] = 0x32323232;
------>OPCODE :14
pFlag[21] = 0xc
------>OPCODE :14
pFlag[22] = 0xc
------>OPCODE :9
pFlag[22] = 0x31313131;
------>OPCODE :14
pFlag[23] = 0xd
------>OPCODE :9
pFlag[23] = 0x32323232;
------>OPCODE :14
pFlag[24] = 0x10
------>OPCODE :2
pFlag[23] = pFlag[24]:0x10 * pFlag[23]:0x32323232;   ====
------>OPCODE :14
pFlag[24] = 0xd
------>OPCODE :9
pFlag[24] = 0x32323232;
------>OPCODE :14
pFlag[25] = 0x20
------>OPCODE :12
exchange pFlag[25]:0x32323232, pFlag[24]:0x20
------>OPCODE :3
pFlag[24] = pFlag[25]:0x32323232 / pFlag[24]:0x20;                  ====
------>OPCODE :7
pFlag[23] = pFlag[24]:0x1919191 ^ pFlag[23]:0x23232320;
------>OPCODE :14
pFlag[24] = 0xd
------>OPCODE :9
pFlag[24] = 0x32323232;                                                                     ====
------>OPCODE :0
pFlag[23] = pFlag[24]:0x32323232 + pFlag[23]:0x22b2b2b1;          ====
------>OPCODE :14
pFlag[24] = 0xb
------>OPCODE :9
pFlag[24] = 0xce0a6e55;
------>OPCODE :14
pFlag[25] = 0xb
------>OPCODE :9
pFlag[25] = 0xce0a6e55;
------>OPCODE :14
pFlag[26] = 0x3
------>OPCODE :5
pFlag[25] = pFlag[26]:0x3 & pFlag[25]:0xce0a6e55;
------>OPCODE :14
pFlag[26] = 0xe
------>OPCODE :0
pFlag[25] = pFlag[26]:0xe + pFlag[25]:0x1;
------>OPCODE :9
pFlag[25] = 0x6f76;
------>OPCODE :0
pFlag[24] = pFlag[25]:0x6f76 + pFlag[24]:0xce0a6e55;
------>OPCODE :7
pFlag[23] = pFlag[24]:0xce0addcb ^ pFlag[23]:0x54e4e4e3;
------>OPCODE :0
pFlag[22] = pFlag[23]:0x9aee3928 + pFlag[22]:0x31313131;  ===
------>OPCODE :8
pFlag[12] = 0xcc1f6a59;
------>OPCODE :14
pFlag[21] = 0xb
------>OPCODE :14
pFlag[22] = 0xb
------>OPCODE :9
pFlag[22] = 0xce0a6e55;                         ===                上一轮循环剩下的
------>OPCODE :14
pFlag[23] = 0xa
------>OPCODE :9
pFlag[23] = 0x75bcd15;
------>OPCODE :0
pFlag[22] = pFlag[23]:0x75bcd15 + pFlag[22]:0xce0a6e55;
------>OPCODE :8
pFlag[11] = 0xd5663b6a;====
------>OPCODE :14
pFlag[21] = 0xd
------>OPCODE :14
pFlag[22] = 0xd
------>OPCODE :9
pFlag[22] = 0x32323232;
------>OPCODE :14
pFlag[23] = 0xc
------>OPCODE :9
pFlag[23] = 0xcc1f6a59;
------>OPCODE :14
pFlag[24] = 0x10
------>OPCODE :2
pFlag[23] = pFlag[24]:0x10 * pFlag[23]:0xcc1f6a59; ===
------>OPCODE :14
pFlag[24] = 0xc
------>OPCODE :9
pFlag[24] = 0xcc1f6a59;
------>OPCODE :14
pFlag[25] = 0x20
------>OPCODE :12
exchange pFlag[25]:0xcc1f6a59, pFlag[24]:0x20
------>OPCODE :3
pFlag[24] = pFlag[25]:0xcc1f6a59 / pFlag[24]:0x20;
------>OPCODE :7
pFlag[23] = pFlag[24]:0xfe60fb53 ^ pFlag[23]:0xc1f6a590;
------>OPCODE :14
pFlag[24] = 0xc
------>OPCODE :9
pFlag[24] = 0xcc1f6a59;
------>OPCODE :0
pFlag[23] = pFlag[24]:0xcc1f6a59 + pFlag[23]:0x3f965ec3;
------>OPCODE :14
pFlag[24] = 0xb
------>OPCODE :9
pFlag[24] = 0xd5663b6a;
------>OPCODE :14
pFlag[25] = 0xb
------>OPCODE :9
pFlag[25] = 0xd5663b6a;
------>OPCODE :14
pFlag[26] = 0x800
------>OPCODE :12
exchange pFlag[26]:0xd5663b6a, pFlag[25]:0x800
------>OPCODE :3
pFlag[25] = pFlag[26]:0xd5663b6a / pFlag[25]:0x800;
------>OPCODE :14
pFlag[26] = 0x3
------>OPCODE :5
pFlag[25] = pFlag[26]:0x3 & pFlag[25]:0xfffaacc8; ====
------>OPCODE :14
pFlag[26] = 0xe
------>OPCODE :0
pFlag[25] = pFlag[26]:0xe + pFlag[25]:0;
------>OPCODE :9
pFlag[25] = 0x494c;
------>OPCODE :0
pFlag[24] = pFlag[25]:0x494c + pFlag[24]:0xd5663b6a;===
------>OPCODE :7
pFlag[23] = pFlag[24]:0xd56684b6 ^ pFlag[23]:0xbb5c91c; ===
------>OPCODE :0
pFlag[22] = pFlag[23]:0xded34daa + pFlag[22]:0x32323232;
------>OPCODE :8
pFlag[13] = 0x11057fdc;                                         === 
------>OPCODE :14
pFlag[21] = 0x13
------>OPCODE :9
pFlag[21] = 0x2;
------>OPCODE :14
pFlag[22] = 0
------>OPCODE :0
pFlag[21] = pFlag[22]:0 + pFlag[21]:0x2;
------>OPCODE :14
pFlag[22] = 0xc
------>OPCODE :9
pFlag[22] = 0xcc1f6a59;
------>OPCODE :8
pFlag[2] = 0xcc1f6a59;
------>OPCODE :14
pFlag[21] = 0x13
------>OPCODE :9
pFlag[21] = 0x2;
------>OPCODE :14
pFlag[22] = 0x1
------>OPCODE :0
pFlag[21] = pFlag[22]:0x1 + pFlag[21]:0x2;
------>OPCODE :14
pFlag[22] = 0
------>OPCODE :0
pFlag[21] = pFlag[22]:0 + pFlag[21]:0x3;
------>OPCODE :14
pFlag[22] = 0xd
------>OPCODE :9
pFlag[22] = 0x11057fdc;
------>OPCODE :8
pFlag[3] = 0x11057fdc;
------>OPCODE :18  =============================================v13准备开始
------>OPCODE :14
pFlag[21] = 0x14
------>OPCODE :14
pFlag[22] = 0x14
------>OPCODE :9
pFlag[22] = 0x13;
------>OPCODE :14
pFlag[23] = 0x1
------>OPCODE :0
pFlag[22] = pFlag[23]:0x1 + pFlag[22]:0x13;
------>OPCODE :8
pFlag[20] = 0x14;
------>OPCODE :15
------>OPCODE :14
pFlag[21] = 0x14
------>OPCODE :9
pFlag[21] = 0x14;
------>OPCODE :14
pFlag[22] = 0x14
------>OPCODE :12
exchange pFlag[22]:0x14, pFlag[21]:0x14
------>OPCODE :1
pFlag[21] = pFlag[22]:0x14 - pFlag[21]:0x14;
------>OPCODE :11
pFlag[21] = 0;
------>OPCODE :10
pFlag[21] = 1;
------>OPCODE :16
------>OPCODE :14
pFlag[21] = 0x13
------>OPCODE :14
pFlag[22] = 0x13
------>OPCODE :9
pFlag[22] = 0;
------>OPCODE :14
pFlag[23] = 0x2
------>OPCODE :0
pFlag[22] = pFlag[23]:0x2 + pFlag[22]:0;
------>OPCODE :8
pFlag[19] = 0x2;
------>OPCODE :15
------>OPCODE :14
pFlag[21] = 0x13
------>OPCODE :9
pFlag[21] = 0x2;
------>OPCODE :14
pFlag[22] = 0xa
------>OPCODE :12
exchange pFlag[22]:0x2, pFlag[21]:0xa
------>OPCODE :1
pFlag[21] = pFlag[22]:0x2 - pFlag[21]:0xa;
------>OPCODE :11
pFlag[21] = 1;
------>OPCODE :10
pFlag[21] = 0;
------>OPCODE :16
------>OPCODE :14
pFlag[21] = 0x14
------>OPCODE :14
pFlag[22] = 0
------>OPCODE :8
pFlag[20] = 0;
------>OPCODE :14
pFlag[21] = 0x14
------>OPCODE :9
pFlag[21] = 0;
------>OPCODE :14
pFlag[22] = 0x14
------>OPCODE :12
exchange pFlag[22]:0, pFlag[21]:0x14
------>OPCODE :1
pFlag[21] = pFlag[22]:0 - pFlag[21]:0x14;
------>OPCODE :11
pFlag[21] = 1;
------>OPCODE :10
pFlag[21] = 0;
------>OPCODE :16
------>OPCODE :14
pFlag[21] = 0xc
------>OPCODE :14
pFlag[22] = 0x13
------>OPCODE :9
pFlag[22] = 0x2;
------>OPCODE :14
pFlag[23] = 0
------>OPCODE :0
pFlag[22] = pFlag[23]:0 + pFlag[22]:0x2;
------>OPCODE :9
pFlag[22] = 0xcc1f6a59;
------>OPCODE :8
pFlag[12] = 0xcc1f6a59;
------>OPCODE :14
pFlag[21] = 0xd
------>OPCODE :14
pFlag[22] = 0x13
------>OPCODE :9
pFlag[22] = 0x2;
------>OPCODE :14
pFlag[23] = 0x1
------>OPCODE :0
pFlag[22] = pFlag[23]:0x1 + pFlag[22]:0x2;
------>OPCODE :14
pFlag[23] = 0
------>OPCODE :0
pFlag[22] = pFlag[23]:0 + pFlag[22]:0x3;
------>OPCODE :9
pFlag[22] = 0x11057fdc;
------>OPCODE :8
pFlag[13] = 0x11057fdc;
------>OPCODE :14
pFlag[21] = 0xb
------>OPCODE :14
pFlag[22] = 0xb
------>OPCODE :9
pFlag[22] = 0x798dcdf9;
------>OPCODE :14
pFlag[23] = 0xa
------>OPCODE :9
pFlag[23] = 0x154cbf7; =                        =====系统中的立即数
------>OPCODE :0
pFlag[22] = pFlag[23]:0x154cbf7 + pFlag[22]:0x798dcdf9; == 这2个数是固定的
------>OPCODE :8
pFlag[11] = 0x7ae299f0; =========
------>OPCODE :14
pFlag[21] = 0xc
------>OPCODE :14
pFlag[22] = 0xc
------>OPCODE :9
pFlag[22] = 0xcc1f6a59;
------>OPCODE :14
pFlag[23] = 0xd
------>OPCODE :9
pFlag[23] = 0x11057fdc;
------>OPCODE :14
pFlag[24] = 0x10
------>OPCODE :2
pFlag[23] = pFlag[24]:0x10 * pFlag[23]:0x11057fdc;========
------>OPCODE :14
pFlag[24] = 0
------>OPCODE :14
pFlag[25] = 0xe
------>OPCODE :0
pFlag[24] = pFlag[25]:0xe + pFlag[24]:0;
------>OPCODE :9
pFlag[24] = 0x5354;
------>OPCODE :0
pFlag[23] = pFlag[24]:0x5354 + pFlag[23]:0x1057fdc0; =======
------>OPCODE :14
pFlag[24] = 0xd
------>OPCODE :9
pFlag[24] = 0x11057fdc;
------>OPCODE :14
pFlag[25] = 0xb
------>OPCODE :9
pFlag[25] = 0x7ae299f0;
------>OPCODE :0
pFlag[24] = pFlag[25]:0x7ae299f0 + pFlag[24]:0x11057fdc;
------>OPCODE :14
pFlag[25] = 0xd
------>OPCODE :9
pFlag[25] = 0x11057fdc;
------>OPCODE :14
pFlag[26] = 0x20
------>OPCODE :12
exchange pFlag[26]:0x11057fdc, pFlag[25]:0x20
------>OPCODE :3
pFlag[25] = pFlag[26]:0x11057fdc / pFlag[25]:0x20;                ### 0x882bfe
------>OPCODE :14
pFlag[26] = 0x1
------>OPCODE :14
pFlag[27] = 0xe
------>OPCODE :0
pFlag[26] = pFlag[27]:0xe + pFlag[26]:0x1;
------>OPCODE :9
pFlag[26] = 0x4f4d;
------>OPCODE :0
pFlag[25] = pFlag[26]:0x4f4d + pFlag[25]:0x882bfe;
------>OPCODE :7
pFlag[24] = pFlag[25]:0x887b4b ^ pFlag[24]:0x8be819cc; =====
------>OPCODE :7
pFlag[23] = pFlag[24]:0x8b606287 ^ pFlag[23]:0x10585114;==
------>OPCODE :0
pFlag[22] = pFlag[23]:0x9b383393 + pFlag[22]:0xcc1f6a59;=====
------>OPCODE :8
pFlag[12] = 0x67579dec;        ######
------>OPCODE :14
pFlag[21] = 0xd
------>OPCODE :14
pFlag[22] = 0xd
------>OPCODE :9
pFlag[22] = 0x11057fdc;
------>OPCODE :14
pFlag[23] = 0xc
------>OPCODE :9
pFlag[23] = 0x67579dec;
------>OPCODE :14
pFlag[24] = 0x10
------>OPCODE :2
pFlag[23] = pFlag[24]:0x10 * pFlag[23]:0x67579dec;
------>OPCODE :14
pFlag[24] = 0x2
------>OPCODE :14
pFlag[25] = 0xe
------>OPCODE :0
pFlag[24] = pFlag[25]:0xe + pFlag[24]:0x2;
------>OPCODE :9
pFlag[24] = 0x2074;
------>OPCODE :0
pFlag[23] = pFlag[24]:0x2074 + pFlag[23]:0x7579dec0;                === 49
------>OPCODE :14
pFlag[24] = 0xc
------>OPCODE :9
pFlag[24] = 0x67579dec;
------>OPCODE :14
pFlag[25] = 0xb
------>OPCODE :9
pFlag[25] = 0x7ae299f0;
------>OPCODE :0
pFlag[24] = pFlag[25]:0x7ae299f0 + pFlag[24]:0x67579dec;                =====
------>OPCODE :14
pFlag[25] = 0xc
------>OPCODE :9
pFlag[25] = 0x67579dec;
------>OPCODE :14
pFlag[26] = 0x20
------>OPCODE :12
exchange pFlag[26]:0x67579dec, pFlag[25]:0x20
------>OPCODE :3
pFlag[25] = pFlag[26]:0x67579dec / pFlag[25]:0x20;==='0x33abcef'
------>OPCODE :14
pFlag[26] = 0x3
------>OPCODE :14
pFlag[27] = 0xe
------>OPCODE :0
pFlag[26] = pFlag[27]:0xe + pFlag[26]:0x3;
------>OPCODE :9
pFlag[26] = 0x6561;
------>OPCODE :0
pFlag[25] = pFlag[26]:0x6561 + pFlag[25]:0x33abcef;
------>OPCODE :7
pFlag[24] = pFlag[25]:0x33b2250 ^ pFlag[24]:0xe23a37dc;
------>OPCODE :7
pFlag[23] = pFlag[24]:0xe101158c ^ pFlag[23]:0x7579ff34;
------>OPCODE :0
pFlag[22] = pFlag[23]:0x9478eab8 + pFlag[22]:0x11057fdc; # '0xa57e6a94'
------>OPCODE :8
pFlag[13] = 0xa57e6a94;
------>OPCODE :14
pFlag[21] = 0x13
------>OPCODE :9
pFlag[21] = 0x2;
------>OPCODE :14
pFlag[22] = 0
------>OPCODE :0
pFlag[21] = pFlag[22]:0 + pFlag[21]:0x2;
------>OPCODE :14
pFlag[22] = 0xc
------>OPCODE :9
pFlag[22] = 0x67579dec;
------>OPCODE :8
pFlag[2] = 0x67579dec;
------>OPCODE :14
pFlag[21] = 0x13
------>OPCODE :9
pFlag[21] = 0x2;
------>OPCODE :14
pFlag[22] = 0x1
------>OPCODE :0
pFlag[21] = pFlag[22]:0x1 + pFlag[21]:0x2;
------>OPCODE :14
pFlag[22] = 0
------>OPCODE :0
pFlag[21] = pFlag[22]:0 + pFlag[21]:0x3;
------>OPCODE :14
pFlag[22] = 0xd
------>OPCODE :9
pFlag[22] = 0xa57e6a94;
------>OPCODE :8
pFlag[3] = 0xa57e6a94;
------>OPCODE :18
----------------------------------------------------------------------------

分析算法

A = FLAG[0:4]
B = FLAG[4:8]

pFlag[23] = B * 0x10
pFlag[24] = B / 0X20                                                
pFlag[23] = pFlag[23] ^ pFlag[24]
pFlag[23] = B + pFlag[23]        
pFlag[23] = (0xCE0A6E55 + 0X6F76) ^ pFlag[23]                                        
pFlag[22] = pFlag[23] + A                                                                                
TMP1 = pFlag[22]  # 173行  0xcc1f6a59 ***V12导出 # v0

pFlag[22] = 0xCE0A6E55 # (过会回来补坑,这个是上一轮循环剩下的) 这个与FLAG无关,是固定的
pFlag[22] = 0x75bcd15(立即数) + 0xce0a6e55
TMP2 = pFlag[22]  # 187行  0xd5663b6a   #TMP2 = sum1

pFlag[23] = TMP1
pFlag[23] = TMP1 * 0X10  # 201
pFlag[24] = TMP1 / 0x20  # 213
pFlag[23] = pFlag[23] ^ pFlag[24]
pFlag[23] = TMP1 + pFlag[23]                                                

pFlag[26] = TMP2
pFlag[25] = pFlag[26] / 0x800  #233行
pFlag[24] = TMP2 + 0x494c   ###245
pFlag[23] = pFlag[24] ^ pFlag[23]

pFlag[22] = pFlag[23] + B 

TMP3 = pFlag[22]          ### 251行   0x11057fdc  ***V12导出   #v1

pFlag[22] = 0x154cbf7(立即数) + 0x798dcdf9; #这2个数是固定的 #在第一轮的时候是这个,其他的还没测试
TMP4 = pFlag[22]         ###407行  0x7ae299f0
pFlag[23] = TMP3 * 0X10
pFlag[23] = pFlag[23] + 0X5354 # 421  
pFlag[24] = TMP4 + TMP3  #441 

pFlag[25] = TMP3 / 0x20                 #451  ### 0x882bfe
pFlag[25] = 0x4f4d + pFlag[25] 
pFlag[24] = pFlag[25] ^ pFlag[24]
pFlag[23] = pFlag[24] ^ pFlag[23]  #465 ## 0x9b383393
pFlag[22] = pFlag[23] + TMP1
TMP5 = pFlag[22]   ####        469  0x67579dec

pFlag[23] = TMP5 * 0X10
pFlag[23] = pFlag[23] + 0x2074  ## 0x7579ff34
pFlag[24] = TMP4 + TMP5  ####503行
pFlag[25] = TMP5 / 0x20
pFlag[25] = pFlag[25] + 0x6561
pFlag[24] = pFlag[25] ^ pFlag[24]
pFlag[23] = pFlag[24] ^ pFlag[23]
pFlag[22] = pFlag[23] + TMP3  # 529行 0xa57e6a94
TMP6 = pFlag[22]  #        0xa57e6a94

通过 * 0x10 、/0x20、 /0x800、 &3等特征,猜测是xtea, tea算法

一边猜一边还原算法,用C语言写出1轮的循环加密算法

int tea_key[4] = { 0X5354, 0x4f4d, 0x2074, 0x6561 };
int xtea_key[4] = { 0x494c, 0X6F76 , 0x6520, 0x4355 };

void encrypt(int* v, int& sum_xtea, int& sum_tea)
{

        int v0 = v[0], v1 = v[1];

        v0 += (((v1 << 4) ^ (v1 / 0x20)) + v1) ^ (sum_xtea + xtea_key[sum_xtea & 3]);
        sum_xtea += 0x75bcd15;
        v1 += (((v0 << 4) ^ (v0 / 0x20)) + v0) ^ (sum_xtea + xtea_key[(sum_xtea / 0x800) & 3]);

        sum_tea += 0x154cbf7;
        v0 += ((v1 << 4) + tea_key[0]) ^ (v1 + sum_tea) ^ ((v1 / 0x20) + tea_key[1]);
        v1 += ((v0 << 4) + tea_key[2]) ^ (v0 + sum_tea) ^ ((v0 / 0x20) + tea_key[3]);

        v[0] = v0;
        v[1] = v1;
}

sum_tea 和 sum_xtea,对于每一组来说,初始值是不同的,比如第二组这里是0x798dcdf9 和 0xce0a6e55

最后通过打印三,四,五组第一个循环的日志,来与第二组的日志做对比,找到了所有组的初始的sum_tea 和 sum_xtea

int sum[4][2] = {
        0xCE0A6E55, 0x798dcdf9, 
        0x613673f9, 0x942dbd45,
        0xf462799d, 0xaecdac91,
        0x878e7f41, 0xc96d9bdd
};

最终写脚本解密

#include <windows.h>
#include <stdio.h>

int sum[4][2] = {
        0xCE0A6E55, 0x798dcdf9,
        0x613673f9, 0x942dbd45,
        0xf462799d, 0xaecdac91,
        0x878e7f41, 0xc96d9bdd
};

int tea_key[4] = { 0X5354, 0x4f4d, 0x2074, 0x6561 };
int xtea_key[4] = { 0x494c, 0X6F76 , 0x6520, 0x4355 };

void encrypt(int* v, int& sum_xtea, int& sum_tea)
{

        int v0 = v[0], v1 = v[1];

        v0 += (((v1 << 4) ^ (v1 / 0x20)) + v1) ^ (sum_xtea + xtea_key[sum_xtea & 3]);
        sum_xtea += 0x75bcd15;
        v1 += (((v0 << 4) ^ (v0 / 0x20)) + v0) ^ (sum_xtea + xtea_key[(sum_xtea / 0x800) & 3]);

        sum_tea += 0x154cbf7;
        v0 += ((v1 << 4) + tea_key[0]) ^ (v1 + sum_tea) ^ ((v1 / 0x20) + tea_key[1]);
        v1 += ((v0 << 4) + tea_key[2]) ^ (v0 + sum_tea) ^ ((v0 / 0x20) + tea_key[3]);

        v[0] = v0;
        v[1] = v1;
}
void decrypt(int* v, int& sum_xtea, int& sum_tea)
{

        int v0 = v[0], v1 = v[1];
        v1 -= ((v0 << 4) + tea_key[2]) ^ (v0 + sum_tea) ^ ((v0 / 0x20) + tea_key[3]);
        v0 -= ((v1 << 4) + tea_key[0]) ^ (v1 + sum_tea) ^ ((v1 / 0x20) + tea_key[1]);
        sum_tea -= 0x154cbf7;;

        v1 -= (((v0 << 4) ^ (v0 / 0x20)) + v0) ^ (sum_xtea + xtea_key[(sum_xtea / 0x800) & 3]);
        sum_xtea -= 0x75bcd15;
        v0 -= (((v1 << 4) ^ (v1 / 0x20)) + v1) ^ (sum_xtea + xtea_key[sum_xtea & 3]);

        v[0] = v0;
        v[1] = v1;
}

char compare_date[100] =  //这里是从程序中提取的加密后的flag的值
{
  0xE8, 0xFA, 0xE0, 0xAE, 0x01, 0x41, 0x3E, 0xFC, 0x92, 0xAD,
  0x7C, 0x16, 0xBE, 0x6C, 0xEA, 0x51, 0x00, 0x01, 0x2A, 0x24,
  0x1B, 0x1A, 0x51, 0x01, 0x94, 0x66, 0x4D, 0x51, 0xEB, 0xBF,
  0x5F, 0x2F, 0x98, 0x63, 0xD3, 0x46, 0xF0, 0xE3, 0xEE, 0x79
};

int main()
{
        int v[2] = { 0 };
        int* encFlag = (int*)compare_date;

        //flag的前8个字符爆破得到的  L3HCTF{D
        for (int j = 0; j < 4; j++) //后32个字符,分4组
        {
                for (int i = 0; i < 20; i++)
                        encrypt(v, sum[j][0], sum[j][1]);  //提升sum_xtea 和 sum_tea

                for (int i = 0; i < 20; i++)
                        decrypt(&encFlag[j * 2 + 2], sum[j][0], sum[j][1]);

        }

        char* flag = (char*)&encFlag[2];
        printf("flag is L3HCTF{D%s  \n", flag);

        return 0;
}

// L3HCTF{D0uBle_vM_W1th_dOubIe_TEA}

Load

IDA打开程序分析

image-20211116213515345.png

进入LOAD_PE函数,就是创建了个傀儡进程

image-20211116213833328.png

在ResumeThread这里下断点,dump,然后foremost分离

注意在foremost分离的时候要把dump下来的程序的MZ头抹去,这样才能分离解密后的PE文件来

image-20211116214156793.png

image-20211116214613497.png

IDA打开分析

image-20211116214535505.png

获取flag后,对flag中的字符在 0x30-0x39或 a-f 范围做了个小处理

0x30 - 0x39  ---> 0x00 - 0x09
a - f                  --->   0xA ---0xF
# 然后
假设输入的是123f  -->  0x12, 0x3f 存在了0x434380的位置

注意这里全是对应的十六进制,猜测输入的flag的范围就是[0-9a-f]

最终434380处的数据是13个。下面又分为9 + 4 个,正好是3和2的平方,并且下面验证的时候也是分为9 + 4进行验证的

猜测是3   3 + 2 2的某个矩阵运算,   在上述图89行位置下断点,修改src处的数据为100010001,

1 0 0
0 1 0
0 0 1
正好是单位矩阵

然后运行,加密后发现Src处的数据没变,但是v29处的数据全乱了,猜测是逆矩阵

提取出加密后Src 和 v29处的数据

Src: 
1    0  -9
0   -1  -6
-1  -2  -4 

v29:
7    3
30  13

写脚本求逆矩阵,并转换为flag

import numpy

if __name__ == "__main__":
    a = numpy.array([[1, 0, -9], [0, -1, -6], [-1, -2, -4]])
    b = numpy.array([[7, 3], [30, 13]])

    a_inv = numpy.linalg.inv(a)
    b_inv = numpy.linalg.inv(b)

    a_list = [list(i) for i in a_inv]
    b_list = [list(i) for i in b_inv]

    flag_list = a_list[0] + a_list[1] + a_list[2] + b_list[0] + b_list[1]
    flag_list = [int(i) & 0xff for i in flag_list]
    flag = bytes(flag_list).hex()

    print(flag)
    #  f812f706f306ff02ff0dfde207

拼接后进行验证,Load.exe在 ResumeThread那里下断点,输入flag,程序断下,在运行dump提取出来的exe,验证成功

image-20211116222434611.png

最终flag为 : flag{f812f706f306ff02ff0dfde207}

免费评分

参与人数 4吾爱币 +2 热心值 +4 收起 理由
kolt1911 + 1 我很赞同!
xjd21221 + 1 用心讨论,共获提升!
xhever + 1 + 1 我很赞同!
m1n9yu3 + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

搜索曾经的回忆 发表于 2021-11-17 14:50
有几张图片挂了,师傅能补一下吗?
 楼主| zsky 发表于 2021-11-17 15:26
搜索曾经的回忆 发表于 2021-11-17 15:28
 楼主| zsky 发表于 2021-11-17 15:37

好吧,抱歉,过会上完课回去重新传
 楼主| zsky 发表于 2021-11-17 19:01
明次 发表于 2021-11-19 17:16
感谢楼主分享
Atomhua 发表于 2021-11-20 16:27

感谢楼主分享,wp很详细
douluodalu 发表于 2021-11-30 05:06

感谢楼主分享
jnsf077 发表于 2022-3-17 11:15
楼主好人啊
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 11:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表