这是一个很好的例子;。“文本”;对于GCC编译的应用程序,在内存中访问和从光盘加载的节不同

这是一个很好的例子;。“文本”;对于GCC编译的应用程序,在内存中访问和从光盘加载的节不同,gcc,mingw,executable,visual-c++,compiler-specific,Gcc,Mingw,Executable,Visual C++,Compiler Specific,使用如下代码访问“.text”部分的内容: 1) 对于加载到内存中的应用程序(即执行): //访问内存中的代码 PIMAGE_DOS_头pDOSHeader=NULL; pDOSHeader=静态浇铸((空心*)hModule); ... PIMAGE\u NT\u HEADERS pNTHeader=reinterpret\u cast((字节*)hModule+pDOSHeader->e\u lfanew); ... PIMAGE\u FILE\u HEADER pFileHeader=重新

使用如下代码访问“.text”部分的内容:

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

//访问内存中的代码
PIMAGE_DOS_头pDOSHeader=NULL;
pDOSHeader=静态浇铸((空心*)hModule);
...
PIMAGE\u NT\u HEADERS pNTHeader=reinterpret\u cast((字节*)hModule+pDOSHeader->e\u lfanew);
...
PIMAGE\u FILE\u HEADER pFileHeader=重新解释强制转换((字节*)&pNTHeader->FileHeader);
...
PIMAGE_可选_头PopultationHeader=
重新解释强制转换((字节*)&pNTHeader->OptionalHeader);
...
PIMAGE\U SECTION\U HEADER PSSECTIONHEADER=重新解释(
(字节*)&pNTHeader->OptionalHeader+
pNTHeader->FileHeader.SizeOfOptionalHeader);
//因此,迭代标题并选择一个具有正确名称的标题
常量字符文本[]=“.TEXT”;
常量char BSSTEXT[]=“.textbss”;
unsigned int nSectionCount=pNTHeader->FileHeader.NumberOfSections;
char szSectionName[图像大小/短名称+1];
szSectionName[图像大小或短名称]='\0';
for(无符号整数i=0;iName,
图像大小(简称);
如果(0==strncmp(TEXT,szSectionName,
图像大小(短名称)
{
打破
}
psheader++;
}
pVirtualAddress=(void*)(pSectionHeader->VirtualAddress);
dwCodeSize=pSectionHeader->Misc.VirtualSize;
//似乎合理:要计算内存中给定部分的实际起始地址,
//将映像的基址添加到此字段中存储的节的VirtualAddress。
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 );
//从文件和映射加载代码
hFile=CreateFile(文件名、文件读取数据、文件共享读取、NULL、打开现有、文件属性正常、0);
...        
hFileMapping=CreateFileMapping(hFile,NULL,PAGE_READONLY),0,0,NULL);
...
pBaseAddress=MapViewOfFile(文件映射,文件映射,读取,0,0);
...
PIMAGE_DOS_标头pDOSHeader=静态_cast(pBaseAddress);
...
PIMAGE\u NT\u HEADERS pNTHeader=重新解释铸件(
(PBYTE)_pBaseAddress()+pDOSHeader->e_lfanew);
...       
PIMAGE\u FILE\u HEADER pFileHeader=重新解释\u cast(
(PBYTE)&pNTHeader->FileHeader);
...
PIMAGE_可选_头PopultationHeader=
重新解释(
(PBYTE)&pNTHeader->OptionalHeader);
PIMAGE_SECTION_HEADER pSectionHeader=
重新解释(
(PBYTE)&pNTHeader->可选标题+
pNTHeader->FileHeader.SizeOfOptionalHeader);
DWORD dwEntryPoint=pNTHeader->OptionalHeader.AddressOfEntryPoint;
UINT nSectionCount=pNTHeader->FileHeader.NumberOfSections;
常量字符文本[]=“.TEXT”;
常量char BSSTEXT[]=“.textbss”;
char szSectionName[图像大小/短名称+1];
szSectionName[图像大小或短名称]='\0';
for(无符号整数i=0;iName,
图像大小(简称);
如果(0==strncmp(TEXT,szSectionName,
图像大小(短名称)
{
打破
}
psheader++;
}
//在磁盘上探测时使用此选项。这是事情发生的地方
//在磁盘上,而不是在内存中
dwRawData=pSectionHeader->PointerToRawData;
//在磁盘上探测时使用此选项。这是事情发生的地方
//在磁盘上,而不是在内存中
pCodeStart=(void*)((byte*)pBaseAddress+
pSectionHeader->PointerToRawData);
pEntryPoint=(void*)((字节*)pBaseAddress)+dwEntryPoint);
dwCodeSize=pSectionHeader->Misc.VirtualSize;
pCodeEnd=(void*)((byte*)pCodeStart+pSectionHeader->Misc.VirtualSize);
如果应用程序是使用Visual Studio构建的,则在这两种情况下,pCodeStart和pCodeEnd之间的所有字节都是匹配的

但如果应用程序是用GCC(MIWW)构建的,则遵循PCoDESTART和以前的PCODEN的一些字节是相同的,但在中间的某个地方出现了一些不同的字节。


为什么会发生这种情况?

实际上,在不同位置出现的两个字节组合是不同的。第一个:FC 9F 53 00-->00 73 CD 6F和第二个:78 A0 53 00-->7C 73 CD 6F如果应用程序是静态链接的,则不会发生这种情况。假定由于重新定位,字节发生了更改,但遗憾的是.reloc节不存在,PIMAGE_section_HEADER.NumberOfRelocations和PointerToRelocations为0。
 //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 );