注释PEMaker6源代码(三)

来源:互联网 发布:linux samba 用户管理 编辑:程序博客网 时间:2024/05/16 10:46
今天大概看了一下精华8《向PE中注入代码》的译文,之前没有仔细看过,因为发现看过之后对源代码还是不是很明白,所以就没有参照这篇译文进行注释,大多都是自己理解+网上搜索,今天发现很多地方有失误。 
大框的地方一定要参照译文,不要被我蒙蔽了。 
继续注释CPECryptor类,如下:
//在pecrypt.cpp里,我提供了另外一个类――CPECryptor,用它组建新区段的数据。
//然而,新区段的数据是被loader.cpp里的DynLoader()(在DynLoader Step 1中介绍的)创建的。
//因此,我们用CPECryptor类把这些数据(也有其它的数据)输入新区段。
//看完这段翻译基本没懂
const char *szWindowsAPIs[]=
{
    "Kernel32.dll",
    "GetModuleHandleA",
    "VirtualProtect",
    "GetModuleFileNameA",
    "CreateFileA",
    "GlobalAlloc",
    "VirtualAlloc",
    "LoadLibraryA",
    "GetProcAddress",
    0,
    "User32.dll",
    "MessageBoxA",
    0,
    0,
};
//================================================================
//----------------------------------------------------------------
// Function: ReturnToBytePtr
// void* FuncNum:   Function Name
// DWORD findstr:   String to find
// This code was written by FEUERRADER [AHTeam], Thanks him!
//在loader.cpp文件中的DynLoader函数里寻找指定字符串,并返回其地址
void* CPECryptor::ReturnToBytePtr(void* FuncName, DWORD findstr)
{
    void* tmpd;
    __asm
    {
        mov eax, FuncName
        jmp df
hjg:    inc eax
df:        mov ebx, [eax]
        cmp ebx, findstr
        jnz hjg
        mov tmpd, eax
    }
    return tmpd;
}
//================================================================
//此函数构建新节及导入表----------------------------------------------------------------
void CPECryptor::CryptFile(int(__cdecl *progress) (unsigned intunsigned int))
{
    PCHAR ch_temp;
    PIMAGE_SECTION_HEADER pimage_section_header;
    DWORD dwNewSectionSize;
    DWORD dwCodeSize;
    DWORD dwCodeOffset;
    //进度条控件----------------------------------------
    progress(0,0);
    //是否DLL
    if((image_nt_headers->FileHeader.Characteristics&IMAGE_FILE_DLL)==IMAGE_FILE_DLL)
    {
        //构造CITMaker类
        ImportTableMaker = new CITMaker(IMPORT_TABLE_OCX);
    }
    else
    {
        ImportTableMaker = new CITMaker(IMPORT_TABLE_EXE);
    }
    //----------------------------------------
    //========================================
    //ch_temp指向DYN_LOADER_START_MAGIC之后的地址
    ch_temp=(PCHAR)DWORD(ReturnToBytePtr(DynLoader, DYN_LOADER_START_MAGIC))+4;
    //计算DynLoader函数代码长度
    dwCodeSize=DWORD(ReturnToBytePtr(DynLoader, DYN_LOADER_END_MAGIC))-DWORD(ch_temp);
    //自定义导入表大小
    dwCodeOffset = ImportTableMaker->dwSize;
    //新节大小=DynLoader函数代码长度+自定义导入表大小
    dwNewSectionSize = dwCodeSize + ImportTableMaker->dwSize;
    //分配空间
    pNewSection=new TCHAR[dwNewSectionSize];
    //复制DynLoader函数代码到偏移dwCodeOffset的位置之后
    memcpy(pNewSection+dwCodeOffset, ch_temp, dwCodeSize);
    //========================================
    //----------------------------------------
    //添加新节,并返回新节指针
    pimage_section_header=AddNewSection(".xxx",dwNewSectionSize);
    //----------------------------------------
    //========================================
    //参数为新节在内存的偏移地址
    CopyData1(pimage_section_header->VirtualAddress);
    //参数同上,构建自定义导入表
    ImportTableMaker->Build(pimage_section_header->VirtualAddress);// build import table by the current virtual address
    //构建的导入表在新节数据前,注意相互位置
    memcpy(pNewSection, ImportTableMaker->pMem, ImportTableMaker->dwSize);
    //========================================
    //将新节数据复制到image_section(已经初始化)----------------------------------------
    memcpy(image_section[image_nt_headers->FileHeader.NumberOfSections-1],
           pNewSection,
           dwNewSectionSize);
    //入口地址更改为新节的DynLoader函数代码处
    image_nt_headers->OptionalHeader.AddressOfEntryPoint=pimage_section_header->VirtualAddress + dwCodeOffset;
    //导入表地址更改为新导入表地址
    image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress=pimage_section_header->VirtualAddress;
    image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size=ImportTableMaker->dwSize;
    image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress=0;
    image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size=0;
    SetSectionsWritePermission();
    //----------------------------------------
    delete []pNewSection;
    delete ImportTableMaker;
    //----------------------------------------
    progress(100,0);
}
//这个结构对应DynLoader函数里DYN_LOADER_START_DATA1标志后面的东西,具体
//是自定义结构?请高手指点,本人水平到此,分析不出了
//译文:为了找到OEP的virtual address,我们立即保存原始的OEP和Image Base。
//我在DynLoader()的尾部预留了一块空地来保存它们
typedef struct
{
    //保留
    DWORD dwReserved1;
    //文件类型
    DWORD dwFileType;
    //基地址
    DWORD dwImageBase;
    //原始入口点
    DWORD dwOrgEntryPoint;
    //导入表虚拟地址
    DWORD dwImportVirtualAddress;
    //重定位表虚拟地址及大小
    DWORD dwRelocationVirtualAddress;
    DWORD dwRelocationSize;
    //TLS
    IMAGE_TLS_DIRECTORY32 image_tls_directory;
}t_DATA_1,*pt_DATA_1;
//此函数将实际数据填充到DynLoader函数指定位置里
void CPECryptor::CopyData1(DWORD dwVirtualAddress)
{
    int i, API_num;
    PCHAR pData1;
    DWORD dwOffset;
    size_t l;
    UCHAR temp;
    //为结构分配内存
    pt_DATA_1 pDataTable=new(t_DATA_1);
    //----------------------------------------
    //保留,0xcccccccc应该没有意义
    pDataTable->dwReserved1=0xCCCCCCCC;
    //如果为DLL,填入文件类型
    if((image_nt_headers->FileHeader.Characteristics&IMAGE_FILE_DLL)==IMAGE_FILE_DLL)
        pDataTable->dwFileType=IMPORT_TABLE_OCX;
    else
        pDataTable->dwFileType=IMPORT_TABLE_EXE;
    //填充镜像首地址
    pDataTable->dwImageBase=image_nt_headers->OptionalHeader.ImageBase;
    //填充入口点
    pDataTable->dwOrgEntryPoint=image_nt_headers->OptionalHeader.AddressOfEntryPoint;
    //填充导入表地址(RVA)
    pDataTable->dwImportVirtualAddress=image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    if((image_nt_headers->FileHeader.Characteristics&IMAGE_FILE_DLL)==IMAGE_FILE_DLL)
    {
        //如果是DLL,填充重定位表
        pDataTable->dwRelocationVirtualAddress=image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
        pDataTable->dwRelocationSize=image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
    }
    //前面已经将DynLoader函数读入我们申请的内存中----------------------------------------
    //故在pNewSection指向的内存中找到DYN_LOADER_START_DATA1标志,返回地址
    pData1=(PCHAR)ReturnToBytePtr(pNewSection, DYN_LOADER_START_DATA1);
    //看了好几个TLS了,是什么?
    //通过使用线程本地储存(TLS),一个程序能够执行多线程程序,
    //这样子的程序大多数是用Borland链接器:Delphi和C++, Builder. 
    //当你包装一个PE文件时,你应该小心的清空TLS,
    //否则,你的打包器就不支持Borland Delphi 和 C++ Builder链接的EXE文件。
    //修正可选头部TLS目录入口是很有必要的。
    if(image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress!=0)
    {
        //image_tls_directory定义在pelib.cpp中
        memcpy(&pDataTable->image_tls_directory,
                image_tls_directory,
                sizeof(IMAGE_TLS_DIRECTORY32));
        dwOffset=DWORD(pData1)-DWORD(pNewSection);
        //计算偏移
        dwOffset+=sizeof(t_DATA_1)-sizeof(IMAGE_TLS_DIRECTORY32);
        //更新文件头,指向新的TLS表
        //传递的参数在这里应用
        image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress=dwVirtualAddress + dwOffset;
    }
    //替换为实际数值----------------------------------------
    memcpy(pData1,pDataTable,sizeof(t_DATA_1));
    dwOffset=sizeof(t_DATA_1);
    i=API_num=0;
    temp=0;
    //循环填充实际数值
    do
    {
        l=strlen(szWindowsAPIs[i])+1;
        //复制动态库名
        memcpy(pData1+dwOffset,szWindowsAPIs[i],l);
        //偏移长度
        dwOffset+=l;
        do
        {
            i++;
            if(szWindowsAPIs[i]!=0)
            {
                //复制下一个函数名
                l=strlen(szWindowsAPIs[i])+1;
                memcpy(pData1+dwOffset,szWindowsAPIs[i],l);
                dwOffset+=l;
                //API数量
                API_num++;
            }
            else
            {
                //放置0
                CopyMemory(pData1+dwOffset,&temp,1);
                dwOffset++;
            }
        }while(szWindowsAPIs[i]!=0);
        i++;
    }
    while(szWindowsAPIs[i]!=0);
    //----------------------------------------
    delete pDataTable;
}
//----------------------------------------------------------------
void CPECryptor::SetSectionsWritePermission()
{
    for(int i=0;i<image_nt_headers->FileHeader.NumberOfSections;i++)
    {
        //设置所有表的标志
        image_section_header[i]->Characteristics=0xC0000040;
    }
}
//----------------------------------------------------------------
 
原创粉丝点击