-3

Is it possible to make MS visual C++ compiler treat Win32 API import calls as (unresolved) external symbols?

In other words, I need to change dword ptr calls which reference to some IAT, e.g.:

FF 15 00 00 00 00  call        dword ptr [__imp__MessageBoxA@16]

to external symbol calls, e.g.:

E8 00 00 00 00     call        _MessageBoxA@16

This implies that after the compilation I don't need linking, because obviously it won't be possible. So as a product I want to get (MS) COFF .obj files which such unusual calls of Win32 API.

RIscRIpt
  • 163
  • 3
  • 12
  • 1
    Why is linking "obviously" not possible? – Bo Persson Sep 03 '17 at 12:21
  • 2
    This makes little sense, `__imp_MessageBoxA@16` is exactly as "unresolved" as `_MessageBoxA@16`. The difference is caused by the `__declspec(dllimport)` attribute on the declaration that the compiler #included from WinUser.h, it is an optimization. Defeating the optimization by redeclaring the function does not make it "better" in any way, linking the import library is always required. Only using LoadLibrary + GetProcAddress could avoid linking. – Hans Passant Sep 03 '17 at 12:23
  • @BoPersson, because Win32 API functions are defined in system DLLs, which are loaded into the process when it starts. So there's no way you can resolve these symbols with real Win32 API functions during the linking stage. But, ... yes, I must admit that linking can be done with "fake" symbols. – RIscRIpt Sep 03 '17 at 12:26
  • @HansPassant, thank you for your comment, I'll try to fix my question. I meant that in the first example I get a call which requires IAT (import address table), but I want to get an ms-coff file which doesn't require IAT. – RIscRIpt Sep 03 '17 at 12:35
  • `So there's no way you can resolve these symbols with real Win32 API functions during the linking stage` - you simply do implicit linking, so store in *PE* which api from which dll you want use. and loader at runtime load this dlls and resolve your import – RbMm Sep 03 '17 at 12:36
  • @RbMm, if I understood you correctly, you suggest me to use `LoadLibrary` and `GetProcAddr`. Yes, I know it's possible, but I want to know whether there exists some compiler flag, or something else, which doesn't require *a lot of* code modification. As I said at the end of my question, I'd like to get a `coff (.obj)` file with unresolved Win32 API symbols. – RIscRIpt Sep 03 '17 at 12:41
  • @RIscRIpt - no, you wrong understand me. i mean use usual [implicit linking](https://msdn.microsoft.com/en-us/library/d14wsce5.aspx) - in what problem with this ? – RbMm Sep 03 '17 at 12:42
  • and `I want to get an ms-coff file` - and what you will be do with this files ? in any way you not got error unresolved symbol if you not linking. anf you not need something special - simply look in .obj (x86) file. here no `__imp__MessageBoxA@16` or even `_MessageBoxA@16` - will be `MessageBoxA@16` - but what different at all - what here ? how you direct plan use it ? – RbMm Sep 03 '17 at 12:44
  • if declare api with `__declspec(dllimport)` compiler generate `call [__imp__xxx]` form, if declare without this attribute `call xxx` form – RbMm Sep 03 '17 at 12:48
  • @RbMm and @HansPassant, thanks for pointing me out to `__declspec(dllimport)`. This answers my question (see below). – RIscRIpt Sep 03 '17 at 13:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/153552/discussion-between-riscript-and-rbmm). – RIscRIpt Sep 03 '17 at 13:17
  • *"I'd like to get a coff (.obj) file with unresolved Win32 API symbols"* doesn't make any sense. The imports **are** unresolved in the object file. They get resolved later, by the linker, provided you are passing it the correct import libraries as input. This really sounds like an [XY Problem](http://xyproblem.info/). What are you *really* trying to accomplish? – IInspectable Sep 03 '17 at 16:49
  • @IInspectable, I'm sorry for bad formulation of the question, I just cannot find good definitions and notions (i.e. how do you call an unresolved symbol in the first example? and how do you call it in the second example?). Anyway, I found the solution to my problem (see answer below), and for more information, what I'm trying to do you can find in the [chat](http://chat.stackoverflow.com/rooms/153552/discussion-between-riscript-and-rbmm). – RIscRIpt Sep 03 '17 at 17:07

1 Answers1

0

As it was pointed out in the comments under the question, the reason why Win32 API calls are compiled into call [__imp__xxx] is __declspec(dllimport).

So to achieve what was asked in the question, all Win32 API functions must defined without __declspec(dllimport).

In the Win32 header files (such as WinUser.h) you can see that all functions are defined with WINxxxAPI macro, which in turn are defined in apisetcconv.h. In the later file WINxxxAPI macros are defined with DECLSPEC_IMPORT, which in turn is defined as __declspec(dllimport).

So, an easy way to achieve the requirement is to re-define DECLSPEC_IMPORT with the following empty preprocessor definition ( see /D flag ):

/DDECLSPEC_IMPORT=

Which is equivalent to

#define DECLSPEC_IMPORT

P.S. If there are alternative ways, I would still like to know them.

RIscRIpt
  • 163
  • 3
  • 12
  • simply add `user32.lib` as linker input. and you got *pe* – RbMm Sep 03 '17 at 13:31
  • You do realize this doesn't remove the need to for an IAT. For the code to work the call to `_MessageBoxA@16` needs to be resolved to a stub that consists of just `jmp dword ptr [__imp__MessageBoxA@16]`. – Ross Ridge Sep 03 '17 at 14:37
  • yes I do understand this. You can check my [conversation with RbMm](http://chat.stackoverflow.com/rooms/153552/discussion-between-riscript-and-rbmm) for the background story, why do I need it and how I want to use this. Tl;dr: if you do run-time linking then no IAT is needed because you can get addresses of all functions in the active process using GetProcAddr or by manually inspecting IATs of DLLs in an active process. – RIscRIpt Sep 03 '17 at 14:46