标签:style c class blog code java
1 ;------------------------- 2 ; 补丁代码 3 ; 本段代码使用了API函数地址动态获取以及重定位技术 4 ; 程序功能:弹出对话框 5 ; 作者:戚利 6 ; 开发日期:2011.2.22 7 ;------------------------- 8 9 .386 10 .model flat,stdcall 11 option casemap:none 12 13 include windows.inc 14 15 ;注意此处不静态包含引入任何其他动态链接库 16 17 _ProtoGetProcAddress typedef proto :dword,:dword 18 _ProtoLoadLibrary typedef proto :dword 19 20 _ApiGetProcAddress typedef ptr _ProtoGetProcAddress 21 _ApiLoadLibrary typedef ptr _ProtoLoadLibrary 22 23 24 ;------------------------------------------- 25 ; 补丁代码中引入的其他动态链接库的函数的声明 26 ;------------------------------------------- 27 28 29 _ProtoMessageBox typedef proto :dword,:dword,:dword,:dword 30 _ApiMessageBox typedef ptr _ProtoMessageBox 31 32 33 ;被添加到目标文件的代码从这里开始,到APPEND_CODE_END处结束 34 35 .code 36 37 jmp _NewEntry 38 39 ; 以下内容为两个重要函数名 40 ; 几乎所有补丁都必须使用的 41 szGetProcAddr db ‘GetProcAddress‘,0 42 szLoadLib db ‘LoadLibraryA‘,0 43 44 ;------------------------------------------------------ 45 ; 补丁代码中其他全局变量的定义 46 ;------------------------------------------------------ 47 48 szUser32Dll db ‘user32.dll‘,0 49 szMessageBox db ‘MessageBoxA‘,0 ;该方法在kernel32.dll中 50 szHello db ‘HelloWorldPE‘,0 ;要创建的目录 51 52 53 ;----------------------------- 54 ; 错误 Handler 55 ;----------------------------- 56 _SEHHandler proc _lpException,_lpSEH,_lpContext,_lpDispatcher 57 pushad 58 mov esi,_lpException 59 mov edi,_lpContext 60 assume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT 61 mov eax,_lpSEH 62 push [eax+0ch] 63 pop [edi].regEbp 64 push [eax+8] 65 pop [edi].regEip 66 push eax 67 pop [edi].regEsp 68 assume esi:nothing,edi:nothing 69 popad 70 mov eax,ExceptionContinueExecution 71 ret 72 _SEHHandler endp 73 74 ;------------------------------------ 75 ; 获取kernel32.dll的基地址 76 ;------------------------------------ 77 _getKernelBase proc 78 local @dwRet 79 80 pushad 81 82 assume fs:nothing 83 mov eax,fs:[30h] ;获取PEB所在地址 84 mov eax,[eax+0ch] ;获取PEB_LDR_DATA 结构指针 85 mov esi,[eax+1ch] ;获取InInitializationOrderModuleList 链表头 86 ;第一个LDR_MODULE节点InInitializationOrderModuleList成员的指针 87 lodsd ;获取双向链表当前节点后继的指针 88 mov eax,[eax+8] ;获取kernel32.dll的基地址 89 mov @dwRet,eax 90 popad 91 mov eax,@dwRet 92 ret 93 _getKernelBase endp 94 95 ;------------------------------- 96 ; 获取指定字符串的API函数的调用地址 97 ; 入口参数:_hModule为动态链接库的基址 98 ; _lpApi为API函数名的首址 99 ; 出口参数:eax为函数在虚拟地址空间中的真实地址 100 ;------------------------------- 101 _getApi proc _hModule,_lpApi 102 local @ret 103 local @dwLen 104 105 pushad 106 mov @ret,0 107 ;计算API字符串的长度,含最后的零 108 mov edi,_lpApi 109 mov ecx,-1 110 xor al,al 111 cld 112 repnz scasb 113 mov ecx,edi 114 sub ecx,_lpApi 115 mov @dwLen,ecx 116 117 ;从pe文件头的数据目录获取导出表地址 118 mov esi,_hModule 119 add esi,[esi+3ch] 120 assume esi:ptr IMAGE_NT_HEADERS 121 mov esi,[esi].OptionalHeader.DataDirectory.VirtualAddress 122 add esi,_hModule 123 assume esi:ptr IMAGE_EXPORT_DIRECTORY 124 125 ;查找符合名称的导出函数名 126 mov ebx,[esi].AddressOfNames 127 add ebx,_hModule 128 xor edx,edx 129 .repeat 130 push esi 131 mov edi,[ebx] 132 add edi,_hModule 133 mov esi,_lpApi 134 mov ecx,@dwLen 135 repz cmpsb 136 .if ZERO? 137 pop esi 138 jmp @F 139 .endif 140 pop esi 141 add ebx,4 142 inc edx 143 .until edx>=[esi].NumberOfNames 144 jmp _ret 145 @@: 146 ;通过API名称索引获取序号索引再获取地址索引 147 sub ebx,[esi].AddressOfNames 148 sub ebx,_hModule 149 shr ebx,1 150 add ebx,[esi].AddressOfNameOrdinals 151 add ebx,_hModule 152 movzx eax,word ptr [ebx] 153 shl eax,2 154 add eax,[esi].AddressOfFunctions 155 add eax,_hModule 156 157 ;从地址表得到导出函数的地址 158 mov eax,[eax] 159 add eax,_hModule 160 mov @ret,eax 161 162 _ret: 163 assume esi:nothing 164 popad 165 mov eax,@ret 166 ret 167 _getApi endp 168 169 ;------------------------ 170 ; 补丁功能部分 171 ; 传入三个参数: 172 ; _kernel:kernel32.dll的基地址 173 ; _getAddr:函数GetProcAddress地址 174 ; _loadLib:函数LoadLibraryA地址 175 ;------------------------ 176 _patchFun proc _kernel,_getAddr,_loadLib 177 178 ;------------------------------------------------------ 179 ; 补丁功能代码局部变量定义 180 ;------------------------------------------------------ 181 182 local hUser32Base:dword 183 local _messageBox:_ApiMessageBox 184 185 186 pushad 187 188 189 ;------------------------------------------------------ 190 ; 补丁功能代码,以下只是一个范例,功能为弹出对话框 191 ;------------------------------------------------------ 192 193 194 ;获取user32.dll的基地址 195 mov eax,offset szUser32Dll 196 add eax,ebx 197 198 mov edx,_loadLib 199 push eax 200 call edx 201 mov hUser32Base,eax 202 203 204 ;使用GetProcAddress函数的首址, 205 ;传入两个参数调用GetProcAddress函数, 206 ;获得MessageBoxA的首址 207 mov eax,offset szMessageBox 208 add eax,ebx 209 210 mov edx,_getAddr 211 mov ecx,hUser32Base 212 push eax 213 push ecx 214 call edx 215 mov _messageBox,eax 216 217 ;调用函数MessageBox !! 218 mov eax,offset szHello 219 add eax,ebx 220 mov edx,_messageBox 221 222 push MB_OK 223 push NULL 224 push eax 225 push NULL 226 call edx 227 228 229 popad 230 ret 231 _patchFun endp 232 233 234 _start proc 235 local hKernel32Base:dword ;存放kernel32.dll基址 236 237 local _getProcAddress:_ApiGetProcAddress ;定义函数 238 local _loadLibrary:_ApiLoadLibrary 239 240 pushad 241 242 ;获取kernel32.dll的基地址 243 lea edx,_getKernelBase 244 add edx,ebx 245 call edx 246 mov hKernel32Base,eax 247 248 ;从基地址出发搜索GetProcAddress函数的首址 249 mov eax,offset szGetProcAddr 250 add eax,ebx 251 252 mov edi,hKernel32Base 253 mov ecx,edi 254 lea edx,_getApi 255 add edx,ebx 256 257 push eax 258 push ecx 259 call edx 260 mov _getProcAddress,eax 261 262 ;从基地址出发搜索LoadLibraryA函数的首址 263 mov eax,offset szLoadLib 264 add eax,ebx 265 266 mov edi,hKernel32Base 267 mov ecx,edi 268 lea edx,_getApi 269 add edx,ebx 270 271 push eax 272 push ecx 273 call edx 274 mov _loadLibrary,eax 275 276 ;调用补丁代码 277 lea edx,_patchFun 278 add edx,ebx 279 280 push _loadLibrary 281 push _getProcAddress 282 push hKernel32Base 283 call edx 284 285 popad 286 ret 287 _start endp 288 289 ; EXE文件新的入口地址 290 291 _NewEntry: 292 call @F ; 免去重定位 293 @@: 294 pop ebx 295 sub ebx,offset @B 296 297 invoke _start 298 jmpToStart db 0E9h,0F0h,0FFh,0FFh,0FFh 299 ret 300 end _NewEntry
标签:style c class blog code java
原文地址:http://www.cnblogs.com/onetheway/p/3754262.html