简体   繁体   中英

How to turn off position-independent code compilation in Microsoft Visual Studio C/C++ compiler?

I'm wondering if it's possible to turn off this position-independent code thing to change the assembly call instruction from something like

call [rip+0x1234] // this address is relative to the current code position

to something like

call qword ptr[0x12345678] // this address is absolute and doesn't crash the program

The reason for this is that I create a remote thread by calling CreateRemoteThread from WinAPI and I want to be able to call other WinAPI functions inside by just typing normal code, but now as the PIC is on, every time I call any function inside the remote thread I get an access violation and the process crashes. It's also worth mentioning that I know every process has different imported functions addresses, but I'm only calling functions from kernel32.dll which is loaded at the same absolute address in every process as far as I know, so this isn't a problem.

Is there some macro or compiler option for this? I would also like to change that behaviour only for compilation of one file, not all in the solution.

Of course my CPU architecture is amd64 but I thinks that's irrelevant.

Thanks in advance!

If I understood you correctly, this is wrong on at least three levels.

  1. There is no guarantee the new host process is importing the APIs you call. If you call CryptAcquireContext the linker will be sure to add an entry for advapi32.dll and CryptAcquireContext in the PE built, which is the source binary. The target may not have such import in the first place.

  2. call QWORD [target] still uses a 32-bit displacement. The import address fixed by the loader can very well be above 4GiB (and almost always is). I don't think you can force cl (try with the link option /LARGEADDRESSAWARE:no , but it's a link option, not a compiler one) to not use a RIP-relative address for these calls, but even if you did that would work for your PE, not for the target PE. Your PE would need to be loaded below the 4GiB while it's almost certain the target PE will not be.

  3. An absolute address needs a relocation. You may be able to force cl / link to emit a PE that is not moveable and avoid the need for relocations but, again, this is for your PE, not the target one.

In short, your code and your binary are tied together to create a process where your code will work as excepted.
If you migrate to another process you have to make up for the differences and it won't be like writing normal code (including accessing global data).

If you are already writing a DLL the easiest thing is to use SetWindowsHookEx to hook the newly created remote thread with a function in your DLL. Windows will automatically inject your whole DLL into the target process. Use any hook you know will be called at least once (this is easy since you control the code of the remote thread).

Otherwise, you can move the injected code in a DLL and inject a shim/loader that loads said DLL from disk/memory.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM