Board logo

标题: 修改特征码打造免杀后门之WinShell篇 [打印本页]

作者: 柔肠寸断    时间: 2009-5-13 18:31     标题: 修改特征码打造免杀后门之WinShell篇

修改特征码打造免杀后门之WinShell

/ Tankaiha[NE365][FCG]

       各位读者,新年好,又和大家见面了。上一期给大家介绍了使用特征码******和反汇编程序打造免杀的后门,大家感觉如何?这次给大家介绍另外一种修改方法。对于大多数没有源代码的程序来说,只能使用反汇编工具进行逆向工程,可如果你搞到了它的源代码,道路会宽广得多:在源代码级别修改再编译出的黑器,不仅没有特征码,而且运行也会非常稳定的!
源代码级别的特征码修改有以下几个主要步骤:程序的特征码定位、特征码在源代码中的定位、源代码的修改。由于编程语言的多样性,特征码在源代码中的表现也不一样:汇编语言属于所见即所得的类型,特征码什么样儿,源代码中的指令就是什么样;而对于高级语言(CDelphi等)生成的文件,想找到特征码对应的语句还得花点功夫。这次我们就以C语言编写的小型后门WinShell5.0为例讲讲修改方法,抛砖引玉。

特征码的定位
这一步必须在样本的基础上进行,所以先将WinShell的源代码在VC6中编译成可执行文件。先用“司机”来检测一下,显示发现Backdoor.Win32.WinShell.50,如图1所示。



1

由于2005年第1期黑防已经说细地讲过了使用CCL进行特征码定位的过程,所以这里不再详细叙述,简单讲一下过程:打开CCL,设为手动定位,生成30个文件,然后打开WinShell.exe,发现文件有3个段,我们选择.text即代码段,点击生成后用卡巴斯基查杀目标文件夹,剩下没有被删除的3个文件,即特征码范围如下:

-------------
定位结果------------

      序号    起始偏移     大小     结束偏移

0001
000017D0
000002AA
00001A7A


0002
00001FA0
000002AA
0000224A


0003
00002770
000002AA
00002A1A

手动检测只是定位大致范围,下面用自动功能来精确定位。重新设置CCL为自动检测,等待时间设置为7秒(我的机器比较慢)。范围我们就选择序号0001,起始偏移17D0,大小2AA个字节的区段。自动定位结果如下:

-------------
定位结果------------

      序号    起始偏移     大小     结束偏移

0001
0000180F

0000000A
00001819

只有一个地址,而且大小才0A个字节,天助我也。下面就是寻找它在源代码中的位置了(CCL在我的主页上提供最新版,修正了一些BUG,欢迎指点)。

特征码在源代码中的定位
这里还是先请出反汇编界的老大IDA,在IDA中打开WinShell.exe,来看看180F处到底是什么:
.text:00401809
movsx
eax, [esp+270h+var_204]

.text:0040180E
add
eax, 0FFFFFFC1h

.text:00401811
cmp
eax, 39h

.text:00401814
ja
loc_401976

.text:0040181A
xor
ecx, ecx

.text:0040181C
mov
cl, ds:byte_401A0C[eax]

.text:00401822

jmp
ds:off_4019E4[ecx*4]

哇!已经面目全非了,这让人怎么找对应的源代码啊?如果你熟悉VC编译程序的特点,很快会发现这里是一个Switch/case结构。可我们是菜鸟啊,怎么可能看得出来?这里给大家说个小技巧:尽量在上下文中寻找明显的提示。就好比我们经常寻找某个地点时,都是先找出周围的标志性建筑一样。
我们在IDA中从.text:00401809这一句向上看,发现隔了没多少行有这几条指令:
.text:004017B8
push
offset aHttp
; char *

.text:004017BD
push
ecx
; char *

.text:004017BE
call
_strstr

这是调用Strstr函数,将鼠标移到“aHttp”上,会弹出提示窗口显示:
char aHttp[]
aHttp
db
‘http://’,0
;
DATA XREF:StartAddress + 1C8
o

这行提示信息的告诉了我们Strstr的第二个参数aHttp指向了字符串“http://”。这行调用算是挺特别的,而且离特征码不远,就用它作为标志吧。打开WinShell的源代码,搜索“http://”,果然找到了调用它的语句:

if(strstr(cmd,"http://")) {


send(wsh,msg_ws_down,strlen(msg_ws_down),0);


if(DownloadFile(cmd,wsh))


send(wsh,msg_ws_err,strlen(msg_ws_err),0);


else


send(wsh,msg_ws_ok,strlen(msg_ws_ok),0);


}

该句后面的代码经过三次调用Send,紧接着就是一个Switch/case结构:



switch(cmd[0]) {


// help


case '?': {





send(wsh,msg_ws_cmd,strlen(msg_ws_cmd),0);


break;


}


初步断定这就是我们的目标。如果你想更确定的话,可以在源代码中Switch前插入几条特殊的汇编指令,编译后再定位,看看那几句汇编指令是不是出现在了00401809的指令之前。如果是,说明我们判断是正确的,特征码就是这条Switch语句。呵呵,还觉得麻烦?好吧,还有个简便的方法:用Ollydbg打开WinShell.exe,会直接分析出这里是选择/分支结构。如图2所示。

Ollydbg已经自动判断出来了







2
       括号里的(cases 3F .. 78)表示了该选择/分支结构的具体数据。第一个3F是“?”的ASC码,这不正对应源代码中的第一句“case ‘?’ ”吗!

源程序的修改
位置已经确定,剩下的就是修改源代码了。可我们是菜鸟啊,哪里会编程呢?更不用说修改那么复杂的后门了。其实不用担心,我们需要做的只是将原程序的特征码改变,而并不需要多么高升的编程功底,这种改变有时只需要一个字节就够了。看看我是怎么做的。在源代码中的Switch前加上一句最最简单的汇编指令NOP。源代码变成:

_asm nop;
//
这里是我们添加的



switch(cmd[0]) {


// help


case '?': {





send(wsh,msg_ws_cmd,strlen(msg_ws_cmd),0);


break;


}

再用VC6编译源代码,用卡巴斯基检查WinShell.exe。呵呵,奇迹发生了,司机大叔不再报警了!一个免杀的WinShell只用了几分钟就在我们的手中诞生!
当然,你也可以将NOP插在别的地方,比如SendBreak之间,也可以不选择NOP而替换为别的汇编指令,原则就是一个:不能改变原程序的关键寄存器值和执行顺序。





作者: 冷酷鲨鱼    时间: 2010-4-17 21:00

谢谢了。学习了。




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