在内存中访问并从光盘加载的“.text”部分因GCC编译应用程序而异

时间:2013-06-13 19:53:23

标签: gcc mingw executable visual-c++ compiler-specific

使用以下代码访问'.text'部分的内容:

1)对于加载到内存中的应用程序(即执行):

//accessing code in memory
        PIMAGE_DOS_HEADER pDOSHeader = NULL;
        pDOSHeader = static_cast<PIMAGE_DOS_HEADER>( (void*)hModule);
        ...

        PIMAGE_NT_HEADERS pNTHeader = reinterpret_cast<PIMAGE_NT_HEADERS>((byte*)hModule + pDOSHeader->e_lfanew );
        ...
        PIMAGE_FILE_HEADER pFileHeader = reinterpret_cast<PIMAGE_FILE_HEADER>((byte*)&pNTHeader->FileHeader );
        ...
          PIMAGE_OPTIONAL_HEADER pOptionalHeader = 
            reinterpret_cast<PIMAGE_OPTIONAL_HEADER>((byte*)&pNTHeader->OptionalHeader );
        ...
            PIMAGE_SECTION_HEADER pSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(
            (byte*)&pNTHeader->OptionalHeader +
            pNTHeader->FileHeader.SizeOfOptionalHeader );

        //so iterate headers and select one with right name
        const char TEXT[] = ".text";
        const char BSSTEXT[] = ".textbss";
        unsigned int nSectionCount = pNTHeader->FileHeader.NumberOfSections;
        char szSectionName[ IMAGE_SIZEOF_SHORT_NAME + 1 ];
        szSectionName[ IMAGE_SIZEOF_SHORT_NAME ] = '\0';
        for( unsigned int i = 0; i < nSectionCount; i++ )
        {
            memcpy( szSectionName, pSectionHeader->Name,
                    IMAGE_SIZEOF_SHORT_NAME );

            if( 0 == strncmp( TEXT, szSectionName,
                              IMAGE_SIZEOF_SHORT_NAME ) )
            {
                break;
            }
            pSectionHeader++;
        }

        pVirtualAddress = (void*)(pSectionHeader->VirtualAddress);
        dwCodeSize = pSectionHeader->Misc.VirtualSize;

        //seems resonable: To calculate the real starting address of a given section in memory, 
        //add the base address of the image to the section's VirtualAddress stored in this field.
        pCodeStart = (void*)(((byte*)hModule) +(size_t)((byte*)pVirtualAddress) );
        pCodeEnd = (void*)((byte*)pCodeStart + dwCodeSize); 

2)对于从hdd读取并映射到内存的应用程序文件:

 //loading code from file and mapping 
      hFile = CreateFile( filename, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
      ...        
      hFileMapping = CreateFileMapping( hFile, NULL, PAGE_READONLY ),0, 0, NULL );
      ...
      pBaseAddress = MapViewOfFile( hFileMapping, FILE_MAP_READ, 0, 0, 0 );
      ...
      PIMAGE_DOS_HEADER pDOSHeader = static_cast<PIMAGE_DOS_HEADER>( pBaseAddress);
      ...
      PIMAGE_NT_HEADERS pNTHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(
            (PBYTE)_pBaseAddress() + pDOSHeader->e_lfanew );
      ...       
      PIMAGE_FILE_HEADER pFileHeader = reinterpret_cast<PIMAGE_FILE_HEADER>(
            (PBYTE)&pNTHeader->FileHeader );
      ...
          PIMAGE_OPTIONAL_HEADER pOptionalHeader = 
            reinterpret_cast<PIMAGE_OPTIONAL_HEADER>(
            (PBYTE)&pNTHeader->OptionalHeader );

      PIMAGE_SECTION_HEADER pSectionHeader = 
            reinterpret_cast<PIMAGE_SECTION_HEADER>(
            (PBYTE)&pNTHeader->OptionalHeader +
            pNTHeader->FileHeader.SizeOfOptionalHeader );


      DWORD dwEntryPoint = pNTHeader->OptionalHeader.AddressOfEntryPoint;
      UINT nSectionCount = pNTHeader->FileHeader.NumberOfSections;

      const char TEXT[] = ".text";
      const char BSSTEXT[] = ".textbss";
      char szSectionName[ IMAGE_SIZEOF_SHORT_NAME + 1 ];
      szSectionName[ IMAGE_SIZEOF_SHORT_NAME ] = '\0';
      for( unsigned int i = 0; i < nSectionCount; i++ )
      {
           memcpy( szSectionName, pSectionHeader->Name,
                   IMAGE_SIZEOF_SHORT_NAME );

           if( 0 == strncmp( TEXT, szSectionName,
                             IMAGE_SIZEOF_SHORT_NAME ) )
            {
                break;
            }
            pSectionHeader++;
       }

       // Use this when probing On Disk. It is where things
       //   are on disk - not where they will be in memory            
       dwRawData = pSectionHeader->PointerToRawData;

       // Use this when probing On Disk. It is where things
       //   are on disk - not where they will be in memory
       pCodeStart = (void*)((byte*)pBaseAddress +
           pSectionHeader->PointerToRawData );


       pEntryPoint = (void*)(((byte*)pBaseAddress) + dwEntryPoint);

       dwCodeSize = pSectionHeader->Misc.VirtualSize;
       pCodeEnd = (void*)((byte*)pCodeStart + pSectionHeader->Misc.VirtualSize );

如果应用程序是使用Visual Studio构建的,则pCodeStart和pCodeEnd之间的所有字节在两种情况下都是匹配的。

但是如果应用程序是用GCC(MinGW)构建的,那么跟随pCodeStart和之前的pCodeEnd的一些字节是相同的,但在中间的某个地方会出现一些不同的字节。

为什么会这样?

0 个答案:

没有答案