The GL loader generated with GLLoadGen contains the following code:
static void* AppleGLGetProcAddress (const GLubyte *name)
{
static const struct mach_header* image = NULL;
NSSymbol symbol;
char* symbolName;
if (NULL == image)
{
image = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
}
/* prepend a '_' for the Unix C symbol mangling convention */
symbolName = (char*)malloc(strlen((const char*)name) + 2);
strcpy(symbolName+1, (const char*)name);
symbolName[0] = '_';
symbol = NULL;
/* if (NSIsSymbolNameDefined(symbolName))
symbol = NSLookupAndBindSymbol(symbolName); */
symbol = image ? NSLookupSymbolInImage(image, symbolName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) : NULL;
free(symbolName);
return symbol ? NSAddressOfSymbol(symbol) : NULL;
}
This function apparently loads the address of the OpenGL function name. However the calls to NSAddImage and related are deprecated since OSX 10.5. What is the current (non-deprecated) approach to load the function addresses?
dlopen(), dlsym() and friends are probably the best option. This will also make your code more portable, since they are available on most Unix systems as well.
Following is some code I've used in the past to load GL functions on Mac OSX (tested on version 10.8, should still work OK for Mavericks):
// Handle to the OpenGL dynlib:
static void * glLibrary;
// Path to GL on OSX. True for version 10.8.
static const char * glLibPath = "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL";
// Loads the OpenGL library:
void LoadGL()
{
// Load GL dynlib:
glLibrary = dlopen(glLibPath, RTLD_LAZY);
if (!glLibrary)
{
const char * error = dlerror();
// handle error
}
}
// Unloads the GL library:
void UnloadGL()
{
if (glLibrary)
{
if (dlclose(glLibrary) != 0)
{
// problem...
}
glLibrary = NULL;
}
}
// Grab a function pointer form the previously loaded GL library:
void * GetGLFunctionPointer(const char * funcName)
{
assert(funcName != NULL);
assert(glLibrary != NULL && "OpenGL dynlib not yet loaded!");
return dlsym(glLibrary, funcName);
}
// Usage example:
int main()
{
LoadGL();
void * fn = GetGLFunctionPointer("glEnable");
assert(fn != NULL);
UnloadGL();
return 0;
}
Related
I'm trying to list all the mount points in a kernel module. The method in this answer doesn't list all the mount point, and this answer is for older kernel version.
I'm working on kernel version 4.15.0.
I found this method (iterate_mounts) and wrote this simple kernel module.
int mount_f(struct vfsmount *mnt, void *arg)
{
char *tmp, *path;
if(mnt == NULL || mnt->mnt_root == NULL)
{
return 0;
}
tmp = (char*)__get_free_page(GFP_KERNEL);
path = dentry_path_raw(mnt->mnt_root, tmp, PAGE_SIZE);
if(!IS_ERR(path))
{
pr_info("mounted path=%s\n", path);
}
free_page((unsigned long)tmp);
return 0;
}
int init_module(void)
{
struct path path;
struct vfsmount *root_mnt;
int err;
err = kern_path("/", 0, &path);
if (err)
{
return -1;
}
root_mnt = path.mnt;
path_put(&path);
if (IS_ERR(root_mnt))
{
return -1;
}
iterate_mounts(mount_f, NULL, root_mnt);
return 0;
}
but it doesn't print the correct path (it prints just "/" for all mounts).
Am I missing something here?
Also, which methods gets called when a new mount is mounted or unmounted?
I'm assuming for unmounting (do_umount) gets called?
Edit: another question, how can I identify the mount if it's removable or not? any flags in the struct vfsmount or struct super_block that can help me identify that?
I'm trying to see how I can get a loaded module image name from an arbitrary address from the kernel code.
In user mode I would do this:
void* pAddr;
VOID* pBase;
WCHAR buff[MAX_PATH] = {0};
//Get address of some function in some module (just to test it)
pAddr = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetCurrentProcess");
//Get module base address
RtlPcToFileHeader(pAddr, &pBase);
//Get module image file name
GetModuleFileNameEx(GetCurrentProcess(), (HMODULE)pBase, buff, SIZEOF(buff));
Is there a way to do the same in kernel mode if I have pAddr that can point to some address in kernel or user space?
EDIT: While waiting for the answer I came up with my own code (using undocumented way of traversing PEB):
#ifdef CALLING_FROM_KERNEL_MODE
//Kernel mode
TEB* pTEB = (TEB*)PsGetCurrentThreadTeb();
#else
//User mode
#if defined(_M_X64)
//64-bit
TEB* pTEB = reinterpret_cast<TEB*>(__readgsqword(reinterpret_cast<DWORD_PTR>(&static_cast<NT_TIB*>(nullptr)->Self)));
#else
//32-bit
TEB* pTEB = reinterpret_cast<TEB*>(__readfsdword(reinterpret_cast<DWORD_PTR>(&static_cast<NT_TIB*>(nullptr)->Self)));
#endif
#endif
PEB* p_PEB = pTEB->ProcessEnvironmentBlock;
PEB_LDR_DATA* pPLD = p_PEB->Ldr;
const WCHAR* pModName = NULL;
LIST_ENTRY* pLE = &pPLD->InMemoryOrderModuleList;
LIST_ENTRY* pLE_Head = pLE;
while(pLE_Head != pLE->Flink)
{
PLDR_DATA_TABLE_ENTRY pLDTE = CONTAINING_RECORD(pLE, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
size_t szcbSizeOfImg = (size_t)pLDTE->Reserved3[1];
if((size_t)pAddr - (size_t)pLDTE->DllBase < szcbSizeOfImg)
{
pModName = pLDTE->FullDllName.Buffer;
break;
}
pLE = pLE->Flink;
}
The problem is that although it works from a user-mode, from a kernel mode PsGetCurrentThreadTeb() seems to return NULL. Does this mean kernel threads do not have a TEB?
this can be done by creating list of all loaded modules via ZwQuerySystemInformation with SystemModuleInformation
void fgt(PVOID *Callers, ULONG Count)
{
NTSTATUS status;
ULONG cb = 0x10000;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (PRTL_PROCESS_MODULES prpm = (PRTL_PROCESS_MODULES)ExAllocatePool(PagedPool, cb))
{
if (0 <= (status = NtQuerySystemInformation(SystemModuleInformation, prpm, cb, &cb)))
{
do
{
PVOID Caller = *Callers++;
if (ULONG NumberOfModules = prpm->NumberOfModules)
{
PRTL_PROCESS_MODULE_INFORMATION Modules = prpm->Modules;
do
{
if ((SIZE_T)Caller - (SIZE_T)Modules->ImageBase < Modules->ImageSize)
{
DbgPrint("%p> %s\n", Caller, Modules->FullPathName);
break;
}
} while (Modules++, --NumberOfModules);
}
} while (--Count);
}
ExFreePool(prpm);
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
}
I'm working on a heap profiler for Linux, called heaptrack. Currently, I rely on LD_PRELOAD to overload various (de-)allocation functions, and that works extremely well.
Now I would like to extend the tool to allow runtime attaching to an existing process, which was started without LD_PRELOADing my tool. I can dlopen my library via GDB just fine, but that won't overwrite malloc etc. I think, this is because at that point the linker already resolved the position dependent code of the already running process - correct?
So what do I do instead to overload malloc and friends?
I am not proficient with assembler code. From what I've read so far, I guess I'll somehow have to patch malloc and the other functions, such that they first call back to my trace function and then continue with their actual implementation? Is that correct? How do I do that?
I hope there are existing tools out there, or that I can leverage GDB/ptrace for that.
Just for the lulz, another solution without ptracing your own process or touching a single line of assembly or playing around with /proc. You only have to load the library in the context of the process and let the magic happen.
The solution I propose is to use the constructor feature (brought from C++ to C by gcc) to run some code when a library is loaded. Then this library just patch the GOT (Global Offset Table) entry for malloc. The GOT stores the real addresses for the library functions so that the name resolution happen only once. To patch the GOT you have to play around with the ELF structures (see man 5 elf). And Linux is kind enough to give you the aux vector (see man 3 getauxval) that tells you where to find in memory the program headers of the current program. However, better interface is provided by dl_iterate_phdr, which is used below.
Here is an example code of library that does exactly this when the init function is called. Although the same could probably be achieved with a gdb script.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <sys/auxv.h>
#include <elf.h>
#include <link.h>
#include <sys/mman.h>
struct strtab {
char *tab;
ElfW(Xword) size;
};
struct jmpreltab {
ElfW(Rela) *tab;
ElfW(Xword) size;
};
struct symtab {
ElfW(Sym) *tab;
ElfW(Xword) entsz;
};
/* Backup of the real malloc function */
static void *(*realmalloc)(size_t) = NULL;
/* My local versions of the malloc functions */
static void *mymalloc(size_t size);
/*************/
/* ELF stuff */
/*************/
static const ElfW(Phdr) *get_phdr_dynamic(const ElfW(Phdr) *phdr,
uint16_t phnum, uint16_t phentsize) {
int i;
for (i = 0; i < phnum; i++) {
if (phdr->p_type == PT_DYNAMIC)
return phdr;
phdr = (ElfW(Phdr) *)((char *)phdr + phentsize);
}
return NULL;
}
static const ElfW(Dyn) *get_dynentry(ElfW(Addr) base, const ElfW(Phdr) *pdyn,
uint32_t type) {
ElfW(Dyn) *dyn;
for (dyn = (ElfW(Dyn) *)(base + pdyn->p_vaddr); dyn->d_tag; dyn++) {
if (dyn->d_tag == type)
return dyn;
}
return NULL;
}
static struct jmpreltab get_jmprel(ElfW(Addr) base, const ElfW(Phdr) *pdyn) {
struct jmpreltab table;
const ElfW(Dyn) *dyn;
dyn = get_dynentry(base, pdyn, DT_JMPREL);
table.tab = (dyn == NULL) ? NULL : (ElfW(Rela) *)dyn->d_un.d_ptr;
dyn = get_dynentry(base, pdyn, DT_PLTRELSZ);
table.size = (dyn == NULL) ? 0 : dyn->d_un.d_val;
return table;
}
static struct symtab get_symtab(ElfW(Addr) base, const ElfW(Phdr) *pdyn) {
struct symtab table;
const ElfW(Dyn) *dyn;
dyn = get_dynentry(base, pdyn, DT_SYMTAB);
table.tab = (dyn == NULL) ? NULL : (ElfW(Sym) *)dyn->d_un.d_ptr;
dyn = get_dynentry(base, pdyn, DT_SYMENT);
table.entsz = (dyn == NULL) ? 0 : dyn->d_un.d_val;
return table;
}
static struct strtab get_strtab(ElfW(Addr) base, const ElfW(Phdr) *pdyn) {
struct strtab table;
const ElfW(Dyn) *dyn;
dyn = get_dynentry(base, pdyn, DT_STRTAB);
table.tab = (dyn == NULL) ? NULL : (char *)dyn->d_un.d_ptr;
dyn = get_dynentry(base, pdyn, DT_STRSZ);
table.size = (dyn == NULL) ? 0 : dyn->d_un.d_val;
return table;
}
static void *get_got_entry(ElfW(Addr) base, struct jmpreltab jmprel,
struct symtab symtab, struct strtab strtab, const char *symname) {
ElfW(Rela) *rela;
ElfW(Rela) *relaend;
relaend = (ElfW(Rela) *)((char *)jmprel.tab + jmprel.size);
for (rela = jmprel.tab; rela < relaend; rela++) {
uint32_t relsymidx;
char *relsymname;
relsymidx = ELF64_R_SYM(rela->r_info);
relsymname = strtab.tab + symtab.tab[relsymidx].st_name;
if (strcmp(symname, relsymname) == 0)
return (void *)(base + rela->r_offset);
}
return NULL;
}
static void patch_got(ElfW(Addr) base, const ElfW(Phdr) *phdr, int16_t phnum,
int16_t phentsize) {
const ElfW(Phdr) *dphdr;
struct jmpreltab jmprel;
struct symtab symtab;
struct strtab strtab;
void *(**mallocgot)(size_t);
dphdr = get_phdr_dynamic(phdr, phnum, phentsize);
jmprel = get_jmprel(base, dphdr);
symtab = get_symtab(base, dphdr);
strtab = get_strtab(base, dphdr);
mallocgot = get_got_entry(base, jmprel, symtab, strtab, "malloc");
/* Replace the pointer with our version. */
if (mallocgot != NULL) {
/* Quick & dirty hack for some programs that need it. */
/* Should check the returned value. */
void *page = (void *)((intptr_t)mallocgot & ~(0x1000 - 1));
mprotect(page, 0x1000, PROT_READ | PROT_WRITE);
*mallocgot = mymalloc;
}
}
static int callback(struct dl_phdr_info *info, size_t size, void *data) {
uint16_t phentsize;
data = data;
size = size;
printf("Patching GOT entry of \"%s\"\n", info->dlpi_name);
phentsize = getauxval(AT_PHENT);
patch_got(info->dlpi_addr, info->dlpi_phdr, info->dlpi_phnum, phentsize);
return 0;
}
/*****************/
/* Init function */
/*****************/
__attribute__((constructor)) static void init(void) {
realmalloc = malloc;
dl_iterate_phdr(callback, NULL);
}
/*********************************************/
/* Here come the malloc function and sisters */
/*********************************************/
static void *mymalloc(size_t size) {
printf("hello from my malloc\n");
return realmalloc(size);
}
And an example program that just loads the library between two malloc calls.
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void loadmymalloc(void) {
/* Should check return value. */
dlopen("./mymalloc.so", RTLD_LAZY);
}
int main(void) {
void *ptr;
ptr = malloc(42);
printf("malloc returned: %p\n", ptr);
loadmymalloc();
ptr = malloc(42);
printf("malloc returned: %p\n", ptr);
return EXIT_SUCCESS;
}
The call to mprotect is usually useless. However I found that gvim (which is compiled as a shared object) needs it. If you also want to catch the references to malloc as pointers (which may allow to later call the real function and bypass yours), you can apply the very same process to the symbol table pointed to by the DT_RELA dynamic entry.
If the constructor feature is not available for you, all you have to do is resolve the init symbol from the newly loaded library and call it.
Note that you may also want to replace dlopen so that libraries loaded after yours gets patched as well. Which may happen if you load your library quite early or if the application has dynamically loaded plugins.
This can not be done without tweaking with assembler a bit. Basically, you will have to do what gdb and ltrace do: find malloc and friends virtual addresses in the process image and put breakpoints at their entry. This process usually involves temporary rewriting the executable code, as you need to replace normal instructions with "trap" ones (such as int 3 on x86).
If you want to avoid doing this yourself, there exists linkable wrapper around gdb (libgdb) or you can build ltrace as a library (libltrace). As ltrace is much smaller, and the library variety of it is available out of the box, it will probably allow you to do what you want at lower effort.
For example, here's the best part of the "main.c" file from the ltrace package:
int
main(int argc, char *argv[]) {
ltrace_init(argc, argv);
/*
ltrace_add_callback(callback_call, EVENT_SYSCALL);
ltrace_add_callback(callback_ret, EVENT_SYSRET);
ltrace_add_callback(endcallback, EVENT_EXIT);
But you would probably need EVENT_LIBCALL and EVENT_LIBRET
*/
ltrace_main();
return 0;
}
http://anonscm.debian.org/cgit/collab-maint/ltrace.git/tree/?id=0.7.3
I'm trying to locate the entry for wglGetProcAddress (OpenGl32.dll) imported in a test application. For some reason, the import whose name is "wglGetProcAddress" does point to the same function returned by calling GetModuleHandle and GetProcAddress on Opengl32.dll.
The executable file has been loaded into memory and is a process with its thread currently suspended. The following code correctly reads the names modules and their functions imported by that executable. Hence, the IAT should not contain RVAs since it has been loaded.
HMODULE h = GetModuleHandle("OPENGL32.dll");
DWORD expect_addr = (DWORD)GetProcAddress(h, "wglGetProcAddress");
PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)(pmem + import_dir);
while (import_desc->Name)
{
PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)(pmem + import_desc->OriginalFirstThunk);
while (thunk->u1.Function)
{
PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME)(pmem + thunk->u1.AddressOfData);
printf("%s 0x%X\n", import->Name, thunk->u1.Function);
if ((DWORD)expect_addr == (DWORD)thunk->u1.Function)
{
printf("Found wglGetProcAddress\n");
}
else if (!strcmp((const char*)import->Name, "wglGetProcAddress"))
{
printf("Found wglGetProcAddress's import, but the function has a different value.\n");
}
++thunk;
}
++import_desc;
}
GetProcAddress from that original value returns the address 60XXC245 where XX varies, but thunk->u1.Function always returns 0xA46D8. Everything in thunk->u1 (Function, AddressOfData, Ordinal and ForwarderString) has
the same value. The names of the import descriptors and imports correct. Does anyone see what I'm missing?
Edit:
I'm trying something else: I'm scanning pmem (image of the executable in memory) for what I expect is the IAT entry, but it doesn't locate that either:
HMODULE h = GetModuleHandle("OPENGL32.dll");
DWORD expect_addr = (DWORD)GetProcAddress(h, "wglGetProcAddress");
printf("Looking for 0x%X\n", expect_addr);
for (int i = 0; i < pmem_size - sizeof(DWORD); i++)
{
if (*(DWORD*)(pmem + i) == expect_addr)
{
printf("0x%X at 0x%X\n", *(DWORD*)(pmem + i), i);
}
}
SOLVED: I didn't realize it, but calling CreateProcess with CREATE_SUSPENDED prevents the windows loader from populating FirstThunk with the actual addresses. If I let the process run for a second and then suspend the thread, it hooks the IAT address perfectly fine. Now I have to go look for a way to fix that.
u1.Function represents the relative offset to the IMAGE_IMPORT_BY_NAME entry (or the ordinal entry if the IMAGE_ORDINAL_FLAG bit is set). this is why it doesn't match the value from GetProcAddress, because it isn't the address of the function, its the address of the function import entry.
When you have found the thunk matching your function, you need to use this too lookup the virtualized address altered by the linker, form the other thunk list. altering your code so it does this yeilds:
while (import_desc->Name)
{
PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)((DWORD)GetModuleHandle(NULL) + import_desc->OriginalFirstThunk);
int i = 0;
while (thunk->u1.Function)
{
PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME)((DWORD)GetModuleHandle(NULL) + thunk->u1.AddressOfData);
void** p = (void**)((DWORD)GetModuleHandle(NULL) + import_desc->FirstThunk);
printf("%s 0x%X\n", import->Name, p[i]);//thunk->u1.Function);
if ((DWORD)expect_addr == (DWORD)p[i])
{
printf("Found wglGetProcAddress\n");
}
else if (!strcmp((const char*)import->Name, "wglGetProcAddress"))
{
printf("Found wglGetProcAddress's import, but the function has a different value.\n");
}
++thunk;
}
++import_desc;
}
To get the IAT entries, I do things a little differently:
inline const void** GetImportAddress(HMODULE hModule, IMAGE_IMPORT_DESCRIPTOR* pTable, size_t nThunk)
{
const void** pAddressBlock = (const void**)((DWORD)hModule + pTable->FirstThunk);
return &pAddressBlock[nThunk];
}
const void** GetImport(HMODULE hModule, const char* szDll, const char* szFunction)
{
const char* szDllName = NULL;
IMAGE_IMPORT_DESCRIPTOR* pTable = GetImportDescriptor(hModule);
while(pTable->Characteristics != 0 && (szDllName = GetImportTableName(hModule,pTable)) != NULL)
{
if(!lstrcmpiA(szDll,szDllName))
{
IMAGE_THUNK_DATA* pThunkData = GetThunk(hModule,pTable);
if(pThunkData != NULL)
{
size_t nThunk = 0;
while(pThunkData->u1.AddressOfData != 0)
{
if(pThunkData->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
if(IMAGE_ORDINAL32(pThunkData->u1.Ordinal) == (DWORD)szFunction)
return GetImportAddress(hModule,pTable,nThunk);
}
else
{
IMAGE_IMPORT_BY_NAME* pImport = GetImport(hModule,pThunkData);
if(!lstrcmpA(szFunction,(const char*)pImport->Name))
return GetImportAddress(hModule,pTable,nThunk);
}
nThunk++;
pThunkData++;
}
}
}
pTable++;
}
return NULL;
}
I'm trying to debug some code that uses COM, which I am a beginner at.
The two calls to IUnknown::Release at the end have got me worried.
The interfaces were created with DllGetClassObject and IClassFactory::CreateInstance.
I have seen other similar code that does not call IUnknown::Release on these - which is correct?
int OpenMixer_Win_DirectSound(px_mixer *Px, int index)
{
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA desc;
HMODULE hDsound = INVALID_HANDLE_VALUE;
GCO DllGetClassObject;
IClassFactory *pcf = NULL;
IKsPropertySet *pps = NULL;
HRESULT hr;
ULONG bytes;
LPGUID guidIn;
LPGUID guidOut;
UINT deviceIn = -1;
UINT deviceOut = -1;
int ret = FALSE;
guidIn = PaWinDS_GetStreamInputGUID(Px->pa_stream);
guidOut = PaWinDS_GetStreamOutputGUID(Px->pa_stream);
do {
hDsound = LoadLibraryA("dsound.dll");
if (hDsound == NULL) {
break;
}
DllGetClassObject = (GCO) GetProcAddress(hDsound, "DllGetClassObject");
if (DllGetClassObject == NULL) {
break;
}
hr = DllGetClassObject(&CLSID_DirectSoundPrivate,
&IID_IClassFactory,
(void **)(&pcf));
if (hr || pcf == NULL) {
break;
}
hr = IClassFactory_CreateInstance(pcf,
NULL,
&IID_IKsPropertySet,
(void **)(&pps));
if (hr || pps == NULL) {
break;
}
/* Do stuff with the interfaces */
} while( FALSE );
if (pps) {
IUnknown_Release(pps);
}
if (pcf) {
IUnknown_Release(pcf);
}
// Free the library. Note that portaudio also opens dsound.dll
// so this probably doesn't do anything until Pa_Terminate is called.
if (hDsound != INVALID_HANDLE_VALUE) {
FreeLibrary(hDsound);
}
}
Absolutely. Both functions create a new interface pointer, they will have a reference count of 1, the AddRef() function was already called. When you're done with it then you have to call Release(). You'll leak memory if you don't. Every interface in COM works this way.
Yes. As seen in DllGetClassObject sample, the return ppvObj will have a refcount.
Yes, DllGetClassObject() will create an object and pass ownership of that object to your code. Your code will now own the object and be responsible for releasing it by calling IUnknown::Release().