为了顺应当前形势和更好的发展,黑基网已于9月19日正式更名为【安基网】,域名更换为www.safebase.cn,请卸载旧的APP并安装新的APP,给您带来不便,敬请理解!谢谢

黑基Web安全攻防班
安基网 首页 IT技术 安全攻防 查看内容

输入表隐藏、加密的原理和手工实现

2009-10-21 09:49| 投稿: security

摘要: 一、前言:现在对输入表的查杀已经成为杀毒软件杀毒的一个重要方面,没有一个杀毒软件不把输入表作为查杀的对象,通常的输入表移位、重建已经不能作为免杀的重要手段,可以说杀毒软件也在逐步进步,而我先前倡导的输...
一、前言:现在对输入表的查杀已经成为杀毒软件杀毒的一个重要方面,没有一个杀毒软件不把输入表作为查杀的对象,通常的输入表移位、重建已经不能作为免杀的重要手段,可以说杀毒软件也在逐步进步,而我先前倡导的输入表按序号重建也因为存在系统兼容性问题不能作为输入表免杀的手段。如何改变输入表部分的内容与结构,使其与原先的不同,这就是本文要探讨的问题。二、目的:通过本文的学习,可以掌握手工导入输入表和手工加密输入表函数的名称的办法,并能学习到汇编语言的精辟。三、基本知识在开始之前,我们先来了解二个kernel32.dll的函数的使用方法,即:kernel32.LoadLibraryA和kernel32.GetProcAddress,它们是本文要用到的二个关键函数。具体的函数介绍可以看看这篇文章:《3个脱壳相关的重要函数介绍》http://bbs.pediy.com/showthread.php?threadid=202301、LoadLibraryA函数LoadLibrary函数是把指定的可执行模块映射进调用进程的地址空间。通俗的说,如程序需要调用ole32.dll里面的CreateStreamOnHGlobal函数,首先应该用LoadLibraryA函数找到ole32.dll的句柄。然后根据这个句柄用GetProcAddress找到CreateStreamOnHGlobal的内存指针。它有一个参数,即动态链接库名称的内存地址。汇编语言是这样实现的(以前面为例):PUSH 10018888   //10018888指向ole32.dll名称。CALL DWORD PTR DS:[10019990]   //10019990是LoadLibraryA的内存指针。结果放在EAX里面,返回值为模块句柄。2、GetProcAddress函数GetProcAddress函数返回指定的输出动态链接库内的函数地址。它有二个参数。汇编语言是这样实现的(以前面为例):PUSH 1001888C   //1001888C指向CreateStreamOnHGlobal名称。PUSH EAX   //EAX的值为LoadLibraryA的返回值,即ole32.dll的句柄。CALL DWORD PTR DS:[1001999C]   //1001999C为GetProcAddress函数的内存指针。结果也放在EAX里面,返回值为DLL输出函数的内存地址。四、输入表加密工具的原理和优缺点我在之前的免杀文章中采用了一个加密工具,可以用来加密EXE的输入表,通过这个工具加密之后,整个输入表大部分消失了,只剩下kernel32.dll和它的二个API函数,就是上面介绍的二个,LoadLibraryA函数和GetProcAddress函数。它加密的原理就是采用LoadLibraryA函数和GetProcAddress函数在程序中用代码把加密的输入表DLL的名称以及API函数的名称和内存指针恢复,用汇编语言实现是很简单的。这个加密工具的缺点是只能加密部分EXE文件(虽然我对加密工具进行了一个修正,但据反映,有些EXE文件还是不能用来加密输入表),不能加密DLL文件。而且用这个工具加密后再通过我的改壳免杀处理服务端的方法已经被瑞星关注了,瑞星就杀在加壳后的输入表GetProcAddress函数上。五、手工编写输入表隐藏和加密代码现在开始本文的重点,就是用手工编写代码改变输入表的结构,隐藏部分输入表。我们以Pcshare中的PcMain.dll为例,为什么采用这个做为例子,因为下一个教程我准备出DLL改壳免杀的教程,用这个教程为下一个教程做铺垫。我做二个示范,分别属于二种情况,一种是隐藏输入表中链接库DLL和其所有API函数,另外一种是只隐藏链接库DLL中的某一个API函数。至于加密函数名称,可以采用我的输出表加密函数名称的办法(双字节异或加密),这里不做介绍了,一般采用隐藏输入表就可以达到免杀的目的。PcMain.dll中ole32.dll只有一个函数CreateStreamOnHGlobal,把ole32.dll和其CreateStreamOnHGlobal隐藏, 另外隐藏shell32.dll中的ShellExecuteA函数。1、加空区段。作为代码写入的区域。记住程序原入口点为100116E3。2、写入代码。一般采用PUSHAD开始,POPAD结束,以避免不必要的错误。同时采用CALL(下一句的地址)和POP结构实现程序的自定位,通过内存的相对位置使程序也能用于DLL文件的输入表隐藏。我们记下几个内存值:程序新入口点10018000EBP:10018000ole32.dll名称起始内存地址:1001333C(用C32ASM寻找,再换算),与EBP的差值为4CC4。CreateStreamOnHGlobal名称起始内存地址:10013326(用C32ASM寻找,再换算),与EBP的差值为4CDA。CreateStreamOnHGlobal原程序中起始内存指针地址:1001236C(在OD里同时按CTRL和N,再查找),与EBP的差值为5C94。Shell32.dll名称起始内存地址:10013318(用C32ASM寻找,再换算),与EBP的差值为4CE8。ShellExecuteA名称起始内存地址:100132E0(用C32ASM寻找,再换算),与EBP的差值为4D20。ShellExecuteA原程序中起始内存指针地址:10012248(在OD里同时按CTRL和N查找),与EBP的差值为5DB8。LoadLibraryA函数内存指针:100121BC(在OD里同时按CTRL和N),与EBP的差值为5E44。GetProcAddress函数内存指针:1001210C(在OD里同时按CTRL和N),与EBP的差值为5EF4。开始写代码,看操作。代码如下:10018000     60               pushad10018001     E8 00000000     call PcMain01.10018006//自定位10018006     5D               pop ebp//EBP的值为本行地址10018007     83ED 06         sub ebp,61001800A     8BDD             mov ebx,ebp1001800C     81EB C44C0000   sub ebx,4CC4//EBX指向ole32.dll名称起始内存地址 10018012     53               push ebx//作为参数进栈10018013     8BDD             mov ebx,ebp10018015     81EB 445E0000   sub ebx,5E44//EBX指向LoadLibraryA函数内存指针1001801B     FF13         call dword ptr ds:[ebx]//调用LoadLibraryA函数1001801D     8BF8             mov edi,eax//结果放在EDI1001801F     8BDD             mov ebx,ebp10018021   81EB DA4C0000   sub ebx,4CDA//EBX指向CreateStreamOnHGlobal名称起始内存地址10018027     53               push ebx//参数进栈10018028     57               push edi//参数进栈10018029     8BDD             mov ebx,ebp1001802B     81EB F45E0000   sub ebx,5EF4//EBX指向GetProcAddress函数内存指针10018031     FF13             call dword ptr ds:[ebx]//调用GetProcAddress函数10018033     8BDD             mov ebx,ebp10018035     81EB 945C0000   sub ebx,5C94//EBX指向CreateStreamOnHGlobal原程序中起始内存指针地址1001803B     8903             mov dword ptr ds:[ebx],eax//将CreateStreamOnHGlobal内存地址放入原内存指针地址1001803D     8BDD             mov ebx,ebp//以下步骤同上,处理ShellExecuteA1001803F     81EB E84C0000   sub ebx,4CE810018045     53               push ebx10018046     8BDD             mov ebx,ebp10018048     81EB 445E0000   sub ebx,5E441001804E     FF13             call dword ptr ds:[ebx]10018050     8BF8             mov edi,eax10018052     8BDD             mov ebx,ebp10018054     81EB 204D0000   sub ebx,4D201001805A     53               push ebx1001805B     57               push edi1001805C     8BDD             mov ebx,ebp1001805E     81EB F45E0000   sub ebx,5EF410018064     FF13             call dword ptr ds:[ebx]10018066     8BDD             mov ebx,ebp10018068     81EB B85D0000   sub ebx,5DB81001806E     8903             mov dword ptr ds:[ebx],eax10018070     61               popad10018071   - E9 6D96FFFF     jmp PcMain01.100116E3//跳回原入口点二进制代码如下:60 E8 00 00 00 00 5D 83 ED 06 8B DD 81 EB C4 4C 00 00 53 8B DD 81 EB 44 5E 00 00 FF 13 8B F8 8B DD 81 EB DA 4C 00 00 53 57 8B DD 81 EB F4 5E 00 00 FF 13 8B DD 81 EB 94 5C 00 00 89 03 8B DD 81 EB E8 4C 00 00 53 8B DD 81 EB 44 5E 00 00 FF 13 8B F8 8B DD 81 EB 20 4D 00 00 53 57 8B DD 81 EB F4 5E 00 00 FF 13 8B DD 81 EB B8 5D 00 00 89 03 61 E9 6D 96 FF FF3、删除原链接库DLL和其API函数指针。对于ole32.dll我们采用LORDPE进行操作,我们在输入表里删除ole32.dll,对于ShellExecuteA我们采用C32ASM打开文件,根据上面的ShellExecuteA原程序中起始内存指针地址换算成偏移地址,然后将其填充为00。这样我们的修改就好了。修改好的输入表里我们删除了ole32.dll,ShellExecuteA虽然在输入表里还存在,但是它的内存指针已经没有了,可以用OD看下,同样按CTRL和N,找到ShellExecuteA,看它的内存指针变成了00。我们在Od跟踪下,指针恢复了。测试上线成功。功能无损。这种方法适用于所有PE文件,包括EXE和DLL文件的输入表处理。

小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册黑基账号,公开课频道价值万元IT培训教程免费学,让您少走弯路、事半功倍,好工作升职加薪!



免责声明:本文由投稿者转载自互联网,版权归原作者所有,文中所述不代表本站观点,若有侵权或转载等不当之处请联系我们处理,让我们一起为维护良好的互联网秩序而努力!联系方式见网站首页右下角。


鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论

最新

返回顶部