Looking for an ASM equivalent to calling (C++) LoadLibrary(), GetProcAddress(), and calling the returned proc address. I have dissassembled a small program that does this, but the way that the address of these functions are being referenced is unclear to me. Perhaps if I understand how a statically stubbed reference to these functions worked, it would be clear as to how to call a function in an external DLL, removing the need for LoadLibrary() et al.
Posted on 2004-08-30 23:12:57 by Randalism
>>how to call a function in an external DLL, removing the need for LoadLibrary() et al.

good luck :-D
Posted on 2004-08-31 00:03:11 by JimmyClif
What do you mean? The functions are to be loaded dynamically (ie not using IAT) or using IAT?
Posted on 2004-08-31 06:06:30 by roticv
i don't understand your question either. if you don't want to use loadlibrary you'll need the IAT (and the assembler/linker will do that job for you) or you have to obtain the module base in another way (but i have no idea why you to do want something like that)
Posted on 2004-08-31 09:14:39 by lifewire
Sorry if my original post made it seem so, but I am not looking for a way to get around using LoadLibrary() et al, I was just wondering if a native, lower-level mechanism for this sort of operation exists.
As far as accomplishing my goal (writing a peice of NASM code that calls a function in another DLL) is concerned, whatever works will suit me just fine.

My problem now is finding out how to call Win32 API functions (like LoadLibrary, GetProcAddress and FreeLibrary) in NASM. I have written a short C program:



typedef int (*ABSPROC)( int );

ABSPROC pAbsFn = NULL;

HMODULE hm = ::LoadLibrary( "ntdll.dll" );

if ( hm != NULL )
{
pAbsFn = (ABSPROC)::GetProcAddress( hm, "abs" );

if ( pAbsFn != NULL )
{
long lInput = -1;

long lOutput = pAbsFn( lInput );
}

::FreeLibrary( hm );
}


The disassembly (BDASM) of which is:



.text:10001000: 55 push ebp
.text:10001001: 8BEC mov ebp, esp
.text:10001003: 83EC10 sub esp, 10
.text:10001006: C745F800000000 mov dword ptr [ebp-08], 00000000
.text:1000100D: 6834600010 push 10006034 ; 'ntdll.dll'

; Reference to import LoadLibraryA - Ord: 01C2h

.text:10001012: FF1508500010 call [10005008]
.text:10001018: 8945FC mov [ebp-04], eax
.text:1000101B: 837DFC00 cmp dword ptr [ebp-04], 00
.text:1000101F: 7436 je 10001057
.text:10001021: 6830600010 push 10006030 ; 'abs'
.text:10001026: 8B45FC mov eax, [ebp-04]
.text:10001029: 50 push eax

; Reference to import GetProcAddress - Ord: 013Eh

.text:1000102A: FF1504500010 call [10005004] ; reference to segment '.rdata'
.text:10001030: 8945F8 mov [ebp-08], eax
.text:10001033: 837DF800 cmp dword ptr [ebp-08], 00
.text:10001037: 7414 je 1000104d
.text:10001039: C745F0FFFFFFFF mov dword ptr [ebp-10], ffffffff
.text:10001040: 8B4DF0 mov ecx, [ebp-10]
.text:10001043: 51 push ecx
.text:10001044: FF55F8 call [ebp-08]
.text:10001047: 83C404 add esp, 04
.text:1000104A: 8945F4 mov [ebp-0c], eax
.text:1000104D:loc_1000104D:
.text:1000104D: 8B55FC mov edx, [ebp-04]
.text:10001050: 52 push edx

; Reference to import FreeLibrary - Ord: 00B4h

.text:10001051: FF1500500010 call [10005000]
.text:10001057:loc_10001057: ; Referenced 1 time(s)
.text:10001057: B801000000 mov eax, 00000001
.text:1000105C: 8BE5 mov esp, ebp
.text:1000105E: 5D pop ebp
.text:1000105F: C20C00 ret 000c
.text:10001062:loc_10001062:
.text:10001062: 8B442408 mov eax, [esp+08]
.text:10001066: 83F801 cmp eax, 01
.text:10001069: 0F8588000000 jnz 100010f7



I have not yet found a way to get BDASM to show me the format of the data (in the .rdata segment) that holds the key to being able to ?call [.rdata_address]?. I have been looking through hex dumps of the binary image to try and make sense of it all. I am about to try looking at hex dumps of kernel32.lib (static library for the functions provided by kernel32.dll).

As to why I am doing this, I am writing an event logging system for a DLL to which I do not have the source code. I am attempting to call the logging DLL functions from the main DLL, and the only way to modify this DLL is through disassemble/reassemble with BDASM/NASM. I am sure this will be a snap, once I figure out how to call the Win32 APIs for loading and calling functions in an external DLL.
Posted on 2004-08-31 12:25:01 by Randalism
In NASM, you can use the IMPORT statement to make an import in an OMF file.
The format is:
IMPORT symbol filename
If the exported name is omitted, it is assumed to be the same as the symbol assigned to to the import.
You have to declare these symbols as extern, with:
EXTERN symbol

You can not have imports in COFF files.
Posted on 2004-08-31 14:39:25 by Sephiroth3
Randalism, if you want to call DLL functions, it's either through implicit dynamic linking (use of import libraries, PE import section) or through runtime dynamic linking (LoadLibrary + GetProcAddress).

There's some "lower level" ways of doing this, but it's somewhat dirty and platform-specific, and in your case it doesn't sound like there's a need for it.

If you're going to call the DLL in a program that is already running, LoadLibrary and GetProcAddress is probably the best method.

Here's a VERY simple nasm example, raw and unsugared, assuming that you're using Microsoft-style import libraries and the MS linker:

nasm -fwin32 test.asm
link /subsystem:windows /entry:entry test.obj kernel32.lib



BITS 32
SECTION .data

hLibrary dd 0
pProc dd 0
szDllName db "ntdll.dll", 0
szFuncName db "abs", 0

EXTERN _FreeLibrary@4
EXTERN _LoadLibraryA@4
EXTERN _GetProcAddress@8
EXTERN _ExitProcess@4

GLOBAL _entry

SECTION .text

_entry:
push szDllName
call _LoadLibraryA@4
mov [hLibrary], eax

push szFuncName
push eax ; DLL handle
call _GetProcAddress@8

mov [pProc], eax
push dword -10
call eax ; ntdll:abs

push dword -20
call dword [pProc]

push dword [hLibrary]
call _FreeLibrary@4

push dword 0
call _ExitProcess@4
Posted on 2004-09-01 05:03:18 by f0dder
f0dder,
Thanks for the source.

Since I am using BDASM/NASM to assemble-on-the-fly, I can not use ?EXTERN? or other pre-linker notation. I will have to perform the linking manually by crafting an .rdata-like segment (the DLL I am modifying has no .rdata segment), pasting it into the binary and somehow referencing it with a virtual address like ?[10005000]?. I am still not sure of how to go about this, or why virtual addressing is necessary at all.

I would happily receive any ?dirty? lower-level methods you could share with me. I am basically working at the opcode level at this point.

I found this in the .rdata segment (IMPORT Hints/Names & DLL Names) of one of my own disassembled C programs (text data shown as text):



B4 00 FreeLibrary 00
3E 01 GetProcAddress 00
C2 01 LoadLibraryA 00 00
KERNEL32.dll 00 00
(other kernel32.dll functions?)


I thought it was interesting that the 3 kernel32.dll functions my C code calls are listed (in reverse order of the actual calls), followed by a double terminator (?\0\0?), the DLL name (?KERNEL32.dll?), another double terminator (?\0\0?) and a list of what seems to be all of the other entry points exported by kernel32.dll. The 2-byte prefix of each imported function name matches the ?hint? ordinal exposed by the dependency walker (depends.exe) with kernel32.dll opened.

Questions:
    If I were to construct a data field, like the one above, could I use it to ?link? to any function exposed by another DLL (or does this methodology only apply to Win32 APIs)?
    Where should I place it?
    How should I reference it (via a ?call? operation)?
    Must it reside in an .rdata segment?
    Is there a way to attach an .rdata segment to a binary PE file that currently does not have one?
Posted on 2004-09-01 09:52:32 by Randalism