LoadLibrary(*mem)

Just starting out? Need help? Post your questions and find answers here.
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

LoadLibrary(*mem)

Post by cas »

In this forum we can find code for executing exe from memory and for injecting dll to other process. The only thing that is missing (and it have some similarities in code) is how to load dll from memory. I know that we have userlib PBOSL_LoadDllMemory but it would be great to translate it to PB because if error happens in userlib --> program could crash without OnError library catching source of crash (http://purebasic.fr/english/viewtopic.php?t=37955 :cry:).

If there is someone reading this who have very good knowledge about file PE structure and at least some knowledge of c language (and of course, some free time :)), please try to convert this code from c to PB.
This would eliminate need for other commercial packers (like Molebox) for our programs which uses lots of dll's and it would save a little of our money.

Source is located in usual place:

Code: Select all

http://pbosl.purearea.net/pbosl_src.zip
Thanks
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: LoadLibrary(*mem)

Post by ts-soft »

cas wrote: Source is located in usual place:

Code: Select all

http://pbosl.purearea.net/pbosl_src.zip
Thanks
Original-Source is here: http://www.joachim-bauch.de/tutorials/d ... -0.0.2.zip
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Re: LoadLibrary(*mem)

Post by cas »

ts-soft wrote:Original-Source is here: http://www.joachim-bauch.de/tutorials/d ... -0.0.2.zip
Thanks for posting this here.
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Needed help in converting from c to PB

Post by cas »

Looks like nobody is interested so i tried converting it myself and i, of course, failed :roll:
Here is code, it is real mess because i commented out every line and then when i converted it i left original line as comment to check later if i converted it properly. I converted almost all in PB_LoadLibraryM() procedure since it is main procedure which is called first. Converted code is not working so i didn't converted other parts yet.
If anyone knows something more please look at this code and try to convert at least only small part of it so we won't need to buy commercial products like Molebox or BoxedApp or something similar.


Here it is (original c code is commented out):

Code: Select all

EnableExplicit
;{ header - comments
; /*
;  * Memory DLL loading code
;  * Version 0.0.2
;  *
;  * Copyright (c) 2004-2005 by Joachim Bauch / mail@joachim-bauch.de
;  * http://www.joachim-bauch.de
;  *
;  * The contents of this file are subject To the Mozilla Public License Version
;  * 1.1 (the "License"); you may not use this file except in compliance with
;  * the License. You may obtain a copy of the License at
;  * http://www.mozilla.org/MPL/
;  *
;  * Software distributed under the License is distributed on an "AS IS" basis,
;  * WITHOUT WARRANTY OF ANY KIND, either express Or implied. See the License
;  * For the specific language governing rights And limitations under the
;  * License.
;  *
;  * The Original Code is MemoryModule.c
;  *
;  * The Initial Developer of the Original Code is Joachim Bauch.
;  *
;  * Portions created by Joachim Bauch are Copyright (C) 2004-2005
;  * Joachim Bauch. All Rights Reserved.
;  *
;  */
; 
; // disable warnings about pointer <-> DWORD conversions
; //#pragma warning( disable : 4311 4312 )
; 
; #include <Windows.h>
; #include <winnt.h>
; #ifdef DEBUG_OUTPUT
; #include <stdio.h>
; #endif
; 
; #include "MemoryModule.h"
; 
;}
;
;

;{************************** TAKEN FROM PUREBASIC FORUMS *********************
Structure Misc
   PhysicalAddress.l
   VirtualSize.l
EndStructure

Structure IMAGE_SECTION_HEADER
  Name.l
  Misc.Misc
  VirtualAddress.l
  SizeOfRawData.l
  PointerToRawData.l
  PointerToRelocations.l
  PointerToLinenumbers.l
  NumberOfRelocations.w
  NumberOfLinenumbers.w
  Characteristics.l
EndStructure

ImportC "msvcrt.lib"
  memset_ ( *str.l, char.l, length.l ) As "_memset@12"
EndImport

#IMAGE_DOS_SIGNATURE = $5A4D
#IMAGE_NT_SIGNATURE = $4550

;}****************************************************************************



Structure MEMORYMODULE     ;typedef struct {
  headers.IMAGE_NT_HEADERS  ; PIMAGE_NT_HEADERS headers;
	*codeBase.c               ; unsigned char *codeBase;
	*modules.HMODULE          ; HMODULE *modules;
	numModules.i              ; int numModules;
	initialized.i             ; int initialized;
EndStructure               ;} MEMORYMODULE, *PMEMORYMODULE;

Declare PB_FreeLibraryM(*mod.MEMORYMODULE)

; 
; typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
; 
; #define GET_HEADER_DICTIONARY(module, idx)	&(module)->headers->OptionalHeader.DataDirectory[idx]
; 
; #ifdef DEBUG_OUTPUT
; Static void
; OutputLastError(const char *msg)
; {
; 	LPVOID tmp;
; 	char *tmpmsg;
; 	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
; 		NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&tmp, 0, NULL);
; 	tmpmsg = (char *)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3);
; 	sprintf(tmpmsg, "%s: %s", msg, tmp);
; 	OutputDebugString(tmpmsg);
; 	LocalFree(tmpmsg);
; 	LocalFree(tmp);
; }
; #endif
; 
; Static void
Procedure CopySections(*dData, *old_headers.IMAGE_NT_HEADERS, *module.MEMORYMODULE); CopySections(const unsigned char *Data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module)
  ; {
  Protected i, size; 	int i, size;
  Protected *codeBase.c = *module\codeBase; 	unsigned char *codeBase = module->codeBase;
  Protected *dest.c; 	unsigned char *dest;
  Protected *section.IMAGE_SECTION_HEADER = *module\headers + 24 + *module\headers\FileHeader\SizeOfOptionalHeader; 	PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
  For i=0 To *module\headers\FileHeader\NumberOfSections; 	For (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++)
    ; 	{
    If *section\SizeOfRawData = 0; 		If (section->SizeOfRawData == 0)
      ; 		{
      ; 			// section doesn't contain data in the dll itself, but may define
      ; 			// uninitialized Data
      size = *old_headers\OptionalHeader\SectionAlignment; 			size = old_headers->OptionalHeader.SectionAlignment;
      If size > 0; 			If (size > 0)
        ; 			{
        *dest = VirtualAlloc_(*codeBase + *section\VirtualAddress,size,#MEM_COMMIT,#PAGE_READWRITE); 				dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
        ; 					size,
        ; 					MEM_COMMIT,
        ; 					PAGE_READWRITE);
        ; 
        *section\Misc\PhysicalAddress = *dest; 				section->Misc.PhysicalAddress = (DWORD)dest;
        memset_(*dest, 0, size); 				memset(dest, 0, size);
      EndIf; 			}
      ; 
      ; 			// section is empty
      Continue; 			Continue;
    EndIf; 		}
    ; 
    ; 		// commit memory block And copy Data from dll
    *dest = VirtualAlloc_(*section\VirtualAddress,*section\SizeOfRawData,#MEM_COMMIT,#PAGE_READWRITE); 		dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
    ;   section->SizeOfRawData,
    ; 	MEM_COMMIT,
    ; 	PAGE_READWRITE);
    CopyMemory(*dData + *section\PointerToRawData, *dest, *section\SizeOfRawData); 		memcpy(dest, Data + section->PointerToRawData, section->SizeOfRawData);
    *section\Misc\PhysicalAddress = *dest; 		section->Misc.PhysicalAddress = (DWORD)dest;
    i+1
    *section+1 ;I know this is error, probably needed to declare *section as(?):  Dim *section.IMAGE_SECTION_HEADER(*old_headers\FileHeader\NumberOfSections)   
  Next; 	}
EndProcedure; }
; 
; // Protection flags For memory pages (Executable, Readable, Writeable)
; Static int ProtectionFlags[2][2][2] = {
; 	{
; 		// Not executable
; 		{PAGE_NOACCESS, PAGE_WRITECOPY},
; 		{PAGE_READONLY, PAGE_READWRITE},
; 	}, {
; 		// executable
; 		{PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY},
; 		{PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE},
; 	},
; };
; 
; Static void
Procedure FinalizeSections(*module.MEMORYMODULE); FinalizeSections(PMEMORYMODULE module)
  ; {
  ; 	int i;
  ; 	PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
  ; 	
  ; 	// loop through all sections And change access flags
  ; 	For (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++)
  ; 	{
  ; 		DWORD protect, oldProtect, size;
  ; 		int executable = (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
  ; 		int readable =   (section->Characteristics & IMAGE_SCN_MEM_READ) != 0;
  ; 		int writeable =  (section->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
  ; 
  ; 		If (section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
  ; 		{
  ; 			// section is Not needed any more And can safely be freed
  ; 			VirtualFree((LPVOID)section->Misc.PhysicalAddress, section->SizeOfRawData, MEM_DECOMMIT);
  ; 			Continue;
  ; 		}
  ; 
  ; 		// determine protection flags based on characteristics
  ; 		protect = ProtectionFlags[executable][readable][writeable];
  ; 		If (section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
  ; 			protect |= PAGE_NOCACHE;
  ; 
  ; 		// determine size of region
  ; 		size = section->SizeOfRawData;
  ; 		If (size == 0)
  ; 		{
  ; 			If (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
  ; 				size = module->headers->OptionalHeader.SizeOfInitializedData;
  ; 			Else If (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
  ; 				size = module->headers->OptionalHeader.SizeOfUninitializedData;
  ; 		}
  ; 
  ; 		If (size > 0)
  ; 		{
  ; 			// change memory access flags
  ; 			If (VirtualProtect((LPVOID)section->Misc.PhysicalAddress, section->SizeOfRawData, protect, &oldProtect) == 0)
  ; #ifdef DEBUG_OUTPUT
  ; 				OutputLastError("Error protecting memory page")
  ; #endif
  ; 			;
  ; 		}
  ; 	}
EndProcedure; }
; 
; Static void
Procedure PerformBaseRelocation(*module.MEMORYMODULE, delta); PerformBaseRelocation(PMEMORYMODULE module, DWORD delta)
  ; {
  ; 	DWORD i;
  ; 	unsigned char *codeBase = module->codeBase;
  ; 
  ; 	PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);
  ; 	If (directory->Size > 0)
  ; 	{
  ; 		PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION)(codeBase + directory->VirtualAddress);
  ; 		For (; relocation->VirtualAddress > 0; )
  ; 		{
  ; 			unsigned char *dest = (unsigned char *)(codeBase + relocation->VirtualAddress);
  ; 			unsigned short *relInfo = (unsigned short *)((unsigned char *)relocation + IMAGE_SIZEOF_BASE_RELOCATION);
  ; 			For (i=0; i<((relocation->SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++)
  ; 			{
  ; 				DWORD *patchAddrHL;
  ; 				int type, offset;
  ; 
  ; 				// the upper 4 bits Define the type of relocation
  ; 				type = *relInfo >> 12;
  ; 				// the lower 12 bits Define the offset
  ; 				offset = *relInfo & 0xfff;
  ; 				
  ; 				switch (type)
  ; 				{
  ; 				Case IMAGE_REL_BASED_ABSOLUTE:
  ; 					// skip relocation
  ; 					Break;
  ; 
  ; 				Case IMAGE_REL_BASED_HIGHLOW:
  ; 					// change complete 32 bit address
  ; 					patchAddrHL = (DWORD *)(dest + offset);
  ; 					*patchAddrHL += delta;
  ; 					Break;
  ; 
  ; 				Default:
  ; 					//printf("Unknown relocation: %d\n", type);
  ; 					Break;
  ; 				}
  ; 			}
  ; 
  ; 			// advance To Next relocation block
  ; 			relocation = (PIMAGE_BASE_RELOCATION)(((DWORD)relocation) + relocation->SizeOfBlock);
  ; 		}
  ; 	}
EndProcedure; }
; 
; Static int
Procedure BuildImportTable(*module.MEMORYMODULE); BuildImportTable(PMEMORYMODULE module)
  ; {
  ; 	int result=1;
  ; 	unsigned char *codeBase = module->codeBase;
  ; 
  ; 	PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);
  ; 	If (directory->Size > 0)
  ; 	{
  ; 		PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR)(codeBase + directory->VirtualAddress);
  ; 		For (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++)
  ; 		{
  ; 			DWORD *thunkRef, *funcRef;
  ; 			HMODULE handle = LoadLibrary((LPCSTR)(codeBase + importDesc->Name));
  ; 			If (handle == INVALID_HANDLE_VALUE)
  ; 			{
  ; #if DEBUG_OUTPUT
  ; 				OutputLastError("Can't load library");
  ; #endif
  ; 				result = 0;
  ; 				Break;
  ; 			}
  ; 
  ; 			module->modules = (HMODULE *)realloc(module->modules, (module->numModules+1)*(SizeOf(HMODULE)));
  ; 			If (module->modules == NULL)
  ; 			{
  ; 				result = 0;
  ; 				Break;
  ; 			}
  ; 
  ; 			module->modules[module->numModules++] = handle;
  ; 			If (importDesc->OriginalFirstThunk)
  ; 			{
  ; 				thunkRef = (DWORD *)(codeBase + importDesc->OriginalFirstThunk);
  ; 				funcRef = (DWORD *)(codeBase + importDesc->FirstThunk);
  ; 			} Else {
  ; 				// no hint table
  ; 				thunkRef = (DWORD *)(codeBase + importDesc->FirstThunk);
  ; 				funcRef = (DWORD *)(codeBase + importDesc->FirstThunk);
  ; 			}
  ; 			For (; *thunkRef; thunkRef++, funcRef++)
  ; 			{
  ; 				If IMAGE_SNAP_BY_ORDINAL(*thunkRef)
  ; 					*funcRef = (DWORD)GetProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef));
  ; 				Else {
  ; 					PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)(codeBase + *thunkRef);
  ; 					*funcRef = (DWORD)GetProcAddress(handle, (LPCSTR)&thunkData->Name);
  ; 				}
  ; 				If (*funcRef == 0)
  ; 				{
  ; 					result = 0;
  ; 					Break;
  ; 				}
  ; 			}
  ; 
  ; 			If (!result)
  ; 				Break;
  ; 		}
  ; 	}
  ; 
  ; 	Return result;
EndProcedure; }
; 
Procedure PB_LoadLibraryM(*dData); extern HMEMORYMODULE PB_LoadLibraryM(const void *Data)
  ; {
  Debug "[OK] Started PB_LoadLibraryM()"
  Protected *result.MEMORYMODULE; 	PMEMORYMODULE result;
  Protected *dos_header.IMAGE_DOS_HEADER; 	PIMAGE_DOS_HEADER dos_header;
  Protected *old_header.IMAGE_NT_HEADERS; 	PIMAGE_NT_HEADERS old_header;
  Protected *code.c, *headers.c; 	unsigned char *code, *headers;
  Protected locationDelta; 	DWORD locationDelta;
  Protected DllEntry; 	DllEntryProc DllEntry;    ;!!!!!! needs this to be converted first: typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
  Protected successfull.b; 	BOOL successfull;
  ; 
  *dos_header = *dData; 	dos_header = (PIMAGE_DOS_HEADER)Data;
  If *dos_header\e_magic <> #IMAGE_DOS_SIGNATURE; 	If (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
    ; 	{
    ; #if DEBUG_OUTPUT
    Debug "[Fail] Not a valid executable file"; 		OutputDebugString("Not a valid executable file.\n");
    ; #endif
    ProcedureReturn #Null; 		Return NULL;
  Else
    Debug "[OK] Valid executable file"
  EndIf; 	}
  ; 
  *old_header = *dData + *dos_header\e_lfanew ; 	old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(Data))[dos_header->e_lfanew];
  If *old_header\Signature <> #IMAGE_NT_SIGNATURE; 	If (old_header->Signature != IMAGE_NT_SIGNATURE)
    ; 	{
    ; #if DEBUG_OUTPUT
    Debug "[Fail] No PE header found"; 		OutputDebugString("No PE header found.\n");
    ; #endif
    ProcedureReturn #Null; 		Return NULL;
  Else
    Debug "[OK] PE header found"
  EndIf; 	}
  ; 
  ; 	// reserve memory For image of library
  *code = VirtualAlloc_(*old_header\OptionalHeader\ImageBase,*old_header\OptionalHeader\SizeOfImage,#MEM_RESERVE,#PAGE_READWRITE); 	code = (unsigned char *)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase),
  ; 		old_header->OptionalHeader.SizeOfImage,
  ; 		MEM_RESERVE,
  ; 		PAGE_READWRITE);
  ; 
  If *code = #Null;     If (code == NULL)
  ;         // try To allocate memory at arbitrary position
  *code = VirtualAlloc_(#Null,*old_header\OptionalHeader\SizeOfImage,#MEM_RESERVE,#PAGE_READWRITE);         code = (unsigned char *)VirtualAlloc(NULL,
  ;             old_header->OptionalHeader.SizeOfImage,
  ;             MEM_RESERVE,
  ;             PAGE_READWRITE);
  EndIf;     
  
  If *code = #Null; 	If (code == NULL)
    ; 	{
    ; #if DEBUG_OUTPUT
    Debug "[Fail] Can't reserve memory"; 		OutputLastError("Can't reserve memory");
    ; #endif
    ProcedureReturn #Null; 		Return NULL;
  EndIf; 	}
  ; 
  *result = HeapAlloc_(GetProcessHeap_(), 0, SizeOf(MEMORYMODULE)); 	result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), 0, SizeOf(MEMORYMODULE));
  *result\codeBase = *code; 	result->codeBase = code;
  *result\numModules = 0; 	result->numModules = 0;
  *result\modules = #Null; 	result->modules = NULL;
  *result\initialized = 0; 	result->initialized = 0;
  ; 
  ; 	// XXX: is it correct To commit the complete memory region at once?
  ;     //      calling DllEntry raises an exception If we don't...
  VirtualAlloc_(*code,*old_header\OptionalHeader\SizeOfImage,	#MEM_COMMIT,#PAGE_READWRITE); 	VirtualAlloc(code,
  ; 		old_header->OptionalHeader.SizeOfImage,
  ; 		MEM_COMMIT,
  ; 		PAGE_READWRITE);
  ; 
  ; 	// commit memory For headers
  *headers = VirtualAlloc_(*code,*old_header\OptionalHeader\SizeOfHeaders,#MEM_COMMIT,#PAGE_READWRITE); 	headers = (unsigned char *)VirtualAlloc(code,
  ; 		old_header->OptionalHeader.SizeOfHeaders,
  ; 		MEM_COMMIT,
  ; 		PAGE_READWRITE);
  ; 	
  ; 	// copy PE header To code
  CopyMemory(*dos_header,*headers,*dos_header\e_lfanew + *old_header\OptionalHeader\SizeOfHeaders); 	memcpy(headers, dos_header, dos_header->e_lfanew + old_header->OptionalHeader.SizeOfHeaders);
  ;
  ;************** NEXT LINE IS NOT PROPERLY CONVERTED TO PUREBASIC !!!!!!!!!!! ***************
  CopyMemory(*dos_header\e_lfanew,@*result\headers,4); 	result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew]; 
  ; 
  ; 	// update position
  ;************** NEXT LINE IS NOT PROPERLY CONVERTED TO PUREBASIC !!!!!!!!!!! ***************
  CopyMemory(@*code,@*result\headers\OptionalHeader\ImageBase,4); 	result->headers->OptionalHeader.ImageBase = (DWORD)code;
  ; 
  ; 	// copy sections from DLL file block To new memory location
  CopySections(*dData, *old_header, *result); 	CopySections(Data, old_header, result);
  ; 
  ; 	// adjust base address of imported Data
  locationDelta = *code - *old_header\OptionalHeader\ImageBase; 	locationDelta = (DWORD)(code - old_header->OptionalHeader.ImageBase);
  If locationDelta <> 0; 	If (locationDelta != 0)
    PerformBaseRelocation(*result, locationDelta); 		PerformBaseRelocation(result, locationDelta);
  EndIf; 
  ; 	// load required dlls And adjust function table of imports
  If Not BuildImportTable(*result); 	If (!BuildImportTable(result))
    Goto error; 		Goto error;
  EndIf; 
  ; 	// mark memory pages depending on section headers And release
  ; 	// sections that are marked As "discardable"
  FinalizeSections(*result); 	FinalizeSections(result);
  ; 
  ; 	// get entry point of loaded library
  If *result\headers\OptionalHeader\AddressOfEntryPoint <> 0 ; 	If (result->headers->OptionalHeader.AddressOfEntryPoint != 0)
    ; 	{
    DllEntry = *code + *result\headers\OptionalHeader\AddressOfEntryPoint; 		DllEntry = (DllEntryProc)(code + result->headers->OptionalHeader.AddressOfEntryPoint);
    If DllEntry = 0; 		If (DllEntry == 0)
      ; 		{
      ; #if DEBUG_OUTPUT
      Debug "[Fail] Library has no entry point"; 			OutputDebugString("Library has no entry point.\n");
      ; #endif
      Goto error; 			Goto error;
    EndIf; 		}
    ; 
    ; 		// notify library about attaching To process
    ;*********** NEXT LINE NEEDS TO BE CONVERTED TO PUREBASIC **************
    ; 		successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0);
    If Not successfull; 		If (!successfull)
      ; 		{
      ; #if DEBUG_OUTPUT
      Debug "[Fail] Can't attach library"; 			OutputDebugString("Can't attach library.\n");
      ; #endif
      Goto error; 			Goto error;
    EndIf; 		}
    *result\initialized = 1; 		result->initialized = 1;
  EndIf; 	}
  ; 
  ProcedureReturn *result; 	Return (HMEMORYMODULE)result;
  ; 
  error: ; error:
    ; 	// cleanup
    PB_FreeLibraryM(*result); 	PB_FreeLibraryM(result);
    ProcedureReturn #Null; 	Return NULL;
EndProcedure; }
; 
Procedure PB_GetProcAddressM(*module.MEMORYMODULE, *name.c); extern FARPROC PB_GetProcAddressM(HMEMORYMODULE module, const char *name)
  ; {
  ; 	unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase;
  ; 	int idx=-1;
  ; 	DWORD i, *nameRef;
  ; 	WORD *ordinal;
  ; 	PIMAGE_EXPORT_DIRECTORY exports;
  ; 	PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT);
  ; 	If (directory->Size == 0)
  ; 		// no export table found
  ; 		Return NULL;
  ; 
  ; 	exports = (PIMAGE_EXPORT_DIRECTORY)(codeBase + directory->VirtualAddress);
  ; 	If (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0)
  ; 		// DLL doesn't export anything
  ; 		Return NULL;
  ; 
  ; 	// search function name in List of exported names
  ; 	nameRef = (DWORD *)(codeBase + exports->AddressOfNames);
  ; 	ordinal = (WORD *)(codeBase + exports->AddressOfNameOrdinals);
  ; 	For (i=0; i<exports->NumberOfNames; i++, nameRef++, ordinal++)
  ; 		If (strcmp(name, (const char *)(codeBase + *nameRef)) == 0)
  ; 		{
  ; 			idx = *ordinal;
  ; 			Break;
  ; 		}
  ; 
  ; 	If (idx == -1)
  ; 		// exported symbol Not found
  ; 		Return NULL;
  ; 
  ; 	If ((DWORD)idx > exports->NumberOfFunctions)
  ; 		// name <-> ordinal number don't match
  ; 		Return NULL;
  ; 
  ; 	// AddressOfFunctions contains the RVAs To the "real" functions
  ; 	Return (FARPROC)(codeBase + *(DWORD *)(codeBase + exports->AddressOfFunctions + (idx*4)));
EndProcedure; }
; 
Procedure PB_FreeLibraryM(*mod.MEMORYMODULE);  extern void PB_FreeLibraryM(HMEMORYMODULE mod)
  ; {
  ; 	int i;
  ; 	PMEMORYMODULE module = (PMEMORYMODULE)mod;
  ; 
  ; 	If (module != NULL)
  ; 	{
  ; 		If (module->initialized != 0)
  ; 		{
  ; 			// notify library about detaching from process
  ; 			DllEntryProc DllEntry = (DllEntryProc)(module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint);
  ; 			(*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0);
  ; 			module->initialized = 0;
  ; 		}
  ; 
  ; 		If (module->modules != NULL)
  ; 		{
  ; 			// free previously opened libraries
  ; 			For (i=0; i<module->numModules; i++)
  ; 				If (module->modules[i] != INVALID_HANDLE_VALUE)
  ; 					FreeLibrary(module->modules[i]);
  ; 
  ; 			free(module->modules);
  ; 		}
  ; 
  ; 		If (module->codeBase != NULL)
  ; 			// release memory of library
  ; 			VirtualFree(module->codeBase, 0, MEM_RELEASE);
  ; 
  ; 		HeapFree(GetProcessHeap(), 0, module);
  ; 	}
EndProcedure; }


Debug "START"
Define file = ReadFile(#PB_Any,"C:\test.dll")
If file
  Debug "[OK] Local file found"
  Global *dll = AllocateMemory(Lof(file))
  If *dll
    Debug "[OK] Memory allocated"
    ReadData(file,*dll,Lof(file))
    CloseFile(file)
  Else
    Debug "[Fail] Couldn't allocate the requested memory"
  EndIf
  Define dllLoadResult = PB_LoadLibraryM(*dll)
  If dllLoadResult
    Debug "[OK] Success!!"
  Else
    Debug "[Fail] PB_LoadLibraryM() returned #False"
  EndIf
Else
  Debug "[Fail] File not found"
EndIf

Debug "END"
Thanks in advance
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

ts-soft, I'm pretty sure you can't do that without setting off DEP. Can you confirm it works on a DEP-enabled processor?
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Post by cas »

Mistrel wrote:ts-soft, I'm pretty sure you can't do that without setting off DEP. Can you confirm it works on a DEP-enabled processor?
Yes, library from pbosl works on windows xp and vista x86 and x64.
Data Execution Prevention (DEP) is a security feature included in modern Microsoft Windows operating systems that is intended to prevent an application or service from executing code from a non-executable memory region.
If you look closely in code you will see VirtualAlloc_() for memory regions so nothing suspicious could happen.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

@Mistrel
I have make version in pb for some month but will not run :mrgreen:
In the moment no time for this, using of static lib do the same.

@cas
the lib in pbosl doesn't work on x64
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Post by cas »

ts-soft wrote:@cas
the lib in pbosl doesn't work on x64
You mean it doesn't work with x64 compiler or when executed on x64 windows?
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

cas wrote:
ts-soft wrote:@cas
the lib in pbosl doesn't work on x64
You mean it doesn't work with x64 compiler or when executed on x64 windows?
it doesn't work with x64 compiler and can't work with 64-bit DLLs
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Post by cas »

Comment (from http://www.joachim-bauch.de/tutorials/l ... emory.html):
Posted by Anonymous User at 2009-06-24 19:56:50

Hi, I've noticed that if an exception occurs inside the loaded dll, then program terminates, but if I load dll using loadlibrary, the execution continues after throwing an exception. Any idea how I can make exceptions behave the same way as in dlls ?

Btw, I've also modified the code to support x64 platform. I can send the code if needed. Thanks, Sergey.
So we just need to convert current code to PB and then it will need some minor modifications to support x64 8)
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

I see. It loads the DLL into memory and calls its entry point. It doesn't actually use "LoadLibrary". This should work, I think. :)
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Post by cas »

Mistrel wrote:This should work, I think. :)
And it will...
Even with x64 compiler one day. 8)
I think everyone would want first to make x86 version to work. :wink:
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

But if it's not loaded with LoadLibrary how can you find other entry points for exposed functions?
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Post by cas »

With this procedure you get pointer:

Code: Select all

PB_GetProcAddressM()
and then that pointer you pass to

Code: Select all

CallFunctionFast()
example:

dll code:

Code: Select all

ProcedureDLL MyFunction()
  MessageRequester("Hello", "This is a PureBasic DLL !", 0)
EndProcedure

ProcedureDLL MyFunction2()
  MessageRequester("Hello", "Hello from MyFunction2()!", 0)
EndProcedure
then we call it like this:

Code: Select all

Define file = ReadFile(#PB_Any,"C:\testmodule.dll")
Global *dll = AllocateMemory(Lof(file))
ReadData(file,*dll,Lof(file))
CloseFile(file)

; open dll from memory
Define dllLoadResult = LoadLibraryM(*dll)

;get procedure addresses
Define dllProcAddr = GetProcAddressM(dllLoadResult,"MyFunction")
Define dllProcAddr2 = GetProcAddressM(dllLoadResult,"MyFunction2")

;call procedures
Define result1 = CallFunctionFast(dllProcAddr)
Define result2 = CallFunctionFast(dllProcAddr2)

;free dll at end
FreeLibraryM(dllLoadResult)
Last edited by cas on Sat Jul 18, 2009 1:44 pm, edited 1 time in total.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

Fancy! I'll have to play with this sometime. :D
Post Reply