(開始這段別人總結的比較好,我就拿來用了)
1.rva to foa
即我們現在知道記憶體狀態下的偏移,需要找到檔案狀態下的偏移。
步驟如下圖:
step1:記憶體中的位址減去記憶體基址得到偏移,即rva。
step2:迴圈遍歷節表中各個節的資訊,判斷在哪個節中。(需要滿足:記憶體偏移+節資料沒對齊的大小》image_panyi>記憶體偏移)
step3:找出在哪個節後,減去該節在記憶體中的偏移(virturaladdress)得到在該節中的相對偏移。
step4:上一步得到的該節的相對偏移+該節在檔案中的偏移(pointtorawdata),即得到foa
2.foa to rva
現在我們已經知道如何從記憶體中的偏移轉化為檔案中的偏移。現在是它的逆過程
step1:檔案中的位址減去檔案基址,得到在檔案中的偏移,即foa。
step2:迴圈遍歷節表中各個節的資訊,判斷在哪個節中。(檔案對齊+檔案偏移》file_panyi>檔案偏移)
step3:找出在哪個節後,減去該節在檔案中的偏移(virturaladdress)得到在該節中的相對偏移。
step4:上一步得到的該節的相對偏移+該節在記憶體中的偏移(virtualaddress),即得到rva。
3.**實現
#include#include#include#define test 1
dword toloaderpe(lpstr file_path, pvoid* pfilebuffer);
dword foatoimageoffset(pvoid pbuffer, dword dwfoa);
dword rvatofileoffset(pvoid pbuffer, dword dwrva);
char file_path = "c:\\users\\njupt\\desktop\\notepad.exe";
char write_file_path = "d:\\lib\\cp_xx.exe";
//返回pe檔案大小
dword toloaderpe(lpstr file_path, pvoid* pfilebuffer)
fseek(pfile, 0, seek_end);
filesize = ftell(pfile);
printf("filebuffer: %#x\n", filesize);
fseek(pfile, 0, seek_set);
pfilebuffertemp = malloc(filesize);
if (!pfilebuffertemp)
dword n = fread(pfilebuffertemp, filesize, 1, pfile);
if (!n)
*pfilebuffer = pfilebuffertemp;
pfilebuffertemp = null;
fclose(pfile);
return filesize;
}dword rvatofileoffset(pvoid pbuffer, dword dwrva)
if (*((pword)pbuffer) != image_dos_signature)
pdosheader = (pimage_dos_header)pbuffer;
if (*((pdword)((dword)pbuffer + pdosheader->e_lfanew)) != image_nt_signature)
printf("imageoffset: %#x\n", dwrva);
pntheader = (pimage_nt_headers)((dword)pbuffer + pdosheader->e_lfanew);
ppeheader = (pimage_file_header)((dword)pntheader + 4); // 這裡必須強制型別轉換
poptionheader = (pimage_optional_header32)((dword)ppeheader + image_sizeof_file_header);
psectionheader = (pimage_section_header)((dword)poptionheader + ppeheader->sizeofoptionalheader);
pimage_section_header psectiontemp = psectionheader;
if (dwrva <= poptionheader->sizeofheaders)
return (dword)dwrva;
else
}} printf("rvatofoa failed!\n");
return 0;
}dword foatoimageoffset(pvoid pbuffer, dword dwfoa)
if (*((pword)pbuffer) != image_dos_signature)
pdosheader = (pimage_dos_header)pbuffer;
if (*((pdword)((dword)pbuffer + pdosheader->e_lfanew)) != image_nt_signature)
printf("fileoffset: %#x\n", dwfoa);
pntheader = (pimage_nt_headers)((dword)pbuffer + pdosheader->e_lfanew);
ppeheader = (pimage_file_header)((dword)pntheader + 4); // 這裡必須強制型別轉換
poptionheader = (pimage_optional_header32)((dword)ppeheader + image_sizeof_file_header);
psectionheader = (pimage_section_header)((dword)poptionheader + ppeheader->sizeofoptionalheader);
pimage_section_header psectiontemp = psectionheader;
if (dwfoa <= poptionheader->sizeofheaders)
return (dword)dwfoa;
else
}} printf("foatorva failed!\n");
return 0;
}void operate()
int main()
4.結果展示
RVA與FOA的轉換
1.pe程式加載入記憶體後頭的位址與檔案中一致,但對齊方式 偏移 不同 2.結構體 typedef struct image section header misc dword virtualaddress 節區的rva位址 dword sizeofrawdata 在檔案中對齊後的尺寸 dword ...
RVA與FOA的轉換
我們執行程式可以看見相應的值,那麼我們可以是否可以在檔案中直接搜尋對應的值然後修改呢?這種方法沒有毛病,但是檔案中也許會存在很多個0x12345678,你無法準確的知道哪乙個才是全域性變數 那麼,又是否可以通過已經給出的這個位址0x42ba30直接去尋找呢?當然也是不行的,因為在之前章節的學習中我們...
PE檔案學習 RVA與FOA轉換
當我們的pe檔案沒有被裝載到記憶體中的時候,它是以什麼樣的儲存方式在磁碟中儲存呢?當被裝載到記憶體之後,pe檔案的內容又是什麼樣的光景呢?今天我們說的重點就是rva和foa的轉換,之前我們已經知道pe檔案在磁碟檔案中的對齊粒度是0x200,在記憶體中的對齊粒度是0x1000,我們來看一張 windo...