Getmodulehandle(Null) on Linux

GetModuleHandle(NULL) on Linux

The documentation for dlopen(3) states:

The function dlopen() loads the dynamic library file named by the
null-terminated string filename and returns an opaque "handle" for the
dynamic library. If filename is NULL, then the returned handle is for
the main program.

Therefore, you can use the value returned by dlopen(NULL) as the handle argument to dlsym().

GetModuleHandle(NULL) vs hInstance

In an EXE, it does not make any difference. hInstance from WinMain() and GetModuleHandle(NULL) both refer to the same HINSTANCE (the module of the .exe file). But it does make a difference if you are creating windows inside of a DLL instead, since you have to use the DLL's hInstance but GetModuleHandle(NULL) will still return the HINSTANCE of the EXE that loaded the DLL.

Why doesn't this code work (Please See Details)?

The code fails because GetProcAddress requires the supplied symbol to have been exported from the module in question. That is, the symbol must have been listed in the PE module's export table. You do not export the symbol, and so GetProcAddress cannot find it. Hence GetProcAddress returns NULL. If you wish to use GetProcAddress then you must export the symbol. Either by naming it in a .def file, or by using __declspec(dllexport).

Some other comments:

  1. You appear to have a mismatch of calling conventions, stdcall and cdecl.
  2. You don't perform any error checking. For these particular function you need to check the return value. If that indicates that the function has failed, then call GetLastError for extended error information.

How does GetModuleHandle work in Visual c++

You can only call GetModuleHandle(L"C:\\Users\\Steve\\Desktop\\stub.exe"); when you're running C:\Users\Steve\Desktop\stub.exe.

But in general, you don't call GetModuleHandle for your EXE name. Since there's only one EXE per process, you just call GetModuleHandle(0).

How to determine if a so file has been loaded or not?

You can actually use dlopen to check this, with the RTLD_NOLOAD flag:

Don't load the library. This can be used to test if the library is already resident (dlopen() returns NULL if it is not, or the library's handle if it is resident).

Get loaded address of a ELF binary, dlopen is not working as expected

On Linux, dlopen doesn't return the address where the ELF binary was loaded. It returns struct link_map instead, which has .l_addr member. So you'll want something like:

struct link_map *lm = (struct link_map*) dlopen(0, RTLD_NOW);
printf("%p\n", lm->l_addr);

However, despite what comment in /usr/include/link.h says, .l_addr is actually not a load address either. Instead, it's the difference between where ELF image was linked to load, and where it was actually loaded.

For non-PIE main executable, that difference is always 0. For non-prelinked shared library, that difference is always the load address (because non-prelinked ELF shared libraries are linked to load at address 0).

So how do you find the base address of the main executable? The easiest method is to use this code (linked into main executable):

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <link.h>
#include <stdio.h>
#include <stdlib.h>

static int
callback(struct dl_phdr_info *info, size_t size, void *data)
{
int j;
const char *cb = (const char *)&callback;
const char *base = (const char *)info->dlpi_addr;
const ElfW(Phdr) *first_load = NULL;

for (j = 0; j < info->dlpi_phnum; j++) {
const ElfW(Phdr) *phdr = &info->dlpi_phdr[j];

if (phdr->p_type == PT_LOAD) {
const char *beg = base + phdr->p_vaddr;
const char *end = beg + phdr->p_memsz;

if (first_load == NULL) first_load = phdr;
if (beg <= cb && cb < end) {
// Found PT_LOAD that "covers" callback().
printf("ELF header is at %p, image linked at 0x%zx, relocation: 0x%zx\n",
base + first_load->p_vaddr, first_load->p_vaddr, info->dlpi_addr);
return 1;
}
}
}
return 0;
}

int
main(int argc, char *argv[])
{
dl_iterate_phdr(callback, NULL);
exit(EXIT_SUCCESS);
}

Here is what you should see on 32-bit system:

$ gcc -g t.c -ldl -m32  && ./a.out
ELF header is at 0x8048000, image linked at 0x8048000, relocation: 0x0
$ gcc -g t.c -ldl -m32 -pie -fPIE && ./a.out
ELF header is at 0xf779a000, image linked at 0x0, relocation: 0xf779a000

(The last address: 0xf779a000 will vary from run to run if you have address randomization enabled (as you should)).

How to check if stdout has been redirected to NUL on Windows (a.k.a. /dev/null on Linux)?

I figured it out myself. It's annoying.

#include <Windows.h>
#include <io.h>
#pragma comment(lib, "ntdll.lib") // can instead use GetProcAddress (below)
extern "C" NTSTATUS __stdcall NtQueryVolumeInformationFile(
HANDLE FileHandle, struct _IO_STATUS_BLOCK *IoStatusBlock,
void *FsInformation, unsigned long Length,
enum _FSINFOCLASS FsInformationClass);
bool isdevnull(FILE *file)
{
struct FILE_FS_DEVICE_INFORMATION
{ unsigned long DeviceType, Characteristics; } fsinfo;
struct { void *info, *status; } iosb;
typedef NTSTATUS (__stdcall *PNTQIF)(
HANDLE FileHandle, struct _IO_STATUS_BLOCK *IoStatusBlock,
void *FsInformation, unsigned long Length,
enum _FSINFOCLASS FsInformationClass);
PNTQIF const ntqif =
true // True if you have ntdll.lib, false otherwise
? NtQueryVolumeInformationFile
: (PNTQIF) GetProcAddress(
GetModuleHandle(TEXT("ntdll.dll")),
"NtQueryVolumeInformationFile");
return ntqif(
(HANDLE) _get_osfhandle(_fileno(stdout)),
(struct _IO_STATUS_BLOCK *)&iosb,
&fsinfo, sizeof(fsinfo),
(enum _FSINFOCLASS)4
) == 0 && fsinfo.DeviceType == 0x00000015 /*FILE_DEVICE_NULL*/;
}
int main()
{
bool b = isdevnull(stdout);
}


Related Topics



Leave a reply



Submit