首页
社区
课程
招聘
[原创]KCTF2022秋季赛 第八题 商贸往来 题解
2022-12-3 20:16 12105

[原创]KCTF2022秋季赛 第八题 商贸往来 题解

2022-12-3 20:16
12105

开头包装的一层调用可以手动清理出来,他调用了sub_4026D2作为窗口回调,在WM_COMMAND里面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
v21 = (*(int (__stdcall **)(int, int))(dword_4ABE44 + 92))(a1, 1001);// GetDlgItem
    if ( v21 )
    {
      for ( i = 0; i < 0x100; ++i )
        v7[i] = 0;
      v42 = (*(int (__stdcall **)(int))(v35 + 96))(v21);// GetWindowTextLengthA
      if ( v42 <= 210 && v42 >= 1 )
      {
        (*(void (__stdcall **)(int, char *, int))(v35 + 100))(v21, v7, 255);// GetWindowTextA
        v42 = (*(int (__stdcall **)(char *))(v35 + 24))(v7);// lstrlenA
        if ( v42 >= 1 && v42 <= 128 )
        {
          for ( j = v42; j < 128; ++j )
          {
            if ( j % 2 )
              v7[j] = 0x20;
            else
              v7[j] = 0x7F;
          }
          v34 = 1;
        }
        else
        {
          v34 = 0;
        }
      }
      else
      {
        v34 = 0;
      }
    }
    else
    {
      v34 = 0;
    }
    if ( v34 )
    {
      v43 = dword_4ABE44;
      if ( (*(int (__stdcall **)(_DWORD, char *, int))(dword_4ABE44 + 56))(0, v5, 255) )
      {
        strcpy(v27, "h");
        v27[2] = 0;
        v27[3] = 0;
        v27[4] = 0;
        v27[5] = 0xB8;
        v27[6] = 0;
        v27[7] = 0;
        v27[8] = 0;
        v27[9] = 0;
        v27[10] = 0xFF;
        v27[11] = 0xD0;
        Eax = 0;
        v31 = 0;
        v8[17] = 0xFFFFFFFF;
        for ( k = 0; k < 0x44; ++k )
          *((_BYTE *)v8 + k) = 0;
        v8[0] = 68;
        for ( m = 0; m < 0x10; ++m )
          *((_BYTE *)&v37 + m) = 0;
        if ( (*(int (__stdcall **)(char *, _DWORD, _DWORD, _DWORD, _DWORD, int, _DWORD, _DWORD, int *, int *))(v43 + 28))(// CreateProcessW
               v5,
               0,
               0,
               0,
               0,
               4,
               0,
               0,
               v8,
               &v37) )
        {
          v6.ContextFlags = 0x10007;
          if ( !(*(int (__stdcall **)(int, CONTEXT *))(v43 + 32))(v38, &v6) )// GetThreadContext
            goto LABEL_69;
          Eax = v6.Eax;
          v31 = (*(int (__stdcall **)(int, _DWORD, int, int, int))(v43 + 44))(v37, 0, 128, 4096, 4);
          if ( !v31 )
            goto LABEL_69;
          for ( n = 0; n < 0x80; n += v17 )
          {
            v17 = 0;
            if ( !(*(int (__stdcall **)(int, unsigned int, char *, unsigned int, int *))(v43
                                                                                       + 0x30))(// WriteProcessMemory
                    v37,
                    n + v31,
                    &v7[n],
                    128 - n,
                    &v17) )
            {
              v16 = 0;
              goto LABEL_45;
            }
          }
          v16 = 1;
          if ( !v16 )
            goto LABEL_69;
LABEL_45:
          v20 = (PIMAGE_DOS_HEADER)(*(int (__stdcall **)(_DWORD))(v43 + 20))(0);// GetModuleHandleW
          v10 = (int)v20 + v20->e_lfanew;
          v9 = Eax - *(_DWORD *)(v10 + 40);
          v11 = (char *)sub_401000 - (char *)v20;
          *(_DWORD *)&v27[1] = v31;
          *(_DWORD *)&v27[6] = (char *)sub_401000 - (char *)v20 + v9;
          for ( ii = 0; ii < 0xC; ii += v15 )
          {
            v15 = 0;
            if ( !(*(int (__stdcall **)(int, unsigned int, char *, unsigned int, int *))(v43 + 48))(
                    v37,
                    ii + Eax,
                    &v27[ii],
                    12 - ii,
                    &v15) )
            {
              v14 = 0;
              goto LABEL_52;
            }
          }
          v14 = 1;
LABEL_52:
          if ( v14 )
          {
            (*(void (__stdcall **)(int))(v43 + 36))(v38);// ResumeThread
            v30 = 2;
            if ( (*(int (__stdcall **)(int, int))(v43 + 60))(v37, 30000) )// WaitForSingleObject
            {
              (*(void (__stdcall **)(int, int))(v43 + 64))(v37, 2);// TerminateProcess
            }
            else
            {
              v18 = 0;
              if ( (*(int (__stdcall **)(int, int *))(v43 + 52))(v37, &v18) && v18 != 2 )// GetExitCodeProcess
                v30 = v18;
            }

会再执行一次crackme,将入口点改为

1
2
3
push input
mov eax,0x401000
call eax

0x401000通过调用Decompress函数,解压数据

 

类似格式是

1
2
3
4
struct CodeData{
    uint32_t CodeSize;
    uint8_t code[CodeSize];
};

在这里进行调用,v47用于加密,v45用于最后的验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
if ( v38 )
  {
    v90 = 0;
    v29[0] = 5;
    v29[1] = 0;
    v29[2] = 4;
    v29[3] = 3;
    v29[4] = 2;
    v29[5] = 1;
    for ( ii = 0; ii < 6; ++ii )
    {
      v32 = v29[ii];
      v92 = 0;
      v47 = 0;
      for ( jj = 0; jj <= v32; ++jj )
      {
        v47 = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD))(v108[30] + v92 + 4);
        v46 = *(_DWORD *)(v108[30] + v92);
        v92 += v46 + 4;
      }
      v90 = v47;
      if ( !v47(*v108, v108[1], v108[2], a1) )
        goto LABEL_134;
    }
    v56 = 1;
    v91 = 0;
    v45 = 0;
    for ( kk = 0; kk <= 6; ++kk )
    {
      v45 = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD))(v108[30] + v91 + 4);
      v48 = *(_DWORD *)(v108[30] + v91);
      v91 += v48 + 4;
    }
    v90 = v45;
    if ( !v45(*v108, v108[1], v108[2], a1) )
      v56 = 0;
  }

通过强制F5了几个函数发现,对应输入只进行了基于字节的异或加密、交换、查表,修改其中一个字节,只会对加密结果产生一个字节的影响。

 

这些代码花式调用了大量API,拖慢了计算速度,同时也有反调试。

 

其实根据附带的题目描述我感觉是叫你硬看,但我就偏要硬爆

 

将最后一个函数F5找到比对逻辑,将其导出。

 

将原始文件patch 入口点,push 0x402d4c call 0x401000 后 跟一个int3,然后nop0x04026C8ExitProcess,到达int3后读取和重写flag的值,然后更改Eip为入口点进行下次爆破。

 

需要用到ScyllaHide,爆的时候执行一下InjectorCLIx86.exe sb.exe HookLibraryx86.dll nowait加载一下反反调试,配置文件选Themida x86/x64

 

预计时间是(128 + 94) * 10 / 60 = 37分钟,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include <windows.h>
#include <TlHelp32.h>
#include <stdint.h>
#include <stdio.h>
 
char trueflag[0x81] = { 0 };
// char flag[0x81] = { 0x3a,0x2a,0x44,0x23,0x4f,0x2b,0x5f,0x49,0x33,0x3b,0x60,0x7d,0x30,0x4e,0x66,0x50,
// 0x2d,0x3d,0x32,0x2f,0x2b,0x59,0x22,0x5f,0x3e,0x41,0x38,0x53,0x36,0x5d,0x4c,0x7c,
// 0x34,0x47,0x3b,0x55,0x48,0x69,0x41,0x35,0x6d,0x6e,0x6f,0x6c,0x5e,0x6b,0x3b,0x23,
// 0x4f,0x68,0x57,0x32,0x21,0x55,0x45,0x4a,0x66,0x30,0x22,0x37,0x3f,0x44,0x74,0x35,
// 0x6d,0x7b,0x43,0x71,0x45,0x2a,0x41,0x5a,0x72,0x7e,0x24,0x31,0x28,0x7a,0x57,0x40,
// 0x54,0x42,0x58,0x4b,0x4c,0x26,0x32,0x72,0x3f,0x2b,0x33,0x6b,0x77,0x78,0x43,0x39,
// 0x30,0x4f,0x27,0x25,0x26,0x50,0x79,0x56,0x6f,0x7e,0x29,0x27,0x51,0x25,0x5a,0x40,
// 0x36,0x62,0x7d,0x52,0x45,0x4b,0x46,0x5b,0x63,0x67,0x46,0x65,0x2f,0x2d,0x3f,0x49 };
char flag[0x81] = { 0 };
 
int flagcount = 0;
int _current = 0;
uint8_t encrelative[0x80] = { 0 };
uint8_t enctable[0x80] = { 0 };
// uint8_t enctable[0x80] = { 0x09,0x0a,0x07,0x08,0x05,0x06,0x03,0x04,0x01,0x02,0x40,0x00,0x42,0x41,0x44,0x43,
// 0x46,0x45,0x48,0x47,0x4a,0x49,0x4c,0x4b,0x4e,0x4d,0x50,0x4f,0x52,0x51,0x54,0x53,
// 0x56,0x55,0x58,0x57,0x5a,0x59,0x5c,0x5b,0x5e,0x5d,0x60,0x5f,0x62,0x61,0x64,0x63,
// 0x66,0x65,0x68,0x67,0x6a,0x69,0x6c,0x6b,0x6e,0x6d,0x70,0x6f,0x72,0x71,0x74,0x73,
// 0x76,0x75,0x78,0x77,0x7a,0x79,0x7c,0x7b,0x7e,0x7d,0x3f,0x7f,0x3d,0x3e,0x3b,0x3c,
// 0x39,0x3a,0x37,0x38,0x35,0x36,0x33,0x34,0x31,0x32,0x2f,0x30,0x2d,0x2e,0x2b,0x2c,
// 0x29,0x2a,0x27,0x28,0x25,0x26,0x23,0x24,0x21,0x22,0x1f,0x20,0x1d,0x1e,0x1b,0x1c,
// 0x19,0x1a,0x17,0x18,0x15,0x16,0x13,0x14,0x11,0x12,0x0f,0x10,0x0d,0x0e,0x0b,0x0c };
int stage = 1;
int guess = 33;
uint8_t enc[0x80] = {121, 23, 66, 107, 59, 80, 122, 227, 70, 208, 222, 78, 36, 167, 138, 106, 105, 208, 2, 6, 240, 39, 36, 189, 192, 187, 227, 30, 9, 163, 151, 48, 60, 182, 235, 104, 144, 9, 208, 234, 17, 242, 196, 96, 165, 203, 195, 252, 69, 251, 92, 83, 192, 128, 58, 153, 89, 111, 47, 84, 74, 217, 14, 106, 52, 222, 210, 236, 175, 74, 11, 164, 138, 182, 250, 147, 31, 4, 16, 68, 238, 228, 214, 158, 244, 69, 18, 77, 55, 60, 240, 17, 248, 200, 68, 118, 99, 16, 115, 45, 104, 215, 157, 47, 195, 132, 42, 182, 204, 181, 55, 97, 79, 15, 22, 188, 187, 140, 83, 39, 238, 119, 170, 31, 156, 194, 24, 222 };
uint8_t tmp[0x80] = { 0 };
 
 
 
int main(void) {
    STARTUPINFOA si = { sizeof(si) };
    PROCESS_INFORMATION pi = { sizeof(pi) };
    DWORD ret = CreateProcessA("D:/Users/CShi/Desktop/sb.exe", "", NULL, NULL, FALSE, DEBUG_PROCESS | CREATE_SUSPENDED, NULL, NULL, &si, &pi);
    DWORD __sb = 0;
    uint8_t original = 0;
    uint8_t int3 = 0xcc;
 
    ReadProcessMemory(pi.hProcess, 0x004041B5, &original, 1, &__sb);
 
    WriteProcessMemory(pi.hProcess, 0x004041B5, &int3, 1, &__sb);
    ResumeThread(pi.hThread);
    DEBUG_EVENT de = {0};
    CONTEXT ThreadContext = { 0 };
    ThreadContext.ContextFlags = 0x10007;
    while (1){
        WaitForDebugEvent(&de, INFINITE);
        if(de.dwDebugEventCode == EXCEPTION_DEBUG_EVENT){
            if(de.u.Exception.ExceptionRecord.ExceptionCode == 0x80000003){
                if(de.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)0x004041B5){
 
                    puts("InjectorCLIx86.exe sb.exe HookLibraryx86.dll nowait");
                    system("pause");
 
                    WriteProcessMemory(pi.hProcess, 0x4041b5, &original, 1, &__sb);
 
                    HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, de.dwThreadId);
                    GetThreadContext(hThread, &ThreadContext);
                    WriteProcessMemory(pi.hProcess, 0x402d4c, &flag, 0x80, &__sb);
                    ThreadContext.Eip = 0x4041b5;
                    SetThreadContext(hThread, &ThreadContext);
                    CloseHandle(hThread);
                }
                else if (de.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)0x04041BF){
                    if(stage == 1){
                        if(encrelative[0] == 0){
                            ReadProcessMemory(pi.hProcess, 0x402d4c, &encrelative, 0x80, &__sb);
                        }
                        else{
                            ReadProcessMemory(pi.hProcess, 0x402d4c, &tmp, 0x80, &__sb);
                            for(int i = 0 ;i<0x80;i++){
                                if(tmp[i] != encrelative[i]){
                                    enctable[_current - 1] = i;
                                    break;
                                }
                            }
                        }
                        memset(flag, 0, sizeof(flag));
                        if (_current == 0x81) {
                            memset(flag, 0, sizeof(flag));
                            stage = 2;
                            _current = 0;
                            flag[_current] = guess;
                        }
                        else{
                            flag[_current] = 1;
                            _current += 1;
                        }
                        puts("enctable debug:");
                        for (int i = 0; i < 128; i++) {
 
                            printf("0x%02x,", enctable[i]);
                            if (i % 16 == 15) {
                                puts("");
                            }
                        }
 
                    }
                    else{
                        ReadProcessMemory(pi.hProcess, 0x402d4c, &tmp, 0x80, &__sb);
                        for(int i = 0;i< 0x80;i++){
                            if (tmp[i] == enc[i]) {
                                for (int j = 0; j < 0x80; j++) {
                                    if(enctable[j] == i){
                                        printf("%x: %c OK!\n", j, flag[j]);
                                        flagcount += 1;
                                        trueflag[j] = flag[j];
                                        if (flagcount == 0x80) {
                                            printf("%s\n", trueflag);
                                            system("pause");
                                        }
                                        break;
                                    }
 
                                }
                            }
                        }
 
                        puts("");
                        memset(flag, guess, 128);
 
                        guess += 1;
                        printf("%x: %c current\n", _current, flag[_current]);
                        puts("flag debug:");
                        for (int i = 0; i < 128; i++) {
                            printf("0x%02x,", trueflag[i]);
                            if (i % 16 == 15) {
                                puts("");
                            }
                        }
                        if (guess == 128) {
                            puts("No Solve!");
                        }
                    }
 
                    HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, de.dwThreadId);
                    GetThreadContext(hThread, &ThreadContext);
                    WriteProcessMemory(pi.hProcess, 0x402d4c, &flag, 0x80, &__sb);
                    ThreadContext.Eip = 0x4041b5;
                    SetThreadContext(hThread, &ThreadContext);
                    CloseHandle(hThread);
 
                }
 
            }
            ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
 
        }
 
 
        else {
 
            ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
 
        }
 
    }
 
 
 
 
 
}

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2022-12-3 20:23 被mb_xxgcvcih编辑 ,原因:
收藏
点赞2
打赏
分享
最新回复 (1)
雪    币: 370
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
wx_Sambty 2022-12-4 20:23
2
0
厉害的
游客
登录 | 注册 方可回帖
返回