Hello, all!

I have a question about using 'call' command in Windows dlls. As far as
I understand, when I use 'call ' form of the command, eip
register will be _loaded_ with a value where is pointing to.
Very well.

When I am calling a function from a dll, compiler inserts 'call imm32',
where 'imm32' is used as offset, which will be _added_ to eip register.
This offset points to 'jmp ' instruction, which will be
corrected when the dll will be loaded. Very well.

So, the form of the command 'call ' is position dependent and
'call imm32' is position independent. Since we don't know where dll
will be placed in memory, it is better to use the last one. But I saw library
calls, where 'call ' form of the command were used. How it
works? If a dll, where such form were used will be loaded to another
address the call will fail! May be, this is indication of a library
with constant address of loading?.. Or, may be, I just didn't understand format of PE? Please, help me to make things clear!

Thanking you in anticipation and sorry for my English :).
Posted on 2006-04-14 05:00:04 by Mika0x65
when a PE is loaded (be it exe or dll), its calls/jumps to external functions are 'resolved'. it doesn't matter whether it has to correct a jump or a call. it also doesn't matter where (in the code) such jmp or call is. when you write an app, the compiler/linker marks such 'to be corrected/resolved' places within the PE. So, a call to external function may be a 'call/jmp' pair, or just a call, or 'push/jmp', or whatever.
Posted on 2006-04-14 05:24:40 by ti_mo_n
So, the form of the command 'call ' is position dependent and
'call imm32' is position independent. Since we don't know where dll
will be placed in memory, it is better to use the last one. But I saw library
calls, where 'call ' form of the command were used. How it
works? If a dll, where such form were used will be loaded to another
address the call will fail! May be, this is indication of a library
with constant address of loading?..


In reality the assembler builds a jump table to external calls of the form...

extern1: jmp immed32
extern2: jmp immed32
extern3: jmp immed32

So that when you call a function in a DLL you are actually calling an address in your program then being redirected to the external call. This is done so that the PE Loader will only have to resolve one address at load time as opposed to resolving every call to the function. For example you might have 100 calls to user32.dll:MessageBoxA in your program, instead of fixing each instance you simply call the appropriate entry in the jump table and that address is fixed at load-time.
Posted on 2006-04-17 06:57:37 by donkey
To put things simply:

			push好bsp; 好bsp; 0			
push好bsp; 好bsp; CB_ADDSTRING
push好bsp; 好bsp;
push好bsp; 好bsp; offset SendMessage
jmp好bsp; 好bsp; near SendMessage


is translated to something like this:

0040403B好bsp; 好bsp;. 6A 00好bsp; 好bsp; 好bsp; 好bsp; 好bsp; push好bsp; 好bsp; 0
0040403D好bsp; 好bsp;. 68 43010000好bsp; 好bsp; push好bsp; 好bsp; 143
00404042好bsp; 好bsp;. FF77 F0好bsp; 好bsp; 好bsp; 好bsp; push好bsp; 好bsp;
00404045好bsp; 好bsp;. 68 02464000好bsp; 好bsp; push好bsp; 好bsp; <jmp.&USER32.SendMessageA>好bsp; 好bsp; 好bsp; 好bsp;;好bsp; Entry address
0040404A好bsp; 好bsp;. E9 B3050000好bsp; 好bsp; jmp好bsp; 好bsp; 好bsp;<jmp.&USER32.SendMessageA>

....

00404602好bsp; 好bsp;$-FF25 24624300好bsp; jmp好bsp; 好bsp; 好bsp;

The address at 00404604 (not 00404602) is 'resolved' at run-time (just like Donkey said).

while

			call	SendMessage


is translated to comething like:

00403E3F好bsp; 好bsp;. E8 BE070000好bsp; 好bsp; call好bsp; 好bsp; <jmp.&USER32.SendMessageA>好bsp; 好bsp; 好bsp; 好bsp;; \SendMessageA


BE070000 is a relative offset to jump to. It jumps to 00404602 which is "jmp Send Message" with its jump-address resolved at run-time.

(Please don't pay attention to what the above codes do. They're just parts of my apps. Instead focus on the instructions themselves.)
Posted on 2006-04-17 23:30:19 by ti_mo_n
Donkey, isn't it rather...


extern1: jmp dword
extern2: jmp dword
extern3: jmp dword


?
Posted on 2006-04-18 08:10:49 by f0dder
By the way, I always have thinked that the jump table is constructed by the linker, ie, the assembler only flag a symbol to be defined as extern.... there is no diference between a label for a variable and a label for a function tought now that Im trying to get... I see a little nonsense because how know the linker if is a label or a function... I guess the answer is the lib files or the scan of the dll for symbols (they also handle if is a function and label)?
Is a work of 2... and then of a 3 being the loader called...


Anyway, time ago Frank BK in some discusion about this thing, have get the hint of use something like call... why? for take over the 2 bytes of the encoding of jmp (IIRC) and get directly the value at "[" and "]"


(1) (assembly time)
Contructed at assembly time (flag the symbol as extern only?)
call

(2) (link time)
The jump table like this one constructed at link time
someSymbol: jmp [ someSymbol Filled at runtime]

(3) (loading time)
jmp


And because the only diference between jmp and call IS that jump is jump and call is call :roll:, but the memory reference/operation is the same (branch the instruction flow), then you can use some like:


call

And you will be getting directly the address to where to jump... bypassing the jump






Perhaps I have missed something :P... I feel it... watching, I guess that instead of jmp should be direct for use call extern symbol+2... it was about the IAT... sorry have passed time and I cant recall correctly :S...

call extern (1)
symbol: jmp xxxFiledRuntime (2: constructed by linker)
jmp: externSymbol (3)


And I feel that in that way it should work the thing about call ... (a lot of misses isnt it??) ;). (I need ollydbg running under wine :S :P lol)...
Posted on 2006-04-18 12:16:28 by rea

Donkey, isn't it rather...


extern1: jmp dword
extern2: jmp dword
extern3: jmp dword


?



In a conventional LINK environment (VC6 and earlier), the .LIB file for each DLL will supply code like the following:

public _extern1@12
public _extern2@16
public _extern3@12
extern _impl_extern1@12:dword
extern _impl_extern2@16:dword
extern _impl_extern3@12:dword
_extern1@12: jmp dword ptr [_impl_extern1@12]
_extern2@16: jmp dword ptr [_impl_extern2@16]
_extern3@12: jmp dword ptr [_impl_extern3@12]



; The following data will be filled in when the defining DLL loads
public _impl_extern1@12
public _impl_extern2@16
public _impl_extern3@12
_impl_extern1@12 dd ?
_impl_extern2@16 dd ?
_impl_extern3@12 dd ?
Posted on 2006-04-18 16:16:01 by tenkey
exactly, tenkey.

For later builds, the .lib files don't contain the actual code, but just enough information that the linker can create it ("new-style import libraries").
Posted on 2006-04-19 06:26:37 by f0dder
In reality the assembler builds a jump table to external calls of the form...


Yes I know it. This is why I was wondered. Because 'call ' is not the most suitable for this situation, as I understand. The most suitable is 'call ', not 'call '. Isn't it?..

So that when you call a function in a DLL you are actually calling an address in your program then being redirected to the external call. This is done so that the PE Loader will only have to resolve one address at load time as opposed to resolving every call to the function. For example you might have 100 calls to user32.dll:MessageBoxA in your program, instead of fixing each instance you simply call the appropriate entry in the jump table and that address is fixed at load-time.


As I understand, it will no work for this case. Imaging, that my dll will be loaded at another address. Loader will correct jmp to appropriate values. But 'call ' as I read , will LOAD imm32 into EIP register, not ADD it to. So, we have an absolute, not a relative address in 'call '. And we will need to correct a value namely in 'call ', not in 'jmp'.

This is a picture in my head for now. I feel, that something is wrong and want to understand, what exactly.
Posted on 2006-04-20 15:30:41 by Mika0x65

Donkey, isn't it rather...


extern1: jmp dword
extern2: jmp dword
extern3: jmp dword


?


It probably is, I have never looked at it in such detail, I had assumed that at load time the executable calling the DLL would have references resolved to immediate addresses after the DLL is loaded (imm32). However they may be kept in memory (), I will have to disassemble a running app to check.

When I say immediate 32 I mean that the immediate address is inserted after the JMP opcode. Relative jumps would be difficult as the compile time linker would not know how many bytes to allocate for the instruction (rel8, rel16 etc...). Once the DLL has been loaded and the offset from the beginning is known the immediate address can be calculated and inserted after the JMP, which will always have the same opcode and instruction length in that case. Ofcourse, as I said I have never looked the jump table after the PE Loader has resolved the addresses to see what opcode is used (immed or ).

Donkey
Posted on 2006-04-20 18:51:30 by donkey
Hi f0dder,

Well, I'm home now and tested it and yes, you are right...

004270D2  -FF25 D4764200    JMP DWORD PTR DS:[<&KERNEL32.GetModuleHa>; KERNEL32.GetModuleHandleA
DS:[004276D4]=7C590B1A (KERNEL32.GetModuleHandleA)

FF25 = Jump absolute indirect m32

The jump table consists of JMP instructions, in this case GetProcAddress returned 7C590B1A as well.

Donkey
Posted on 2006-04-20 19:54:35 by donkey
That's the smart thing about PE executables - basically, only a "list of DWORDs" has to be updated because of the indirect calling.
Posted on 2006-04-21 01:28:35 by f0dder
Woops... Seems to me that I mixed up 'far call ' and 'call '...
Posted on 2006-04-21 04:42:40 by Mika0x65
there is no such thing as "call " (at least not in 32bit x86) - the mean indirection. What you mean is probably "call imm32", which is eip-relative :)
Posted on 2006-04-21 08:26:45 by f0dder

there is no such thing as "call " (at least not in 32bit x86) - the mean indirection. What you mean is probably "call imm32", which is eip-relative :)



Yes, I was wrong. I meant 'call ', on of  the 'call ' indirect command. And I am still wondering, why this kind of the command is used in dlls. I noticed, that calls to MY functions in dlls are using 'call rel32' kind of the command, but calls to system functions in system dlls are using 'call '. This is why I thought, that a few of system libraries have static address of load.
Posted on 2006-04-21 12:10:29 by Mika0x65


there is no such thing as "call " (at least not in 32bit x86) - the mean indirection. What you mean is probably "call imm32", which is eip-relative :)



Yes, I was wrong. I meant 'call ', on of  the 'call ' indirect command. And I am still wondering, why this kind of the command is used in dlls. I noticed, that calls to MY functions in dlls are using 'call rel32' kind of the command, but calls to system functions in system dlls are using 'call '. This is why I thought, that a few of system libraries have static address of load.


It depends on the include/header files you use. MessageBox can be made to refer either to the DWORD in the import address table, or to the "dummy" function that jumps to the forementioned DWORD.

MASM32 used to do the "call-function-that-jumps-indirectly" route, but later versions have come with a tool to generate headers that do the calls directly. Dunno if the most recent versions do that as default.
Posted on 2006-04-21 12:23:38 by f0dder

MASM32 used to do the "call-function-that-jumps-indirectly" route, but later versions have come with a tool to generate headers that do the calls directly. Dunno if the most recent versions do that as default.


Well, but in this case linker must correct the command itself, as I understand.

For example, I have a library, compiled for address 0x1000. It contains 'call [0x1100]' -- a call to external function. Both libraries (source and target), due a few reasons cannot be loaded at prospective address and must be patched. In this case we need also to patch 'call [0x1100]' command itself, because the address 0x1100 in it became invalid.

Isn't it?..
Posted on 2006-04-21 13:02:56 by Mika0x65
A statically linked library will be fixed by the linker, yes.

A DLL will usually be linked with a /BASE: argument to avoid relocation, but if that address is taken, the DLL must be relocated - that's handled by the PE loader, and requires that relocations are present in the .DLL.
Posted on 2006-04-21 13:05:00 by f0dder

A statically linked library will be fixed by the linker, yes.


I am speaking about only dlls.


A DLL will usually be linked with a /BASE: argument to avoid relocation, but if that address is taken, the DLL must be relocated - that's handled by the PE loader, and requires that relocations are present in the .DLL.


And command 'call ' will be also patched by PE loader? This is what I want to hear :).
Posted on 2006-04-21 13:16:38 by Mika0x65
Yup, "call dword " will be fixed by PE loader, "call imm32" (relative) won't.
Posted on 2006-04-21 13:20:11 by f0dder