首页
社区
课程
招聘
[原创]第八题 惊天阴谋 by k1ee
发表于: 2020-12-7 20:46 6208

[原创]第八题 惊天阴谋 by k1ee

2020-12-7 20:46
6208

去花,修复各种干扰后,取得程序逻辑如下

注册码分为两部分

魔改的AES,动调取得sbox,手算rsbox,解密。

每一位+0x7F得到第二位

调用API进行解密即可

六种运算的虚拟机,把所有指令打出来,然后分析可以看出有很多重复的部分,懒得写程序提炼,于是手动提炼了一部分,12万行缩小到1.2万行,编译爆破程序求解,16线程106分钟解得所有逆向关系

一个可逆算法,直接算出输入

最令人头痛的算法,我记录了所有和输入有关的运算,发现还是可逆的,也就三处需要记录

image-20201207204140227

image-20201207204152042

每一处输入输出关系也就65423个,因此爆破即可,从后往前还原数据

似乎是个矩阵,不过当时太累了,爆破也不是很难

此题应该多解,我没求出预期解

https://docs.microsoft.com/en-us/windows/win32/debug/pe-format

image-20201204150243977

实际上是从KernelBase和advapi32里找函数

image-20201204151820844

const char* username = "141E8F96636898EF";
const char* serial = "dd8c5dd5bff047cb86c51fc808254c0950ebd2d9c7e6b34679a6cda7f96ea0f46d105248c68b6534546d34c26534546d34c26534542538d289a28b2d14d06534546614d225146289a28b6614d249a7096d10522538d22538d289a28b48a21b2d14d041a69b2d14d06614d289a28b25146250a28948a21b48c68b48c68b49829948a21b6d105249a7092c345289a28b6534542c34522d14d050a2896d105225146289a28b6d105249a7092d14d049a7096d34c26d10522d14d049a70948a21b2d14d048c68b48a21b49a70925146248c68b41a69b08a69948c68b48c68b498299";
 
uint8_t username_md5[16] = { 0 };
md5((uint8_t*)username, strlen(username), username_md5);
uint8_t username_md5_1[16] = { 0 };
md5(username_md5, 8, username_md5_1);
uint8_t username_md5_2[16] = { 0 };
md5(username_md5 + 8, 8, username_md5_2);
 
uint8_t serial_hex[224] = { 0 };
char* sp = (char*)serial;
for (int i = 0; i < 224; ++i)
{
    sscanf_s(sp, "%2hhx", &serial_hex[i]);
    sp += 2;
}
uint8_t* serial_1 = serial_hex;
uint8_t* serial_2 = serial_hex + 32;
 
uint8_t result1_1[32] = { 0 };
uint32_t* pi = (uint32_t*)serial_1;
uint32_t* po = (uint32_t*)result1_1;
for (int i = 0; i < 8; ++i)
{
    *po++ = transform1_1(*pi++);
}
 
uint8_t result1_2[32] = { 0 };
memcpy(result1_2, result1_1, 32);
HCRYPTPROV ctx;
CryptAcquireContextA(&ctx, 0, 0, 24, 0xF0000000);
HCRYPTHASH hash;
CryptCreateHash(ctx, 0x800C, 0, 0, &hash);
unsigned char hashData[20] = { 0x31, 0x5F, 0x4C, 0x30, 0x56, 0x33, 0x5F, 0x42, 0x58, 0x53, 0x5F, 0x46, 0x30, 0x52, 0x45, 0x56, 0x45, 0x52, 0x21, 0x00 };
CryptHashData(hash, hashData, 19, 0);
HCRYPTKEY key;
CryptDeriveKey(ctx, 0x6610, hash, 0, &key);
DWORD len = 32;
CryptEncrypt(key, 0, 0, 0, result1_2, &len, 32);
 
uint8_t result1_2_trans[16] = { 0 };
for (int i = 0; i < 16; ++i)
{
    result1_2_trans[i] = result1_2[2 * i];
}
 
transform1_2(result1_2_trans);
 
//Equals MD5 Part1
 
uint8_t result2_1[32] = { 0 };
transform2_1(serial_2, result2_1);
 
uint8_t result2_2[16] = { 0 };
transform2_2(result2_1, result2_2);
 
transform2_3(result2_2, username_md5_2);
const char* username = "141E8F96636898EF";
const char* serial = "dd8c5dd5bff047cb86c51fc808254c0950ebd2d9c7e6b34679a6cda7f96ea0f46d105248c68b6534546d34c26534546d34c26534542538d289a28b2d14d06534546614d225146289a28b6614d249a7096d10522538d22538d289a28b48a21b2d14d041a69b2d14d06614d289a28b25146250a28948a21b48c68b48c68b49829948a21b6d105249a7092c345289a28b6534542c34522d14d050a2896d105225146289a28b6d105249a7092d14d049a7096d34c26d10522d14d049a70948a21b2d14d048c68b48a21b49a70925146248c68b41a69b08a69948c68b48c68b498299";
 
uint8_t username_md5[16] = { 0 };
md5((uint8_t*)username, strlen(username), username_md5);
uint8_t username_md5_1[16] = { 0 };
md5(username_md5, 8, username_md5_1);
uint8_t username_md5_2[16] = { 0 };
md5(username_md5 + 8, 8, username_md5_2);
 
uint8_t serial_hex[224] = { 0 };
char* sp = (char*)serial;
for (int i = 0; i < 224; ++i)
{
    sscanf_s(sp, "%2hhx", &serial_hex[i]);
    sp += 2;
}
uint8_t* serial_1 = serial_hex;
uint8_t* serial_2 = serial_hex + 32;
 
uint8_t result1_1[32] = { 0 };
uint32_t* pi = (uint32_t*)serial_1;
uint32_t* po = (uint32_t*)result1_1;
for (int i = 0; i < 8; ++i)
{
    *po++ = transform1_1(*pi++);
}
 
uint8_t result1_2[32] = { 0 };
memcpy(result1_2, result1_1, 32);
HCRYPTPROV ctx;
CryptAcquireContextA(&ctx, 0, 0, 24, 0xF0000000);
HCRYPTHASH hash;
CryptCreateHash(ctx, 0x800C, 0, 0, &hash);
unsigned char hashData[20] = { 0x31, 0x5F, 0x4C, 0x30, 0x56, 0x33, 0x5F, 0x42, 0x58, 0x53, 0x5F, 0x46, 0x30, 0x52, 0x45, 0x56, 0x45, 0x52, 0x21, 0x00 };
CryptHashData(hash, hashData, 19, 0);
HCRYPTKEY key;
CryptDeriveKey(ctx, 0x6610, hash, 0, &key);
DWORD len = 32;
CryptEncrypt(key, 0, 0, 0, result1_2, &len, 32);
 
uint8_t result1_2_trans[16] = { 0 };
for (int i = 0; i < 16; ++i)
{
    result1_2_trans[i] = result1_2[2 * i];
}
 
transform1_2(result1_2_trans);
 
//Equals MD5 Part1
 
uint8_t result2_1[32] = { 0 };
transform2_1(serial_2, result2_1);
 
uint8_t result2_2[16] = { 0 };
transform2_2(result2_1, result2_2);
 
transform2_3(result2_2, username_md5_2);
AES_ctx actx;
int akey[8] = { 0 };
akey[0] = 0x59206F57;
akey[1] = 0x59676E6F;
akey[2] = 0x206E6175;
akey[3] = 0x75486958;
akey[4] = 0x4B206E61;
akey[5] = 0x75586E61;
akey[6] = 0x754C206E;
akey[7] = 0x6E61546E;
AES_init_ctx(&actx, (uint8_t*)akey);
AES_ECB_decrypt(&actx, username_md5_1);
AES_ctx actx;
int akey[8] = { 0 };
akey[0] = 0x59206F57;
akey[1] = 0x59676E6F;
akey[2] = 0x206E6175;
akey[3] = 0x75486958;
akey[4] = 0x4B206E61;
akey[5] = 0x75586E61;
akey[6] = 0x754C206E;
akey[7] = 0x6E61546E;
AES_init_ctx(&actx, (uint8_t*)akey);
AES_ECB_decrypt(&actx, username_md5_1);
uint8_t part1_1[32] = { 0 };
for (int i = 0; i < 16; ++i)
{
    part1_1[i * 2] = username_md5_1[i];
    part1_1[i * 2 + 1] = username_md5_1[i] + 0x7F;
}
uint8_t part1_1[32] = { 0 };
for (int i = 0; i < 16; ++i)
{
    part1_1[i * 2] = username_md5_1[i];
    part1_1[i * 2 + 1] = username_md5_1[i] + 0x7F;
}
HCRYPTPROV ctx;
CryptAcquireContextA(&ctx, 0, 0, 24, 0xF0000000);
HCRYPTHASH hash;
CryptCreateHash(ctx, 0x800C, 0, 0, &hash);
unsigned char hashData[20] = { 0x31, 0x5F, 0x4C, 0x30, 0x56, 0x33, 0x5F, 0x42, 0x58, 0x53, 0x5F, 0x46, 0x30, 0x52, 0x45, 0x56, 0x45, 0x52, 0x21, 0x00 };
CryptHashData(hash, hashData, 19, 0);
HCRYPTKEY key;
CryptDeriveKey(ctx, 0x6610, hash, 0, &key);
DWORD len = 32;
CryptDecrypt(key, 0, 0, 0, part1_1, &len);
HCRYPTPROV ctx;
CryptAcquireContextA(&ctx, 0, 0, 24, 0xF0000000);
HCRYPTHASH hash;
CryptCreateHash(ctx, 0x800C, 0, 0, &hash);
unsigned char hashData[20] = { 0x31, 0x5F, 0x4C, 0x30, 0x56, 0x33, 0x5F, 0x42, 0x58, 0x53, 0x5F, 0x46, 0x30, 0x52, 0x45, 0x56, 0x45, 0x52, 0x21, 0x00 };
CryptHashData(hash, hashData, 19, 0);
HCRYPTKEY key;
CryptDeriveKey(ctx, 0x6610, hash, 0, &key);
DWORD len = 32;
CryptDecrypt(key, 0, 0, 0, part1_1, &len);
uint32_t* ansbuf = new uint32_t[0x10000000];
for (int i = 0; i < 16; ++i)
{
    uint32_t val = i * 0x10000000;
    char filename[128] = { 0 };
    sprintf_s(filename, "E:/Ctf/KCTF2020Q4/KCTF-KeyME/Solver/Solver/Release/%08X_%08X.bin", val, val + 0xFFFFFFF);
    FILE* fp;
    fopen_s(&fp, filename, "rb"); 
    int ret = fread(ansbuf, 4, 0x10000000, fp);
    fclose(fp);
    for (int k = 0; k < 0x10000000; ++k)
    {
        uint32_t input = val++;
        uint32_t output = ansbuf[k];
        for (int t = 0; t < 8; ++t)
        {
            if (pi[t] == output)
            {
                po[t] = input;
                //pos[t].push_back(input);
            }
        }
    }
}
delete[] ansbuf;
 
printf("Serial Part 1\n");
for (int i = 0; i < 32; ++i)
{
    printf("%02x", part1_2[i]);
}
uint32_t* ansbuf = new uint32_t[0x10000000];
for (int i = 0; i < 16; ++i)
{
    uint32_t val = i * 0x10000000;
    char filename[128] = { 0 };
    sprintf_s(filename, "E:/Ctf/KCTF2020Q4/KCTF-KeyME/Solver/Solver/Release/%08X_%08X.bin", val, val + 0xFFFFFFF);
    FILE* fp;
    fopen_s(&fp, filename, "rb"); 
    int ret = fread(ansbuf, 4, 0x10000000, fp);
    fclose(fp);
    for (int k = 0; k < 0x10000000; ++k)
    {
        uint32_t input = val++;
        uint32_t output = ansbuf[k];
        for (int t = 0; t < 8; ++t)
        {
            if (pi[t] == output)
            {
                po[t] = input;
                //pos[t].push_back(input);
            }
        }
    }
}
delete[] ansbuf;
 
printf("Serial Part 1\n");
for (int i = 0; i < 32; ++i)
{
    printf("%02x", part1_2[i]);
}
83bde72e2806ce3c8f424e242559a66314bb37008d62a69bfd1a960f8e4102c8
83bde72e2806ce3c8f424e242559a66314bb37008d62a69bfd1a960f8e4102c8
int buf1[8] = { 0x18111C1A, 0x1190C08, 0x10070B20, 0x151D0217, 0x12161B14, 0xA1E05, 0xD130309, 0x1F0E0604 };
int buf2[8] = { 0x14161715, 0x12040C13, 0xE100603, 0xF1C180A, 0x50B001F, 0x200D1A08, 0x9111D1E, 0x1B010219 };
int buf3[8] = { 0x11ECEE03, 0xC050E14, 0x5F7ED03, 0xE700F600, 0xBEFE800, 0xFF0403F5, 0xF4061600, 0xF90918EF }; 
uint8_t* p1 = (uint8_t*)buf1;
uint8_t* p2 = (uint8_t*)buf2;
uint8_t* p3 = (uint8_t*)buf3;
 
uint8_t target_m[16] = { 0x15, 0x09, 0x0c, 0x1f, 0x1c, 0x13, 0x16, 0x19, 0x1d, 0x03, 0x10, 0x0f, 0x01, 0x02, 0x1e, 0x06 };
 
for (int i = 0; i < 16; ++i)
    uint8_t mid = target_m[i] - p3[i] + md5c[i];
    cal[i] = __ROL__(mid, p1[i] & 7) ^ p2[i];
}
int buf1[8] = { 0x18111C1A, 0x1190C08, 0x10070B20, 0x151D0217, 0x12161B14, 0xA1E05, 0xD130309, 0x1F0E0604 };
int buf2[8] = { 0x14161715, 0x12040C13, 0xE100603, 0xF1C180A, 0x50B001F, 0x200D1A08, 0x9111D1E, 0x1B010219 };
int buf3[8] = { 0x11ECEE03, 0xC050E14, 0x5F7ED03, 0xE700F600, 0xBEFE800, 0xFF0403F5, 0xF4061600, 0xF90918EF }; 
uint8_t* p1 = (uint8_t*)buf1;
uint8_t* p2 = (uint8_t*)buf2;
uint8_t* p3 = (uint8_t*)buf3;
 
uint8_t target_m[16] = { 0x15, 0x09, 0x0c, 0x1f, 0x1c, 0x13, 0x16, 0x19, 0x1d, 0x03, 0x10, 0x0f, 0x01, 0x02, 0x1e, 0x06 };
 
for (int i = 0; i < 16; ++i)
    uint8_t mid = target_m[i] - p3[i] + md5c[i];
    cal[i] = __ROL__(mid, p1[i] & 7) ^ p2[i];
}
 
 
 
uint16_t r2_r1(uint64_t res, uint64_t v3, uint64_t v2)
{
    std::vector<int> ret;
    for (int i = 65422; i >= 0; --i)
    {
        if (res == (i * (v3 * v3 % 65423 * v2 % 65423) % 65423))
        {
            ret.push_back(i);
        }
    }
    if (ret.size() != 1)
    {
        _CrtDbgBreak();
    }
    return ret[0];
}
 
uint16_t r2_r2(uint64_t res, uint64_t val, uint64_t bp)
{
    std::vector<int> ret;
    for (int i = 65422; i >= 0; --i)
    {
        uint64_t r = ((int64_t)(i - val * bp) % 65423 + 65423) % 65423;
        if (res == r)
        {
            ret.push_back(i);
        }
    }
    if (ret.size() != 1)
    {
        _CrtDbgBreak();
    }
    return ret[0];
}
 
uint16_t r2_r3(uint64_t res, uint64_t v1, uint64_t v2, uint64_t v3)
{
    std::vector<int> ret;
    for (int i = 65422; i >= 0; --i)
    {
        uint64_t r = ((int64_t)(i * v1 - v2 * v3) % 65423 + 65423) % 65423;
        if (res == r)
        {
            ret.push_back(i);
        }
    }
    if (ret.size() != 1)
    {
        _CrtDbgBreak();
    }
    return ret[0];
}
 
struct re2_op
{
    int bufptr_res;
    int bufptr_another;
    uint64_t mul_val1;
    uint64_t min_val3;
};
 
void reverse2_2(uint16_t* input, uint8_t* output)
{
    uint8_t buf1[0x370 * 16] = { 0 };
    int64_t* b1ptr1 = (int64_t*)buf1;
    int32_t* t1ptr = (int32_t*)table_trans2;
    for (int i = 0; i < 16; ++i)
    {
        int64_t val1 = *t1ptr++;
        for (int k = 15; k >= 0; --k)
        {
            int64_t val2 = 0;
            if (k > 0)
            {
                int64_t val3 = transform2_calc1(val1, k >> 1);
                val2 = val3 * val3 % 65423;
                if (k & 1)
                    val2 = val2 * val1 % 65423;
            }
            else
            {
                val2 = 1;
            }
            *b1ptr1++ = val2;
        }
        b1ptr1 = (int64_t*)(buf1 + 0x370 * (i + 1));
    }
 
    for (int i = 0; i < 16; ++i)
    {
        uint64_t* b1ptr2 = (uint64_t*)(buf1 + 0x80 + i * 0x370);
        *b1ptr2 = 0xDEAD;
    }
 
    std::vector<re2_op> ops;
    uint64_t* b1ptr3 = (uint64_t*)buf1;
    for (int i = 1; i <= 15; ++i)
    {
        uint64_t* b1ptr7 = (uint64_t*)(buf1 + 0x370 * i + 8 * (i - 1));
        for (int a1 = 16 - i; a1 >= 1; --a1)
        {
            uint64_t val3 = *b1ptr7;
            uint64_t* b1ptr8 = b1ptr3;
            uint64_t* b1ptr9 = b1ptr7;
            for (int a2 = 18 - i; a2 >= 1; --a2)
            {
                uintptr_t diff3 = ((uintptr_t)b1ptr3 - (uintptr_t)buf1);
                uintptr_t diff7 = ((uintptr_t)b1ptr7 - (uintptr_t)buf1);
                uintptr_t diff8 = ((uintptr_t)b1ptr8 - (uintptr_t)buf1);
                uintptr_t diff9 = ((uintptr_t)b1ptr9 - (uintptr_t)buf1);
 
                if (diff9 % 0x370 == 0x80)
                {
                    re2_op op;
                    op.bufptr_res = diff9 / 0x370;
                    op.bufptr_another = diff8 / 0x370;
                    op.mul_val1 = *b1ptr3;
                    op.min_val3 = val3;
                    ops.push_back(op);
                }
 
                *b1ptr9++ = ((int64_t)(*b1ptr9 * *b1ptr3 - val3 * *b1ptr8++) % 65423 + 65423) % 65423;
            }
            b1ptr7 += 110;
        }
        b1ptr3 += 111;
    }
 
    uint16_t* op = (uint16_t*)output;
    uint64_t bufrec_1[16] = { 0 };
    int64_t* b1p2 = (int64_t*)buf1;
    for (int k = 0; k < 16; ++k)
    {
        int64_t v2 = *b1p2;
        int64_t v3 = transform2_calc1(*b1p2, 0x7FC6);
 
        uint16_t ret = r2_r1(input[k], v3, v2);
 
        for (int t = 15; t > k; --t)
        {
            ret = r2_r2(ret, input[t], *(uint64_t*)(buf1 + k * 0x370 + t * 8));
        }
 
        bufrec_1[k] = ret;
        b1p2 += 111;
    }
 
    for (int i = ops.size() - 1; i >= 0; --i)
    {
        re2_op op = ops[i];
        bufrec_1[op.bufptr_res] = r2_r3(bufrec_1[op.bufptr_res], op.mul_val1, op.min_val3, bufrec_1[op.bufptr_another]);
    }
 
    for (int i = 0; i < 16; ++i)
    {
        op[i] = bufrec_1[i];
    }
}
uint16_t r2_r1(uint64_t res, uint64_t v3, uint64_t v2)
{
    std::vector<int> ret;
    for (int i = 65422; i >= 0; --i)
    {
        if (res == (i * (v3 * v3 % 65423 * v2 % 65423) % 65423))
        {
            ret.push_back(i);
        }
    }
    if (ret.size() != 1)
    {
        _CrtDbgBreak();
    }
    return ret[0];
}
 
uint16_t r2_r2(uint64_t res, uint64_t val, uint64_t bp)
{
    std::vector<int> ret;
    for (int i = 65422; i >= 0; --i)
    {
        uint64_t r = ((int64_t)(i - val * bp) % 65423 + 65423) % 65423;
        if (res == r)
        {
            ret.push_back(i);
        }
    }
    if (ret.size() != 1)
    {
        _CrtDbgBreak();
    }
    return ret[0];
}
 
uint16_t r2_r3(uint64_t res, uint64_t v1, uint64_t v2, uint64_t v3)
{
    std::vector<int> ret;
    for (int i = 65422; i >= 0; --i)
    {
        uint64_t r = ((int64_t)(i * v1 - v2 * v3) % 65423 + 65423) % 65423;
        if (res == r)
        {
            ret.push_back(i);
        }
    }
    if (ret.size() != 1)
    {
        _CrtDbgBreak();
    }

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//