瑞星卡卡安全论坛
闪电风暴 - 2008-7-17 15:54:00
Lightning(
kxsystem@163.com)
My BLOG:
http://hi.baidu.com/aegisys不足之处请指出,谢谢。
样本来自:baohe@ikaka.com(在此感谢)
使用工具:OllyDbg 1.10
用EXECOPE看一下,有个UPX区段,应该是这个UPX壳,但是PEID说“什么也没找到”。看来可以自己手动做掉它了。
我没有多少脱壳经验,所以这个壳的每一步都跟了下去。如果只为了脱壳没有这么麻烦。
刚开始不用多说,不一会儿就到了壳获取需要的函数地址的时候了。
// 通过跟踪可以看出NewVirus.0043A457模拟了GetProcAddress的功能,参数也一样。
// PVOID _stdcall NewVirus_0043A457(HMODULE hModule, LPCTSTR lpFuncName);
0043A099 50 PUSH EAX // offset string "ExitProcess"
0043A09A FFB5 B84E4000 PUSH DWORD PTR SS:[EBP+404EB8] ; kernel32.7C800000 // The Base of "kernel32.dll"
0043A0A0 E8 B2030000 CALL NewVirus.0043A457
但是NewVirus_0043A457会检查这个函数的开头是否被下断,如果下断则会跳转到一条错误指令导致程序异常退出。比方说:有的调试器为了对抗病毒的FindWindowA方法,在FindWindowA 上下断将EAX清空后跳回去
0043A386 8038 CC CMP BYTE PTR DS:[EAX],0CC // 反调试代码,EAX == offset string lpFuncName
0043A389 74 01 JE SHORT NewVirus.0043A38C // 如果被调试就跳到下面的LOCK CMPXCHG8B EAX自杀
0043A38B C3 RETN
0043A38C F0:0FC7C8 LOCK CMPXCHG8B EAX ; 非法使用寄存器 // 可以把这里用RETN填了,这样无论如何都不会异常。
通过这个函数依次获得函数地址的有:
LoadLibraryA
GetProcAddress
ExitProcess
IsDebuggerPresent // 得到地址后就CALL,检测调试器,被OD插件做掉
lstrcmpA
然后进入解压函数0x43A3AB,不用管它,RETN处下断跟踪。
0043A139 LoadLibrary("user32");
再获得FindWindowA地址,然后调用:
FindWindowA(NULL, "TrainerSpy XP + NT / 2000 / XP + Coded By BofeN");
获得:CallNextHookEx
0043A19A 05 CC000000 ADD EAX,0CC // EAX = user32.CallNextHookEx
0043A19F 8B85 A44E4000 MOV EAX,DWORD PTR SS:[EBP+404EA4] // user32.FindWindowA,上面那句好像没用
// 邪恶的代码来了,病毒要检测OD
0043A1A5 6A 00 PUSH 0
0043A1A7 8DB5 B64D4000 LEA ESI,DWORD PTR SS:[EBP+404DB6]
0043A1AD 56 PUSH ESI ; NewVirus.0043A5F2 offset string "OLLYDBG"
0043A1AE FFD0 CALL EAX // EAX == user32.FindWindowA
0043A1B0 0BC0 OR EAX,EAX
0043A1B2 0F85 79010000 JNZ NewVirus.0043A331
反C:
FindWindowA("OllyDbg", NULL); // 使用类名来查找OD窗口
OD的插件并没有正确地隐藏OD窗口,这里可以获得句柄eax == 00140142(在我的机子上)
这里需要强制清空EAX,或者修改那个JNZ为NOP。
接着检测了一些其它调试器:
ESI=0043A61B (NewVirus.0043A61B), ASCII "API-Log v1.2 by M.o.D. [F2F]"
ESI=0043A638 (NewVirus.0043A638), ASCII "VxDMonClass"
ESI=0043A644 (NewVirus.0043A644), ASCII "TRW2000 for Windows 9x" // 连TRW2000的9X版本那么老的调试器也不放过
ESI=0043A65B (NewVirus.0043A65B), ASCII "Cool Debugger for Win32"
ESI=0043A673 (NewVirus.0043A673), ASCII "The Customiser Configuration Screen"
ESI=0043A697 (NewVirus.0043A697), ASCII "The Customiser"
ESI=0043A6A6 (NewVirus.0043A6A6), ASCII "Hacked Spy"
再获得CreateFileA地址并调用:
CreateFileA("\\\\.\\NTICE", 0xC0000000, 3, 0, 3, 80, 0); // 还得防SoftICE(NTICE是SI的服务)
0043A2B8 40 INC EAX
0043A2B9 74 02 JE SHORT NewVirus.0043A2BD
0043A2BB EB 74 JMP SHORT NewVirus.0043A331
0043A2BD 83BD 8C4E4000 0>CMP DWORD PTR SS:[EBP+404E8C],1
如果SoftICE服务不存在,那么EAX = 0xFFFFFFFF,INC EAX将它加1后即为0,JE SHORT就跳转到正确的代码。
如果存在的话,直接JMP SHORT NewVirus.0043A331强行退出程序。
跳过一些代码,再检测:
ESI=0043A6B1 (NewVirus.0043A6B1), ASCII "\\.\SIWVID"
然后再获得WriteProcessMemory地址。
0043A324 8038 CC CMP BYTE PTR DS:[EAX],0CC
0043A327 74 08 JE SHORT NewVirus.0043A331 // 如果在WriteProcessMemory处下断将会掉入陷阱
0043A329 8D85 FE4A4000 LEA EAX,DWORD PTR SS:[EBP+404AFE]
0043A32F FFE0 JMP EAX // JMP 0043A33A
// 这个为陷阱
0043A331 8D85 0F4B4000 LEA EAX,DWORD PTR SS:[EBP+404B0F]
0043A337 50 PUSH EAX
0043A338 FFE0 JMP EAX
// 这个才是正确的,上面的JMP EAX会跳到这里。
0043A33A 8B85 C04E4000 MOV EAX,DWORD PTR SS:[EBP+404EC0]
0043A340 0BC0 OR EAX,EAX
0043A342 74 07 JE SHORT NewVirus.0043A34B
0043A344 894424 1C MOV DWORD PTR SS:[ESP+1C],EAX
0043A348 61 POPAD
0043A349 FFE0 JMP EAX // 跳到 00437CD0
00437CD0 60 PUSHAD
00437CD1 BE 00704200 MOV ESI,NewVirus.00427000
00437CD6 8DBE 00A0FDFF LEA EDI,DWORD PTR DS:[ESI+FFFDA000]
00437CDC C787 C4700200 3>MOV DWORD PTR DS:[EDI+270C4],25B1CE39
00437CE6 57 PUSH EDI
00437CE7 83CD FF OR EBP,FFFFFFFF
00437CEA EB 0E JMP SHORT NewVirus.00437CFA
00437DFA LoadLibraryA("kernel32");
然后再获取Sleep地址(获取这个干嘛?后面有用。)
// 下面的代码跳转到一个内部函数。
004277C9 8BEC MOV EBP,ESP
004277CB 83C4 F0 ADD ESP,-10
004277CE B8 A8764200 MOV EAX,NewVirus.004276A8
004277D3 E8 ECEDFDFF CALL NewVirus.004065C4
接着在CALL了一堆kernel32.dll中的函数之后终于开始做正事了!
004277D8 E8 2FFDFFFF CALL NewVirus.0042750C // The Real Original Entry Point!!
// 进入WinMain 函数(实际上不能叫WinMain),这里可以脱壳了。不过脱壳后PEID仍然不能分出是什么语言写的。
0042750C 55 PUSH EBP
0042750D 8BEC MOV EBP,ESP
0042750F 33C9 XOR ECX,ECX // 可能是这儿影响了OD的判断
00427511 51 PUSH ECX
00427512 51 PUSH ECX
00427513 51 PUSH ECX
00427514 51 PUSH ECX
00427515 51 PUSH ECX
00427516 53 PUSH EBX
00427517 BB 7C9A4200 MOV EBX,NewVirus.00429A7C
0042751C 33C0 XOR EAX,EAX
0042751E 55 PUSH EBP
0042751F 68 03764200 PUSH NewVirus.00427603
00427524 64:FF30 PUSH DWORD PTR FS:[EAX]
00427527 64:8920 MOV DWORD PTR FS:[EAX],ESP
0042752A 8D55 F8 LEA EDX,DWORD PTR SS:[EBP-8]
0042752D 33C0 XOR EAX,EAX
0042752F E8 70B4FDFF CALL NewVirus.004029A4
00427534 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
00427537 8D55 FC LEA EDX,DWORD PTR SS:[EBP-4]
0042753A E8 A5FEFDFF CALL NewVirus.004073E4
0042753F 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
00427542 50 PUSH EAX
00427543 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
00427546 E8 2900FEFF CALL NewVirus.00407574
0042754B FF75 EC PUSH DWORD PTR SS:[EBP-14]
0042754E 68 18764200 PUSH NewVirus.00427618 ; ASCII "drivers\"
00427553 68 2C764200 PUSH NewVirus.0042762C ; ASCII "suchost.exe" // 释放病毒文件u和v长得不像啊。
00427558 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-10]
0042755B BA 03000000 MOV EDX,3
00427560 E8 DBD3FDFF CALL NewVirus.00404940
00427565 8B45 F0 MOV EAX,DWORD PTR SS:[EBP-10]
00427568 8D55 F4 LEA EDX,DWORD PTR SS:[EBP-C]
0042756B E8 74FEFDFF CALL NewVirus.004073E4
00427570 8B55 F4 MOV EDX,DWORD PTR SS:[EBP-C]
00427573 58 POP EAX
00427574 E8 53D4FDFF CALL NewVirus.004049CC
00427579 75 46 JNZ SHORT NewVirus.004275C1
0042757B B9 38764200 MOV ECX,NewVirus.00427638 ; ASCII "c:\go.sys" // 释放驱动程序 go.sys
00427580 BA 44764200 MOV EDX,NewVirus.00427644 ; ASCII "sys"
00427585 B8 0A000000 MOV EAX,0A
0042758A E8 6D01FEFF CALL NewVirus.004076FC
0042758F B8 38764200 MOV EAX,NewVirus.00427638 ; ASCII "c:\go.sys"
00427594 E8 D736FFFF CALL NewVirus.0041AC70
00427599 8B15 48894200 MOV EDX,DWORD PTR DS:[428948] ; NewVirus.00429968
0042759F 8902 MOV DWORD PTR DS:[EDX],EAX
004275A1 68 D0070000 PUSH 7D0
004275A6 E8 0DF3FDFF CALL NewVirus.004068B8 ; JMP 到 kernel32.Sleep
004275AB A1 48894200 MOV EAX,DWORD PTR DS:[428948]
004275B0 8B00 MOV EAX,DWORD PTR DS:[EAX]
004275B2 E8 7537FFFF CALL NewVirus.0041AD2C
004275B7 68 38764200 PUSH NewVirus.00427638 ; ASCII "c:\go.sys"
004275BC E8 3FF1FDFF CALL NewVirus.00406700 ; JMP 到 kernel32.DeleteFileA
004275C1 E8 125CFFFF CALL NewVirus.0041D1D8
004275C6 E8 4DFEFFFF CALL NewVirus.00427418
004275CB E8 28FFFFFF CALL NewVirus.004274F8
004275D0 EB 06 JMP SHORT NewVirus.004275D8
004275D2 53 PUSH EBX
004275D3 E8 28F4FDFF CALL NewVirus.00406A00 ; JMP 到 USER32.DispatchMessageA // 这是一个标准的Win32应用程序。
004275D8 6A 00 PUSH 0
004275DA 6A 00 PUSH 0
004275DC 6A 00 PUSH 0
004275DE 53 PUSH EBX
004275DF E8 5CF4FDFF CALL NewVirus.00406A40 ; JMP 到 USER32.GetMessageA
004275E4 85C0 TEST EAX,EAX
004275E6 ^ 75 EA JNZ SHORT NewVirus.004275D2
004275E8 33C0 XOR EAX,EAX
004275EA 5A POP EDX
004275EB 59 POP ECX
004275EC 59 POP ECX
004275ED 64:8910 MOV DWORD PTR FS:[EAX],EDX
004275F0 68 0A764200 PUSH NewVirus.0042760A
004275F5 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
004275F8 BA 05000000 MOV EDX,5
004275FD E8 06D0FDFF CALL NewVirus.00404608
00427602 C3 RETN
那个go.sys用了一种老掉牙的方法恢复了SSDT(通过ZW**读取文件然后XXX),代码又是抄的,一点意思也没:
mov eax, [ebx+3Ch]
.text:00010416 add eax, ebx
.text:00010418 mov eax, [eax+34h]
.text:0001041B mov [ebp+var_10], eax
.text:0001041E push offset loc_10634 // KeServiceDescriptorTable
.text:00010423 call sub_10280
.text:00010428 mov edx, [eax+8]
.text:0001042B mov [ebp+var_14], edx
.text:0001042E mov eax, [eax]
.text:00010430 mov [ebp+var_18], eax
.text:00010433 push 206B6444h ; Tag
.text:00010438 mov eax, [ebp+var_14]
.text:0001043B add eax, eax
.text:0001043D add eax, eax
.text:0001043F push eax ; NumberOfBytes
.text:00010440 push 1 ; PoolType
.text:00010442 call ExAllocatePoolWithTag用户系统信息:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1
闪电风暴 - 2008-7-17 15:57:00
提供一种比较XX的防范方法:
开启OD,什么事也别做!
然后病毒就无法运行!:default6:
闪电风暴 - 2008-7-17 16:00:00
当然用户不可能一直开着OD,我们可以编写一个程序HOOK掉FindWindowA,一旦发现OLLYDBG就总返回不为0的数字,使得病毒认为自己被调试从而主动退出。
HWND _stdcall Hook_FindWindowA(char* pClassName, char* pTitle)
{
if(lstrcmpiA(pClassName, "OllyDbg") == 0)
return 0x12345678; // 随便一点,返回一个不为0的数据
else
return Real_FindWindowA(pClassName, pTitle);
}
或者直接创建一个类名为"OLLYDBG"的窗口也行。
超级游戏迷 - 2008-7-17 17:33:00
现在暂时看不懂,纯支持一下:default5:
awen31 - 2008-7-17 17:51:00
能不能,将上述的编程写成.bat文件给大家方便下
天月来了 - 2008-7-17 17:53:00
这个得弄个一般用户直观可操作的东西才好。
否则看蒙了都不知道说的什么:default14:
闪电风暴 - 2008-7-17 18:01:00
也想写个免疫程序
aaccbbdd - 2008-7-17 18:15:00
Lz高手
闪电风暴 - 2008-7-17 18:18:00
原来没有那么复杂。由于这个病毒查TrainerSpy XP + NT / 2000 / XP + Coded By BofeN的窗口是根据窗口名而不是类名判断的,所以直接创建一个窗口名为TrainerSpy XP + NT / 2000 / XP + Coded By BofeN的工程就行了。
不需要自己写一行源代码,打开VC,利用VC的向导生成一个MFC EXE,打开对话框资源将标题改为“TrainerSpy XP + NT / 2000 / XP + Coded By BofeN”(不包括引号)就行了。
下载:
附件: MyStopIt.rar (2008-7-17 18:17:58, 90.21 K)
该附件被下载次数 233
闪电风暴 - 2008-7-17 18:22:00
在运行了MyStopIt之后再运行病毒文件 .exe,那东西就会自杀
networkedition - 2008-7-18 8:37:00
对已经感染该病毒是否有效???
闪电风暴 - 2008-7-18 9:26:00
如果已经感染,那么运行MyStopIt后用其它工具结束掉病毒进程它就不会起来了。。。
闪电风暴 - 2008-7-18 9:28:00
瑞星现在 还不报毒。
这个东西的行为和熊猫烧香是一致的,开启后都要在drivers目录下创建一文件,然后用那个文件启动。
可见瑞星的启发特征提得不是很恰当。
炫Oo逍遥oO - 2008-7-18 13:29:00
得到地址后就CALL,检测调试器,被OD插件做掉
什么意思? 啥插件:default3:
btw:脱UPX貌似没什么难度的啊.. 变异?..
偶查壳一般用PE Detective:default3:
闪电风暴 - 2008-7-18 15:25:00
OD的中文汉化版中有一些插件可以防止OD被被调试程序发现。比如屏蔽IsDebuggerPresent等等。
这个不是标准的UPX壳,标准的UPX应该不会有太多的反调试功能。
这个壳经过修改,既然PEID无法认出,可能瑞星也没有正确认出,所以无法脱壳。因此里面的熊猫也就没事了。
闪电风暴 - 2008-7-18 17:15:00
瑞星最新的病毒库可以查杀此病毒了。
轩辕小聪 - 2008-7-25 21:15:00
搜索闪电的文章,发现这篇我没看过,虽然那壳我也已经看过,得出同样的结论:default6:
其实应该说是两层壳,外层这一层完全属于anti-debug,里面是一层UPX。
的确只要装有SOFTICE或开着OllyDbg的,病毒程序就跑不起来。
驱动虽说都是科普技术,但至少是全在Ring0完成还原SSDT的操作呀,不需要和Ring3程序通信,不需要Ring3程序用遍历重定位表的方式来找SSDT偏移,相对于磁碟机的形式,还是方便一些的。
当然驱动非常简单,我在IDA里把代码逆向一下,用Kmdkit编译成功:default6:
注意,这个go.sys只还原SSDT(不要怀疑,就那么点代码,我把它每一行都弄清楚了),并没有穿还原,所以有人说这是第 四 代机器狗,完全是想当然,没有的事。
轩辕小聪 - 2008-7-25 21:23:00
又看了一眼楼主帖,肯定闪电不常看Delphi写的程序:default6:
004277C8 55 push ebp
004277C9 8BEC mov ebp, esp
004277CB 83C4 F0 add esp, -10
004277CE B8 A8764200 mov eax, 004276A8
004277D3 E8 ECEDFDFF call 004065C4
004277D8 E8 2FFDFFFF call 0042750C
这里其实已经是OEP了,这就是Delphi写的程序的入口点形式。
在004277C8处dump出来,用PEID就知道是Borland Delphi 6.0 - 7.0了
要是在下面才dump,那Delphi的初始化代码都过去了,当然什么都找不到:default6:
轩辕小聪 - 2008-7-25 21:31:00
另外如果不知道这程序是啥语言写的,你基本没法分析得清楚。
004275C1 E8 125CFFFF CALL NewVirus.0041D1D8
004275C6 E8 4DFEFFFF CALL NewVirus.00427418
004275CB E8 28FFFFFF CALL NewVirus.004274F8
这几个procedure才是这个东东的主要行为所在。
因为这程序是Delphi写的,使用大量的Delphi的函数,以及一些VCL的类(如遍历文件时使用Delphi的FileFirst/FileNext,使用TSearchRec类)。
如果在IDA里不加载上Delphi的sig文件的话,看这些函数绝对看得吐血。比如遍历文件部分,最好从Delphi中得到TSearchRec的结构,自己加到Structures中,然后使用IDA的相应功能,这样对该部分的分析才能真正搞清楚。
闪电风暴 - 2008-7-26 15:05:00
004277C8 55 push ebp
004277C9 8BEC mov ebp, esp
004277CB 83C4 F0 add esp, -10
我记得网上有文章说add esp,一个负数是delphi的特征。但是在那个push ebp上脱壳PEID仍然认不出
闪电风暴 - 2008-7-26 15:10:00
其实SSDT已经没有什么意思了,现在的危险已经倒置:HOOK SSDT的全部都是杀毒软件,恢复SSDT的几乎都是病毒。
1
© 2000 - 2026 Rising Corp. Ltd.