Board logo

标题: [讨论]关于杀毒(nod32)把病毒码定位到程序的iat输入表的API [打印本页]

作者: jjcd    时间: 2008-7-20 23:25     标题: [讨论]关于杀毒(nod32)把病毒码定位到程序的iat输入表的API

[讨论]关于杀毒(nod32)把病毒码定位到程序的iat输入表的API
议题作者:混世魔王
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

关于杀毒(nod32)把病毒码定位到程序的iat输入表的API .这种情况,怎么免杀?
我lord PE 重新down出来,再iat 修复,还是给查杀。
谁熟悉免杀,欢迎加Q交流.QQ:26836659取保候审中........


帖子181 精华10 积分3720 阅读权限100 性别男 在线时间88 小时 注册时间2005-3-12 最后登录2008-6-19 查看详细资料引用 报告 回复 TOP 软件项目外包

sdzbyy
晶莹剔透§烈日灼然
作者: 原始宝宝    时间: 2008-7-20 23:25

不用iat不就行了。
帖子8 精华0 积分39 阅读权限40 性别男 在线时间17 小时 注册时间2007-2-27 最后登录2007-11-11 查看详细资料引用 报告 回复 TOP 爱要怎么说出口

幽游
荣誉会员

作者: 老虎仔    时间: 2008-7-20 23:25

先给篇以前写的,现在NOD的杀毒机制又升级了,下面的方法有时候已经失效,因为最近的那篇介绍NOD32特征码定位在输入输出表的文章会在黑防第4期发,所以现在不能贴出来,等杂志出来了我就发出来,如果魔王急着要可以和我联系,QQ:149367。

本文除例子及定义引用自看雪论坛(www.pediy.com),其余内容为原创,转载请注明版权,转自(http://www.0x08.com
NOD32一般把特征码定位在输入表,输出表和节表三个地方,网上流传的过NOD32的方法是修改输入表,将函数名称用0填充然后在空白处加上被填充的函数名,再将IAT里函数对应的thunk值改到指向新的函数名称,这种方法固然改变了输入表,但并不能躲过NOD32的查杀,因为NOD32的查杀机制并不是直接读取特定位置比如函数名称位置的十六进制的值来比对,而是根据IAT表里的thunk值跟进到函数名称位置,然后再比对,应该比较容易理解。可以举个例子:
先看一下PE文件输入表部分结构
从PE头+0x80可以找到输入表的RVA,转化成对应文件偏移找到输入表位置
IMAGE_IMPORT_DESCRIPTOR
开始一般是各动态链接库DLL文件的名字字符串的RVA和First thunk值,准确点应该是
OriginalFirstThunk 该字段是指向一32位以00结束的RVA偏移地址串,此地址串中每个地址描述一个输入函数
TimeDateStamp 一个32位的时间标志,有特殊的用处
ForwarderChain 输入函数列表的32位索引
Name DLL文件名(一个以00结束的ASCII字符串)的32位RVA地址
FirstThunk 该字段是指向一32位以00结束的RVA偏移地址串,此地址串中每个地址描述一个输入函数,它在输入表中的顺序是可变的

引用看雪学院的一个例子吧
------------------------------------------------------------------------------------------------------------------------------------------------------------
0000C1E8h : 00 00 00 00 00 00 00 00 00 00 00 00 BA C2 00 00 ````````````----
0000C1F8h : 38 C2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ----````````````
0000C208h : C5 C2 00 00 44 C2 00 00 00 00 00 00 00 00 00 00 --------````````
0000C218h : 00 00 00 00 D2 C2 00 00 54 C2 00 00 00 00 00 00 ````--------````
0000C228h : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ````````````````
0000C238h : 7F 89 E7 77 4C BC E8 77 00 00 00 00 E6 9F F1 77 --------````----
0000C248h : 1A 38 F1 77 10 40 F1 77 00 00 00 00 4F 1E D8 77 --------````----
0000C258h : 00 00 00 00 00 00 4D 65 73 73 61 67 65 42 6F 78 ``````MessageBox
0000C268h : 41 00 00 00 77 73 70 72 69 6E 74 66 41 00 00 00 A```wsprintfA```
0000C278h : 45 78 69 74 50 72 6F 63 65 73 73 00 00 00 4C 6F ExitProcess```Lo
0000C288h : 61 64 4C 69 62 72 61 72 79 41 00 00 00 00 47 65 adLibraryA````Ge
0000C298h : 74 50 72 6F 63 41 64 64 72 65 73 73 00 00 00 00 tProcAddress````
0000C2A8h : 47 65 74 4F 70 65 6E 46 69 6C 65 4E 61 6D 65 41 GetOpenFileNameA
0000C2B8h : 00 00 55 53 45 52 33 32 2E 64 6C 6C 00 4B 45 52 ``USER32.dll`KER
0000C2C8h : 4E 45 4C 33 32 2E 64 6C 6C 00 63 6F 6D 64 6C 67 NEL32.dll`comdlg
0000C2D8h : 33 32 2E 64 6C 6C 00 00 00 00 00 00 00 00 00 00 32.dll``````````

正如你看到的,这个输入表被分成三个主要部分:
- C1E8h - C237h:IMAGE_IMPORT_DESCRIPTOR 结构部分,对应着每一个需要输入的动态
链接库(DLL)。这部分以关键字 00 结束。
IMAGE_IMPORT_DESCRIPTOR struct
OriginalFirstThunk dd 0 ;原拆分 IAT 的 RVA
TimeDateStamp dd 0 ;没有使用
ForwarderChain dd 0 ;没有使用
Name dd 0 ;DLL 名字符串的 RVA
FirstThunk dd 0 ;IAT 部分的 RVA
IMAGE_IMPORT_DESCRIPTOR ends
- C238h - C25Bh:这部分双字(DWord) 称作“IAT”,由 IMAGE_IMPORT_DESCRIPTOR
结构中的 FirstThunk 部分指明。这部分每一个 DWord 对应一个输入函数。
- C25Ch - C2DDh : 这里是输入函数和 DLL 文件的名称。问题是,这些是没有规定顺序
的:有时候 DLL 文件在函数前面,有时候正好相反,另外一些时候它们混在一起。
------------------------------------------------------------------------------------------------------------------------------------------------------------
从C1E8到C1FB对应第一个DLL文件
比如定位ExitProcess为特征码,NOD32是先读取OriginalFirstThunk、TimeDateStamp、ForwarderChain 均为0,DLL名称RVA为C2BA,First Thunk为C238,本来RVA要转化为文件偏移才能找到对应名称的,本例为求简单。两者设置成了相同的,至于如何转化可以参考网上其他文章。C2BA处为user.dll,C238处为第一个dll文件的各函数名称的RVA也就是thunk值,4个字节为一组,也就是32位为一组,可见user.dll有两个API,以0结尾,其余的类似。
理解以后就不难发现,NOD32注意的是函数的thunk,注意,不是thunk值,thunk是指根据First Thunk找到的指明各函数地址的地址,此地址的值即Thunk值则为各函数的地址,可以通过它找到函数名称,所以修改函数thunk也就是把函数转移到别的空白区域是没用的,照样被杀!
那该如何做呢?既然抓的是Thunk那我就把Thunk改掉,比如整个函数的所有thunk均前移一位,此时First Thunk也要修改,但经过测试修改后的文件运行会提示是无效的Windows映象,很是奇怪,还请高手赐教!
如果定位出了NOD32只是输入表有特征码可以用ASProtect加密IAT函数即可,手工修改的方法还在研究中,搞定以后会更新出来!个人不建议加2层北斗,第一加后容易文件损坏,第二加后本来过金山,卡巴的又会被杀(定位了加壳后的特征码)!

至于定位在输出表上还是可以手工修改过NOD的,简要介绍下,以灰鸽子的键盘记录插件为例,需要修改3-4处:删掉特征码,输出表把对应的比如PluginRun移到后面空白处,不过与之相关的也要修改掉,比如定义函数PluginRun位置的地方也要修改,还有比如定义函数名的地方,还有定义函数顺序的地方都要修改,详细方法待续!

至于修改节表的特征码修改还没成功,如果有高手可以点拨一二的话感激不尽!
本文除例子及定义引用自看雪论坛(www.pediy.com),其余内容为原创,转载请注明版权转自(http://www.0x08.com)知我者谓我心忧不知我者谓我何求悠悠苍天此何人哉
帖子24 精华2 积分3081 阅读权限100 性别男 在线时间324 小时 注册时间2006-3-3 最后登录2008-7-15 查看详细资料引用 报告 回复 TOP 爱要怎么说出口

混世魔王
荣誉会员

作者: 好穷的人    时间: 2008-7-20 23:25

iat 在脱壳遇到也是比较头疼的事,难道要沦落到加壳过杀毒的地步...取保候审中........

帖子181 精华10 积分3720 阅读权限100 性别男 在线时间88 小时 注册时间2005-3-12 最后登录2008-6-19 查看详细资料引用 报告 回复 TOP

langouster
荣誉会员

作者: 哨牙甸奴    时间: 2008-7-20 23:25

可以用LoadLibrary GetProcAddress的方法。不过要注意下NOD32不仅查IAT,它在程序的任意位置发现如CreateRemoteThread这样的字符串也会把程序当木马。
下面这个程序用了CreateRemoteThread函数但在NOD32下免杀。

PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");

  typedef HANDLE(WINAPI *PFNCreateRemoteThread)(HANDLE hProcess,LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags,LPDWORD lpThreadId );
  HMODULE h = LoadLibrary("KERNEL32.DLL");
  if(h!=NULL)
  {
    char temp[]="daerhTetomeRetaerC";
    strrev(temp);
    DWORD *Addr=(DWORD *)GetProcAddress(h,temp);
    hRemoteThread =((PFNCreateRemoteThread)Addr)(hRemoteProcess, NULL, 0, pfnThreadRtn, pszLibFileRemote, 0, NULL);
  }

把CreateRemoteThread这几字倒着写,它傻了。。。。。我的BLOG:http://www.langouster.com

帖子48 精华10 积分3538 阅读权限100 性别男 在线时间80 小时 注册时间2006-7-22 最后登录2008-7-14 查看个人网站
查看详细资料引用 报告 回复 TOP 良辰择日,预测咨询,公司改名,权威易经

混世魔王
荣誉会员

作者: 雯雯    时间: 2008-7-20 23:25

langouster 的方法不错。
从编程角度免杀.希望有朋友能有在没原码情况下,给出更好的解决办法。取保候审中........

帖子181 精华10 积分3720 阅读权限100 性别男 在线时间88 小时 注册时间2005-3-12 最后登录2008-6-19 查看详细资料引用 报告 回复 TOP 良辰择日,预测咨询,公司改名,权威易经

111111113
晶莹剔透§烈日灼然
作者: pat-k    时间: 2008-7-20 23:25

过NOD很简单撒!

1,把输入表藏起来,让NOD找不到!

2,比较麻烦 对应修改调用的语句 如CALL 等!

3,加壳
在NE365上很早就发表,至今仍然免杀!
帖子12 精华0 积分48 阅读权限40 在线时间26 小时 注册时间2005-10-2 最后登录2008-4-23 查看详细资料引用 报告 回复 TOP 让女孩一夜变的更有女人味

hiphop
晶莹剔透§烈日灼然
作者: 雨落空林    时间: 2008-7-20 23:25

恩... 已经解决了啊
那我就回复一下2楼朋友的问题吧...
你都改变了 First Thunk 怎么不代码修复呢?```
你的 First Thunk 都向前移动了1字节...
代码还是调用 原来地方的 不出错 才是见鬼了!~```
自己用 C32ASM 载入 Ctrl+K 看一下 改改 就OK 了
不过呢... 貌似这个方法 对NOD32 8 管用哦!~```

还是楼上的 说得比较正确... 不过那个你说的 "把输入表藏起来" 要怎么搞?```
自己用 汇编实现 输入表的 加载?```
帖子1 精华0 积分6 阅读权限40 性别女 在线时间1 小时 注册时间2006-3-2 最后登录2008-3-17 查看详细资料引用 报告 回复 TOP

白老会
晶莹剔透§烈日灼然
作者: SUNNY仔    时间: 2008-7-20 23:25

现在免杀手工改造啊?
强.
我现在基本是用工具加一下省事...
帖子37 精华0 积分90 阅读权限40 性别男 在线时间4 小时 注册时间2005-11-29 最后登录2008-6-30 查看详细资料引用 报告 回复 TOP

greyair
晶莹剔透§烈日灼然
作者: listenbreeze    时间: 2008-7-20 23:25

楼上的几个方法还是不太懂。貌似我最近也在研究这个。有谁做个动画什么的说清楚点。
帖子14 精华0 积分40 阅读权限40 在线时间83 小时 注册时间2007-3-12 最后登录2008-6-25 查看详细资料引用 报告 回复 TOP

81635631
晶莹剔透§烈日灼然
作者: 车大炮    时间: 2008-7-20 23:25

引用:
引用第4楼langouster于2007-03-23 21:08发表的 :
可以用LoadLibrary GetProcAddress的方法。不过要注意下NOD32不仅查IAT,它在程序的任意位置发现如CreateRemoteThread这样的字符串也会把程序当木马。
下面这个程序用了CreateRemoteThread函数但在NOD32下免杀。

PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");

.......
这样应该不查了吧
感觉这种方法最好``
(嘿嘿 其实我也是这样想的。。。不过被抢先了。。但是我没试过
langouster用过吧 ?
帖子30 精华0 积分98 阅读权限40 性别男 在线时间32 小时 注册时间2007-4-13 最后登录2007-11-20 查看详细资料引用 报告 回复 TOP

bosket
晶莹剔透§烈日灼然




欢迎光临 【3.A.S.T】网络安全爱好者 (http://3ast.com./) Powered by Discuz! 7.2