最近没什么心情写博客,似乎停止不前了,唉,越来越懒了,不知道怎么回事,整理以前的笔记,这个免杀的,不知道内容过时了没。
各个杀毒软件查杀特点不一样,大致总结以下,API函数,字符串,代码段,资源段。免杀方法大致有如下几种手段,动态函数调用,延迟加载DLL,合并区段,字符串隐藏,删版权换版权,花指令,反调试等等细节,以上几种方法基本上过掉大部分杀软,当然有能力也可以自己改变程序的代码实现原来的功能。
1.动态函数调用
有两个函数是不能调用的,GetProcAddress,LoadLibrary。
杀毒软件如果查杀到API函数上,可以用动态函数调用解决。
typedef int (WINAPI *MessageBoxAT)
(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
MessageBoxAT pMessageBoxA= (MessageBoxAT)GetProcAddress(LoadLibrary("user32.dll"),"MessageBoxA");
2.字符串隐藏
利用数组来隐藏,字符串处理相对比较简单,隐藏的办法有很多,举出一种吧。
char name[]={'a','b','c','\0'};
name替换掉原来的字符串.
3.延迟加载DLL
源代码上加上,或者写成头文件加上也可以.
#pragma comment(linker, "/OPT:NOWIN98")
#pragma comment(lib, "DELAYIMP.LIB")
#pragma comment(linker, "/DELAYLOAD:WININET.dll")
#pragma comment(linker, "/DELAYLOAD:WS2_32.dll")
#pragma comment(linker, "/DELAYLOAD:PSAPI.DLL")
#pragma comment(linker, "/DELAYLOAD:GDI32.dll")
#pragma comment(linker, "/DELAYLOAD:ADVAPI32.dll")
#pragma comment(linker, "/DELAYLOAD:SHELL32.dll")
#pragma comment(linker, "/DELAYLOAD:WINMM.dll")
#pragma comment(linker, "/DELAYLOAD:USER32.dll")
#pragma comment(linker, "/DELAYLOAD:WTSAPI32.dll")
#pragma comment(linker, "/DELAYLOAD:AVICAP32.dll")
#pragma comment(linker, "/DELAYLOAD:SHLWAPI.dll")
#pragma comment(linker, "/DELAYLOAD:MSVFW32.dll")
#pragma comment(linker, "/DELAY:nobind")
#pragma comment(linker, "/DELAY:unload")
4.合并区段
把其他区段合并到一个区段里,以前这个方法还管用,可以试试,但最好不要加。
#pragma comment(linker, "/MERGE:.rdata=.data")//把rdata区段合并到data区段里
#pragma comment(linker, "/MERGE:.text=.data")//把text区段合并到data区段里
#pragma comment(linker, "/MERGE:.reloc=.data")//把reloc区段合并到data区段里
4 .删版权资源
有时对版权也查杀,可以换版权或者删除。
5.花指令
如果杀在代码段上可以加NOP来打乱程序的位置,一般不要加太多,有时也会查杀NOP。
__asm nop;
__asm nop;
__asm nop;
5.反调试
HKEY ck;
char strreg[] = {'S','O','F','T','W','A','R','E','\\','O','D','B','C','\0'};
if(ERROR_SUCCESS!=RegOpenKeyEx(HKEY_LOCAL_MACHINE,(LPCTSTR)strreg,0,KEY_ALL_ACCESS,&ck))
{
return 0;
}
6.代码换位
定位到特征码后,看代码中的程序是否可以代码换位。
注意的细节:
定位360BD引擎的时候,找到入口点,填充入口点以上的代码,查杀,如果免杀,就说明在这一区段.
map文件定位:
用OD找代码的时候,有时上下没有参考,可以用map文件来帮助,在VC6.0中设置map文件,然后拿出来,用OD里面的一个插件loadmap,载入map,重新运行,就可以了.
二进制文件与源码定位之map文件利用
map文件是二进制和源码之间对应的一个映射文件。
我们假设根据第三步我们定位出了病毒的特征码:
病毒名称 特征码位置 内存地址
svchost.dll 000038AA_00000002 100044AA
svchost.dll 00005F98_00000002
第一步设置VC编译环境生成Map文件。
在 VC 中,点击菜单“Project -> Settings”选项页(或按下 Alt+F7),选择 C/C++ 选项卡,并在最下面的 Project Options 里面输入:/Zd ,然后要点击 Link 选项卡,选中“Generate mapfile”复选框,并在最下面的 Project Options 里面输入:/mapinfo:lines,表示生成 MAP 文件时,加入行信息。设置完成。
第二步编译VC工程,设置活动工程编译即可,这个不用说明。这个步骤完成后,在release(或debug)目录,多了一个.map文件(比如svchost.map)。
第三步打开map文件(用UE或文本编辑器打开都行),形式如下:
(begin)
Timestamp is 488fcef2 (Wed Jul 30 10:16:18 2008)
Preferred load address is 10000000
---------------------------------------------------------------------------1----(为方便说明,wrw添加)
Start Length Name Class
0001:00000000 00010a50H .text CODE
0001:00010a50 00000485H .text$x CODE
0002:00000000 000004c8H .idata$5 DATA
......
0003:00000010 00000004H .CRT$XIZ DATA
0003:00000020 00001a50H .data DATA
0003:00001a70 00000688H .bss DATA
0004:00000000 000000a8H .rsrc$01 DATA
0004:000000b0 00000cf0H .rsrc$02 DATA
----------------------------------------------------------------------------2---(为方便说明,wrw添加)
Address Publics by Value Rva+Base Lib:Object
0001:00000000 ??0CAudio@@QAE@XZ 10001000 f Audio.obj
0001:000000d0 ??_GCAudio@@UAEPAXI@Z 100010d0 f i Audio.obj
0001:000000d0 ??_ECAudio@@UAEPAXI@Z 100010d0 f i Audio.obj
0001:000000f0 ??1CAudio@@UAE@XZ 100010f0 f Audio.obj
0001:000001e0 ?getRecordBuffer@CAudio@@QAEPAEPAK@Z 100011e0 f Audio.obj
0001:00000240 ?playBuffer@CAudio@@QAE_NPAEK@Z 10001240 f Audio.obj
0001:000002c0 ?InitializeWaveIn@CAudio@@AAE_NXZ 100012c0 f Audio.obj
......
0001:00003310 ?SendToken@CFileManager@@AAEHE@Z 10004310 f FileManager.obj
0001:00003320 ?UploadToRemote@CFileManager@@AAE_NPAE@Z 10004320 f FileManager.obj
0001:00003440 ?FixedUploadList@CFileManager@@AAE_NPBD@Z 10004440 f FileManager.obj
0001:00003670 ?StopTransfer@CFileManager@@AAEXXZ 10004670 f FileManager.obj
0001:00003730 ?CreateLocalRecvFile@CFileManager@@AAEXPAE@Z 10004730 f FileManager.obj
......
----------------------------------------------------------------------------3---(为方便说明,wrw添加)
Line numbers for .\Release\FileManager.obj(E:\vtmp\gh0st3src\Server\svchost\common\FileManager.cpp) segment .text
17 0001:00002630 20 0001:0000267f 21 0001:00002698 24 0001:000026d0
25 0001:000026f8 26 0001:0000273c 29 0001:000027d0 33 0001:000027ee
77 0001:000027f8 36 0001:000027fb 37 0001:00002803 77 0001:0000280d
......
532 0001:0000340f 534 0001:00003414 537 0001:00003428 540 0001:00003440
546 0001:0000345d 547 0001:00003487 548 0001:00003490 549 0001:00003492
551 0001:0000349e 552 0001:000034b8 553 0001:000034cb 554 0001:000034d4
558 0001:000034de 560 0001:000034e9 563 0001:000034ee 564 0001:00003506
......
(end)
我们看下,定位svchost.dll 的第一个特征码内存地址为:100044AA,在第2块中,我们可以找到RVA+BASE与之很接近的是
0001:00003440 ?FixedUploadList@CFileManager@@AAE_NPBD@Z 10004440 f FileManager.obj
这样我们可以定位到FileManager.cpp中的FixedUploadList函数,是不是范围缩小了?
下面我们再缩小代码行
利用这个公式:特征码行偏移 = 特征码地址(Crash Address)- 基地址(ImageBase Address)- 0x1000
看起来好像很难,其实很简单,我们将100044AA去掉内存基址10000000,再减1000,因为PE很多从1000开始,可以得到代码偏移地址为34AA。到第3块中找对应的代码行。
偏移地址34AA在(551 0001:0000349e 552 0001:000034b8 )中间,也就是551行和552行中间,我们到源程序中查找第551行:
wsprintf(lpszFilter, "%s%s*.*", lpPathName, lpszSlash);
这样就定位出源代码了,要怎么修改就怎么修改它就可以了。