PE解析到区段表

// PE001.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<windows.h>
#include<time.h>


//函数声明,转换文件偏移量
DWORD CalcOffect(DWORD Rva);



int _tmain(int argc, _TCHAR* argv[])
{

    //删除文件
    //DeleteFile(TEXT("D:\\Test.txt"));
    //拷贝文件,同时也可以改名字
    //CopyFile(TEXT("D:\\Test.txt"), TEXT("D:\\123\\Testhehe.txt"),TRUE);
    //移动文件,同时也可以改名字
    //MoveFile(TEXT("D:\\Test.txt"), TEXT("D:\\123\\Testheihei.txt"));

    //设置文件指针,这个函数需要注意一下。
    //SetFilePointer()

    //得到文件的句柄
    HANDLE hFile = CreateFile(
        TEXT("D:\\5.exe"),
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL
        );
    //获得文件大小
    DWORD dwFileSize = GetFileSize(hFile, NULL);
    char *pFile = new char[dwFileSize];
    DWORD dwRubbish = 0;
    //将文件内容读取到开辟的空间中
    ReadFile(hFile, pFile, dwFileSize, &dwRubbish, NULL);
    if (((PIMAGE_DOS_HEADER)pFile)->e_magic != IMAGE_DOS_SIGNATURE)
    {
        //不是DOS头,返回
        return -1;
    }
    //将文件偏移值取出,保存
    DWORD dwNewPos = (DWORD)pFile + ((PIMAGE_DOS_HEADER)pFile)->e_lfanew;
    //将地址转换为NT头指针
    PIMAGE_NT_HEADERS32 pNTHeader = (PIMAGE_NT_HEADERS32)(dwNewPos);
    if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
    {
        //不是NT头,说明不是PE文件,返回
        return -1;
    }
    //取出NT头文件中成员
    PIMAGE_FILE_HEADER         pFileHeader = &(pNTHeader->FileHeader);
    
    //打印出头文件中结构体成员
    printf("文件运行平台:    %x\n", pFileHeader->Machine);
    printf("区段的数量:      %x\n", pFileHeader->NumberOfSections);
    printf("文件创建时间:    %x\n", pFileHeader->TimeDateStamp);
    printf("符号表偏移:      %x\n", pFileHeader->PointerToSymbolTable);
    printf("符号个数:        %x\n", pFileHeader->NumberOfSymbols);
    printf("扩展头大小:      %x\n", pFileHeader->SizeOfOptionalHeader);
    printf("PE文件的一些属性:%x\n\n", pFileHeader->Characteristics);
    //转换时间  tm *FIleTime = gmtime((time_t *)pFileHeader->TimeDateStamp);
    //扩展头信息打印
    PIMAGE_OPTIONAL_HEADER32   pOptionalHeader = &(pNTHeader->OptionalHeader);
    printf("魔数:                       %x\n", pOptionalHeader->Magic);
    printf("所有代码区段的总大小:       %x\n", pOptionalHeader->SizeOfCode);
    printf("已初始化数据总大小:         %x\n", pOptionalHeader->SizeOfInitializedData);
    printf("未初始化数据总大小:         %x\n", pOptionalHeader->SizeOfUninitializedData);
    printf("程序开始执行的相对虚拟地址: %x\n", pOptionalHeader->AddressOfEntryPoint);
    printf("起始代码的相对虚拟地址:     %x\n", pOptionalHeader->BaseOfCode);
    printf("起始数据的相对虚拟地址:     %x\n", pOptionalHeader->BaseOfData);
    printf("默认加载基址:               %x\n", pOptionalHeader->ImageBase);
    printf("块对齐数:                   %x\n", pOptionalHeader->SectionAlignment);
    printf("文件对齐数:                 %x\n", pOptionalHeader->FileAlignment);
    printf("内存大小:                   %x\n", pOptionalHeader->SizeOfImage);
    printf("文件起始偏移:               %x\n", pOptionalHeader->SizeOfHeaders);
    printf("子系统:                     %x\n", pOptionalHeader->Subsystem);
    printf("特征标志:                   %x\n", pOptionalHeader->DllCharacteristics);
    printf("栈最大值:                   %x\n", pOptionalHeader->SizeOfStackReserve);
    printf("栈初始值:                   %x\n", pOptionalHeader->SizeOfStackCommit);
    printf("堆最大值:                   %x\n", pOptionalHeader->SizeOfHeapReserve);
    printf("堆初始值:                   %x\n", pOptionalHeader->SizeOfHeapCommit);
    printf("数据目录个数:               %x\n", pOptionalHeader->NumberOfRvaAndSizes);

    //读取数据目录表信息

    PIMAGE_DATA_DIRECTORY pDataDirectory = pOptionalHeader->DataDirectory;
    
    //循环读取出数据目录中的相对虚拟地址和大小

    DWORD i = 0;
    while (i != 0x10)
    {
        //显示相对虚拟地址
        printf("第 %d 个相对虚拟地址  %7x", i, pDataDirectory[i].VirtualAddress);
        printf("         大小为:     %7x\n", pDataDirectory[i].Size);
        i++;
    }

    //区段头表

    PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNTHeader);

    //循环输出,区段表信息,可以用两种方式判断结束,一个是文件头给出的区段的数量
    //可以用那个,也可以判断最后一个全零的区段头
    int j = 0;
    while (j<pOptionalHeader->NumberOfRvaAndSizes)
    {
        //输出或者获取每一个pSectionHeader中的成员
        printf("名称:%7x   V0ffset:%7x   VSize:%7x \n  ROffset:%7x   RSize:%7x    标志:%7x\n",
            pSectionHeader->Name,                 //区段名称
            pSectionHeader->VirtualAddress,       //起始的相对虚拟地址
            pSectionHeader->Misc,                 //加载后区段大小
            pSectionHeader->PointerToRawData,     //文件偏移
            pSectionHeader->SizeOfRawData,          //区段大小,文件中
            pSectionHeader->Characteristics          //区段的属性
            
            );
        ++pSectionHeader;
        j++;
    }




    ////计算偏移量
    //DWORD CalcOffect(DWORD Rva)
    //{
    //    //获取NT头
    //    PIMAGE_NT_HEADERS32 pNTHeader = (PIMAGE_NT_HEADERS32)((long)pFile + (PIMAGE_DOS_HEADER)pFile->e_lfanew);
    //    //获取区段头表
    //    PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNTHeader);
    //    //循环比较它在哪个区段中,不在这个区段就继续循环,注意假如
    //    //VirtualAddress比SizeOfRawData大的话,说明大出来的部分是未初始化的数据,所以这里要用SizeOfRawData
    //    while (!(Rva) > pSectionHeader->VirtualAddress&&Rva <
    //        pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData))
    //    {
    //        ++pSectionHeader;
    //        //防止错误的PE文件引发崩溃
    //        if (pSectionHeader->PointerToRawData == 0)
    //            return 0;
    //    }
    //    return Rva - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
    //};
    return 0;

    }

 

posted @ 2016-03-28 15:39  天还是那么蓝  阅读(1115)  评论(0编辑  收藏  举报