注释PEMaker6源代码(三)

转载 2007年09月26日 09:10:00
今天大概看了一下精华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;
    }
}
//----------------------------------------------------------------
 

xv6分析--mkfs源代码注释

xv6中mkfs.c的作用是构建一个跟文件系统镜像,添加用户指定的文件到这个镜像, 本人水平有限,分析难免有错,各位大神指正,分析如下: #include #include #include ...
  • Mumu3w
  • Mumu3w
  • 2017年01月07日 13:46
  • 551

javaWeb服务详解(含源代码,测试通过,注释) ——Emp的Dao层

IEmpDao的接口 /** * @Title: IEmpDao.java * @Package org.dao * @Description: TODO该方法的主要作用: * @author...

严蔚敏 数据结构 课本中 栈应用 走迷宫 C语言 完整版 源代码和注释 可直接执行

#include #include #include #define STACK_INIT_SIZE 100 #define INCREMENT 10 /* typedef ...

Java毕业设计之简单易懂计算器+源代码+注释

Java毕业设计之简单易懂计算器+源代码+注释

利用专有命名空间实现单一实例源代码注释

要实现单一实例有三种 一种是对象句柄继承 一种是专有命名  另外一种是复制对象句柄今天来看看专有命名空间 void CheckInstances() { // 创建边界描述符...

libsvm源代码注释+算法描述:svm_train

(I will try my best to make this note clearer.)We mainly focus on solve_c_svc in this note.Our goal:...

Java项目导出源代码jar包在Eclipse中查看中文注释乱码的问题

Java项目导出源代码jar包在Eclipse中查看中文注释乱码的问题由于项目比较多,全部添加到Maven主项目中的话虽然更新调试方便,但项目多了严重影响Eclipse的速度,所以将一部分项目单独导出...

《C#程序设计》第一次作业 给定一个源代码文件(.cs, ),输出该文件的代码行数、注释行数、空行数、代码总行数、。

foreach该程序可以查看指定目录下的 “.cs”类型文件的代码行数、注释行数、空行数、代码总行数。using System; using System.IO; namespace C...
  • Ajixk
  • Ajixk
  • 2015年04月10日 16:57
  • 658

背景建模之:贝叶斯背景建模——cvbgfg_acmmm2003 源代码注释(一)

前面的模型定义还有参数的变量定义可以参考源文件background_segm.hpp 里面英文注释已经说得很清楚了 我就不再写了 这里只写文件cvbgfg_acmmm2003 论文是Foregrou...

javaWeb服务详解(含源代码,测试通过,注释) ——Emp的Service层

IEmpService的接口 /** * @Title: IEmpService.java * @Package org.service * @Description: TODO该方法的主要作...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:注释PEMaker6源代码(三)
举报原因:
原因补充:

(最多只允许输入30个字)