Departure Posted May 20, 2008 Share Posted May 20, 2008 While I was wondering around on the net a stumbled accross and interesting example, Corvu5 has showen this example in delphiWith this Unit written by me, you can load a Dll directly from a Bytearray, use the Functions of the DLL and free it at last.Post Bugs if you find some here!{[===========================================][?]uDllFromMem - Loading a DLL from Memory[?][v] Version 1.0 [v][c] Hamtaro aka CorVu5 [c][@] hamtaro.6x.to OR corvu5.6x.to [@][================Description================][With this Code, you can load a DLL in your ][application directly from Memory, the file ][doesnt have to be present on your Harddrive][===================Note====================][ This example doesnt work with Bound ][ Import Tables at this time ][==================thx to===================][ CDW, Cryptocrack ][ & Joachim Bauch for his ][ GetSectionProtection function ][===========================================][ there must be 50 ways to learn to hover ][===========================================]}unit uDllfromMem;interfaceuses windows;typePImageBaseRelocation = ^TImageBaseRelocation; _IMAGE_BASE_RELOCATION = packed record VirtualAddress: DWORD; SizeOfBlock: DWORD;end;{$EXTERNALSYM _IMAGE_BASE_RELOCATION} TImageBaseRelocation = _IMAGE_BASE_RELOCATION; IMAGE_BASE_RELOCATION = _IMAGE_BASE_RELOCATION;{$EXTERNALSYM IMAGE_BASE_RELOCATION}typePImageImportDescriptor = ^TImageImportDescriptor; TImageImportDescriptor = packed record OriginalFirstThunk: dword; TimeDateStamp: dword; ForwarderChain: dword; Name: dword; FirstThunk: dword;end;typePImageImportByName = ^TImageImportByName; TImageImportByName = packed record Hint : WORD; Name : array[0..255] of Char;end;typePImageThunkData = ^TImageThunkData; TImageThunkData = packed record case integer of 0 : (ForwarderString: PBYTE); 1 : (FunctionPtr : PDWORD); 2 : (Ordinal : DWORD); 3 : (AddressOfData : PImageImportByName);end;type TDllEntryProc = function(hinstdll: THandle; fdwReason: DWORD; lpReserved: Pointer): BOOL; stdcall;function memLoadLibrary(FileBase : Pointer) : Pointer;function memGetProcAddress(Physbase : Pointer; NameOfFunction : String) : Pointer;function memFreeLibrary(physbase : Pointer) : Boolean;constIMAGE_REL_BASED_HIGHLOW = 3;IMAGE_ORDINAL_FLAG32 = DWORD($80000000);var DllentryProc : TDLLEntryProc;implementation//strComp Function from SysUtilsfunction StrComp(const Str1, Str2: PChar): Integer; assembler;asm PUSH EDI PUSH ESI MOV EDI,EDX MOV ESI,EAX MOV ECX,0FFFFFFFFH XOR EAX,EAX REPNE SCASB NOT ECX MOV EDI,EDX XOR EDX,EDX REPE CMPSB MOV AL,[ESI-1] MOV DL,[EDI-1] SUB EAX,EDX POP ESI POP EDIend;function GetSectionProtection(ImageScn: cardinal): cardinal; begin Result := 0; if (ImageScn and IMAGE_SCN_MEM_NOT_CACHED) <> 0 then begin Result := Result or PAGE_NOCACHE; end; if (ImageScn and IMAGE_SCN_MEM_EXECUTE) <> 0 then begin if (ImageScn and IMAGE_SCN_MEM_READ)<> 0 then begin if (ImageScn and IMAGE_SCN_MEM_WRITE)<> 0 then begin Result := Result or PAGE_EXECUTE_READWRITE end else begin Result := Result or PAGE_EXECUTE_READ end; end else if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then begin Result := Result or PAGE_EXECUTE_WRITECOPY end else begin Result := Result or PAGE_EXECUTE end; end else if (ImageScn and IMAGE_SCN_MEM_READ)<> 0 then begin if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then begin Result := Result or PAGE_READWRITE end else begin Result := Result or PAGE_READONLY end end else if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then begin Result := Result or PAGE_WRITECOPY end else begin Result := Result or PAGE_NOACCESS; end; end;function memLoadLibrary(FileBase : Pointer) : Pointer;varpfilentheader : PIMAGENTHEADERS;pfiledosheader: PIMAGEDOSHEADER;pphysntheader : PIMAGENTHEADERS;pphysdosheader: PIMAGEDOSHEADER;physbase : Pointer;pphyssectionheader : PIMAGESECTIONHEADER;i : Integer;importsDir : PImageDataDirectory;importsBase: Pointer;importDesc : PImageImportDescriptor;importThunk: PImageThunkData;dll_handle : Cardinal;importbyname : pimageimportbyname;relocbase : Pointer;relocdata : PIMAGeBaseRElocation;relocitem : PWORD;reloccount : Integer;dllproc : TDLLEntryProc;beginresult := 0;pfiledosheader := filebase;pfilentheader := Pointer(Cardinal(filebase) + pfiledosheader^._lfanew);/////////////////////////////////////allozieren/physbase := VirtualAlloc(Pointer(pfilentheader^.OptionalHeader.ImageBase),pfilentheader^.OptionalHeader.SizeOfImage,MEM_RESERVE,PAGE_READWRITE);if Cardinal(physbase) = 0 Then beginphysbase := VirtualAlloc(0,pfilentheader^.OptionalHeader.SizeOfImage,MEM_RESERVE Or Mem_COMMIT,PAGE_READWRITE);end;//////////////////////////////////////////header kopieren/CopyMemory(physbase,filebase,pfilentheader^.OptionalHeader.SizeOfHeaders);//header im memory finden & anpassenpphysdosheader := physbase;pphysntheader := Pointer(Cardinal(physbase) + pphysdosheader^._lfanew);pphysntheader^.OptionalHeader.ImageBase := Cardinal(physbase);////////////////////////////////////////////sections kopieren/pphyssectionheader := Pointer(Cardinal(pphysntheader) + SizeOf(TIMAGENTHEADERS));for i := 0 To (pphysntheader^.FileHeader.NumberOfSections - 1) do begin if pphyssectionheader^.SizeOfRawData = 0 Then begin //keine raw data ZeroMemory(Pointer(Cardinal(physbase) + pphyssectionheader^.VirtualAddress),pphyssectionheader^.Misc.VirtualSize); end else begin //raw data vorhanden CopyMemory(Pointer(Cardinal(physbase) + pphyssectionheader^.VirtualAddress),Pointer(Cardinal(filebase) + pphyssectionheader^.PointerToRawData),pphyssectionheader^.SizeOfRawData); end; pphyssectionheader^.Misc.PhysicalAddress := Cardinal(physbase) + pphyssectionheader^.VirtualAddress; //next one please pphyssectionheader := Pointer(Cardinal(pphyssectionheader) + SizeOf(TIMAGESECTIONHEADER));end;///////////////////////////////////imports/importsBase := Pointer(Cardinal(physbase) + pphysntheader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);importDesc := importsBase;while (importDesc.Name) <> 0 Do begin dll_handle := LoadLibrary(pchar(Cardinal(physbase) + importdesc.Name)); importDesc.ForwarderChain := dll_handle; importThunk := Pointer(Cardinal(physbase) + importDesc.FirstThunk); while importThunk.Ordinal <> 0 Do begin importbyname := Pointer(Cardinal(physbase) + importThunk.Ordinal); //Sp Link to comment
Nacho_dj Posted May 20, 2008 Share Posted May 20, 2008 Hmm this reminds me of this:Tutorial: Loading A DLL From Memory Shub-Nigurrath V12.rarAuthor: Shub-NigurrathDescription:The tutorial aims describing a protection technique which consists loading a Dll for a program, directly from memory, without temporary files. Example and sources included./>http://arteam.accessroot.com/tutorials.html?fid=103Good to have different options for the same issue.ThanksNacho_dj Link to comment
pseudonym Posted May 21, 2008 Share Posted May 21, 2008 While I was wondering around on the net a stumbled accross and interesting example, Corvu5 has showen this example in delphiHi Departure, interesting and thanks for source. I do not have access to delphi, do you have a compiled example you could let me have.tia Link to comment
magik Posted May 21, 2008 Share Posted May 21, 2008 nice! very interesting, thanks for sharing Link to comment
NeO Posted May 21, 2008 Share Posted May 21, 2008 nice i wonder if someone can port this into c++ Link to comment
Ufo-Pu55y Posted May 22, 2008 Share Posted May 22, 2008 (edited) nice i wonder if someone can port this into c++ http://www.tuts4you.com/download.php?view.2098 http://arteam.accessroot.com/tutorials.html?fid=103 Edited May 22, 2008 by Ufo-Pu55y Link to comment
metr0 Posted May 22, 2008 Share Posted May 22, 2008 [ CDW, Cryptocrack ][ & Joachim Bauch for his ][ GetSectionProtection function ]Check greetings, J. Bauch also released such a paper some time ago at tuts4you; can't remember right, but I think even Shub's code was based on Bauch's examples? Link to comment
Ufo-Pu55y Posted May 22, 2008 Share Posted May 22, 2008 I'm sure J. Bauch is the origin.. no doubt. Shub credited him with huge letters, but also added useful stuff, which you won't find on Bauch's site. Link to comment
mudlord Posted May 26, 2008 Share Posted May 26, 2008 http://www.tuts4you.com/download.php?view.2098http://arteam.accessroot.com/tutorials.html?fid=103 Thanks UFO for the links! Link to comment
_UE_ Posted September 30, 2008 Share Posted September 30, 2008 does original code support 64 bits? nice i wonder if someone can port this into c++ it seems this guys http://boxedapp.com/ ported Link to comment
high6 Posted October 9, 2008 Share Posted October 9, 2008 Ported it to C# with the C++ source, a bit messy but works. public unsafe static class MemoryLibrary { static ushort Endian(ushort num) { return (ushort)((num << 8) | (num >> 8)); } static void memcpy(byte* dest, byte* src, uint size) { for (uint i = 0; i < size; i++) { *(dest + i) = *(src + i); } } static void memset(byte* dest, byte c, uint size) { for (uint i = 0; i < size; i++) { *dest = c; } } #region IMAGE_DOS_HEADER const ushort IMAGE_DOS_SIGNATURE = 0x4D5A; // MZ [StructLayout(LayoutKind.Sequential, Pack = 1)] struct IMAGE_DOS_HEADER // DOS .EXE header { public ushort e_magic; // Magic number public ushort e_cblp; // Bytes on last page of file public ushort e_cp; // Pages in file public ushort e_crlc; // Relocations public ushort e_cparhdr; // Size of header in paragraphs public ushort e_minalloc; // Minimum extra paragraphs needed public ushort e_maxalloc; // Maximum extra paragraphs needed public ushort e_ss; // Initial (relative) SS value public ushort e_sp; // Initial SP value public ushort e_csum; // Checksum public ushort e_ip; // Initial IP value public ushort e_cs; // Initial (relative) CS value public ushort e_lfarlc; // File address of relocation table public ushort e_ovno; // Overlay number public fixed ushort e_res[4]; // Reserved ushorts public ushort e_oemid; // OEM identifier (for e_oeminfo) public ushort e_oeminfo; // OEM information; e_oemid specific public fixed ushort e_res2[10]; // Reserved ushorts public uint e_lfanew; // File address of new exe header } #endregion #region IMAGE_NT_HEADERS const byte IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct IMAGE_NT_HEADERS { public uint Signature; public IMAGE_FILE_HEADER FileHeader; public IMAGE_OPTIONAL_HEADER32 OptionalHeader; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct IMAGE_FILE_HEADER { public ushort Machine; public ushort NumberOfSections; public uint TimeDateStamp; public uint PointerToSymbolTable; public uint NumberOfSymbols; public ushort SizeOfOptionalHeader; public ushort Characteristics; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct IMAGE_OPTIONAL_HEADER32 { // // Standard fields. // public ushort Magic; public byte MajorLinkerVersion; public byte MinorLinkerVersion; public uint SizeOfCode; public uint SizeOfInitializedData; public uint SizeOfUninitializedData; public uint AddressOfEntryPoint; public uint BaseOfCode; public uint BaseOfData; // // NT additional fields. // public uint ImageBase; public uint SectionAlignment; public uint FileAlignment; public ushort MajorOperatingSystemVersion; public ushort MinorOperatingSystemVersion; public ushort MajorImageVersion; public ushort MinorImageVersion; public ushort MajorSubsystemVersion; public ushort MinorSubsystemVersion; public uint Win32VersionValue; public uint SizeOfImage; public uint SizeOfHeaders; public uint CheckSum; public ushort Subsystem; public ushort DllCharacteristics; public uint SizeOfStackReserve; public uint SizeOfStackCommit; public uint SizeOfHeapReserve; public uint SizeOfHeapCommit; public uint LoaderFlags; public uint NumberOfRvaAndSizes; public fixed ulong DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct IMAGE_DATA_DIRECTORY { public uint VirtualAddress; public uint Size; } #endregion #region VirtualAlloc [DllImport("kernel32.dll")] private static extern uint VirtualAlloc(uint lpAddress, uint dwSize, uint flAllocationType, uint flProtect); [DllImport("kernel32.dll")] private static extern int VirtualFree(uint lpAddress, uint dwSize, uint dwFreeType); [DllImport("kernel32.dll")] private static extern int VirtualProtect(uint lpAddress, uint dwSize, uint flNewProtect, uint* lpflOldProtect); const uint PAGE_NOACCESS = 0x01; const uint PAGE_READONLY = 0x02; const uint PAGE_READWRITE = 0x04; const uint PAGE_WRITECOPY = 0x08; const uint PAGE_EXECUTE = 0x10; const uint PAGE_EXECUTE_READ = 0x20; const uint PAGE_EXECUTE_READWRITE = 0x40; const uint PAGE_EXECUTE_WRITECOPY = 0x80; const uint PAGE_GUARD = 0x100; const uint PAGE_NOCACHE = 0x200; const uint PAGE_WRITECOMBINE = 0x400; const uint MEM_COMMIT = 0x1000; const uint MEM_RESERVE = 0x2000; const uint MEM_DECOMMIT = 0x4000; const uint MEM_RELEASE = 0x8000; const uint MEM_FREE = 0x10000; const uint MEM_PRIVATE = 0x20000; const uint MEM_MAPPED = 0x40000; const uint MEM_RESET = 0x80000; const uint MEM_TOP_DOWN = 0x100000; const uint MEM_WRITE_WATCH = 0x200000; const uint MEM_PHYSICAL = 0x400000; const uint MEM_LARGE_PAGES = 0x20000000; const uint MEM_4MB_PAGES = 0x80000000; #endregion [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MEMORYMODULE { public IMAGE_NT_HEADERS* headers; public byte* codeBase; public uint* modules; public int numModules; public int initialized; } const uint DLL_PROCESS_ATTACH = 1; delegate uint DllEntryPointFunc(uint code, uint method, uint flag); #region IMAGE_SECTION_HEADER const int IMAGE_SIZEOF_SHORT_NAME = 8; const uint IMAGE_SCN_CNT_CODE = 0x00000020; // Section contains code. const uint IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040; // Section contains initialized data. const uint IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080; // Section contains uninitialized data. const uint IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000; // Section contains extended relocations. const uint IMAGE_SCN_MEM_DISCARDABLE = 0x02000000; // Section can be discarded. const uint IMAGE_SCN_MEM_NOT_CACHED = 0x04000000; // Section is not cachable. const uint IMAGE_SCN_MEM_NOT_PAGED = 0x08000000; // Section is not pageable. const uint IMAGE_SCN_MEM_SHARED = 0x10000000; // Section is shareable. const uint IMAGE_SCN_MEM_EXECUTE = 0x20000000; // Section is executable. const uint IMAGE_SCN_MEM_READ = 0x40000000; // Section is readable. const uint IMAGE_SCN_MEM_WRITE = 0x80000000; // Section is writeable. [StructLayout(LayoutKind.Sequential, Pack = 1)] struct IMAGE_SECTION_HEADER { public fixed byte Name[IMAGE_SIZEOF_SHORT_NAME]; public uint PhysicalAddress; public uint VirtualAddress; public uint SizeOfRawData; public uint PointerToRawData; public uint PointerToRelocations; public uint PointerToLinenumbers; public ushort NumberOfRelocations; public ushort NumberOfLinenumbers; public uint Characteristics; } static uint[, ,] ProtectionFlags = new uint[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 IMAGE_SECTION_HEADER* IMAGE_FIRST_SECTION(IMAGE_NT_HEADERS* img) { return (IMAGE_SECTION_HEADER*)((int)img + 0x18 + img->FileHeader.SizeOfOptionalHeader); } static void CopySections(byte* data, IMAGE_NT_HEADERS* old_headers, MEMORYMODULE* module) { uint i, size; byte* codeBase = module->codeBase; byte* dest; IMAGE_SECTION_HEADER* section = IMAGE_FIRST_SECTION(module->headers); for (i = 0; i < module->headers->FileHeader.NumberOfSections; i++, section++) { if (section->SizeOfRawData == 0) { // section doesn't contain data in the dll itself, but may define // uninitialized data size = old_headers->OptionalHeader.SectionAlignment; if (size > 0) { dest = (byte*)VirtualAlloc((uint)codeBase + (uint)section->VirtualAddress, size, MEM_COMMIT, PAGE_READWRITE); section->PhysicalAddress = (uint)dest; memset(dest, 0, size); } // section is empty continue; } // commit memory block and copy data from dll dest = (byte*)VirtualAlloc((uint)codeBase + section->VirtualAddress, section->SizeOfRawData, MEM_COMMIT, PAGE_READWRITE); memcpy(dest, (byte*)((uint)data + (uint)section->PointerToRawData), section->SizeOfRawData); section->PhysicalAddress = (uint)dest; } } static void FinalizeSections(MEMORYMODULE* module) { IMAGE_SECTION_HEADER* section = IMAGE_FIRST_SECTION(module->headers); for (int i = 0; i < module->headers->FileHeader.NumberOfSections; i++, section++) { uint protect, oldProtect, size; uint executable = Convert.ToUInt32((section->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0); uint readable = Convert.ToUInt32((section->Characteristics & IMAGE_SCN_MEM_READ) != 0); uint writeable = Convert.ToUInt32((section->Characteristics & IMAGE_SCN_MEM_WRITE) != 0); if ((section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0) { // section is not needed any more and can safely be freed VirtualFree(section->PhysicalAddress, section->SizeOfRawData, MEM_DECOMMIT); continue; } protect = ProtectionFlags[executable, readable, writeable]; if ((section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) != 0) protect |= PAGE_NOCACHE; // determine size of region size = section->SizeOfRawData; if (size == 0) { if ((section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) != 0) size = module->headers->OptionalHeader.SizeOfInitializedData; else if ((section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0) size = module->headers->OptionalHeader.SizeOfUninitializedData; } if (size > 0) { // change memory access flags VirtualProtect(section->PhysicalAddress, section->SizeOfRawData, protect, &oldProtect); } } } #endregion #region BaseRelocation const uint IMAGE_DIRECTORY_ENTRY_BASERELOC = 5; // Base Relocation Table static IMAGE_DATA_DIRECTORY* GET_HEADER_DICTIONARY(MEMORYMODULE* module, uint idx) { return (IMAGE_DATA_DIRECTORY*)(&module->headers->OptionalHeader.DataDirectory[idx]); } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct IMAGE_BASE_RELOCATION { public uint VirtualAddress; public uint SizeOfBlock; } const uint IMAGE_SIZEOF_BASE_RELOCATION = 8; const uint IMAGE_REL_BASED_ABSOLUTE = 0; const uint IMAGE_REL_BASED_HIGHLOW = 3; static void PerformBaseRelocation(MEMORYMODULE* module, uint delta) { uint i; byte* codeBase = module->codeBase; IMAGE_DATA_DIRECTORY* directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC); if (directory->Size > 0) { IMAGE_BASE_RELOCATION* relocation = (IMAGE_BASE_RELOCATION*)((uint)codeBase + directory->VirtualAddress); for (; relocation->VirtualAddress > 0; ) { byte* dest = (byte*)((uint)codeBase + relocation->VirtualAddress); ushort* relInfo = (ushort*)((byte*)relocation + IMAGE_SIZEOF_BASE_RELOCATION); for (i = 0; i < ((relocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++) { uint* patchAddrHL; uint type, offset; // the upper 4 bits define the type of relocation type = (uint)(*relInfo >> 12); // the lower 12 bits define the offset offset = (uint)(*relInfo & 0xfff); switch (type) { case IMAGE_REL_BASED_ABSOLUTE: // skip relocation break; case IMAGE_REL_BASED_HIGHLOW: // change complete 32 bit address patchAddrHL = (uint*)((uint)dest + offset); *patchAddrHL += delta; break; default: //printf("Unknown relocation: %d\n", type); break; } } // advance to next relocation block relocation = (IMAGE_BASE_RELOCATION*)((uint)relocation + relocation->SizeOfBlock); } } } #endregion #region BuildImportTable [DllImport("kernel32.dll", EntryPoint = "LoadLibraryA")] private static extern uint LoadLibrary(byte* lpLibFileName); [DllImport("kernel32.dll")] private static extern uint GetProcAddress(uint hModule, byte* lpProcName); const uint IMAGE_DIRECTORY_ENTRY_IMPORT = 1; [StructLayout(LayoutKind.Sequential, Pack = 1)] struct IMAGE_IMPORT_DESCRIPTOR { public uint Characteristics; // 0 for terminating null import descriptor public uint TimeDateStamp; // 0 if not bound, // -1 if bound, and real date\time stamp // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) // O.W. date/time stamp of DLL bound to (Old BIND) public uint ForwarderChain; // -1 if no forwarders public uint Name; public uint FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct IMAGE_IMPORT_BY_NAME { public ushort Hint; public fixed byte Name[1]; } static byte* realloc(byte* bytes, uint newsize, uint oldsize) { byte* New = (byte*)Marshal.AllocHGlobal((int)newsize).ToPointer(); if ((int)bytes != 0) { memcpy(New, bytes, oldsize); Marshal.FreeHGlobal(new IntPtr(bytes)); } return New; } static bool BuildImportTable(MEMORYMODULE* module) { bool result = true; byte* codeBase = module->codeBase; IMAGE_DATA_DIRECTORY* directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT); if (directory->Size > 0) { IMAGE_IMPORT_DESCRIPTOR* importDesc = (IMAGE_IMPORT_DESCRIPTOR*)((uint)codeBase + directory->VirtualAddress); for (; importDesc->Name != 0; importDesc++) { uint* thunkRef; uint* funcRef; uint handle = LoadLibrary((byte*)((uint)codeBase + importDesc->Name)); if (handle == 0) { result = false; break; } module->modules = (uint*)realloc((byte*)module->modules, (uint)(module->numModules + 1) * 4, (uint)(module->numModules) * 4); if (module->modules == null) { result = false; break; } module->modules[module->numModules++] = handle; if (importDesc->Characteristics != 0) { thunkRef = (uint*)((uint)codeBase + importDesc->Characteristics); funcRef = (uint*)((uint)codeBase + importDesc->FirstThunk); } else { // no hint table thunkRef = (uint*)((uint)codeBase + importDesc->FirstThunk); funcRef = (uint*)((uint)codeBase + importDesc->FirstThunk); } for (; *thunkRef != 0; thunkRef++, funcRef++) { if ((*thunkRef & 0x80000000) != 0) *funcRef = GetProcAddress(handle, (byte*)(*thunkRef & 0xffff)); else { IMAGE_IMPORT_BY_NAME* thunkData = (IMAGE_IMPORT_BY_NAME*)((uint)codeBase + *thunkRef); *funcRef = GetProcAddress(handle, (byte*)(int)(thunkData) + 2); } if (*funcRef == 0) { result = false; break; } } if (!result) break; } } return result; } #endregion const uint IMAGE_DIRECTORY_ENTRY_EXPORT = 0; // Export Directory [StructLayout(LayoutKind.Sequential, Pack = 1)] struct IMAGE_EXPORT_DIRECTORY { public uint Characteristics; public uint TimeDateStamp; public ushort MajorVersion; public ushort MinorVersion; public uint Name; public uint Base; public uint NumberOfFunctions; public uint NumberOfNames; public uint AddressOfFunctions; // RVA from base of image public uint AddressOfNames; // RVA from base of image public uint AddressOfNameOrdinals; // RVA from base of image } static bool stricmp(string str, byte* bytes) { int idx = 0; while (*bytes != 0 && idx < str.Length) { if (str[idx] != *(bytes + idx)) { return false; } idx++; } return true; } const uint DLL_PROCESS_DETACH = 0; [DllImport("kernel32.dll")] private static extern int FreeLibrary(uint hLibModule); public static int MemoryLoadLibrary(byte[] bytes) { fixed (byte* b = bytes) { IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)b; if (Endian(dos_header->e_magic) != IMAGE_DOS_SIGNATURE) { return 0; } IMAGE_NT_HEADERS* old_header = (IMAGE_NT_HEADERS*)(b + dos_header->e_lfanew); uint code = VirtualAlloc(old_header->OptionalHeader.ImageBase, old_header->OptionalHeader.SizeOfImage, MEM_RESERVE, PAGE_READWRITE); if (code == 0) code = VirtualAlloc(0, old_header->OptionalHeader.SizeOfImage, MEM_RESERVE, PAGE_READWRITE); if (code == 0) return 0; MEMORYMODULE* result = (MEMORYMODULE*)Marshal.AllocHGlobal(sizeof(MEMORYMODULE)); result->codeBase = (byte*)code; result->numModules = 0; result->modules = null; result->initialized = 0; VirtualAlloc(code, old_header->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_READWRITE); uint headers = VirtualAlloc(code, old_header->OptionalHeader.SizeOfHeaders, MEM_COMMIT, PAGE_READWRITE); // copy PE header to code memcpy((byte*)headers, (byte*)dos_header, dos_header->e_lfanew + old_header->OptionalHeader.SizeOfHeaders); result->headers = (IMAGE_NT_HEADERS*)&((byte*)(headers))[dos_header->e_lfanew]; // update position result->headers->OptionalHeader.ImageBase = (uint)code; // copy sections from DLL file block to new memory location CopySections(b, old_header, result); // adjust base address of imported data uint locationDelta = (uint)(code - old_header->OptionalHeader.ImageBase); if (locationDelta != 0) PerformBaseRelocation(result, locationDelta); // load required dlls and adjust function table of imports if (!BuildImportTable(result)) goto error; // mark memory pages depending on section headers and release // sections that are marked as "discardable" FinalizeSections(result); // get entry point of loaded library if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) { uint DllEntry = ((uint)code + result->headers->OptionalHeader.AddressOfEntryPoint); if (DllEntry == 0) { goto error; } // notify library about attaching to process DllEntryPointFunc func = (DllEntryPointFunc)Marshal.GetDelegateForFunctionPointer(new IntPtr(DllEntry), typeof(DllEntryPointFunc)); uint successfull = func(code, DLL_PROCESS_ATTACH, 0); if (successfull == 0) { goto error; } result->initialized = 1; } return (int)result; error: // cleanup //MemoryFreeLibrary(result); return 0; } } public static int MemoryGetProcAddress(int module, string name) { byte* codeBase = ((MEMORYMODULE*)module)->codeBase; int idx = -1; uint i; uint* nameRef; ushort* ordinal; IMAGE_EXPORT_DIRECTORY* exports; IMAGE_DATA_DIRECTORY* directory = GET_HEADER_DICTIONARY((MEMORYMODULE*)module, IMAGE_DIRECTORY_ENTRY_EXPORT); if (directory->Size == 0) // no export table found return 0; exports = (IMAGE_EXPORT_DIRECTORY*)((uint)codeBase + directory->VirtualAddress); if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) // DLL doesn't export anything return 0; // search function name in list of exported names nameRef = (uint*)((uint)codeBase + exports->AddressOfNames); ordinal = (ushort*)((uint)codeBase + exports->AddressOfNameOrdinals); for (i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++) { if (stricmp(name, (byte*)((uint)codeBase + *nameRef))) { idx = *ordinal; break; } } if (idx == -1) // exported symbol not found return 0; if ((uint)idx > exports->NumberOfFunctions) // name <-> ordinal number don't match return 0; // AddressOfFunctions contains the RVAs to the "real" functions return (int)((uint)codeBase + *(uint*)((uint)codeBase + exports->AddressOfFunctions + (idx * 4))); } public static void MemoryFreeLibrary(int mod) { int i; MEMORYMODULE* module = (MEMORYMODULE*)mod; if (module != null) { if (module->initialized != 0) { // notify library about detaching from process uint DllEntry = (uint)((uint)module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint); // notify library about attaching to process DllEntryPointFunc func = (DllEntryPointFunc)Marshal.GetDelegateForFunctionPointer(new IntPtr(DllEntry), typeof(DllEntryPointFunc)); uint successfull = func((uint)module->codeBase, DLL_PROCESS_ATTACH, 0); module->initialized = 0; } if (module->modules != null) { // free previously opened libraries for (i = 0; i < module->numModules; i++) if (module->modules[i] != 0) FreeLibrary(module->modules[i]); Marshal.FreeHGlobal(new IntPtr(module->modules)); } if ((int)module->codeBase != 0) // release memory of library VirtualFree((uint)module->codeBase, 0, MEM_RELEASE); Marshal.FreeHGlobal(new IntPtr(module)); } } } Link to comment
high6 Posted October 11, 2008 Share Posted October 11, 2008 Okay well, there is a problem.Dlls using "MSVCR80.dll" give an error messagebox when LoadLibrary is called on "MSVCR80.dll".Why is this?Does MSVCR80.dll need to be loaded specially? Link to comment
Ufo-Pu55y Posted October 11, 2008 Share Posted October 11, 2008 (edited) Okay well, there is a problem.Dlls using "MSVCR80.dll" give an error messagebox when LoadLibrary is called on "MSVCR80.dll".Why is this?Does MSVCR80.dll need to be loaded specially?about LoadLibrary:"...If the function fails, the return value is NULL. To get extended error information, call GetLastError..."u could add that in c# like this:if (Marshal.GetLastWin32Error() != 0) MessageBox.Show((new Win32Exception()).Message);then look up the error msg.. prolly couldn't find that dll ?EDIT/You also need to add "SetLastError=true" :[DllImport("kernel32.dll", EntryPoint = "LoadLibraryA", SetLastError=true)]private static extern uint LoadLibrary(byte* lpLibFileName); Edited October 11, 2008 by Ufo-Pu55y Link to comment
high6 Posted October 11, 2008 Share Posted October 11, 2008 Okay well, there is a problem.Dlls using "MSVCR80.dll" give an error messagebox when LoadLibrary is called on "MSVCR80.dll".Why is this?Does MSVCR80.dll need to be loaded specially?about LoadLibrary:"...If the function fails, the return value is NULL. To get extended error information, call GetLastError..."u could add that in c# like this:if (Marshal.GetLastWin32Error() != 0) MessageBox.Show((new Win32Exception()).Message);then look up the error msg.. prolly couldn't find that dll ?EDIT/You also need to add "SetLastError=true" :[DllImport("kernel32.dll", EntryPoint = "LoadLibraryA", SetLastError=true)]private static extern uint LoadLibrary(byte* lpLibFileName);Well the dll messageboxes when loaded.I think msvcr80.dll needs to be loaded specially. Link to comment
atlantisx Posted October 12, 2008 Share Posted October 12, 2008 (edited) just a quick question, is DllMain executed here? Cause I tried a similar but much shorter solution but I was unable to execute DllMain and I had some things that was needed to execute there. Nice coding btw Edited October 12, 2008 by atlantisx Link to comment
high6 Posted October 12, 2008 Share Posted October 12, 2008 Well the c++ code I ported from does// get entry point of loaded library if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) { uint DllEntry = ((uint)code + result->headers->OptionalHeader.AddressOfEntryPoint); if (DllEntry == 0) { goto error; } // notify library about attaching to process DllEntryPointFunc func = (DllEntryPointFunc)Marshal.GetDelegateForFunctionPointer(new IntPtr(DllEntry), typeof(DllEntryPointFunc)); uint successfull = func(code, DLL_PROCESS_ATTACH, 0); if (successfull == 0) { goto error; } result->initialized = 1; } Link to comment
_UE_ Posted November 30, 2008 Share Posted November 30, 2008 Okay well, there is a problem.Dlls using "MSVCR80.dll" give an error messagebox when LoadLibrary is called on "MSVCR80.dll".Why is this?Does MSVCR80.dll need to be loaded specially?Yes, it's due to manifest stuff. Link to comment
ntaryl Posted March 13, 2009 Share Posted March 13, 2009 Very nice example http://www.joachim-bauch.de/tutorials/load...ry.html/en/viewWant to ask is possible to do the same in vbasic ?thanks for the time Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now