X-Git-Url: http://git.jankratochvil.net/?a=blobdiff_plain;f=src%2Flibcaptive%2Fldr%2Floader.c;h=48fe811e86169aedaaaefd249ac0c63a0a1406f4;hb=18324b449d5d917b1692de44d2f50d23323bfacd;hp=cfea7b58e1666dec8028a6933c367f5ba61892b2;hpb=2ba9b3cd30f7e13727389d4ff5c257d93234a013;p=captive.git diff --git a/src/libcaptive/ldr/loader.c b/src/libcaptive/ldr/loader.c index cfea7b5..48fe811 100644 --- a/src/libcaptive/ldr/loader.c +++ b/src/libcaptive/ldr/loader.c @@ -33,10 +33,11 @@ #include /* for PROT_READ, MAP_SHARED */ #include "captive/macros.h" #include -#include "reactos/ddk/rtl.h" /* for InsertTailList() */ +#include "reactos/ntos/rtl.h" /* for InsertTailList() */ #include "reactos/internal/debug.h" /* for assert() */ #include /* for g_path_get_basename() */ #include +#include "captive/options-module.h" /* map: ExportAddress -> (struct captive_ModuleList_patchpoint *) */ @@ -65,6 +66,7 @@ static void captive_ModuleList_function_disable_hash_init(void) /* reactos/ntoskrnl/ldr/loader.c file-scope global declaration: */ NTSTATUS LdrProcessModule(PVOID ModuleLoadBase,PUNICODE_STRING ModuleName,PMODULE_OBJECT *ModuleObject); +PVOID LdrGetExportAddress(PMODULE_OBJECT ModuleObject,char *Name,unsigned short Hint); /* 'ntoskrnl/ldr/loader.c' file-scoped declaration: */ @@ -118,59 +120,51 @@ gboolean errbool; /** - * LdrLoadModule: - * @Filename: Filename of module to load based on host OS disk. + * captive_LdrLoadModule: + * @options_module: #captive_options_module structure describing the module to load. * Loading of already loaded module is forbidden. - * @ModuleObject: Returns initialized module object. + * @ModuleObjectp: Returns initialized module object. * * Load and initialize module to reactos using host OS functions. * * Returns: STATUS_SUCCESS if the module was loaded successfuly during the call. */ -NTSTATUS LdrLoadModule(PUNICODE_STRING Filename,PMODULE_OBJECT *ModuleObjectp) +NTSTATUS captive_LdrLoadModule(struct captive_options_module *options_module,PMODULE_OBJECT *ModuleObjectp) { -PVOID ModuleLoadBase; PMODULE_OBJECT Module; NTSTATUS err; -gchar *Filename_utf8=(/* de-const */ gchar *)captive_UnicodeString_to_utf8_alloca(Filename); +gchar *Filename_utf8=options_module->pathname_utf8; gchar *Filename_bslash_utf8,*s; UNICODE_STRING *Filename_bslash; *ModuleObjectp=NULL; - /* Open the Module */ - ModuleLoadBase=captive_rtl_file_mmap( - NULL, /* lenp */ - Filename_utf8, /* path */ - O_RDONLY, /* open_flags */ - PROT_READ, /* mmap_prot */ - MAP_SHARED); /* mmap_flags */ - /* FIXME: convert errno instead of STATUS_INSUFFICIENT_RESOURCES */ - g_return_val_if_fail(ModuleLoadBase!=NULL,STATUS_INSUFFICIENT_RESOURCES); - /* Filename=~s#/#\\#g -> Filename_bslash to satisfy basename-derivations by reactos. */ - Filename_bslash_utf8=g_strdup(Filename_utf8); + Filename_bslash_utf8=(/* de-const as we do not change the length */ gchar *)captive_strdup_alloca(Filename_utf8); for (s=Filename_bslash_utf8;(s=strchr(s,'/'));s++) *s='\\'; Filename_bslash=captive_utf8_to_UnicodeString_alloca(Filename_bslash_utf8); - if ((('M'<<8U)|('Z'<<0U))==GUINT16_FROM_BE(*(const guint16 *)ModuleLoadBase)) { - g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: Loading module format: %s",G_STRLOC,"MZ/PE-32"); - /* examine/relocate the module */ - err=LdrProcessModule(ModuleLoadBase,Filename_bslash,&Module); - if (!NT_SUCCESS(err)) { - g_error("LdrLoadModule(): LdrProcessModule()=0x%08lX",err); - goto err_captive_rtl_file_munmap; - } - } - else { - g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: Loading module format: %s",G_STRLOC,"native .so"); - Module=captive_LdrLoadModule_gmodule(Filename_utf8,Filename_bslash_utf8); - g_assert(Module!=NULL); + switch (options_module->type) { + case CAPTIVE_OPTIONS_MODULE_TYPE_EMPTY: g_assert_not_reached(); + + case CAPTIVE_OPTIONS_MODULE_TYPE_PE32: + g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: Loading module format: %s",G_STRLOC,"MZ/PE-32"); + /* examine/relocate the module */ + err=LdrProcessModule(options_module->u.pe32.base,Filename_bslash,&Module); + if (!NT_SUCCESS(err)) { + g_error("LdrLoadModule(): LdrProcessModule()=0x%08lX",(gulong)err); + goto err; + } + break; + + case CAPTIVE_OPTIONS_MODULE_TYPE_GMODULE: + g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: Loading module format: %s",G_STRLOC,"native .so"); + Module=captive_LdrLoadModule_gmodule(Filename_utf8,Filename_bslash_utf8); + g_assert(Module!=NULL); } /* we were successful */ - captive_rtl_file_munmap(ModuleLoadBase); *ModuleObjectp=Module; /* Hook for KDB on loading a driver. */ @@ -178,18 +172,21 @@ UNICODE_STRING *Filename_bslash; return STATUS_SUCCESS; - /* Error recoveries */ -err_captive_rtl_file_munmap: - captive_rtl_file_munmap(ModuleLoadBase); - +err: g_return_val_if_reached(err); } +NTSTATUS LdrLoadModule(PUNICODE_STRING Filename,PMODULE_OBJECT *ModuleObject) +{ + return STATUS_OBJECT_NAME_NOT_FOUND; +} + + /** * captive_LdrpLoadAndCallImage: * @ModuleObjectp: Returns PMODULE_OBJECT successfuly loaded. - * @ModuleName: Filename of module to load based on host OS disk. + * @options_module: #captive_options_module structure describing the module to load. * Loading of already loaded module is forbidden despite original * LdrpLoadAndCallImage(). * @DriverEntry_DriverObject: argument #DriverObject of #PDRIVER_INITIALIZE call. @@ -201,27 +198,31 @@ err_captive_rtl_file_munmap: * Returns: STATUS_SUCCESS if the driver module was loaded and initialized * successfuly during this call. Ignore returned @ModuleObjectp if function failed. */ -NTSTATUS captive_LdrpLoadAndCallImage(PMODULE_OBJECT *ModuleObjectp,PUNICODE_STRING ModuleName, +NTSTATUS captive_LdrpLoadAndCallImage(PMODULE_OBJECT *ModuleObjectp,struct captive_options_module *options_module, PDRIVER_OBJECT DriverEntry_DriverObject,PUNICODE_STRING DriverEntry_RegistryPath) { PDRIVER_INITIALIZE DriverEntry; PMODULE_OBJECT ModuleObject_tmp; NTSTATUS err; +#if 0 /* TODO */ /* check for duplicity */ g_return_val_if_fail(LdrGetModuleObject(ModuleName)==NULL,STATUS_IMAGE_ALREADY_LOADED); +#endif /* provide our temporary storage if the caller doesn't want to know ModuleObject address */ if (!ModuleObjectp) ModuleObjectp=&ModuleObject_tmp; /* load the module */ - err=LdrLoadModule(ModuleName,ModuleObjectp); + err=captive_LdrLoadModule(options_module,ModuleObjectp); g_return_val_if_fail(NT_SUCCESS(err),err); /* initialize the module */ DriverEntry=(PDRIVER_INITIALIZE)(*ModuleObjectp)->EntryPoint; - err=(*DriverEntry)(DriverEntry_DriverObject,DriverEntry_RegistryPath); + err=(NTSTATUS)captive_stdcall_call_8((CaptiveStdCallFunc8)DriverEntry, + DriverEntry_DriverObject, + DriverEntry_RegistryPath); if (!NT_SUCCESS(err)) goto err_LdrUnloadModule; @@ -371,12 +372,22 @@ static gsize instruction_length(const guint8 *instr) return 1+4; case 0x6A: /* push $single-byte */ return 1+1; + case 0x80: + switch (instr[1]) { + case 0x3D: /* cmpb $byte,immediate-quad-indirect */ + return 1+1+4+1; /* 80 3D immediate-quad-indirect byte */ + case 0x7C: /* cmpb $byte,#immediate(%reg,1) */ + return 1+1+1+1+1; /* 80 7C address-mode immediate byte */ + default: g_assert_not_reached(); + } case 0x83: switch (instr[1]) { case 0x01: /* addl $byte,(%ecx) */ return 1+1+1; case 0x3D: /* cmpl $byte,immediate-quad-indirect */ return 1+1+4+1; /* 83 3D immediate-quad-indirect byte */ + case 0x7C: /* cmpl $byte,#immediate(%reg,1) */ + return 1+1+1+1+1; /* 80 7C address-mode immediate byte */ default: g_assert_not_reached(); } case 0x8A: /* mov ??,?? */ @@ -398,6 +409,16 @@ static gsize instruction_length(const guint8 *instr) return 4; /* 8B 44 address-mode offset */ default: g_assert_not_reached(); } + case 0x8F: /* lea Gb,M */ + switch (instr[1]) { + case 0x04: + switch (instr[2]) { + case 0x24: /* popl (%esp,1) */ + return 3; + default: g_assert_not_reached(); + } + default: g_assert_not_reached(); + } case 0x9C: /* pushf */ return 1; case 0x9D: /* popf */ @@ -410,6 +431,8 @@ static gsize instruction_length(const guint8 *instr) return 1+2; case 0xCC: /* int $0x3 */ return 1; + case 0xF0: /* lock prefix */ + return 1+instruction_length(instr+1); case 0xFA: /* cli */ return 1; case 0xFB: /* sti */ @@ -484,7 +507,7 @@ USHORT Idx; PVOID ExportAddress,*ExportAddressp; const gchar *sym_name; void (*sym_val)(void); -struct captive_ModuleList_patchpoint *patchpoint; +struct captive_ModuleList_patchpoint *patchpoint,*patchpointpatch; GHashTable *exportdir_hash; gboolean errbool; @@ -527,41 +550,48 @@ CHAR *funcname=MODULEOBJECT_BASE_OFFSET_PLUS(NameList[Idx]); va_start(ap,FullName_utf8); while (captive_va_arg(sym_name,ap)) { captive_va_arg(sym_val ,ap); - g_assert(sym_val!=NULL); + /* 'sym_val' may be NULL if 'data' type && "pass"ed */ captive_va_arg(patchpoint,ap); /* 'data' type if ==NULL */ + captive_va_arg(patchpointpatch,ap); /* 'data' type or 'pass' in non-debug mode if ==NULL */ ExportAddressp=g_hash_table_lookup(exportdir_hash,sym_name); if (ExportAddressp==NULL) { - g_error("%s: Function not found for patchpoint: %s",G_STRLOC,sym_name); - g_assert_not_reached(); + g_message("%s: Function not found for patchpoint (ignoring): %s",G_STRLOC,sym_name); + continue; } errbool=g_hash_table_remove(exportdir_hash,sym_name); g_assert(errbool==TRUE); + if (!sym_val) { /* 'data' type && "pass"ed => do not corrupt it by 0xF4 */ + g_assert(!patchpoint); + continue; + } ExportAddress=(PVOID)MODULEOBJECT_BASE_OFFSET_PLUS(*ExportAddressp); *ExportAddressp=(PVOID)MODULEOBJECT_BASE_OFFSET_MINUS(sym_val); if (((ULONG)ExportAddress >= (ULONG)ExportDir) && ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize)) g_assert_not_reached(); /* LdrPEFixupForward() needed */ - if (!patchpoint) /* 'data' type */ + if (!patchpoint) /* 'data' type && !"pass"ed => do not corrupt it by 0xF4 */ continue; patchpoint->orig_w32_func=ExportAddress; - if (0xF4 /* hlt */ ==*patchpoint->orig_w32_func) /* Already patched by name-aliased function? */ + if (!patchpointpatch) /* 'pass' in non-debug mode */ continue; - g_assert(0xF4 /* hlt */ !=*patchpoint->orig_w32_func); - patchpoint->orig_w32_2ndinstr=patchpoint->orig_w32_func - +instruction_length((guint8 *)patchpoint->orig_w32_func); - g_assert(0xF4 /* hlt */ !=*patchpoint->orig_w32_2ndinstr); - patchpoint->wrap_wrap_func=sym_val; - patchpoint->orig_w32_func_byte=*patchpoint->orig_w32_func; - patchpoint->orig_w32_2ndinstr_byte=*patchpoint->orig_w32_2ndinstr; - patchpoint->through_w32_func=FALSE; - g_assert(NULL==g_hash_table_lookup(captive_ModuleList_patchpoint_hash,patchpoint->orig_w32_func)); + if (0xF4 /* hlt */ ==*patchpointpatch->orig_w32_func) /* Already patched by name-aliased function? */ + continue; + g_assert(0xF4 /* hlt */ !=*patchpointpatch->orig_w32_func); + patchpointpatch->orig_w32_2ndinstr=patchpointpatch->orig_w32_func + +instruction_length((guint8 *)patchpointpatch->orig_w32_func); + g_assert(0xF4 /* hlt */ !=*patchpointpatch->orig_w32_2ndinstr); + patchpointpatch->wrap_wrap_func=sym_val; + patchpointpatch->orig_w32_func_byte=*patchpointpatch->orig_w32_func; + patchpointpatch->orig_w32_2ndinstr_byte=*patchpointpatch->orig_w32_2ndinstr; + patchpointpatch->through_w32_func=FALSE; + g_assert(NULL==g_hash_table_lookup(captive_ModuleList_patchpoint_hash,patchpointpatch->orig_w32_func)); g_hash_table_insert(captive_ModuleList_patchpoint_hash, - patchpoint->orig_w32_func, /* key */ - patchpoint); /* value */ - g_assert(NULL==g_hash_table_lookup(captive_ModuleList_patchpoint_hash,patchpoint->orig_w32_2ndinstr)); + patchpointpatch->orig_w32_func, /* key */ + patchpointpatch); /* value */ + g_assert(NULL==g_hash_table_lookup(captive_ModuleList_patchpoint_hash,patchpointpatch->orig_w32_2ndinstr)); g_hash_table_insert(captive_ModuleList_patchpoint_hash, - patchpoint->orig_w32_2ndinstr, /* key */ - patchpoint); /* value */ + patchpointpatch->orig_w32_2ndinstr, /* key */ + patchpointpatch); /* value */ *(guint8 *)ExportAddress=0xF4; /* hlt */ } va_end(ap); @@ -603,3 +633,24 @@ G_CONST_RETURN gchar *captive_ModuleList_function_disable_find(gconstpointer Exp return g_hash_table_lookup(captive_ModuleList_function_disable_hash,ExportAddress); /* funcname */ } + + +void *captive_Module_GetExportAddress(const gchar *ModuleName_utf8,const gchar *FunctionName) +{ +MODULE_OBJECT *ModuleObject; +void *r; + + g_return_val_if_fail(ModuleName_utf8!=NULL,NULL); + g_return_val_if_fail(FunctionName!=NULL,NULL); + + ModuleObject=LdrGetModuleObject(captive_utf8_to_UnicodeString_alloca(g_path_get_basename(ModuleName_utf8))); + g_return_val_if_fail(ModuleObject!=NULL,NULL); + + r=LdrGetExportAddress( + ModuleObject, /* ModuleObject */ + (/* de-const */char *)FunctionName, /* Name */ + -1); /*Hint*/ + g_return_val_if_fail(r!=NULL,NULL); + + return r; +}