Open DLL from memory

Just starting out? Need help? Post your questions and find answers here.
AndyMK
Enthusiast
Enthusiast
Posts: 582
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Open DLL from memory

Post by AndyMK »

Hi, I have been delving in to the world of DLL's and was wondering if it was possible to for example, stream a DLL file from a server directly in to client memory and open it from there so the DLL is never created as a file on the client machine but is still usable by my application in the normal way?

Thanks
Andy
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Open DLL from memory

Post by ts-soft »

you can do this, with this: http://www.joachim-bauch.de/tutorials/l ... om-memory/
c-source (32-bit only). create a static lib with PellesC for example and import the 3 functions.

Or i upload a example for you?

greetings
Thomas
AndyMK
Enthusiast
Enthusiast
Posts: 582
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Open DLL from memory

Post by AndyMK »

A PB example would be great! :mrgreen:
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Open DLL from memory

Post by ts-soft »

you can download the static lib and pb import here: http://www.realsource.de/tmp/memorymodule.zip
I think the import is selfexplaining

Code: Select all

ImportC "memorymodule.lib"
  MemoryLoadLibrary(MemoryPointer)
  MemoryGetProcAddress(hModule, FunctionName.p-ascii)
  MemoryFreeLibrary(hModule)
EndImport
The result of MemoryLoadLibrary is hModule!
AndyMK
Enthusiast
Enthusiast
Posts: 582
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Open DLL from memory

Post by AndyMK »

Thanks i will try this out now. I also just stumbled across this and it seems to work but it runs EXE's from memory. I am using Windows 7 x64 and the latest Avast AntiVirus.. no negative effects and it the application runs fine.

http://www.purebasic.fr/english/viewtop ... dll+in+exe
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Open DLL from memory

Post by ts-soft »

you can use callfunctionfast, but better use prototypes.
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Open DLL from memory

Post by idle »

you can use the pb osl functions to load a dll into memory, loadLibraryM(), GetProcAddressM(), FreeLibraryM()

Code: Select all

      *OutBuffer = PureLZMA_UnCompress(*dat, @BufferLen,key$)
       If *OutBuffer > 0
          My_DLL=LoadLibraryM(*OutBuffer)
          MyDll=GetProcAddressM(My_dll,"MyDll")
          res = CallFunctionFast(SomeFunction,Param1,Param2)
          FreeLibraryM(My_dll)
          FreeMemory(*outbuffer)
          FreeMemory(*dat)
      EndIf 
the RunPe code from hipy001 seems to work fine though the process created is orphaned and runs under Unknown.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Open DLL from memory

Post by ts-soft »

The PBOSL Lib uses the same c-source but you can't use it in Unicode-Mode.
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Open DLL from memory

Post by idle »

I hadn't made the connection, too early in the morning.
AndyMK
Enthusiast
Enthusiast
Posts: 582
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Open DLL from memory

Post by AndyMK »

the RunPe code from hipy001 seems to work fine though the process created is orphaned and runs under Unknown.
What are the implications of this?
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Re: Open DLL from memory

Post by SFSxOI »

AndyMK wrote:
the RunPe code from hipy001 seems to work fine though the process created is orphaned and runs under Unknown.
What are the implications of this?
You don't want orpahaned processes. Orphans waste resources and can potentially leave the system in trouble and possibly vunlerable in some cases.

How about the streaming part, any ideas on that? I'd be interested in seeing what you come up with.
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
pablov
User
User
Posts: 19
Joined: Mon Apr 06, 2009 11:55 am

Re: Open DLL from memory

Post by pablov »

Offer You my variant

Code: Select all

; Author: Pablov 
; Date: 19. 08.2011 
; OS: Windows (for PB4.30 - 4.51) 
;DllFM.pbi
#IMAGE_REL_BASED_ABSOLUTE = 0
#IMAGE_ORDINAL_FLAG32     = $80000000
Structure IMAGE_SECTION_HEADER
  SecName.b[8]
  StructureUnion
    PhysicalAddr.l
    VirtualSize.l
  EndStructureUnion
  VirtualAddress.l
  SizeOfRawData.l
  PointerToRawData.l
  PointerToRelocations.l
  PointerToLinenumbers.l
  NumberOfRelocations.w
  NumberOfLinenumbers.w
  Characteristics.l
EndStructure

Structure IMAGE_SECTION_HEADERS
  ish.IMAGE_SECTION_HEADER[64]
EndStructure

Structure ImageBaseRelocation
    VirtualAddress.l
    SizeOfBlock.l 
EndStructure

Structure _IMAGE_IMPORT_DESCRIPTOR
    OriginalFirstThunk.l
    TimeDateStamp.l                    
    ForwarderChain.l                    
    Name.l                              
    FirstThunk.l                      
EndStructure

Structure DLL_INFO                      
  BaseVirtDll.l
  EntryPoint.l
  loadDLL.l
EndStructure  

Global Dim LibraryLoad(0)               
Global DllInfo.DLL_INFO

ProcedureDLL FreeLibraryEx()   
    CallFunctionFast(DllInfo\BaseVirtDll + DllInfo\EntryPoint, DllInfo\BaseVirtDll, #DLL_PROCESS_DETACH, 0)
    For i.w = 0 To DllInfo\loadDLL - 1 
       FreeLibrary_(LibraryLoad(i))
    Next i
    If DllInfo\BaseVirtDll : VirtualFree_(DllInfo\BaseVirtDll, 0, #MEM_RELEASE) :EndIf
EndProcedure

ProcedureDLL GetProcAddressEx(BaseAddress.l, ProcName.s)
    PExports.IMAGE_EXPORT_DIRECTORY
    _step = 0
    *DOS_HEADER.IMAGE_DOS_HEADER             
    *NT_HEADERS.IMAGE_NT_HEADERS
    *DOS_HEADER      = BaseAddress
    *NT_HEADERS      = BaseAddress + *DOS_HEADER\e_lfanew           
    RtlMoveMemory_(PExports, *NT_HEADERS\OptionalHeader\DataDirectory[0]\VirtualAddress + BaseAddress , SizeOf(IMAGE_EXPORT_DIRECTORY))
    NameAddr.l = PExports\AddressOfNames + BaseAddress
    OrdinalAddres.l = PExports\AddressOfNameOrdinals + BaseAddress
    FuncAddr.l      = PExports\AddressOfFunctions + BaseAddress
    For index.l = 0 To PExports\NumberOfNames - 1
        NameAddr + _step
        OrdinalAddres + _step/2                 
        If ProcName = PeekS(PeekL(NameAddr) + BaseAddress)
           ProcAddress.l = PeekL(FuncAddr + PeekW(OrdinalAddres)*4 ) + BaseAddress
           Break
        EndIf  
        _step = 4                                 
    Next index
 ProcedureReturn ProcAddress   
EndProcedure

ProcedureDLL ImportProc(BaseAddress.l, *NT_HEADERS.IMAGE_NT_HEADERS)
  Protected PImport._IMAGE_IMPORT_DESCRIPTOR
  If *NT_HEADERS\OptionalHeader\DataDirectory[1]\VirtualAddress  
    SizeImportStruct.b = SizeOf(_IMAGE_IMPORT_DESCRIPTOR)
    RtlMoveMemory_(PImport, *NT_HEADERS\OptionalHeader\DataDirectory[1]\VirtualAddress + BaseAddress , SizeImportStruct)
    While PImport\FirstThunk <> 0                
          LibsUsed.s = PeekS(PImport\Name + BaseAddress)
          hModule = GetModuleHandle_(LibsUsed)
          If hModule = 0                                      
            hModule = LoadLibrary_(LibsUsed)                 
            ReDim LibraryLoad(DllInfo\loadDLL)
            LibraryLoad(DllInfo\loadDLL) = hModule
            DllInfo\loadDLL + 1
          EndIf
        While PeekL(PImport\FirstThunk + BaseAddress) <> 0 
          If PeekL(PImport\FirstThunk + BaseAddress) & #IMAGE_ORDINAL_FLAG32 <> 0  
             PokeL(PImport\FirstThunk + BaseAddress, GetProcAddress_(hModule, PeekL(PImport\FirstThunk + BaseAddress) & $FFFF))
          Else                                                                
             PokeL(PImport\FirstThunk + BaseAddress, GetProcAddress_(hModule, PeekS(PeekL(PImport\FirstThunk + BaseAddress) + 2 + BaseAddress)))
          EndIf   
            PImport\FirstThunk + 4
        Wend
         RtlMoveMemory_(PImport, *NT_HEADERS\OptionalHeader\DataDirectory[1]\VirtualAddress + BaseAddress + _step.w + SizeImportStruct, SizeImportStruct)
         _step + SizeImportStruct
    Wend
  EndIf
EndProcedure

ProcedureDLL RelocProc(BaseAddress.l, *NT_HEADERS.IMAGE_NT_HEADERS)
  Protected *PReloc.ImageBaseRelocation
  ImageBaseDelta = BaseAddress - *NT_HEADERS\OptionalHeader\ImageBase                       ; calculate delta
  If ImageBaseDelta    
    RelocsSize.l = *NT_HEADERS\OptionalHeader\DataDirectory[5]\Size
    *PReloc = *NT_HEADERS\OptionalHeader\DataDirectory[5]\VirtualAddress + BaseAddress 
    P.w
    j.l
    ModCount.l
    tempSize.l = 0
    startAdrReloc = *NT_HEADERS\OptionalHeader\DataDirectory[5]\VirtualAddress + BaseAddress + 8
    While tempSize < RelocsSize                                          
       ModCount = (*PReloc\SizeOfBlock - 8) / 2 
       For j = 0 To ModCount-1 
          P = PeekW(startAdrReloc) 
          If P & $f000 <> #IMAGE_REL_BASED_ABSOLUTE
             RelocValue = PeekL(BaseAddress + *PReloc\VirtualAddress + (P & $0fff)) + ImageBaseDelta
             PokeL(BaseAddress + *PReloc\VirtualAddress + (P & $0fff), RelocValue)          ;  Correct reference
             startAdrReloc + 2
          Else
             startAdrReloc + 2
          EndIf
       Next j  
       tempSize        + *PReloc\SizeOfBlock
       *PReloc         + *PReloc\SizeOfBlock 
       startAdrReloc   + 8
    Wend 
  EndIf
EndProcedure

ProcedureDLL LoadLibraryEx(StartFile.l, EndFile.l)
  Protected *DOS_HEADER.IMAGE_DOS_HEADER             
  Protected*SECTION_HEADERS.IMAGE_SECTION_HEADERS  
  Protected BaseVirtDll.l
  Protected *NT_HEADERS.IMAGE_NT_HEADERS
SizeDll =  EndFile - StartFile
If PeekW(StartFile) = $434A                               ; If file pack > PureBasic (signature "JC")
  *Source        = AllocateMemory(SizeDll)           
  *VirtMemOffset = AllocateMemory(SizeDll * 3) 
EnableASM
                  mov ecx, SizeDll
                  mov edi, *Source
                  mov esi, StartFile
                  rep movsb                               ; unpack and write in memory
    UnpackMemory(*Source, *VirtMemOffset)                             
    If *Source : FreeMemory(*Source) : EndIf                     
ElseIf PeekW(StartFile) = $5A4D                          ; else (signature "MZ")
    *VirtMemOffset = AllocateMemory(SizeDll)   
                  mov ecx, SizeDll
                  mov edi, *VirtMemOffset
                  mov esi, StartFile
                  rep movsb                               ; write in memory
DisableASM    
Else
  MessageRequester("Error", " No valid PE File  ", #MB_OK|#MB_ICONERROR)
  End
EndIf   

   ; *****************************************************************************************
   *DOS_HEADER      = *VirtMemOffset
   *NT_HEADERS      = *VirtMemOffset + *DOS_HEADER\e_lfanew           
   *SECTION_HEADERS = *NT_HEADERS\OptionalHeader + *NT_HEADERS\FileHeader\SizeOfOptionalHeader 
   ;******************************************************************************************
   BaseVirtDll = VirtualAlloc_(#Null, *NT_HEADERS\OptionalHeader\SizeOfImage, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
If BaseVirtDll  
   DllInfo\EntryPoint = *NT_HEADERS\OptionalHeader\AddressOfEntryPoint
   RtlMoveMemory_(BaseVirtDll, *VirtMemOffset, *NT_HEADERS\OptionalHeader\SizeOfHeaders)       
   For i = 0 To *NT_HEADERS\FileHeader\NumberOfSections - 1 
     RtlMoveMemory_(BaseVirtDll + *SECTION_HEADERS\ish[i]\VirtualAddress, *VirtMemOffset  + *SECTION_HEADERS\ish[i]\PointerToRawData, *SECTION_HEADERS\ish[i]\SizeOfRawData)      
   Next i
 
   RelocProc(BaseVirtDll, *NT_HEADERS)                           ; Relocation  
 
   ImportProc(BaseVirtDll, *NT_HEADERS)                          ; Import
   
; @@@@@@@@@@@@@@@@@@@@@@@@@@  Flags  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  
    For i = 0 To *NT_HEADERS\FileHeader\NumberOfSections - 1
       SC.l = *SECTION_HEADERS\ish[i]\Characteristics
       protect.l = #PAGE_READONLY
       If  SC & $80000000 : protect = #PAGE_READWRITE  : EndIf           
       If  SC & $20000000 : protect = #PAGE_EXECUTE_READ : EndIf         
       If  SC & $20000000 And SC & $80000000 : protect = #PAGE_EXECUTE_READWRITE : EndIf
       VirtualProtect_(*SECTION_HEADERS\ish[i]\VirtualAddress + BaseVirtDll, *SECTION_HEADERS\ish[i]\VirtualSize, protect, @TempAddr.l) 
    Next i 
; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@     Init DLL    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    If DllInfo\EntryPoint <> 0                       
      If CallFunctionFast(BaseVirtDll + *NT_HEADERS\OptionalHeader\AddressOfEntryPoint, BaseVirtDll, #DLL_PROCESS_ATTACH, 0)
      Else
        FreeLibraryEx()
        ProcedureReturn 0
      EndIf
    EndIf
; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    If *VirtMemOffset : FreeMemory(*VirtMemOffset) : EndIf   
    DllInfo\BaseVirtDll = BaseVirtDll             
    ProcedureReturn BaseVirtDll
 EndIf
    If *VirtMemOffset : FreeMemory(*VirtMemOffset) : EndIf  
    ProcedureReturn 0
EndProcedure
Example:

Code: Select all

;  Example for BASS.dll  !!!!!!!!!!!!!! 

XIncludeFile "DllFM.pbi"
DataSection
  StartFile: 
    IncludeBinary "BASS.dll"                           
  EndFile: 
EndDataSection

BaseDll.l = LoadLibraryEx(?StartFile, ?EndFile) 
If BaseDll
  MessageRequester("Congratulation", "Library loaded to: " + RSet(Hex(BaseDll), 8, "0"), #MB_OK|#MB_ICONINFORMATION)
Else
  MessageRequester("Error", "Can Not load library", #MB_OK|#MB_ICONERROR)
  End
EndIf  
BASS_GetVersion.l = GetProcAddressEx(BaseDll, "BASS_GetVersion")
If BASS_GetVersion
  ver.s = Hex(CallFunctionFast(BASS_GetVersion))
  If ver
    While Right(ver, 1) = "0"
       ver = Mid(ver, 1, Len(ver)-1)
    Wend
    ver = ReplaceString(ver, "0", ".") 
    MessageRequester("Version of BASS", "Version BASS.dll:  " + ver, #MB_OK|#MB_OK|#MB_ICONINFORMATION)
  EndIf 
EndIf 
FreeLibraryEx()
ricardo
Addict
Addict
Posts: 2438
Joined: Fri Apr 25, 2003 7:06 pm
Location: Argentina

Re: Open DLL from memory

Post by ricardo »

Its possible to, instead of loading the dll when compile, downloading from the web on run time?

Code: Select all

XIncludeFile "DllFM.pbi"
DataSection
  StartFile: 
    IncludeBinary "BASS.dll"                           
  EndFile: 
EndDataSection
ARGENTINA WORLD CHAMPION
Post Reply