代码的基础是代码开始
的地方入口点的地址是可执行文件开始执行的地方(主函数的第一条指令)
他们都可以相同或不同
这是一个示例,它们都相同
:\>dumpbin /headers funadd.exe | grep -iE "base of code|entry point"
1000 entry point (00401000) _WinMain@16
1000 base of code
那是因为主函数不引用任何其他函数
假设你有这样的代码
int main (void) { printf ( "%x\n" , dosomecrap() ); }
那么在编译 main 函数时需要引用 dosomecrap() 函数,这样编译器将首先编译 dosomecrap() 并将代码从代码库中放入
在这种情况下, main () 出现在代码部分的后面,
因此它们都不会相同
入口点的地址将指向 main()
代码的基础可能指向 dosomecrap() 的开始
在正常编译的可执行文件中 main 不是第一个执行的代码
它是像 maincrtstartup() 或 WinMainCrtStartup() 这样的 cruntime 初始化代码
首先执行的
导入部分可以合并到文本部分
在这种情况下,解析的导入从代码的基础开始
您可以编写这样的代码并将数据部分合并到 .text 部分,在这种情况下,嵌入的字节将是代码基础的第一个字节
#include <windows.h>
int p[] = { '\x90\x90\x90\x90' };
int funAdd() {
int myvar = 2;
return myvar + p[0];
}
int CALLBACK WinMain(_In_ HINSTANCE,_In_opt_ HINSTANCE,_In_ LPSTR,_In_ int) {
funAdd();
}
如果你编译这个
cl /Zi /W4 /analyze /EHsc /Od /nologo funadd.cpp /link /release /subsystem:windows /entry:WinMain /nologo /merge:.data=.text
并检查您可以看到代码的基址和入口点的地址不同
入口点的地址已移位 16 字节或 0x10 字节(对齐要求表示代码应对齐到 16 字节边界)
:\>dumpbin /headers funadd.exe | grep -iE "base of code|entry point"
1010 entry point (00401010) _WinMain@16
1000 base of code
您可以看到如下所示的 0x90
:\>dumpbin /disasm /range:0x401000,0x401016 funadd.exe
Microsoft (R) COFF/PE Dumper Version 14.14.26430.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file funadd.exe
File Type: EXECUTABLE IMAGE
?p@@3PAHA:
00401000: 90 90 90 90 ....
00401004: 00 00 00 00 00 00 00 00 00 00 00 00 ............
_WinMain@16:
00401010: 55 push ebp
00401011: 8B EC mov ebp,esp
00401013: E8 08 00 00 00 call ?funAdd@@YAHXZ
Summary
1000 .text