flat assembler
Message board for the users of flat assembler.

Index > Main > "extrn"

Author
Thread Post new topic Reply to topic
ouadji



Joined: 24 Dec 2008
Posts: 1081
Location: Belgium
ouadji 20 Jan 2010, 10:35
hi all Wink

sorry about my english, I'll try to do my best.

in the fasm manual, I read this :

extrn directive defines the external symbol, it should be followed by the
name of symbol and optionally the size operator specifying the size of data
labeled by this symbol

in my code :

Code:
format MS COFF
.....
extrn '_KeGetCurrentIrql@0' as KeGetCurrentIrql :dword
    

but, it's works also without " : dword " !

What that does it change exactly when i write ":dword" ?

Can i do without this directive ?

and if "yes" .. why use it ?

thank you Wink

_________________
I am not young enough to know everything (Oscar Wilde)- Image
Post 20 Jan 2010, 10:35
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20461
Location: In your JS exploiting you and your system
revolution 20 Jan 2010, 11:35
ouadji: Can you change 'dword' to 'word'? Or 'byte'? Will the linker still accept the symbol? What about symbols that are not merely call labels but variables?
Post 20 Jan 2010, 11:35
View user's profile Send private message Visit poster's website Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 20 Jan 2010, 11:49
ouadji,

In this case it does not change anything: _KeGetCurrentIrql@0 is a code label for thunk (jmp [__imp__KeGetCurrentIrql@0]) in import library. Size operator is useful when you want to call imported function directly via pointer in IAT (__imp__KeGetCurrentIrql@0) without size operator in each call instruction.
Post 20 Jan 2010, 11:49
View user's profile Send private message Reply with quote
ouadji



Joined: 24 Dec 2008
Posts: 1081
Location: Belgium
ouadji 20 Jan 2010, 12:35
revolution
Quote:

What about symbols that are not merely call labels but variables ?
with variables, if I doesn't use ":dword" directive,
then I must use it in my code.
Otherwise I have a compilation error.
Code:
extrn '_IoFileObjectType' as IoFileObjectType :dword
...
push [IoFileObjectType]

OR <-----

extrn '_IoFileObjectType' as IoFileObjectType
...
push dword [IoFileObjectType]
    

baldr
Quote:

Size operator is useful when you want to call imported function directly via pointer in IAT
"extrn" directive + IAT ... ? i don't understand. Confused
don't you have a small example illustrating this difference?
thank you.

_________________
I am not young enough to know everything (Oscar Wilde)- Image
Post 20 Jan 2010, 12:35
View user's profile Send private message Send e-mail Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 20 Jan 2010, 13:04
ouadji wrote:
"extrn" directive + IAT ... ? i don't understand.
We're talking about PE image as a result, no?

__imp__KeGetCurrentIrql@0 is a label for dword in PE import address table, which contains address of KeGetCurrentIrql after loader finished in-memory binding. When your code uses _KeGetCurrentIrql@0, linker adds thunk from library (jmp [__imp__KeGetCurrentIrql@0]). Nothing stops you from directly call [__imp__KeGetCurrentIrql@0], except when you forget to add :dword size operator.
Post 20 Jan 2010, 13:04
View user's profile Send private message Reply with quote
ouadji



Joined: 24 Dec 2008
Posts: 1081
Location: Belgium
ouadji 20 Jan 2010, 14:26
my code doesn't use " _KeGetCurrentIrql@0", but "KeGetCurrentIrql".

"call KeGetCurrentIrql"


a) No error, all ok !
Code:
extrn '_KeGetCurrentIrql@0' as KeGetCurrentIrql :dword

call  KeGetCurrentIrql  ; ok !

("---> jmp [_KeGetCurrentIrql@0]")
    

but, if i call directly :

b) it doesn't work, undefined symbol.
Code:
extrn '_KeGetCurrentIrql@0' as KeGetCurrentIrql :dword

call [_KeGetCurrentIrql@0] ; error:undefined symbol '_KeGetCurrentIrql@0'
    

_________________
I am not young enough to know everything (Oscar Wilde)- Image
Post 20 Jan 2010, 14:26
View user's profile Send private message Send e-mail Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 20 Jan 2010, 15:58
ouadji,
Code:
; This code does not use _KeGetCurrentIrql@0, it uses KeGetAdministratorPassword!!! Wink
extrn '_KeGetCurrentIrql@0' as KeGetAdministratorPassword
call  KeGetAdministratorPassword    
From where did you get that call [_KeGetCurrentIrql@0]? Above that you wrote extrn '_KeGetCurrentIrql@0' as KeGetCurrentIrql :dword, no wonder FASM complains.
call [KeGetCurrentIrql] will compile, but won't run. As I wrote before,
baldr at 13:49 on 20 Jan 2010 wrote:
_KeGetCurrentIrql@0 is a code label for thunk (jmp [__imp__KeGetCurrentIrql@0])
Code:
; Example
; This is the program source
extrn "_KeGetCurrentIrql@0" as KeGetCurrentIrql
extrn __imp__KeGetCurrentIrql@0:dword
        …
        call    KeGetCurrentIrql                ; through thunk
        call    [__imp__KeGetCurrentIrql@0]     ; direct; Following parts do not appear in program source (they do in PE)

; This code linker adds because of _KeGetCurrentIrql@0 reference
_KeGetCurrentIrql@0:                            ; this is the actual label, but
KeGetCurrentIrql:                               ; FASM uses this, as said in extrn
        jmp     [__imp__KeGetCurrentIrql@0]

; This data is in IAT after loading and binding (in PE on disk it contains import ordinal or RVA of IMAGE_IMPORT_BY_NAME).
__imp__KeGetCurrentIrql@0 dd HAL!KeGetCurrentIrql; function pointer    
Hope this helps.
Post 20 Jan 2010, 15:58
View user's profile Send private message Reply with quote
ouadji



Joined: 24 Dec 2008
Posts: 1081
Location: Belgium
ouadji 20 Jan 2010, 16:28
_KeGetCurrentIrql@0 ? from where ? ... from IDA Very Happy
Image
Code:
extrn "_KeGetCurrentIrql@0" as KeGetCurrentIrql 
extrn __imp__KeGetCurrentIrql@0:dword 
        … 
call    KeGetCurrentIrql                ; through thunk 
call    [__imp__KeGetCurrentIrql@0]     ; direct
    


ok, thank you.
call [_KeGetCurrentIrql@0] .. doesn't work
but
call [__imp___KeGetCurrentIrql@0] ... works fine !

"__imp__" ... I do not knew this directive ! Embarassed

thank a lot,

but :

"call KeGetCurrentIrql"

also works without problem with only :

extrn "_KeGetCurrentIrql@0" as KeGetCurrentIrql

(without "__imp"__")

Finally, should I use "__imp__" or not ??

(thank you for your help baldr)

_________________
I am not young enough to know everything (Oscar Wilde)- Image
Post 20 Jan 2010, 16:28
View user's profile Send private message Send e-mail Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 20 Jan 2010, 22:20
ouadji,

_KeGetCurrentIrql@0 in your program is not the same as _KeGetCurrentIrql@0 in HAL.DLL.

My example shows the difference between two public symbols in HAL.Lib import library:

1. __imp__KeGetCurrentIrql@0 refers to dword from IAT that will point to actual function in HAL.DLL (so you can call that function via call [__imp__KeGetCurrentIrql@0]).

2. _KeGetCurrentIrql@0 refers to thunk that consists of jmp [__imp__KeGetCurrentIrql@0]. This thunk will be statically linked to your program, so you can call it via call _KeGetCurrentIrql@0 and it transfers control to the address pointed by __imp__KeGetCurrentIrql@0 dword. Effectively the same as (1).

__imp__ is not a directive, it is a part of "decorated name" (AKA "mangled"). Actually __imp__KeGetCurrentIrql@0 is KeGetCurrentIrql decorated thrice: once as _KeGetCurrentIrql@0 (stdcall function without parameters), then as _imp__KeGetCurrentIrql@0 (note single underscore, it is "undecorated" name for pointer from IAT, __declspec(dllimport) storage class uses it), and finally __imp__KeGetCurrentIrql@0 (variables get underscore prepended as decoration, like cdecl functions). Confusing, isn't it? Look at this C source (yes, it works):
Code:
extern int printf(char *fmt, ...), (*_imp__printf)(char *fmt, ...);

void main() {
 printf("_imp__printf==%x\n", _imp__printf);
      _imp__printf("printf==%x\n", printf);
}    
First pointer (printed via jmp thunk) is actual function address, second (via call directly into MSVCRT) is address of thunk.

As to direct vs. thunked call: it's memory vs. speed tradeoff. Direct call (goddammit, instruction is "indirect call" Wink) is 1 byte longer than thunked ("relative call"), but thunk itself is 6-bytes "indirect jump". Moreover, IAT almost always is paged-in and page with thunk can be not present yet. Functions that get called once or twice are definitely candidates for call through IAT.
Post 20 Jan 2010, 22:20
View user's profile Send private message Reply with quote
ouadji



Joined: 24 Dec 2008
Posts: 1081
Location: Belgium
ouadji 20 Jan 2010, 23:01

your explanation is very clear. I understand now ! Very Happy

all things considered, i prefer this way of declaring:
Code:
extrn '__imp__KeGetCurrentIrql@0' as KeGetCurrentIrql :dword
+
Call [KeGetCurrentIrql] (or invoke KeGetCurrentIrql)
    
This allows me to avoid the "thunk" in memory.
I think this indirection is unnecessary.
Quote:
it's memory vs. speed tradeoff

i prefer speed ! ... 7 nano sec less! it is very important ! no ? Razz

Thank you very much baldr ! nice of you !

_________________
I am not young enough to know everything (Oscar Wilde)- Image
Post 20 Jan 2010, 23:01
View user's profile Send private message Send e-mail Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.