免杀的个人经验及技巧详谈

免杀的个人经验及技巧详谈



回望免杀的初始:用WinHex逐字节修改木马免杀 -> 到后来软件保护(加壳)的加入、特征码免杀技术的公开、多层加壳的发现、反调试技术、针对于PE文件格式的免杀,到如今盛行的源码免杀
再看反病毒的历程:从文件扫描技术、到通配符扫描技术、内存特征码扫描技术、虚拟机扫描技术、主动防御、启发式病毒查杀技术、云查杀。
我们不难发现,反病毒与反-反病毒这两项处于对立面的技术慢慢的壮大,并形成了各自所拥有的领域。
我们很想让我们心爱的黑软、木马在遇到杀软时依旧装TM牛B,反-反病毒技术的重要性就可想而知了。
但,任何技术都需要一个最简单的东西引领你:
C语言,从一个简单的"Hello World!"开始;
而反-反病毒:我想,还是得从MyCCL来打开免杀世界的大门……
这里,MyCCL陪你开始.
(注:这里只谈及使用技巧,非教程)
分块个数
体积小于200KB的木马在最开始选择50-100之间.
体积大于200KB的木马在最开始选择10-30之间.
尔后由大到小缩小范围定位。
单位长度
事实上单位长度是由文件大小和分块个数决定。相反,分块个数由文件大小和单位长度决定。单位长度决定了每次填充的区域大小。
计算公式:
文件大小 ÷ 分块个数 == 单位长度
(其它自己推)
填充方式

不仅限于00、20或者90,可以是任意00-FF之间的16进制数值。
相比单一的填充方式,MultiCCL的随机数值填充方式更值得借鉴。
开始位置结束位置分段长度
开始位置

决定了从特定的偏移处开始填充,默认情况下在E0处开始填充。有时候杀软会将特征码假定在PE头,因此可以填第一个区段的偏移量,一般第一个区段为.text,起始位置为00000600。
结束位置

一般情况下为文件的末尾。
分段长度
从 开始位置 到 结束位置 所经过的偏移大小。
而某些情况下,若要对某个特定区段进行特征码定位。可以在 开始位置 填入区段的起始位置,在 结束位置 填入区段的结束地址,然后进行常规的定位流程。
正反填充

一般情况下,进行正向填充。若定位时进入死循环或者定位错误,可选择反向定位。
定位精度
个人喜欢定位到4个字节的大小,因为一般特征码大小为4个字节的大小,甚至更大。2个字节大小的特征码许多人修改时在潜意识中会把特征码定义为2个字节,换句话说就是下定决心跟这条特征码干上了。而这样的思维定视会严重影响你的免杀质量和效率,还有心情。
从杀软的角度来看,越小的特征码越容易出现误杀。作为专业的杀毒软件来说,出现误杀的情况是不允许的,当出现这样的情况,会使用户感到困扰和不安。所以他们尽量会选择适当大小的特征码。
MultiCCL
由于这款工具功能的强大性和易使用性,这里只对MultiCCL进行一些说明:
MultiCCL定位出特征码的大小是精确的,MyCCL定位精度是由使用者的决定的。而特征码定位长度精确的代价是花费更长的定位时间。(对于这里的定位精确,是指最终定位出的特征码大小,非定位时的定位精度。)
但是回报也是非常可观的,精确的特征码大小告诉了你可以在多大的范围内修改。
若在免杀时遇到疑难特征码、或者在修改多次失败时,可将那段特征码保护起来,再进行定位。有一个例子就是曾经瑞星把特征码定位在了TLS表,当时修改多次出现错误。无奈将TLS保护起来时,重新定位,结果发现了新大陆......
个人习惯把木马的输入表保护起来,再进行定位。
特征码修改技巧

指令互换 

代码:ADD EAX,521
ADC EAX,521
SUB EAX,521
SBB EAX,521
SUB EAX,521
ADD EAX,-521
TEST EAX,EAX
AND EAX,EAX
OR EAX,EAX
AND EAX,EAX
CMP EAX,EAX
OR EAX,EAX
XOR EAX,EAX
MOV EAX,0
(XOR EAX,EAX为对寄存器进行清0操作,与赋值为0其结果无异。ps:是否有误?)
PUSH 0
PUSH (EAX\EBX\ECX\EDX,若它们其中一个寄存器在当时的值为空)
JLE Address
JBE Address
JB Address
JL Address
JNB Address
JNL Address
???
NOP
(其余见8086指令参考手册)
指令位移
这个是我最喜欢的修改方式之一。
若发现特征码上句或下句与本身的操作数不同,则可进行位移。需要注意的是必须下面的指令先移到上面,再将上面的指令移动到下面。否则若下面的指令大小大于上面的指令,先对上面的指令进行移动后,会破坏原先的完整性。 

代码:MOV EAX,EBX
PUSH 0
PUSH 0
CALL xxxxxxxx
修改后:
PUSH 0
MOV EAX,EBX
PUSH 0
CALL xxxxxxxx
(关于更多的位移演示,可以看看我朋友alph4曾经写的“灰鸽子,依稀依然的邪恶”这篇文章。里面提到了很多指令位移的使用。)
字符串
对于字符串类型的特征码,除了NOP、00填充、修改字符大小写之外,还可对字符类型进行移动。
步骤:
1、用C32载入,记录你想修改的字符串的偏移量。
2、用LPE载入,在"FLC"里的Offset处输入记录的偏移量,记录下计算出的VA值。
3、用OD载入,搜索你想修改的字符串,搜索到后双击。把MOV指令后面的地址改为记录的VA值,保存。
4、回到C32,将原来的字符串00填充。
不仅仅在于特征码修改,很多时候都可以这么用。
二重跳

特征码: 

代码:0x400001 JMP 0x400201 ;假设的地址
........
........
0x400201 xxxxxxxx ;some code
JMP的最终地址是0x400201,那么多跳一次,就构成了二重跳。
比作去学校,我们可以直接去学校;也可以经过图书馆,再去学校。只要目的地不变,就可以。
修改后: 

代码:0x400001 JMP 0x400101 ;一块空白区
........
........
0x400101 JMP 0x400201 ;在空白区填上我们的特征码
........
........
0x400201 xxxxxxxx ;some code
还有一种情况: 

代码:0x400001 CMP EAX,0
0x400002 JNZ 0x400201
0x400003 xxxxxxxx ;some code
........
........
0x400201 xxxxxxxx ;some code
很多人会直接把JNZ 0x400201这句改为JMP 0x400201,但这样做是错的。为什么呢,因为JNZ是一个条件跳转指令,它只有在条件成立时才跳转。
从8086指令手册里我们可以知道JNZ是当条件不等于时才进行跳转,而JMP则是无条件跳转指令。不要忘了,JNZ前面还有个CMP指令,通过这个指令我们显然知道程序原本是想让在EAX不等于0时进行跳转,如果鲁莽的改为JMP,那么即使EAX为0,那么程序也会进行跳转。这样的修改会增加出错的几率。
但我们可以修改的是,把判断和进行跳转的流程转到一个空白区,修改后: 

代码:0x400001 NOP ;NOP之
0x400002 JMP 0x400101 ;空白区的地址
0x400003 xxxxxxxx ;some code
........
........
0x400101 CMP EAX,0
0x400102 JNZ 0x400201
0x400103 JMP 0x400003
........
........
0x400201 xxxxxxxx ;some code
关于内存地址0x400103那个JMP,是因为若CMP EAX,0成立的时候,显然JNZ跳转时不会执行的。在EAX等于0时,程序要执行JNZ后面的代码,由于JNZ已经移动到另一个区域了,为了程序能继续完成流程,所以还需要一个JMP跳回那后面的地址。
CALL指令

CALL +1、-1
这里想要提的是CALL -1这种方法。有时候,CALL -1的时候并未出错,却修改保存后双击没有反应。笔者曾经遇到过这种一个情况: 

代码:0x400001 CALL 0x400050
........
........
0x400050 xxxxxxxx ;some code
使用了CALL -1后程序出现了上面提到的状况,于是想跟进入,看看CALL的内容。无意间按了键盘的向上键,发现了新大陆: 

代码:0x400001 CALL 0x400050
........
........
0x400049 ADD [EAX],AL ;这段代码为在16进制中显示00,即空。
0x400050 xxxxxxxx  ;some code
原来是CALL遇到了00直接使程序退出,但是出现了两种修改方法。
1、将0x400049处的ADD [EAX],AL这段代码NOP。
2、将0x400050的代码NOP,移动到0x400049处。
方法一: 

代码:0x400001 CALL 0x400050
........
........
0x400049 NOP
0x400050 xxxxxxxx  ;some code
方法二: 

代码:0x400001 CALL 0x400050
........
........
0x400049 xxxxxxxx  ;some code
0x400050 NOP
参数修改法

若杀软将某个子程序段作为特征码,可以在周围修改。下面这个例子: 

代码:0x400076 MOV  EAX,EDX
0x400077 PUSH 0   ;parameter 1
0x400078 PUSH 0   ;parameter 2
0x400079 PUSH EAX  ;parameter 3
0x400080 CALL xxxxxxx  ;call it
可以尝试将MOV EAX,EDX改为MOV EBX,EDX,然后把下面的PUSH EAX改为PUSH EBX。
或者把PUSH 0改为PUSH ECX等。
修改的寄存器要确定为空或之前未被其它重要代码使用,否则可能出错!
输入表修改
函数A改W
MessageBoxA
MessageBoxW
这样做修改的原理是:在Win32环境中,WinAPI函数有两个版本,一个为ASCII版本,还有一个则为Unicode版本。
在函数最后加A则表示为ASCII版本,而Unicode的表现形式为W。
在某些情况下,这样修改的修改可以成功。但笔者不保证其修改方法的一定性!
(有时候会出错的原因我估计:可能在函数参数传入的时候,由于使用了不同的编码模式(一个为窄字符型,一个为宽字元版),参数传入类型错误,从而导致了函数的调用失败,程序才会崩溃。还望牛人指点)
以上是个人特征码修改的一些经验和技巧,有些方法可能针对性很强,局限性很大。但对于修改特征码而言,修改方法是死的,思路才是活的。希望不要照搬本文的方法,要适当的进行修改。由于其他输入输出表免杀方法已经多如牛毛了,所以这里只谈一点个人的经验。
                                                                                                                # By Miku_fl0
                                                                                                                # 2010.06.08
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
白盒测试和黑盒测试都是软件测试中常用的测试方法,它们有着不同的测试方式和适用范围。 1. 异同点 白盒测试:测试者需要了解被测试系统的内部结构和实现细节,以此为基础设计测试用例。测试者可以通过调试代码、检查变量、分支覆盖等方式进行测试。白盒测试的优点在于可以发现代码中的错误和潜在问题。缺点是测试者需要具备一定的编程知识,且测试的时间和资源消耗较多。 黑盒测试:测试者不需要了解被测试系统的内部结构和实现细节,只需要根据输入输出来验证系统的正确性、可靠性和安全性等方面。测试者可以通过等价类划分、边界值分析、决策表等方式进行测试。黑盒测试的优点在于不需要测试者具备编程知识,测试时间和资源消耗较少。缺点是无法发现代码中的错误和潜在问题。 2. 用例 白盒测试用例: - 检查变量:检查变量的定义、初始化、赋值、使用等是否正确。 - 分支覆盖:测试所有的分支类型,包括if、switch等。 - 语句覆盖:测试所有的语句类型,包括循环、函数调用、异常处理等。 - 路径覆盖:测试所有的代码路径,包括从一个函数到另一个函数的调用等。 黑盒测试用例: - 等价类划分:将输入值划分为等价类,测试每个等价类的输入是否能得到正确的输出。 - 边界值分析:测试系统在输入的边界值处是否能得到正确的输出。 - 决策表:设计出所有的输入和输出的组合情况,测试每个组合情况的输入是否能得到正确的输出。 总之,白盒测试和黑盒测试都有各自的优缺点和适用范围。在实际的软件测试中,应该根据系统的特点和测试目的,选择合适的测试方法进行测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值