首页
社区
课程
招聘
[原创]32位反汇编引擎开发笔记:Step.2_框架搭建
发表于: 2020-10-8 09:22 3663

[原创]32位反汇编引擎开发笔记:Step.2_框架搭建

2020-10-8 09:22
3663

Step.1_引擎大纲

Step.2_框架搭建

Step.3_经典定长指令的解析

Step.4_变长指令复习1

Step.5_变长指令复习2 - 指令前缀

Step.6_引擎核心->函数封装

本节功能实现:

新建一个win32桌面程序空项目,创建入口方法和一个简单的dialog

定义函数GetCodeList用于判断文件格式并返回代码段字节数组首地址

由于不是所有的PE文件都有.text段,不是所有的.text段都存放可执行代码,因此我们无法通过寻找.text段的形式去取

在读取文件数据前要记得通过fseek()将文件光标移至文件首,否则无法读取数据

这篇没啥好说的,开胃菜而已,没什么难度,下一篇开始将要进行引擎的初步开发

 
 
 
 
 
//代码省略
//代码省略
/*
    判断文件格式并获取代码段字节数组
    参数:
        fileName    文件全路径
        pCodeList    用于存放字节的数组的首地址
    返回值:
        读取成功时,返回数组大小
        0    打开文件失败
        1    获取文件大小失败
        2    分配缓冲区失败
        3    读取文件失败
        4    不是PE文件
        5    不是32位PE文件
*/
long int GetCodeList(TCHAR* fileName,char** pCodeList) {
    USES_CONVERSION;    //W2A A2W使用前必须加上此行代码  用于Unicode与Ascii转换
    FILE* file = fopen(W2A(fileName), "rb");
    if (file==NULL)
        return 0;
    fseek(file,0,SEEK_END);
    long int fileSize = ftell(file);
    if (fileSize == 0)
        return 1;
    char* temp = (char*)malloc(fileSize);
    if (temp == NULL)
        return 2;
    memset(temp, 0, fileSize);
      //将文件光标移向开始,否则下面的读取将返回0
  fseek(file,0,SEEK_SET);
    long int ret_fread = fread(temp,1,fileSize,file);
    if (ret_fread == 0)
        return 3;
    //判断PE标志
    if (*((WORD*)(temp)) != 0x5A4D)
        return 4;
    //获取NT头指针
    char* p_NT = temp + *(DWORD*)(temp + 0x3C);
    //判断PE标志
    if (*(WORD*)(p_NT) != 0x4550)
        return 4;
    //获取可选PE头指针
    char* p_OptionalHeader = p_NT + 0x18;
    //判断文件信息
    if (*(WORD*)(p_OptionalHeader) != 0x10B)
        return 5;
    //取OEP
    DWORD oep = *(DWORD*)(p_OptionalHeader + 0x10);
    //取节表首地址
    char* p_SectionDataBegin = p_OptionalHeader + *(WORD*)(p_NT + 0x04 + 0x10);
    //遍历节表,找到OEP所在节,取出该节的数据
    char* p_NowSectionData = p_SectionDataBegin;
    char* retList;
    long int codeSize = 0;
    while (*((DWORD*)(p_NowSectionData + 0x0C)) != 0)
    {
        DWORD VirtualAddress = *((DWORD*)(p_NowSectionData + 0x0C));
        DWORD VirtualSize = *((DWORD*)(p_NowSectionData + 0x08));
        if (oep >= VirtualAddress && oep <= VirtualAddress + VirtualSize)
        {
            DWORD PointerToRawData = *((DWORD*)(p_NowSectionData + 0x14));
            codeSize = VirtualSize;
            retList = (char*)malloc(codeSize);
            if (retList == NULL)
                return 2;
            memcpy(retList,temp + PointerToRawData, codeSize);
            *pCodeList = retList;
            break;
        }
    }
    fclose(file);
    free(temp);
    return codeSize;
}
/*
    判断文件格式并获取代码段字节数组
    参数:
        fileName    文件全路径
        pCodeList    用于存放字节的数组的首地址
    返回值:
        读取成功时,返回数组大小
        0    打开文件失败
        1    获取文件大小失败
        2    分配缓冲区失败
        3    读取文件失败
        4    不是PE文件
        5    不是32位PE文件
*/
long int GetCodeList(TCHAR* fileName,char** pCodeList) {
    USES_CONVERSION;    //W2A A2W使用前必须加上此行代码  用于Unicode与Ascii转换
    FILE* file = fopen(W2A(fileName), "rb");
    if (file==NULL)
        return 0;
    fseek(file,0,SEEK_END);
    long int fileSize = ftell(file);
    if (fileSize == 0)
        return 1;
    char* temp = (char*)malloc(fileSize);
    if (temp == NULL)
        return 2;
    memset(temp, 0, fileSize);
      //将文件光标移向开始,否则下面的读取将返回0
  fseek(file,0,SEEK_SET);
    long int ret_fread = fread(temp,1,fileSize,file);
    if (ret_fread == 0)
        return 3;
    //判断PE标志
    if (*((WORD*)(temp)) != 0x5A4D)
        return 4;

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

最后于 2020-10-13 17:42 被SSH山水画编辑 ,原因:
收藏
免费 2
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//