公式
RVA = 内存地址-ImageBase
判断RVA在哪一个节上:
- RVA>=节n.VirtualAddress
- RVA<=节n+1.VirtualAddress
偏移=RVA-节n.VirtualAddress
FOV=节n.PointerToRawData+偏移
实验-对齐大小一样
#include <stdio.h> char str[] = "ABC"; int main() { printf("Address: %p\n", &str); printf("V: %s\n", str); return 0; }
- 执行后输出:
Address: 00424D8C V: ABC
获取ImageBase
- ImageBase在扩展PE头上的第十个属性,基于扩展PE头偏移地址28个字节,大小为DWORD。
- 00004000,小端存储转十六进制为0x00400000,所以ImageBase的地址为0x00400000。
计算RVA
- RVA=内存地址-ImageBase=0x00024D8C
获取内存对齐和文件对齐
- SectionAlignment 内存对齐 在扩展PE头上的第十一个属性,大小为DWORD。
- FileAlignment 文件对齐 在扩展PE头上的第十二个属性,大小为DWORD。
- 发现内存对齐和文件对齐都是1000h,实验完再找一个对齐不一样的试试。
判断在哪一个节
- VirtualAddress在每一个节表的第三个属性,偏移为12个字节,大小为DWORD,得到第一个节表的VirtualAddress为00100000,小端转十六进制得到0x00001000。第二个节表的VirtualAddress为00200200,小端存储转十六进制得到0x00022000。第三个节表的VirtualAddress为00400200,小端存储转十六进制为00024000,RVA大于第二个节的VirtualAddress小于第三个节的VirtualAddress。所以在第二个节表里。
计算偏移
- RVA-第二个节的VirtualAddress=0x00024D8C-0x00022000=0x00002D8C
获取节表的PointerToRawData
- PointerToRawData在节表的第五个属性,基于节表偏移20个字节,大小为DWORD。
- 获取第二个节表的PointerToRawData得到00200200,小端存储转十六进制为0x00022000
计算FOV
- FOV=第二个节.PointerToRawData+偏移=0x00022000+0x00002D8C=0x00024D8C
- 发现和RVA是一样的,所以结论是:如果内存对齐和文件对齐是一样的,FOA=RVA。
验证
- 将0x00024D8C后面对应三个字节的改为41 41 41再执行等到
Address: 00424D8C V: AAA
实验-对齐大小不一样
- 预编译修改内存对齐和文件对齐,记得文件对齐不能大于内存对齐。因为重新编译了,所以要重新算。
#pragma comment(linker, "/ALIGN:0x4000") #pragma comment(linker, "/FILEALIGN:0x1000") #include <stdio.h> char str[] = "ABCD"; int main() { printf("Address: %p\n", &str); printf("V: %s\n", str); return 0; }
- 执行后结果为:
Address: 0042CA30 V: ABCD
获取ImageBase
- ImageBase在扩展PE头上的第十个属性,基于扩展PE头偏移地址28个字节,大小为DWORD。
- 00004000,小端存储转十六进制为0x00400000,所以ImageBase的地址为0x00400000。
计算RVA
- RVA=内存地址-ImageBase=0x0042CA30-0x00400000=0x0002CA30
获取内存对齐和文件对齐
- SectionAlignment 内存对齐 在扩展PE头上的第十一个属性,基于扩展PE头偏移地址32个字节,大小为DWORD。
- FileAlignment 文件对齐 在扩展PE头上的第十二个属性,基于扩展PE头偏移地址36个字节,大小为DWORD。
- 发现内存对齐是4000h,文件对齐是1000h。
判断在哪一个节
- VirtualAddress在每一个节表的第三个属性,偏移为12个字节,大小为DWORD,得到第一个节表的VirtualAddress为00400000,小端转十六进制得到0x00004000。第二个节表的VirtualAddress为00800200,小端存储转十六进制得到0x00020800。第三个节表的VirtualAddress为00C00200,小端存储转十六进制为0x0002C000,第四个节表的VirtualAddress为00400300,小端存储转十六进制为0x00034000,RVA大于第三个节的VirtualAddress小于第四个节的VirtualAddress。所以在第三个节表里。
计算偏移
- RVA-第三个节的VirtualAddress=0x0002CA30-0x0002C000=0x00000A30
获取节表的PointerToRawData
- PointerToRawData在节表的第五个属性,基于节表偏移20个字节,大小为DWORD。
- 获取第三个节表的PointerToRawData得到00800200,小端存储转十六进制为0x00028000
计算FOV
- FOV=第三个节.PointerToRawData+偏移=0x00024000+0x00000A30=0x00024A30
验证
- 将0x00024A30后面对应三个字节的改为41 41 41 41再执行等到
Address: 0042CA30 V: AAAA
来源:https://www.cnblogs.com/Kali-Team/p/12207958.html