-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathred.c
executable file
·309 lines (274 loc) · 10.7 KB
/
red.c
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
#include "DECAF_types.h"
#include "DECAF_main.h"
#include "DECAF_callback.h"
#include "DECAF_callback_common.h"
#include "vmi_callback.h"
#include "utils/Output.h"
#include "DECAF_target.h"
#include "hookapi.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static plugin_interface_t red_interface;
static DECAF_Handle processbegin_handle = DECAF_NULL_HANDLE;
static DECAF_Handle blockbegin_handle = DECAF_NULL_HANDLE;
static DECAF_Handle insnbegin_handle = DECAF_NULL_HANDLE;
static DECAF_Handle insnend_handle = DECAF_NULL_HANDLE;
// hook api
static DECAF_Handle isdebuggerpresent_handle = DECAF_NULL_HANDLE;
static DECAF_Handle sleep_handle = DECAF_NULL_HANDLE;
static DECAF_Handle gettickcount_handle = DECAF_NULL_HANDLE;
static DECAF_Handle getsysteminfo_handle = DECAF_NULL_HANDLE;
char targetname[512];
uint32_t target_cr3;
typedef struct {
uint32_t call_stack[1]; //return address only -> VOID
DECAF_Handle hook_handle;
} IsDebuggerPresent_hook_context_t;
typedef struct {
uint32_t call_stack[2]; // return address and parameters ([0]: ret addr, [1]: time)
DECAF_Handle hook_handle;
} Sleep_hook_context_t;
typedef struct {
uint32_t call_stack[1]; // return address only -> VOID
DECAF_Handle hook_handle;
} GetTickCount_hook_context_t;
typedef struct {
uint32_t call_stack[10]; // return address and parameters
DECAF_Handle hook_handle;
} GetSystemInfo_hook_context_t;
/* typedef struct _SYSTEM_INFO { // sinf
call_stack[0]: union {
DWORD dwOemId;
struct {
WORD wProcessorArchitecture;
WORD wReserved;
};
};
call_stack[1]: DWORD dwPageSize;
call_stack[2]: LPVOID lpMinimumApplicationAddress;
call_stack[3]: LPVOID lpMaximumApplicationAddress;
call_stack[4]: DWORD dwActiveProcessorMask;
call_stack[5]: DWORD dwNumberOfProcessors;
call_stack[6]: DWORD dwProcessorType;
call_stack[7]: DWORD dwAllocationGranularity;
call_stack[8]_low: WORD wProcessorLevel;
call_stack[8]_high: WORD wProcessorRevision;
} SYSTEM_INFO;
*/
// bypass level3
static void level3(int line_num)
{
uint32_t NumberOfProcessors = 0;
uint32_t base = 0, peb_addr = 0, peb = 0;
base = cpu_single_env->segs[R_FS].base;
peb_addr = base + 0x30;
DECAF_read_mem(NULL, peb_addr, 4, &peb);
DECAF_read_mem(NULL, peb+0x64, 4, &NumberOfProcessors);
//DECAF_printf("FS(TEB): 0x%08x, peb_addr: 0x%08x, peb: 0x%08x\n", base, peb_addr, peb);
NumberOfProcessors = 0x2; // change NumOfProcessors
DECAF_write_mem(NULL, peb+0x64, 4, &NumberOfProcessors); // write back to memory
}
// level3 end
/*
* BOOL IsDebuggerPresent(VOID);
*/
static void IsDebuggerPresent_ret(void *param)
{
// DECAF_printf("IsDebuggerPresent exit\n");
IsDebuggerPresent_hook_context_t *ctx = (IsDebuggerPresent_hook_context_t *)param;
hookapi_remove_hook(ctx->hook_handle);
cpu_single_env->regs[R_EAX] = 0; // IsDebuggerPresent always return 0
//DECAF_printf("EIP = %08x, EAX = %d\n", cpu_single_env->eip, cpu_single_env->regs[R_EAX]);
free(ctx);
}
static void IsDebuggerPresent_call(void *opaque)
{
// DECAF_printf("IsDebuggerPresent entry\n");
IsDebuggerPresent_hook_context_t *ctx = (IsDebuggerPresent_hook_context_t*)malloc(sizeof(IsDebuggerPresent_hook_context_t));
if(!ctx) return;
DECAF_read_mem(NULL, cpu_single_env->regs[R_ESP], 4, ctx->call_stack);
ctx->hook_handle = hookapi_hook_return(ctx->call_stack[0], IsDebuggerPresent_ret, ctx, sizeof(*ctx));
}
/* IsDebuggerPresent end */
/*
* BOOL Sleep(DWORD dwMilliseconds);
*/
static void Sleep_ret(void *param)
{
// DECAF_printf("Sleep exit\n");
Sleep_hook_context_t *ctx = (Sleep_hook_context_t *)param;
hookapi_remove_hook(ctx->hook_handle);
free(ctx);
}
static void Sleep_call(void *opaque)
{
// DECAF_printf("Sleep entry\n");
Sleep_hook_context_t *ctx = (Sleep_hook_context_t*)malloc(sizeof(Sleep_hook_context_t));
if(!ctx) return;
// bypass Sleep
// 2*4: call_stack size
DECAF_read_mem(NULL, cpu_single_env->regs[R_ESP], 2*4, ctx->call_stack);
ctx->call_stack[1] = 1; // argument is always 1
DECAF_write_mem(NULL, cpu_single_env->regs[R_ESP], 2*4, ctx->call_stack);
// bypass Sleep end
ctx->hook_handle = hookapi_hook_return(ctx->call_stack[0], Sleep_ret, ctx, sizeof(*ctx));
}
/* Sleep end */
/*
* DWORD GetTickCount(VOID)
*/
static void GetTickCount_ret(void *param)
{
static int flag = 0; // level2
// DECAF_printf("GetTickCount exit\n");
GetTickCount_hook_context_t *ctx = (GetTickCount_hook_context_t *)param;
hookapi_remove_hook(ctx->hook_handle);
if (!flag) { // ture is only first call
cpu_single_env->regs[R_EAX] = 0; // return 0
flag = 1;
} else {
flag = 0;
}
// DECAF_printf("EIP = %08x, EAX = %d\n", cpu_single_env->eip, cpu_single_env->regs[R_EAX]);
free(ctx);
}
static void GetTickCount_call(void *opaque)
{
// DECAF_printf("GetTickCount entry\n");
GetTickCount_hook_context_t *ctx = (GetTickCount_hook_context_t*)malloc(sizeof(GetTickCount_hook_context_t));
if(!ctx) return;
DECAF_read_mem(NULL, cpu_single_env->regs[R_ESP], 4, ctx->call_stack);
ctx->hook_handle = hookapi_hook_return(ctx->call_stack[0], GetTickCount_ret, ctx, sizeof(*ctx));
}
/* GetTickCount end */
/*
* VOID GetSystemInfo(LPSYSTEM_INFO lpSystemInfo);
*/
static void GetSystemInfo_ret(void *param)
{
// DECAF_printf("GetSystemInfo exit\n");
GetSystemInfo_hook_context_t *ctx = (GetSystemInfo_hook_context_t *)param;
hookapi_remove_hook(ctx->hook_handle);
DECAF_read_mem(NULL, cpu_single_env->regs[R_ESP], 10*4, ctx->call_stack);
ctx->call_stack[5] = 0x2; // SYSTEM_INFO.dwNumberOfProcessors is 0x2
DECAF_write_mem(NULL, cpu_single_env->regs[R_ESP], 10*4, ctx->call_stack); // write back to memory
// DECAF_printf("EIP = %08x, EAX = %d\n", cpu_single_env->eip, cpu_single_env->regs[R_EAX]);
}
static void GetSystemInfo_call(void *opaque)
{
// DECAF_printf("GetSystemInfo entry\n");
GetSystemInfo_hook_context_t *ctx = (GetSystemInfo_hook_context_t*)malloc(sizeof(GetSystemInfo_hook_context_t));
if(!ctx) return;
DECAF_read_mem(NULL, cpu_single_env->regs[R_ESP], 4, ctx->call_stack);
ctx->hook_handle = hookapi_hook_return(ctx->call_stack[0], GetSystemInfo_ret, ctx, sizeof(*ctx));
}
/* GetSystemInfo end */
/* share function */
static void red_block_begin_callback(DECAF_Callback_Params* params)
{
if(params->bb.env->cr[3] == target_cr3)
{
target_ulong eip = params->bb.env->eip;
target_ulong eax = params->bb.env->regs[R_EAX];
}
}
// level4
static uint32_t save_peb = 0;
static uint32_t save_val[2] = {0, 0};
static uint32_t save_base = 0;
static void red_insn_begin_callback(DECAF_Callback_Params* params)
{
// detect cmpxchg8b and replace fs:[0x1000]
uint32_t cur_insn = 0,
cmpxchg8b = 0x00c70f64, // opcode of 'cmpxchg8b: 0x640fc7 ->(fix endian) 0x00c70f64
base, peb_addr, tmp_addr;
DECAF_read_mem(NULL, cpu_single_env->eip, 3, &cur_insn);
if (cur_insn == cmpxchg8b) { // catch cmpxchg8b
base = cpu_single_env->segs[R_FS].base;
DECAF_read_mem(NULL, base+0x30, 4, &save_peb); // get peb
if (base > save_peb) { // peb is rear base
DECAF_read_mem(NULL, cpu_single_env->regs[R_ESP], 8, save_val);
/* DECAF_printf("FS(TEB): 0x%08x, peb: 0x%08x\n", base, save_peb); */
/* DECAF_printf("edx:eax %08x:%08x, ecx:ebx %08x:%08x\n", cpu_single_env->regs[R_EDX], cpu_single_env->regs[R_EAX], cpu_single_env->regs[R_ECX], cpu_single_env->regs[R_EBX]); */
save_base = base;
cpu_single_env->segs[R_FS].base = cpu_single_env->regs[R_ESP]-0x1000; // fs = ESP - 0x1000
}
}
}
static void red_insn_end_callback(DECAF_Callback_Params* params)
{
return;
}
// level4 end
static void red_loadmainmodule_callback(VMI_Callback_Params* params)
{
// targetname = "blue.exe"
{
DECAF_printf("Process %s you spcecified starts \n", params->cp.name);
target_cr3 = params->cp.cr3;
isdebuggerpresent_handle = hookapi_hook_function_byname("kernel32.dll", "IsDebuggerPresent", 1, target_cr3, IsDebuggerPresent_call, NULL, 0);
sleep_handle = hookapi_hook_function_byname("kernel32.dll", "Sleep", 1, target_cr3, Sleep_call, NULL, 0);
gettickcount_handle = hookapi_hook_function_byname("kernel32.dll", "GetTickCount", 1, target_cr3, GetTickCount_call, NULL, 0);
getsysteminfo_handle = hookapi_hook_function_byname("kernel32.dll", "GetSystemInfo", 1, target_cr3, GetSystemInfo_call, NULL, 0);
blockbegin_handle = DECAF_register_callback(DECAF_BLOCK_BEGIN_CB, &red_block_begin_callback, NULL);
insnbegin_handle = DECAF_register_callback(DECAF_INSN_BEGIN_CB, &red_insn_begin_callback, NULL); // level4
insnend_handle = DECAF_register_callback(DECAF_INSN_END_CB, &red_insn_end_callback, NULL); // level4
level3(__LINE__); // replace NumberOfProcessors
}
}
void do_monitor_proc(Monitor* mon, const QDict* qdict)
{
// targetname = "blue.exe"
if ((qdict != NULL) && (qdict_haskey(qdict, "procname")))
strncpy(targetname, qdict_get_str(qdict, "procname"), 512);
targetname[511] = '\0';
DECAF_printf("red: Ready to track %s\n", targetname);
}
static int red_init(void)
{
DECAF_printf("Hello, World!\n");
processbegin_handle = VMI_register_callback(VMI_CREATEPROC_CB, &red_loadmainmodule_callback, NULL);
if (processbegin_handle == DECAF_NULL_HANDLE)
DECAF_printf("Could not register for the create or remove proc events\n");
return 0;
}
static void red_cleanup(void)
{
DECAF_printf("Bye, World\n");
if (processbegin_handle != DECAF_NULL_HANDLE)
{
VMI_unregister_callback(VMI_CREATEPROC_CB, processbegin_handle);
processbegin_handle = DECAF_NULL_HANDLE;
}
if (blockbegin_handle != DECAF_NULL_HANDLE)
{
DECAF_unregister_callback(DECAF_BLOCK_BEGIN_CB, blockbegin_handle);
blockbegin_handle = DECAF_NULL_HANDLE;
}
// level4
if (insnbegin_handle != DECAF_NULL_HANDLE)
{
DECAF_unregister_callback(DECAF_INSN_BEGIN_CB, insnbegin_handle);
insnbegin_handle = DECAF_NULL_HANDLE;
}
if (insnend_handle != DECAF_NULL_HANDLE)
{
DECAF_unregister_callback(DECAF_INSN_END_CB, insnend_handle);
insnend_handle = DECAF_NULL_HANDLE;
}
// level4 end
}
/* share function end */
static mon_cmd_t red_term_cmds[] =
{
#include "plugin_cmds.h"
{NULL, NULL, },
};
plugin_interface_t* init_plugin(void)
{
red_interface.mon_cmds = red_term_cmds;
red_interface.plugin_cleanup = &red_cleanup;
red_init();
return (&red_interface);
}