【文章标题】: 反--反转存和非侵入性[屏蔽](上)【文章作者】: deroko/ARTeam;译者:kkbing/看雪论坛【作者声明】: 此文时看雪老大从ARETeam移入,见其有些价值拿来翻译。其中存在很多不足甚至是错误的地方,欢迎批评指正。特别感谢aalloverred 的指正……………………………… 2.2 重新得到 kernel32.dll 基址和 APIs 对于自定位代码来说,下一个重要的问题就是在Win32环境下调用APIs。为了能这样做,我们需要定位kernel32.dll的基址。以下是一些我们可以完成它的方法。 -扫描 SEH -由Ratter/29a 提供的 PEB 技巧 -获得硬编码。(译者注:比如Win2k下一般是77e60000h,WinXP SP1 是77e40000h,SP2是7c800000h等。但是这么做不具有通用性) 扫描 SEH---首先我们需要知道描述的SEH(结构化异常处理)的数据结构表 kd> dt nt!_EXCEPTION_REGISTRATION_RECORD +0x000 Next : 前一个 _EXCEPTION_REGISTRATION_RECORD结构 +0x004 Handler : 异常处理回调函数地址 kd> (译者注:这是windbg中的命令,用来获取结构的信息,很实用) 任何SEH链将会赋予一个指向kernel32.dll中某个值的句柄,当然,如果这是最后一个EXCEPTION_REGISTRATION_RECORD,那么_EXCEPTION_REGISTRATION_RECORD 结构的第一个参数名将被置为-1,这样我们就知道何时在kernel32.dll中获取地址了 getkernelbase: pushad xor edx, edx mov esi, dword ptr FS:[edx] __seh: lodsd cmp eax, 0FFFFFFFFh je __kernel mov esi, eax jmp __seh __kernel: mov edi, dword ptr[esi + 4] and edi, 0FFFF0000h __spin: cmp word ptr[edi], 'ZM' jz __test_pe sub edi, 10000h jmp __spin __test_pe: mov ebx, edi add ebx, [ebx.MZ_lfanew] cmp word ptr[ebx],'EP' je __exit_k32 sub edi, 10000h jmp __spin __exit_k32: mov [esp.Pushad_eax], edi popad ret 这个代码并不是最优化的,但是它展示了逻辑。扫描SHE直到这里等于-1,简单的获得句柄的地址和搜索MZ与PE符号。一旦我们找到了他们,我们就获了kernel32.dll的地址。 PEB 方法---这个方法是由Ratter/29a发现和提出的,我会给出例子,但是要想获得更多的解释请回到[2](译者注:应指的是文后参考文献[2],也可以参见http://www.nsfocus.net/index.php?act=magazine&do=view&mid=2002) mov eax, dword ptr FS:[30h] mov eax, dword ptr[eax+0ch] mov eax, dword ptr[eax+1ch] mov eax, dword ptr[eax] mov eax, [eax+8] 首先我们找回PEB的值,接着找到PEB_LDR_DATA,随后我们就进入到InInitializationOrderModuleList,头一个LIST_ENTRY指向ntdll.dll ,再进入下一个表的入口,瞧,kernel32.dll 的基址我们就接收到了。 获得装入时硬编码的值----这个非常简单,并不需要太多的知识,我们用GetModuleHandleA去重新获得kernel32.dll的值并储存到偏移值中。 例码: pushs <"kernel32.dll"> call GetModuleHandleA mov kernel32, eax loader: ... kernel32 dd ?……………………