2012-03-31 11 views
5

से फ़ाइल में ऑफ़सेट हो रहा है मैं एक पीई फ़ाइल पढ़ने की कोशिश कर रहा हूं।
समस्या यह है कि डेटा आरवीए पॉइंटर्स का उपयोग करता है, जबकि मुझे फ़ाइल की आवश्यकता होती है, मुझे फ़ाइल
में ऑफसेट की आवश्यकता होती है। मैं आरवीए को फ़ाइल में ऑफ़सेट करने के लिए कैसे परिवर्तित कर सकता हूं?आरवीए

+0

मान लीजिए आप फ़ाइल से इसे पढ़ा नहीं कर सकता है, कैसे पीई लोडर करता है काम? – harold

+0

मुझे नहीं पता ... क्या यह अनचाहे जानकारी दिखाता है? और अगर मैं इसे फाइल से पढ़ सकता हूं, तो पता ऑफसेट से क्या पता चला है? – Idov

+0

मेरी जानकारी के अनुसार, वे छविबेस (शीर्षलेख में) – harold

उत्तर

4

फ़ाइल RVA की भरपाई का निर्धारण करने के लिए, आप की जरूरत:

  1. जिसमें खंड अंक RVA निर्धारित करने के लिए। अनुभाग
  2. का अपना पता रिश्तेदार वर्चुअल ऐड्रेस से
  3. घटाना फ़ाइल अनुभाग

आप एक फ़ाइल ऑफसेट कि आप की आवश्यकता प्राप्त होगा की भरपाई परिणाम में जोड़ें।

0
file Offset = RVAOfData - Virtual Offset + Raw Offset 

उदाहरण:
हमारे संसाधन अनुभाग (".rsrc") का विवरण:
वर्चुअल ऑफसेट: F000
कच्चे ऑफसेट: C600

enter image description here

चलें संसाधन में से एक पर देखो हमारे पास है:
नाम: बीआईएन
डेटा का आरवीए: F0B0
फाइल ऑफ़सेट:?

enter image description here

fileOffset = RVAOfData - Virtual Offset + Raw Offset 
=> C6B0 = F0B0  - F000   + C600 

फ़ाइल ऑफ़सेट: C6B0

enter image description here

संदर्भ:
Understanding RVAs and Import Tables - by Sunshine

सी # में फंक्शन:

// Example: 
// RVA: F0B0 
// Virtual offset: F000 ("RVA" in PEview) 
// Raw offset: C600 ("Pointer to Raw Data" in PEview) 
// fileOffset = F0B0 - F000 + C600 = C6B0 
private static uint rvaToFileOffset(uint i_Rva, uint i_VirtualOffset, uint i_RawOffset) 
{ 
    return (i_Rva - i_VirtualOffset + i_RawOffset); 
} 
0

उदाहरण के नीचे आरवीए से प्रवेश बिंदु के पते की फ़ाइल ऑफ़सेट देता है। आरवीए से डिस्क डिस्क ऑफसेट प्राप्त करने के लिए कोई भी पॉइंटर पास कर सकता है।

असल में हमें यह पता लगाने की आवश्यकता है कि पता किस अनुभाग से संबंधित है। एक बार सही अनुभाग की पहचान हो जाने के बाद ऑफ़सेट प्राप्त करने के लिए सूत्र का उपयोग करें।

DWORD retAddr = ptr - (sectionHeader-> VirtualAddress) +
(sectionHeader-> PointerToRawData);

तो भौतिक पता

retAddr + (PBYTE) प्राप्त करने के लिए फ़ाइल आधार पता जोड़ने lpFileBase

LPCSTR fileName="exe_file_to_parse"; 
    HANDLE hFile; 
    HANDLE hFileMapping; 
    LPVOID lpFileBase; 
    PIMAGE_DOS_HEADER dosHeader; 
    PIMAGE_NT_HEADERS peHeader; 
    PIMAGE_SECTION_HEADER sectionHeader; 

    hFile = CreateFileA(fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); 

    if(hFile==INVALID_HANDLE_VALUE) 
    { 
     printf("\n CreateFile failed in read mode \n"); 
     return 1; 
    } 

    hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL); 

    if(hFileMapping==0) 
    { 
     printf("\n CreateFileMapping failed \n"); 
     CloseHandle(hFile); 
     return 1; 
    } 

    lpFileBase = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0); // Base pointer to file 

    if(lpFileBase==0) 
    { 
     printf("\n MapViewOfFile failed \n"); 
     CloseHandle(hFileMapping); 
     CloseHandle(hFile); 
     return 1; 
    } 

    dosHeader = (PIMAGE_DOS_HEADER) lpFileBase; //pointer to dos headers 

    if(dosHeader->e_magic==IMAGE_DOS_SIGNATURE) 
    { 
     //if it is executable file print different fileds of structure 
     //dosHeader->e_lfanew : RVA for PE Header 
     printf("\n DOS Signature (MZ) Matched"); 

     //pointer to PE/NT header 
     peHeader = (PIMAGE_NT_HEADERS) ((u_char*)dosHeader+dosHeader->e_lfanew); 

     if(peHeader->Signature==IMAGE_NT_SIGNATURE) 
     { 
      printf("\n PE Signature (PE) Matched \n"); 
      // valid executable so we can proceed 

      //address of entry point 
      DWORD ptr = peHeader->OptionalHeader.AddressOfEntryPoint; 

      //instead of AEP send any pointer to get actual disk offset of it 
      printf("\n RVA : %x \n",ptr); // this is in memory address i.e. RVA 
      //suppose any one wants to know actual disk offset of "address of entry point" (AEP) 

      sectionHeader = IMAGE_FIRST_SECTION(peHeader); //first section address 
      UINT nSectionCount = peHeader->FileHeader.NumberOfSections; 
      UINT i=0; 
      //check in which section the address belongs 
      for(i=0; i<=nSectionCount; ++i, ++sectionHeader) 
      { 
       if((sectionHeader->VirtualAddress) > ptr) 
       { 
        sectionHeader--; 
        break; 
       } 
      } 

      if(i>nSectionCount) 
      { 
       sectionHeader = IMAGE_FIRST_SECTION(peHeader); 
       UINT nSectionCount = peHeader->FileHeader.NumberOfSections; 
       for(i=0; i<nSectionCount-1; ++i,++sectionHeader); 
      } 

      //once the correct section is found below formula gives the actual disk offset 
      DWORD retAddr = ptr - (sectionHeader->VirtualAddress) + 
        (sectionHeader->PointerToRawData); 
      printf("\n Disk Offset : %x \n",retAddr+(PBYTE)lpFileBase); 
      // retAddr+(PBYTE)lpFileBase contains the actual disk offset of address of entry point 

     } 
     UnmapViewOfFile(lpFileBase); 
     CloseHandle(hFileMapping); 
     CloseHandle(hFile); 
     //getchar(); 
     return 0; 
    } 
    else 
    { 
     printf("\n DOS Signature (MZ) Not Matched \n"); 
     UnmapViewOfFile(lpFileBase); 
     CloseHandle(hFileMapping); 
     CloseHandle(hFile); 
     return 1; 
    } 
+0

क्या आप अपने कोड में कुछ टिप्पणियां जोड़ सकते हैं? –

+1

ने कुछ विवरण और साथ ही टिप्पणी भी जोड़े। –