NO

Author Topic: Calling a Windows Function  (Read 149 times)

Online Jokaste

  • Member
  • *
  • Posts: 101
  • Never be pleased, always improve.
    • ImgTools
Calling a Windows Function
« on: October 07, 2017, 06:36:48 pm »
When we call a Windows Function the compiler creates a JUMP to a table.
Each entry into the table is an implib__Function.

Is it possible to remove the jump and directly jumps to the corresponding address into the table?

Code: [Select]

   [0000000140001651] FF25B10C0000                 jmp               qword ptr [0000000140002308]
  [0000000140001657] FF25B30C0000                 jmp               qword ptr [0000000140002310]
  [000000014000165D] FF25B50C0000                 jmp               qword ptr [0000000140002318]
  [0000000140001663] FF25B70C0000                 jmp               qword ptr [0000000140002320]
  [0000000140001669] FF25B90C0000                 jmp               qword ptr [0000000140002328]
  [000000014000166F] FF25BB0C0000                 jmp               qword ptr [0000000140002330]
  [0000000140001675] FF25BD0C0000                 jmp               qword ptr [0000000140002338]
  [000000014000167B] FF25C70C0000                 jmp               qword ptr [0000000140002348]

 0002:00000308       __imp_ExitProcess          0000000140002308     kernel32:KERNEL32.dll
 0002:00000310       __imp_GetModuleHandleA     0000000140002310     kernel32:KERNEL32.dll
 0002:00000318       __imp_GetCommandLineA      0000000140002318     kernel32:KERNEL32.dll
 0002:00000320       __imp_SetThreadErrorMode   0000000140002320     kernel32:KERNEL32.dll
 0002:00000328       __imp_GetModuleFileNameA   0000000140002328     kernel32:KERNEL32.dll
 0002:00000330       __imp_lstrcpy              0000000140002330     kernel32:KERNEL32.dll
 0002:00000338       __imp_CreateDirectoryA     0000000140002338     kernel32:KERNEL32.dll

In the following case
Code: [Select]
                     xor      ecx,ecx
                     mov      rax,OFFSET @End
                     mov      rdx,OFFSET GetCommandLineA
                     push   rax
                     push   rdx
                     jmp      GetModuleHandleA
                     mov      _hInstance,rax
@End :

The "jmp GetModuleHandleA" will be replaced by a jump to the table "0002:00000310"
What I want is "jmp __imp_GetModuleHandleA     0000000140002310"


Many peoples would tell me that remplacing call with jumps is not a good idea, it will be difficult for debuggers...
But what makes the compiler. It create a call then makes a jump into the table...


Thanks Timo for your quick and good answer. :-*
« Last Edit: October 07, 2017, 06:51:22 pm by Jokaste »
Kenavo

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1642
Re: Calling a Windows Function
« Reply #1 on: October 07, 2017, 06:46:34 pm »
Sure.
Code: [Select]
extern __imp_ExitProcess:dword 
ExitProcess TEXTEQU <__imp_ExitProcess>
« Last Edit: October 12, 2017, 04:49:13 pm by TimoVJL »
May the source be with you

Online Jokaste

  • Member
  • *
  • Posts: 101
  • Never be pleased, always improve.
    • ImgTools
Re: Calling a Windows Function
« Reply #2 on: October 07, 2017, 07:03:47 pm »
Code: [Select]

  [00000001400015AC] 48B80823004001000000         mov               rax,140002308
  [00000001400015B6] 488B00                       mov               rax,qword ptr [rax]
  [00000001400015B9] FFD0                         call              rax


0002:00000308       __imp_ExitProcess          0000000140002308     kernel32:KERNEL32.dll


I have replaced One CALL and ONE jump with TWO MOV and ONE CALL


I hope that all these posts wil help some coders to understand the internal process of the assembler and how the compiler does.
Kenavo

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1612
Re: Calling a Windows Function
« Reply #3 on: October 07, 2017, 07:47:25 pm »
Many peoples would tell me that replacing call with jumps is not a good idea, it will be difficult for debuggers...
But what makes the compiler. It create a call then makes a jump into the table...

It is really a bad idea.
This breaks the stack framing and troubles the Frame-based Exception Handling mechanism (__try __except).
The compiler creates the jump table for a different scope than just creating a list of jumps.
A jump table give a location to link locally in the executable, and in the same time a location that could be dynamically updated when the executable will be linked to a DLL at later time.
A standard call to a symbol as:
Code: [Select]
    call dll_func1Is resolved by the linker replacing the symbol 'dll_func1' with the reference in the jump table that exists at time of static link (the static link is when you run the linker as polink) avoiding the error message for inexistent symbol.
Then at run time the loader will write the memory address of the loaded DLL in the jump table.
The flow will be:
Code: [Select]
    call dll_func1    ; make a regular call to an address that exist in our executable

    ....

    ;jump table
dll_func1:               jmp                ; the helper jump instruction
__imp_dll_func1:    0x00000000    ; this location will be replaced by the real address in the DLL by the loader
The use of declaration specifiers allows to avoid jump and call directly the function in the DLL by dereferencing the location '__imp_dll_func1:
Code: [Select]
void __declspec(dllimport) dll_func1(void);
    ...

    dll_func1();    // Standar call. See below as the compiler translates it after the specifier dllexport is applied
The code will be:
Code: [Select]
    call [__imp_dll_func1]    ; dereferences the address at location __imp_dll_func1 avoiding the jump
In the last case the compiler avoid the jump.

Google for jump table for more info. I.e. read this.

Of course pushing the return address and then jumping to the function address is very inefficient compared to a 'call' instruction.
while this works well on a RISC architecture on a CISC is just a time consuming operation.
« Last Edit: October 07, 2017, 09:23:39 pm by frankie »

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1642
Re: Calling a Windows Function
« Reply #4 on: October 07, 2017, 08:35:02 pm »
From PellesC help: Appendix -> Program startup: the true story
Quote
Program startup: the true story
 
When the entry point is main, execution will actually begin in a function called mainCRTStartup. This function is located in the C runtime library, and will initialize things like the memory manager, file I/O support, and the argv parameter. Multi-threading will be initialized for the multi-threaded version of the C runtime. If special startup functions have been defined (#pragma startup function), they will be called. When all this is done, mainCRTStartup will call main.

When the entry point is wmain, execution will begin in a function called wmainCRTStartup, but otherwise it is the same process.

When the entry point is WinMain, execution will begin in a function called WinMainCRTStartup. The initialization is almost the same as for mainCRTStartup and wmainCRTStartup, but the arguments to WinMain are different.

When the entry point is wWinMain, execution will begin in a function called wWinMainCRTStartup.

When the entry point is DllMain, execution will begin in a function called DllMainCRTStartup. The initialization is similar to the WinMain case.
An example:
Code: [Select]
.data
msg DB "Hello ASM",13,10,0

.code
mainCRTStartup PROC C
INVOKE printf, ADDR msg
INVOKE ExitProcess, eax
mainCRTStartup ENDP
END
May the source be with you

Online Jokaste

  • Member
  • *
  • Posts: 101
  • Never be pleased, always improve.
    • ImgTools
Re: Calling a Windows Function
« Reply #5 on: October 07, 2017, 09:57:31 pm »
Thanks Timo & Frankie. Could these posts help every coder to improve himself and his code.
There are programmers that did not make long time at school (me for example; I prefered submarines), it's difficult to write algorythms but use of best instructions is possible.

For example :

Code: [Select]
MOV RAX,12345678h
NOT RAX
or
XOR RAX,0
Kenavo