![]() |
适合读者:黑器爱好者、入侵爱好者 前置知识:基本汇编语法 蝴蝶:新年到了,编辑部各小编都在张罗着给大家送上最好的文章和最新的黑客技术,以代表我们对支持黑防的读者朋友的崇高敬意。;当然,作为编辑部的唯一一员女将,蝴蝶我当然不能拖大家后腿,于是从2005年第 | |
适合读者:黑器爱好者、入侵爱好者 前置知识:基本汇编语法 蝴蝶:新年到了,编辑部各小编都在张罗着给大家送上最好的文章和最新的黑客技术,以代表我们对支持黑防的读者朋友的崇高敬意。;当然,作为编辑部的唯一一员女将,蝴蝶我当然不能拖大家后腿,于是从2005年第1期开始,“免杀”系列后门工具将及时送到大家手上,让大家再也不用担心后门被杀毒软件干掉、被安全工具拦截了,保证大家期期有惊喜,月月乐悠悠! 修改特征码打造免杀后门之WinShell篇 文/图 Tankaiha[NE365][FCG] 各位读者,新年好,又和大家见面了。上一期给大家介绍了使用特征码定位器和反汇编程序打造免杀的后门,大家感觉如何?这次给大家介绍另外一种修改方法。对于大多数没有源代码的程序来说,只能使用反汇编工具进行逆向工程,可如果你搞到了它的源代码,道路会宽广得多:在源代码级别修改再编译出的黑器,不仅没有特征码,而且运行也会非常稳定的! 源代码级别的特征码修改有以下几个主要步骤:程序的特征码定位、特征码在源代码中的定位、源代码的修改。由于编程语言的多样性,特征码在源代码中的表现也不一样:汇编语言属于所见即所得的类型,特征码什么样儿,源代码中的指令就是什么样;而对于高级语言(C或Delphi等)生成的文件,想找到特征码对应的语句还得花点功夫。这次我们就以C语言编写的小型后门WinShell5.0为例讲讲修改方法,抛砖引玉。 特征码的定位 这一步必须在样本的基础上进行,所以先将WinShell的源代码在VC6中编译成可执行文件。先用“司机”来检测一下,显示发现Backdoor.Win32.WinShell.50,如图1所示。
图1 由于2005年第1期黑防已经说细地讲过了使用CCL进行特征码定位的过程,所以这里不再详细叙述,简单讲一下过程:打开CCL,设为手动定位,生成30个文件,然后打开WinShell.exe,发现文件有3个段,我们选择.text即代码段,点击生成后用卡巴斯基查杀目标文件夹,剩下没有被删除的3个文件,即特征码范围如下: -------------定位结果------------ 序号 起始偏移 大小 结束偏移 0001 000017D0 000002AA 0002 00001FA0 000002AA 0003 00002770 000002AA 手动检测只是定位大致范围,下面用自动功能来精确定位。重新设置CCL为自动检测,等待时间设置为7秒(我的机器比较慢)。范围我们就选择序号0001,起始偏移17D0,大小2AA个字节的区段。自动定位结果如下: -------------定位结果------------ 序号 起始偏移 大小 结束偏移 0001 只有一个地址,而且大小才 特征码在源代码中的定位 这里还是先请出反汇编界的老大IDA,在IDA中打开WinShell.exe,来看看 .text:00401809 movsx eax, [esp+270h+var_204] .text:0040180E add eax, 0FFFFFFC1h .text:00401811 cmp eax, 39h .text:00401814 ja loc_401976 .text: .text: .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 + 这行提示信息的告诉了我们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 源程序的修改 位置已经确定,剩下的就是修改源代码了。可我们是菜鸟啊,哪里会编程呢?更不用说修改那么复杂的后门了。其实不用担心,我们需要做的只是将原程序的特征码改变,而并不需要多么高升的编程功底,这种改变有时只需要一个字节就够了。看看我是怎么做的。在源代码中的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插在别的地方,比如Send和Break之间,也可以不选择NOP而替换为别的汇编指令,原则就是一个:不能改变原程序的关键寄存器值和执行顺序。 题外话 能让我们找到源代码的黑器不多,但一旦拥有,我们就可以通过源代码级别的修改打造出一个完美的免杀黑器。修改的方法当然不局限于我介绍的插入汇编指令这一条,但是Delphi和C都可以内嵌汇编,这确实给了我们很大方便。对于这种方法不能解决的,比如VB编写的程序,那只能通过用不同的语句来替换原程序的方法修改了,这就要求大家具有一定的编程功底了。 请大家期待下一期黑防,我将会带大家打造另一个新的免杀黑器! |