【问题标题】:How can I get a function entry point?如何获得函数入口点?
【发布时间】:2012-01-11 10:59:18
【问题描述】:

我使用 CreateProcess() 在我的进程中创建了一个子进程并挂起该子进程。可以在子进程的内存中获取主入口点,但是如何获取子进程的函数入口点呢?

这就是我如何获得子进程的主要入口点

DWORD FindEntryPointAddress( TCHAR *exeFile )
{
  BY_HANDLE_FILE_INFORMATION bhfi;
  HANDLE hMapping;
  char *lpBase;

  HANDLE hFile = CreateFile(exeFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

  if (hFile == INVALID_HANDLE_VALUE)
    ;

  if (!GetFileInformationByHandle(hFile, &bhfi))
    ;

  hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, bhfi.nFileSizeHigh, bhfi.nFileSizeLow, NULL);

  if (!hMapping)
    ;

  lpBase = (char *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, bhfi.nFileSizeLow);

  if (!lpBase)
    ;

  PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpBase;

  if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
    ;

  PIMAGE_NT_HEADERS32 ntHeader = (PIMAGE_NT_HEADERS32)(lpBase + dosHeader->e_lfanew);

  if (ntHeader->Signature != IMAGE_NT_SIGNATURE)
    ;

  DWORD pEntryPoint = ntHeader->OptionalHeader.ImageBase + ntHeader->OptionalHeader.AddressOfEntryPoint;

  UnmapViewOfFile((LPCVOID)lpBase);

  CloseHandle(hMapping);

  CloseHandle(hFile);

  printf( "test.exe entry point: %p\n", pEntryPoint );

  return pEntryPoint;
} // FindEntryPointAddress()

我的目的是如果我没有子进程源代码,我只有子进程.exe文件,我可以得到子进程的函数入口点吗?

这样的子进程

void foo()
{
  char str[10];
  strcpy( str, "buffer\n" );
} // foo()

int main()
{
  foo();
  return 0;
} // main()

【问题讨论】:

  • 我从来没有听说过函数的入口点,据我所知,main 本身就是程序的入口点。如果有这样的事情,我真的很高兴知道!
  • 如果它与main不在同一个源文件中,那么它可能在与主源文件一起编译的另一个源文件中。或者它在一个库中,在这种情况下您需要查找该库。
  • 你的意思是&foo,相当于foo?
  • 欢迎来到 SO。在我看来,您的问题在词汇上存在问题。您能否更详细地描述您要实现的目标?我认为您应该能够相应地“编辑”您的问题。

标签: c


【解决方案1】:

对于一个函数,没有什么叫做entry point。如果你想了解函数被调用时的执行流程,可以写一些printf()语句如下:

#include <stdio.h>

void foo(void)
{
    printf("Entering %s:%s:%d\n", __FILE__, __func__, __LINE__);
    return;
}

int main(void)
{  
    printf("Entering %s:%s:%d\n", __FILE__, __func__, __LINE__);
    foo();
    return 0;
}

或者你可以使用gdb并在每个函数的开头设置breakpoints来查看执行流程!

【讨论】:

    【解决方案2】:

    按照 Sangeeth Saravanaraj 的建议,使用 gdbbreakpoints 实际上是最好的方法,但如果您打算使用运行时解决方案并希望在每个文件中不断复制和粘贴相同的 printf 语句您想跟踪的功能,您可以使用 (可能是危险的) 宏。

    #include <stdio.h>
    
    #define trace_func(_func) printf("Entering %s:%s:%d\n", __FILE__, __func__, __LINE__); _func
    
    void fooAgain(int myValue)
    {
        printf("This is fooAgain, with my value: %d.\n", myValue);
    }
    
    void foo(void)
    {
        printf("Hello, I'm foo.\n");
        trace_func(fooAgain(15));
    }
    
    int main(int argc, char** argv)
    {
        trace_func(foo());
        return 0;
    }
    

    返回:

    Entering *yourfilepath*/main.c:main:18
    Hello, I'm foo.
    Entering *yourfilepath*/main.c:foo:13
    This is fooAgain, with my value: 15
    

    如果您想成为一个糟糕的人,并且即使在为发布而构建时也能够保留代码,您可以这样做(但不要这样做,这是一种可怕的做法并且是错误的。我将其包括在内是为了完成)。

    将定义语句更改为:

    #define TRACE_FUNCTIONS
    
    #ifdef TRACE_FUNCTIONS
        #define trace_func(_func) printf("Entering %s:%s:%d\n", __FILE__, __func__, __LINE__); _func
    #else
        #define trace_func(_func) _func
    #endif
    

    【讨论】:

    • 对不起,我没有解释清楚。如果我有一个进程A,我使用API​​CreateProcess()创建和挂起进程B,我可以从B的内存空间中找到主函数入口点,但是我应该如何找到函数foo()的入口点呢?跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多