如何在VS C/C++编译器关闭位置无关代码编译以适配远程线程调用?
针对单个文件关闭PIC编译并生成绝对地址调用的方案
你提到的场景是可行的——Windows下kernel32.dll等核心系统DLL的加载基址在同一系统版本、同一CPU架构的机器上确实是全局固定的(系统级ASLR不会改变这些DLL的加载地址),因此直接调用其绝对地址不会有问题。以下是针对不同编译器的单个文件修改方案:
MSVC编译器
针对单个文件关闭PIC生成绝对地址调用,有两种常用方式:
- 修改CRT链接方式:在目标文件开头添加编译指令,强制该文件使用静态链接CRT(生成非PIC代码):
这样该文件编译时会生成绝对地址的内存访问指令,替代RIP相对寻址的call。#pragma compiler_options("/MT") - 关闭动态基址选项:如果不想改动CRT链接方式,可在文件中添加链接器指令,强制模块关闭动态基址(ASLR),从而生成绝对调用:
#pragma comment(linker, "/DYNAMICBASE:NO")
GCC/Clang(MinGW等)
直接在目标文件的编译选项中添加 -fno-pic 即可关闭PIC:
- 如果用Makefile编译,在该文件的编译规则中追加选项:
your_file.o: your_file.c gcc -c -fno-pic -o $@ $< - 如果用IDE开发,找到该文件的单独编译设置,添加
-fno-pic选项。
注意事项
- 硬编码kernel32的绝对地址仅适用于同一Windows版本,跨版本运行时需要先通过
GetModuleHandleA或远程进程内存读取获取kernel32的基址,再计算函数偏移得到绝对地址。 - 关闭PIC后的代码无法被自动重定位,因此注入到远程进程时,要确保写入的内存地址与编译时假设的基址一致,或者直接使用硬编码的kernel32函数地址(这也是你当前的需求)。
内容的提问来源于stack exchange,提问作者pazdinho_
相关产品推荐
相关产品推荐

