实验吧 逆向分析 reversemeplz

题目链接:http://www.shiyanbar.com/ctf/738
本站提供该二进制程序下载:challenge
sha1sum: 69c762ec8e80cac7766b783d2d3a652e7cedeb5b
md5sum: bc899372bdfe85b7272ea9b8fe5b5643

我做本题的基本思路就是先根据 sub_8048519 函数制作一张可打印字符的对照表,然后根据后面.text:080488BA 地址的汇编代码推断,加密后的第一个字符为0x62,也就是‘b’,再根据.text:08048880 反推出加密后的密文为 bargjbgursyntlb ,在利用对照表即可还原明文。

获取密文的代码:

#include <stdio.h>

int main()
{
    int dword_8048980[] = {0xFFFFFFFF, 0x11, 0xFFFFFFF5, 3, 0xFFFFFFF8, 5, 0xE,
                           0xFFFFFFFD, 1, 6, 0xFFFFFFF5, 6, 0xFFFFFFF8, 0xFFFFFFF6,
                           0};

    char temp = 'b';
    printf("key: %c", temp);
    for (int i = 0; i < 14; i++)
    {
        temp = temp + dword_8048980[i];
        printf("%c", temp);
    }
    puts("");
}

获取明文的代码:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int dword_8049CA4;
char sub_80484FB(char a1)
{
    ++dword_8049CA4;
    ++dword_8049CA4;
    return a1;
}

int sub_8048519(char a1)
{
    unsigned char v1; // al
    signed int v2;    // edi
    int v3;           // ebx
    signed int v4;    // edi
    int v5;           // ebx
    signed int v6;    // edi
    int v7;           // ebx
    signed int v8;    // edi
    char v9;          // cl
    int v10;          // edx
    signed int v11;   // edi
    int v12;          // edx
    int v13;          // edx
    signed int v14;   // edi
    signed int v15;   // ecx
    int v16;          // edx
    signed int v17;   // ecx
    int v18;          // edx
    signed int v19;   // ecx
    int v20;          // edx
    signed int v21;   // ebx
    int v22;          // edx
    signed int v23;   // ebx
    int v24;          // edx
    signed int v25;   // ebx
    int v26;          // edx
    signed int v27;   // ebx
    int v28;          // edx
    signed int v29;   // ecx
    int v30;          // edx
    signed int v31;   // ecx
    int v32;          // edx
    signed int v33;   // ecx
    signed int v34;   // esi
    int v35;          // edx
    char v36;         // cl
    int v37;          // edx
    signed int v38;   // esi
    int v39;          // edx
    int v40;          // edx
    signed int v41;   // edi
    int v42;          // edx
    signed int v43;   // edi
    int v44;          // edx
    signed int v45;   // ecx
    signed int v46;   // esi
    int v47;          // edx
    int v48;          // esi
    int v49;          // zf
    signed int v50;   // eax
    char v52;         // [esp+4h] [ebp-10h]

    v1 = sub_80484FB(a1);
    v2 = 19;
    if ((v1 & 0x3F) != 38)
        v2 = 0;
    v3 = v2 | (v1 << 8) | 9 * ((v1 & 0x5F) == 86);
    v4 = 71;
    if ((v1 & 0x77) != 116)
        v4 = 0;
    v5 = v4 | v3;
    v6 = 84;
    if ((v1 & 0x3F) != 39)
        v6 = 0;
    v7 = v6 | v5;
    v8 = 48;
    if ((v1 & 0x4F) != 4)
        v8 = 0;
    v9 = v1 & 0x1F;
    v10 = 3 * ((v1 & 0x57) == 80) | 8 * (v9 == 1) | v7 | v8 | 2 * (v9 == 15) | 2 * ((v1 & 0x5B) == 83);
    v11 = 114;
    v52 = ~v1;
    v12 = 8 * (v9 == 2) | 8 * (v9 == 11) | v10 | 2 * ((v1 & 0x57) == 66) | 8 * ((v1 & 0x2E) == 44);
    if ((v1 & 0x37) != 37)
        v11 = 0;
    v13 = v11 | v12;
    v14 = 16;
    v15 = 0;
    if ((v1 & 0x1C) == 8)
        v15 = 16;
    v16 = ((~v1 & 0x78u) < 1 ? 0x48 : 0) | v15 | v13;
    v17 = 64;
    if ((v1 & 0x1D) != 16)
        v17 = 0;
    v18 = v17 | v16;
    v19 = 0;
    if ((v1 & 0xF) == 11)
        v19 = 16;
    v20 = 4 * ((v1 & 0x55) == 64) | v19 | v18;
    v21 = 72;
    if ((v1 & 0x4B) != 1)
        v21 = 0;
    v22 = v21 | v20;
    v23 = 24;
    if ((v1 & 0x47) != 1)
        v23 = 0;
    v24 = v23 | v22;
    v25 = 96;
    if ((v1 & 0x2B) != 34)
        v25 = 0;
    v26 = ((v52 & 0x55u) < 1 ? 0x48 : 0) | v25 | v24;
    v27 = 0;
    if ((v1 & 0x31) == 16)
        v27 = 16;
    v28 = v27 | v26;
    v29 = 0;
    if ((v1 & 0x55) == 81)
        v29 = 68;
    v30 = v29 | v28;
    v31 = 0;
    if ((v1 & 0xE) == 8)
        v31 = 32;
    v32 = v31 | v30;
    v33 = 97;
    if ((v1 & 0x59) != 72)
        v33 = 0;
    v34 = 81;
    v35 = v33 | v32;
    v36 = v1 & 0x17;
    if ((v1 & 0x17) != 4)
        v34 = 0;
    v37 = v34 | v35;
    v38 = 37;
    if ((v1 & 0x47) != 66)
        v38 = 0;
    v39 = v37 | v38 | 8 * ((v1 & 0x43) == 2);
    if ((v1 & 0x46) != 2)
        v14 = 0;
    v40 = v14 | v39;
    v41 = 80;
    if (v36 != 3)
        v41 = 0;
    v42 = v41 | v40;
    v43 = 70;
    if (v36 != 1)
        v43 = 0;
    v44 = v43 | v42;
    v45 = 40;
    if ((v1 & 0x70) != 64)
        v45 = 0;
    v46 = 0;
    v47 = 4 * ((v1 & 0x41) == 1) | ((v52 & 0xBu) < 1 ? 0x60 : 0) | v45 | v44;
    if ((v1 & 0x48) == 64)
        v46 = 32;
    v48 = v47 | v46;
    v49 = (v1 & 0x21) == 1;
    v50 = 0;
    if (v49)
        v50 = 68;
    return v48 | v50;
}

// 找到 字符 find 在字符串数组 s 中的位置
int find_position(char *s, int s_length, char find)
{
    for (int i = 0; i < s_length; i++)
    {
        if (s[i] == find)
        {
            return i;
        }
    }
    printf("Error\n");
    return -1;
}

int main()
{

    char printable[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c";
    char table[1000] = {0}; // 对照表
    int length = strlen(printable);
    for (int i = 0; i < length; i++)
    {
        char temp = sub_8048519(printable[i]);
        printf("%c -> %c -> 0x%02X\n", printable[i], temp, (unsigned char)temp);
        table[i] = temp;
    }
    puts("");

    printf("flag{");
    // 由上面破解得出来的。
    char *key = "bargjbgursyntlb";
    for (int i = 0; i < 15; i++)
    {
        int po = find_position(table, length, key[i]);
        printf("%c", printable[po]);
    }
    puts("}");

    return 0;
}