以前从没听说过这个东西,这是在做HOOK API时知道的概念,书上有个例子,通过PE文件,找到了程序所有的导入函数名和地址,但自己不是很懂,能帮忙描述下PE文件吗,最好推荐本书,上面对PE文件介绍的比较详细,因为我手上这本书支PE文件的描述就几句话,我想知道关于PE文件的更多的知识..
 谢谢!!

解决方案 »

  1.   

    网上搜一下,资料很多。随便给你找了一个:
    http://www.pediy.com/tutorial/chap8/Chap8-1-7.htm
      

  2.   

    这个更全更细
    http://www.codesky.net/showhtml/4178.htm
      

  3.   

    买kanxue的加密与解密第三版了,里面pe讲得很详细了,几十页,够你看了
      

  4.   

    不是很懂~
    up up
    study study
      

  5.   

    PE现在已经不是啥秘密的东东了,网上资料、代码一大把。早期的系统介绍应该是在《win95系统揭秘》里。
      

  6.   

    http://www.du110.com/viewthread.php?tid=4543&extra=page%3D1
      

  7.   

    up!!
    anyone who can introduce the personal view about the "PE" ??
      

  8.   

    PE文件就是可执行的win32程序文件,从Windows 95之后才有的,文件中有一个PE头,是MS规定结构,记录程序的各种信息。既然是规定的,也就没什么“personal view”好introduce的。
      

  9.   

    <<windows应用程序捆绑 核心编程》张正秋编写
    第2章
      

  10.   

    MSDN中就有,一种可执行文件格式,没有个人看法。使用ImageHlp API函数可以方便解析。
      

  11.   

    在《windows图形编程》这本书里面有详细介绍。你可以上网下载个电子版看一下,比较详细。
      

  12.   

    谢谢各位的热心回答,现在我有点明白PE是什么东西了,下面是我写的一小段代码,HOOK windows 的MessageBox函数,
    自己写了个代理函数,
    void __stdcall MyMessage(HWND hWnd , LPCSTR lpText, LPCSTR lpCaption, UINT uType)
    但是,如果我去掉 __stdcall 把这个代理函数声明为
    void MyMessage(HWND hWnd , LPCSTR lpText, LPCSTR lpCaption, UINT uType)
    就会在运行时出错,下面是源码,程序没问题,我想知道的是为什么加了 "__stdcall",程序就没问题// Test3.cpp : Defines the entry point for the console application.
    //#include "stdafx.h"
    #include <windows.h>
    #include <imagehlp.h>
    #include <iostream>
    using namespace std;
    #pragma comment(lib, "ImageHlp")//HOOK API
    void SetHook();
    //代理函数
    //如果把 __stdcall 去掉 改成下面形式就会出错
    //void  MyMessage(HWND hWnd , LPCSTR lpText, LPCSTR lpCaption, UINT uType);void __stdcall MyMessage(HWND hWnd , LPCSTR lpText, LPCSTR lpCaption, UINT uType);HMODULE g_hMod;int main(int argc, char* argv[])
    {
    //应用程序句柄
    g_hMod = GetModuleHandle(NULL);
    //调用系统的函数MessageBox
    MessageBox(NULL, "Hello World!", "", MB_OK);
    //HOOK API
    SetHook();
    //再次调用MessageBox
    MessageBox(NULL, "Hello World!", "", MB_OK);
    system("pause");
    return 0;
    }//代理函数,去掉__stdcall,就出现错误
    //void  MyMessage(HWND hWnd , LPCSTR lpText, LPCSTR lpCaption, UINT uType)
    void __stdcall MyMessage(HWND hWnd , LPCSTR lpText, LPCSTR lpCaption, UINT uType)
    {
    printf("Hello World!\n");
    }void SetHook()
    {
    //得到导入表的头指针
    IMAGE_IMPORT_DESCRIPTOR* pImportDes ;
    DWORD dwSize;
    pImportDes = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToData(g_hMod,
    TRUE,
    IMAGE_DIRECTORY_ENTRY_IMPORT,
    &dwSize);
    //得到模块 USER32.dll
    while (pImportDes->FirstThunk)
    {
    //得到模块名称
    char* pszDllName = (char*)((BYTE*)g_hMod + pImportDes->Name);
    if (strcmp(pszDllName, "USER32.dll") == 0)
    {
    break;
    }
    pImportDes++;
    }
    //在USER32.dll模块中,找到函数MessageBoxA
    IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)((BYTE*)g_hMod + pImportDes->OriginalFirstThunk);
    while (pThunk->u1.Function)
    {
    //函数名
    char* pszFuncName = (char*)((BYTE*)g_hMod + (DWORD)pThunk->u1.AddressOfData + 2);
    if (strcmp(pszFuncName, "MessageBoxA") == 0)
    {
    break;
    }
    pThunk++;
    }
    //修改导入地址表, 使导入地址表中MessageBoxA的地址指向代理函数的地址 
    DWORD* pszFuncAddr = (DWORD*)((BYTE*)g_hMod + pImportDes->FirstThunk );
    DWORD* MyFuncAddr = (DWORD*)MyMessage;
    WriteProcessMemory(GetCurrentProcess(), pszFuncAddr, &MyFuncAddr, sizeof(DWORD), NULL);
    }
      

  13.   

    __stdcall指的函数调用方式,具体是函数调用完由谁来平栈的约定Window的API都是__stdcall方式调用。
      

  14.   

    一般常看到的calling convention有三种类型:Pascal convention:参数传递次序由左而右,由被调用者平栈__cdecl  convention:参数传递次序由右而左,由调用者平栈__stdcall convention : 参数传递次序由右而左,由被调用者平栈VC编译在不指明调用方式时默认为__cdecl,你把__stdcall的函数替换为__cdecl方式导致栈不平而崩溃
      

  15.   

    运行时得到如下错误信息:   
      The   value   of   ESP   was   not   properly   saved   across   a   function   call.     This   is   usually   a   result   of   calling   a   function   declared   with   one   calling   convention   with   a   function   pointer   declared   with   a   different   calling   convention.  
     网上有人说是 调用约定申明不一致 是不是以后要HOOK windows API,在声明代理函数时,都要写成__stdcall形式??
      

  16.   

    调用约定、参数传递约定、调用协议都是calling convention,相同的意思。
    在做Hook时,要根据被Hook的函数的原型来定义Hook函数。(目前Windows API都是WINAPI类型,也就是__stdcall)
      

  17.   

    Thank you !!
    Get It..