[C#] Run non .NET exe from memory

Discussion in 'Mixed Languages' started by Bosh, Jan 21, 2011.

  1. Bosh

    Bosh MDL Developer

    May 30, 2010
    615
    299
    30
    Hi everyone!

    As you must know (or not :p), I'm helping Cody with the Office Toolkit, and now I'm facing this problem.

    Anyone knows how can I execute a non .NET exe from memory? :confused: I know this can be done with Reflection for .NET applications, but I haven't found a way to do this for the Keygen.exe from ZWT (the KMS emulator).

    Thanks in advance! :)
     
  2. Calistoga

    Calistoga MDL Senior Member

    Jul 25, 2009
    420
    198
    10
    It seems like it was possible to launch an unmanaged executable directly from memory in Windows XP and older, due to "a security hole" which was fixed in Vista. So as far as I have understood it (please correct me if I'm wrong), we can no longer do it this way (since we would then bypass all security mechanisms in the OS). Even if it was possible, we would probably get kicked from behind by DEP.

    On the other hand, doing the same thing with DLLs IS possible even today (AutoIt example). You're essentially recreating LoadLibrary() to do what we want. Thinking of this, it has to be possible somehow to load executables, but it probably requires Massive use of Interop and complex undocumented APIs.

    I think you might find the unexpected meeting with a baseball bat considerably more comfortable.

    But theoretically speaking, maybe a RAM-drive would serve the same purpose? I don't know whether it's possible to "mount" a RAM-drive without a drive letter, and would this make the AV's shut up about the KMS? This might be worth looking into. (Is this how you did it Phazor?)

    I'll let you know if I get a revelation :p
     
  3. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,812
    45,404
    150
    A RAM Drive would require a driver unfortunately. I've seen code that said it could load a passed from RAM but couldn't figure it out as as you say a lot of Interops. It was something like CMemoryExecute.cs.

    Ideally I wish I had the actual KMS Emulator code or a recreation of it so we could just run it as a second thread. Phazor makes references to some kind of Virtual Environment but googling it all I see is App-V and VMware.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  4. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,812
    45,404
    150
    #4 CODYQX4, Jul 9, 2011
    Last edited by a moderator: Apr 20, 2017
    OK we have a working AutoIT script, posted by Krakatoa

    It consists of two scripts, one simply feeds the Keygen's hex representation to the more important script.

    Was wondering if someone could help convert this to C#
    Here is the more important script:
    Code:
    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_UseUpx=n
    #AutoIt3Wrapper_UseX64=n
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
    #include <soubory.au3>
    Opt("MustDeclareVars", 1)
    Opt("TrayIconHide", 1)
    
    Global $sData
    Global $bBinary = _KMSserv_exe()
    Global $iNewPID
    
    MsgBox(0, "Run ZWT keygen in RAM", "Click OK = Run hide ZWT keygen in RAM")
    For $i = 1 To 10
    $iNewPID = _RunBinary($bBinary)
    If Not @error Then ExitLoop
    Next
    MsgBox(0, "Close ZWT keygen in RAM", "Click OK = Close ZWT keygen in RAM")
    ProcessClose ($iNewPID)
    
    Func _RunBinary($bBinaryImage, $sCommandLine = "", $sExeModule = @AutoItExe)
    
    Local $fAutoItX64 = @AutoItX64
    Local $tBinary = DllStructCreate("byte[" & BinaryLen($bBinary) & "]")
    DllStructSetData($tBinary, 1, $bBinary)
    Local $pPointer = DllStructGetPtr($tBinary)
    
    #region 3. CREATING NEW PROCESS
    ; STARTUPINFO structure (actually all that really matters is allocated space)
    Local $tSTARTUPINFO = DllStructCreate("dword  cbSize;" & _
    "ptr Reserved;" & _
    "ptr Desktop;" & _
    "ptr Title;" & _
    "dword X;" & _
    "dword Y;" & _
    "dword XSize;" & _
    "dword YSize;" & _
    "dword XCountChars;" & _
    "dword YCountChars;" & _
    "dword FillAttribute;" & _
    "dword Flags;" & _
    "word ShowWindow;" & _
    "word Reserved2;" & _
    "ptr Reserved2;" & _
    "ptr hStdInput;" & _
    "ptr hStdOutput;" & _
    "ptr hStdError")
    DllStructSetData($tSTARTUPINFO, "Flags", BitOR(0x00000001, 0x00000100))
    DllStructSetData($tSTARTUPINFO, "ShowWindow", 0)
    ; This is much important. This structure will hold very some important data.
    Local $tPROCESS_INFORMATION = DllStructCreate("ptr Process;" & _
    "ptr Thread;" & _
    "dword ProcessId;" & _
    "dword ThreadId")
    ; Create new process
    Local $aCall = DllCall("kernel32.dll", "bool", "CreateProcessW", _
    "wstr", $sExeModule, _
    "wstr", $sCommandLine, _
    "ptr", 0, _
    "ptr", 0, _
    "int", 0, _
    "dword", 4, _ ; CREATE_SUSPENDED ; <- this is essential
    "ptr", 0, _
    "ptr", 0, _
    "ptr", DllStructGetPtr($tSTARTUPINFO), _
    "ptr", DllStructGetPtr($tPROCESS_INFORMATION))
    ; Check for errors or failure
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) ; CreateProcess function or call to it failed
    ; Get new process and thread handles:
    Local $hProcess = DllStructGetData($tPROCESS_INFORMATION, "Process")
    Local $hThread = DllStructGetData($tPROCESS_INFORMATION, "Thread")
    ; Check for 'wrong' bit-ness. Not because it could't be implemented, but besause it would be uglyer (structures)
    If $fAutoItX64 And _RunBinary_IsWow64Process($hProcess) Then
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(2, 0, 0)
    EndIf
    
    #region 4. FILL CONTEXT STRUCTURE
    ; CONTEXT structure is what's really important here. It's processor specific.
    Local $iRunFlag, $tCONTEXT
    If $fAutoItX64 Then
    If @OSArch = "X64" Then
    $iRunFlag = 2
    $tCONTEXT = DllStructCreate("align 16; uint64 P1Home; uint64 P2Home; uint64 P3Home; uint64 P4Home; uint64 P5Home; uint64 P6Home;" & _ ; Register parameter home addresses
    "dword ContextFlags; dword MxCsr;" & _ ; Control flags
    "word SegCS; word SegDs; word SegEs; word SegFs; word SegGs; word SegSs; dword EFlags;" & _ ; Segment Registers and processor flags
    "uint64 Dr0; uint64 Dr1; uint64 Dr2; uint64 Dr3; uint64 Dr6; uint64 Dr7;" & _ ; Debug registers
    "uint64 Rax; uint64 Rcx; uint64 Rdx; uint64 Rbx; uint64 Rsp; uint64 Rbp; uint64 Rsi; uint64 Rdi; uint64 R8; uint64 R9; uint64 R10; uint64 R11; uint64 R12; uint64 R13; uint64 R14; uint64 R15;" & _ ; Integer registers
    "uint64 Rip;" & _ ; Program counter
    "uint64 Header[4]; uint64 Legacy[16]; uint64 Xmm0[2]; uint64 Xmm1[2]; uint64 Xmm2[2]; uint64 Xmm3[2]; uint64 Xmm4[2]; uint64 Xmm5[2]; uint64 Xmm6[2]; uint64 Xmm7[2]; uint64 Xmm8[2]; uint64 Xmm9[2]; uint64 Xmm10[2]; uint64 Xmm11[2]; uint64 Xmm12[2]; uint64 Xmm13[2]; uint64 Xmm14[2]; uint64 Xmm15[2];" & _ ; Floating point state (types are not correct for simplicity reasons!!!)
    "uint64 VectorRegister[52]; uint64 VectorControl;" & _ ; Vector registers (type for VectorRegister is not correct for simplicity reasons!!!)
    "uint64 DebugControl; uint64 LastBranchToRip; uint64 LastBranchFromRip; uint64 LastExceptionToRip; uint64 LastExceptionFromRip") ; Special debug control registers
    Else
    $iRunFlag = 3
    ; FIXME - Itanium architecture
    ; Return special error number:
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(102, 0, 0)
    EndIf
    Else
    $iRunFlag = 1
    $tCONTEXT = DllStructCreate("dword ContextFlags;" & _ ; Control flags
    "dword Dr0; dword Dr1; dword Dr2; dword Dr3; dword Dr6; dword Dr7;" & _ ; CONTEXT_DEBUG_REGISTERS
    "dword ControlWord; dword StatusWord; dword TagWord; dword ErrorOffset; dword ErrorSelector; dword DataOffset; dword DataSelector; byte RegisterArea[80]; dword Cr0NpxState;" & _ ; CONTEXT_FLOATING_POINT
    "dword SegGs; dword SegFs; dword SegEs; dword SegDs;" & _ ; CONTEXT_SEGMENTS
    "dword Edi; dword Esi; dword Ebx; dword Edx; dword Ecx; dword Eax;" & _ ; CONTEXT_INTEGER
    "dword Ebp; dword Eip; dword SegCs; dword EFlags; dword Esp; dword SegSs;" & _ ; CONTEXT_CONTROL
    "byte ExtendedRegisters[512]") ; CONTEXT_EXTENDED_REGISTERS
    EndIf
    ; Define CONTEXT_FULL
    Local $CONTEXT_FULL
    Switch $iRunFlag
    Case 1
    $CONTEXT_FULL = 0x10007
    Case 2
    $CONTEXT_FULL = 0x100007
    Case 3
    $CONTEXT_FULL = 0x80027
    EndSwitch
    ; Set desired access
    DllStructSetData($tCONTEXT, "ContextFlags", $CONTEXT_FULL)
    ; Fill CONTEXT structure:
    $aCall = DllCall("kernel32.dll", "bool", "GetThreadContext", _
    "handle", $hThread, _
    "ptr", DllStructGetPtr($tCONTEXT))
    ; Check for errors or failure
    If @error Or Not $aCall[0] Then
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(3, 0, 0) ; GetThreadContext function or call to it failed
    EndIf
    ; Pointer to PEB structure
    Local $pPEB
    Switch $iRunFlag
    Case 1
    $pPEB = DllStructGetData($tCONTEXT, "Ebx")
    Case 2
    $pPEB = DllStructGetData($tCONTEXT, "Rdx")
    Case 3
    ; FIXME - Itanium architecture
    EndSwitch
    
    #region 5. READ PE-FORMAT
    ; Start processing passed binary data. 'Reading' PE format follows.
    ; First is IMAGE_DOS_HEADER
    Local $tIMAGE_DOS_HEADER = DllStructCreate("char Magic[2];" & _
    "word BytesOnLastPage;" & _
    "word Pages;" & _
    "word Relocations;" & _
    "word SizeofHeader;" & _
    "word MinimumExtra;" & _
    "word MaximumExtra;" & _
    "word SS;" & _
    "word SP;" & _
    "word Checksum;" & _
    "word IP;" & _
    "word CS;" & _
    "word Relocation;" & _
    "word Overlay;" & _
    "char Reserved[8];" & _
    "word OEMIdentifier;" & _
    "word OEMInformation;" & _
    "char Reserved2[20];" & _
    "dword AddressOfNewExeHeader", _
    $pPointer)
    ; Save this pointer value (it's starting address of binary image headers)
    Local $pHEADERS_NEW = $pPointer
    ; Move pointer
    $pPointer += DllStructGetData($tIMAGE_DOS_HEADER, "AddressOfNewExeHeader") ; move to PE file header
    ; Get "Magic"
    Local $sMagic = DllStructGetData($tIMAGE_DOS_HEADER, "Magic")
    ; Check if it's valid format
    If Not ($sMagic == "MZ") Then
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(4, 0, 0) ; MS-DOS header missing.
    EndIf
    ; In place of IMAGE_NT_SIGNATURE
    Local $tIMAGE_NT_SIGNATURE = DllStructCreate("dword Signature", $pPointer)
    ; Move pointer
    $pPointer += 4 ; size of $tIMAGE_NT_SIGNATURE structure
    ; Check signature
    If DllStructGetData($tIMAGE_NT_SIGNATURE, "Signature") <> 17744 Then ; IMAGE_NT_SIGNATURE
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(5, 0, 0) ; wrong signature. For PE image should be "PE\0\0" or 17744 dword.
    EndIf
    ; In place of IMAGE_FILE_HEADER
    Local $tIMAGE_FILE_HEADER = DllStructCreate("word Machine;" & _
    "word NumberOfSections;" & _
    "dword TimeDateStamp;" & _
    "dword PointerToSymbolTable;" & _
    "dword NumberOfSymbols;" & _
    "word SizeOfOptionalHeader;" & _
    "word Characteristics", _
    $pPointer)
    ; I could check here if the module is relocatable
    ;    Local $fRelocatable
    ;    If BitAND(DllStructGetData($tIMAGE_FILE_HEADER, "Characteristics"), 1) Then $fRelocatable = False
    ; But I won't (will check data in IMAGE_DIRECTORY_ENTRY_BASERELOC instead)
    ; Get number of sections
    Local $iNumberOfSections = DllStructGetData($tIMAGE_FILE_HEADER, "NumberOfSections")
    ; Move pointer
    $pPointer += 20 ; size of $tIMAGE_FILE_HEADER structure
    ; In place of IMAGE_OPTIONAL_HEADER
    Local $tMagic = DllStructCreate("word Magic;", $pPointer)
    Local $iMagic = DllStructGetData($tMagic, 1)
    Local $tIMAGE_OPTIONAL_HEADER
    If $iMagic = 267 Then ; x86 version
    If $fAutoItX64 Then
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(6, 0, 0) ; incompatible versions
    EndIf
    $tIMAGE_OPTIONAL_HEADER = DllStructCreate("word Magic;" & _
    "byte MajorLinkerVersion;" & _
    "byte MinorLinkerVersion;" & _
    "dword SizeOfCode;" & _
    "dword SizeOfInitializedData;" & _
    "dword SizeOfUninitializedData;" & _
    "dword AddressOfEntryPoint;" & _
    "dword BaseOfCode;" & _
    "dword BaseOfData;" & _
    "dword ImageBase;" & _
    "dword SectionAlignment;" & _
    "dword FileAlignment;" & _
    "word MajorOperatingSystemVersion;" & _
    "word MinorOperatingSystemVersion;" & _
    "word MajorImageVersion;" & _
    "word MinorImageVersion;" & _
    "word MajorSubsystemVersion;" & _
    "word MinorSubsystemVersion;" & _
    "dword Win32VersionValue;" & _
    "dword SizeOfImage;" & _
    "dword SizeOfHeaders;" & _
    "dword CheckSum;" & _
    "word Subsystem;" & _
    "word DllCharacteristics;" & _
    "dword SizeOfStackReserve;" & _
    "dword SizeOfStackCommit;" & _
    "dword SizeOfHeapReserve;" & _
    "dword SizeOfHeapCommit;" & _
    "dword LoaderFlags;" & _
    "dword NumberOfRvaAndSizes", _
    $pPointer)
    ; Move pointer
    $pPointer += 96 ; size of $tIMAGE_OPTIONAL_HEADER
    ElseIf $iMagic = 523 Then ; x64 version
    If Not $fAutoItX64 Then
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(6, 0, 0) ; incompatible versions
    EndIf
    $tIMAGE_OPTIONAL_HEADER = DllStructCreate("word Magic;" & _
    "byte MajorLinkerVersion;" & _
    "byte MinorLinkerVersion;" & _
    "dword SizeOfCode;" & _
    "dword SizeOfInitializedData;" & _
    "dword SizeOfUninitializedData;" & _
    "dword AddressOfEntryPoint;" & _
    "dword BaseOfCode;" & _
    "uint64 ImageBase;" & _
    "dword SectionAlignment;" & _
    "dword FileAlignment;" & _
    "word MajorOperatingSystemVersion;" & _
    "word MinorOperatingSystemVersion;" & _
    "word MajorImageVersion;" & _
    "word MinorImageVersion;" & _
    "word MajorSubsystemVersion;" & _
    "word MinorSubsystemVersion;" & _
    "dword Win32VersionValue;" & _
    "dword SizeOfImage;" & _
    "dword SizeOfHeaders;" & _
    "dword CheckSum;" & _
    "word Subsystem;" & _
    "word DllCharacteristics;" & _
    "uint64 SizeOfStackReserve;" & _
    "uint64 SizeOfStackCommit;" & _
    "uint64 SizeOfHeapReserve;" & _
    "uint64 SizeOfHeapCommit;" & _
    "dword LoaderFlags;" & _
    "dword NumberOfRvaAndSizes", _
    $pPointer)
    ; Move pointer
    $pPointer += 112 ; size of $tIMAGE_OPTIONAL_HEADER
    Else
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(6, 0, 0) ; incompatible versions
    EndIf
    ; Extract entry point address
    Local $iEntryPointNEW = DllStructGetData($tIMAGE_OPTIONAL_HEADER, "AddressOfEntryPoint") ; if loaded binary image would start executing at this address
    ; And other interesting informations
    Local $iOptionalHeaderSizeOfHeadersNEW = DllStructGetData($tIMAGE_OPTIONAL_HEADER, "SizeOfHeaders")
    Local $pOptionalHeaderImageBaseNEW = DllStructGetData($tIMAGE_OPTIONAL_HEADER, "ImageBase") ; address of the first byte of the image when it's loaded in memory
    Local $iOptionalHeaderSizeOfImageNEW = DllStructGetData($tIMAGE_OPTIONAL_HEADER, "SizeOfImage") ; the size of the image including all headers
    ; Move pointer
    $pPointer += 8 ; skipping IMAGE_DIRECTORY_ENTRY_EXPORT
    $pPointer += 8 ; size of $tIMAGE_DIRECTORY_ENTRY_IMPORT
    $pPointer += 24 ; skipping IMAGE_DIRECTORY_ENTRY_RESOURCE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, IMAGE_DIRECTORY_ENTRY_SECURITY
    ; Base Relocation Directory
    Local $tIMAGE_DIRECTORY_ENTRY_BASERELOC = DllStructCreate("dword VirtualAddress; dword Size", $pPointer)
    ; Collect data
    Local $pAddressNewBaseReloc = DllStructGetData($tIMAGE_DIRECTORY_ENTRY_BASERELOC, "VirtualAddress")
    Local $iSizeBaseReloc = DllStructGetData($tIMAGE_DIRECTORY_ENTRY_BASERELOC, "Size")
    Local $fRelocatable
    If $pAddressNewBaseReloc And $iSizeBaseReloc Then $fRelocatable = True
    ; Move pointer
    $pPointer += 88 ; size of the structures before IMAGE_SECTION_HEADER (16 of them).
    
    #region 6. ALLOCATE 'NEW' MEMORY SPACE
    Local $fRelocate
    Local $pZeroPoint
    If $fRelocatable Then ; If the module can be relocated then allocate memory anywhere possible
    $pZeroPoint = _RunBinary_AllocateExeSpace($hProcess, $iOptionalHeaderSizeOfImageNEW)
    ; In case of failure try at original address
    If @error Then
    $pZeroPoint = _RunBinary_AllocateExeSpaceAtAddress($hProcess, $pOptionalHeaderImageBaseNEW, $iOptionalHeaderSizeOfImageNEW)
    If @error Then
    _RunBinary_UnmapViewOfSection($hProcess, $pOptionalHeaderImageBaseNEW)
    ; Try now
    $pZeroPoint = _RunBinary_AllocateExeSpaceAtAddress($hProcess, $pOptionalHeaderImageBaseNEW, $iOptionalHeaderSizeOfImageNEW)
    If @error Then
    ; Return special error number:
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(101, 1, 0)
    EndIf
    EndIf
    EndIf
    $fRelocate = True
    Else ; And if not try where it should be
    $pZeroPoint = _RunBinary_AllocateExeSpaceAtAddress($hProcess, $pOptionalHeaderImageBaseNEW, $iOptionalHeaderSizeOfImageNEW)
    If @error Then
    _RunBinary_UnmapViewOfSection($hProcess, $pOptionalHeaderImageBaseNEW)
    ; Try now
    $pZeroPoint = _RunBinary_AllocateExeSpaceAtAddress($hProcess, $pOptionalHeaderImageBaseNEW, $iOptionalHeaderSizeOfImageNEW)
    If @error Then
    ; Return special error number:
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(101, 0, 0)
    EndIf
    EndIf
    EndIf
    ; If there is new ImageBase value, save it
    DllStructSetData($tIMAGE_OPTIONAL_HEADER, "ImageBase", $pZeroPoint)
    
    #region 7. CONSTRUCT THE NEW MODULE
    ; Allocate enough space (in our space) for the new module
    Local $tModule = DllStructCreate("byte[" & $iOptionalHeaderSizeOfImageNEW & "]")
    ; Get pointer
    Local $pModule = DllStructGetPtr($tModule)
    ; Headers
    Local $tHeaders = DllStructCreate("byte[" & $iOptionalHeaderSizeOfHeadersNEW & "]", $pHEADERS_NEW)
    ; Write headers to $tModule
    DllStructSetData($tModule, 1, DllStructGetData($tHeaders, 1))
    ; Write sections now. $pPointer is currently in place of sections
    Local $tIMAGE_SECTION_HEADER
    Local $iSizeOfRawData, $pPointerToRawData
    Local $iVirtualAddress, $iVirtualSize
    Local $tRelocRaw
    ; Loop through sections
    For $i = 1 To $iNumberOfSections
    $tIMAGE_SECTION_HEADER = DllStructCreate("char Name[8];" & _
    "dword UnionOfVirtualSizeAndPhysicalAddress;" & _
    "dword VirtualAddress;" & _
    "dword SizeOfRawData;" & _
    "dword PointerToRawData;" & _
    "dword PointerToRelocations;" & _
    "dword PointerToLinenumbers;" & _
    "word NumberOfRelocations;" & _
    "word NumberOfLinenumbers;" & _
    "dword Characteristics", _
    $pPointer)
    ; Collect data
    $iSizeOfRawData = DllStructGetData($tIMAGE_SECTION_HEADER, "SizeOfRawData")
    $pPointerToRawData = $pHEADERS_NEW + DllStructGetData($tIMAGE_SECTION_HEADER, "PointerToRawData")
    $iVirtualAddress = DllStructGetData($tIMAGE_SECTION_HEADER, "VirtualAddress")
    $iVirtualSize = DllStructGetData($tIMAGE_SECTION_HEADER, "UnionOfVirtualSizeAndPhysicalAddress")
    If $iVirtualSize And $iVirtualSize < $iSizeOfRawData Then $iSizeOfRawData = $iVirtualSize
    ; If there is data to write, write it
    If $iSizeOfRawData Then
    DllStructSetData(DllStructCreate("byte[" & $iSizeOfRawData & "]", $pModule + $iVirtualAddress), 1, DllStructGetData(DllStructCreate("byte[" & $iSizeOfRawData & "]", $pPointerToRawData), 1))
    EndIf
    ; Relocations
    If $fRelocate Then
    If $iVirtualAddress <= $pAddressNewBaseReloc And $iVirtualAddress + $iSizeOfRawData > $pAddressNewBaseReloc Then
    $tRelocRaw = DllStructCreate("byte[" & $iSizeBaseReloc & "]", $pPointerToRawData + ($pAddressNewBaseReloc - $iVirtualAddress))
    EndIf
    EndIf
    ; Move pointer
    $pPointer += 40 ; size of $tIMAGE_SECTION_HEADER structure
    Next
    ; Fix relocations
    If $fRelocate Then _RunBinary_FixReloc($pModule, $tRelocRaw, $pZeroPoint, $pOptionalHeaderImageBaseNEW, $iMagic = 523)
    ; Write newly constructed module to allocated space inside the $hProcess
    $aCall = DllCall("kernel32.dll", "bool", "WriteProcessMemory", _
    "handle", $hProcess, _
    "ptr", $pZeroPoint, _
    "ptr", $pModule, _
    "dword_ptr", $iOptionalHeaderSizeOfImageNEW, _
    "dword_ptr*", 0)
    ; Check for errors or failure
    If @error Or Not $aCall[0] Then
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(7, 0, 0) ; WriteProcessMemory function or call to it while writting new module binary
    EndIf
    
    #region 8. PEB ImageBaseAddress MANIPULATION
    ; PEB structure definition
    Local $tPEB = DllStructCreate("byte InheritedAddressSpace;" & _
    "byte ReadImageFileExecOptions;" & _
    "byte BeingDebugged;" & _
    "byte Spare;" & _
    "ptr Mutant;" & _
    "ptr ImageBaseAddress;" & _
    "ptr LoaderData;" & _
    "ptr ProcessParameters;" & _
    "ptr SubSystemData;" & _
    "ptr ProcessHeap;" & _
    "ptr FastPebLock;" & _
    "ptr FastPebLockRoutine;" & _
    "ptr FastPebUnlockRoutine;" & _
    "dword EnvironmentUpdateCount;" & _
    "ptr KernelCallbackTable;" & _
    "ptr EventLogSection;" & _
    "ptr EventLog;" & _
    "ptr FreeList;" & _
    "dword TlsExpansionCounter;" & _
    "ptr TlsBitmap;" & _
    "dword TlsBitmapBits[2];" & _
    "ptr ReadOnlySharedMemoryBase;" & _
    "ptr ReadOnlySharedMemoryHeap;" & _
    "ptr ReadOnlyStaticServerData;" & _
    "ptr AnsiCodePageData;" & _
    "ptr OemCodePageData;" & _
    "ptr UnicodeCaseTableData;" & _
    "dword NumberOfProcessors;" & _
    "dword NtGlobalFlag;" & _
    "byte Spare2[4];" & _
    "int64 CriticalSectionTimeout;" & _
    "dword HeapSegmentReserve;" & _
    "dword HeapSegmentCommit;" & _
    "dword HeapDeCommitTotalFreeThreshold;" & _
    "dword HeapDeCommitFreeBlockThreshold;" & _
    "dword NumberOfHeaps;" & _
    "dword MaximumNumberOfHeaps;" & _
    "ptr ProcessHeaps;" & _
    "ptr GdiSharedHandleTable;" & _
    "ptr ProcessStarterHelper;" & _
    "ptr GdiDCAttributeList;" & _
    "ptr LoaderLock;" & _
    "dword OSMajorVersion;" & _
    "dword OSMinorVersion;" & _
    "dword OSBuildNumber;" & _
    "dword OSPlatformId;" & _
    "dword ImageSubSystem;" & _
    "dword ImageSubSystemMajorVersion;" & _
    "dword ImageSubSystemMinorVersion;" & _
    "dword GdiHandleBuffer[34];" & _
    "dword PostProcessInitRoutine;" & _
    "dword TlsExpansionBitmap;" & _
    "byte TlsExpansionBitmapBits[128];" & _
    "dword SessionId")
    ; Fill the structure
    $aCall = DllCall("kernel32.dll", "bool", "ReadProcessMemory", _
    "ptr", $hProcess, _
    "ptr", $pPEB, _ ; pointer to PEB structure
    "ptr", DllStructGetPtr($tPEB), _
    "dword_ptr", DllStructGetSize($tPEB), _
    "dword_ptr*", 0)
    ; Check for errors or failure
    If @error Or Not $aCall[0] Then
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(8, 0, 0) ; ReadProcessMemory function or call to it failed while filling PEB structure
    EndIf
    ; Change base address within PEB
    DllStructSetData($tPEB, "ImageBaseAddress", $pZeroPoint)
    ; Write the changes
    $aCall = DllCall("kernel32.dll", "bool", "WriteProcessMemory", _
    "handle", $hProcess, _
    "ptr", $pPEB, _
    "ptr", DllStructGetPtr($tPEB), _
    "dword_ptr", DllStructGetSize($tPEB), _
    "dword_ptr*", 0)
    ; Check for errors or failure
    If @error Or Not $aCall[0] Then
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(9, 0, 0) ; WriteProcessMemory function or call to it failed while changing base address
    EndIf
    
    #region 9. NEW ENTRY POINT
    ; Entry point manipulation
    Switch $iRunFlag
    Case 1
    DllStructSetData($tCONTEXT, "Eax", $pZeroPoint + $iEntryPointNEW)
    Case 2
    DllStructSetData($tCONTEXT, "Rcx", $pZeroPoint + $iEntryPointNEW)
    Case 3
    ; FIXME - Itanium architecture
    EndSwitch
    
    #region 10. SET NEW CONTEXT
    ; New context:
    $aCall = DllCall("kernel32.dll", "bool", "SetThreadContext", _
    "handle", $hThread, _
    "ptr", DllStructGetPtr($tCONTEXT))
    
    If @error Or Not $aCall[0] Then
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(10, 0, 0) ; SetThreadContext function or call to it failed
    EndIf
    
    #region 11. RESUME THREAD
    ; And that's it!. Continue execution:
    $aCall = DllCall("kernel32.dll", "dword", "ResumeThread", "handle", $hThread)
    ; Check for errors or failure
    If @error Or $aCall[0] = -1 Then
    DllCall("kernel32.dll", "bool", "TerminateProcess", "handle", $hProcess, "dword", 0)
    Return SetError(11, 0, 0) ; ResumeThread function or call to it failed
    EndIf
    
    #region 12. CLOSE OPEN HANDLES AND RETURN PID
    DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess)
    DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hThread)
    ; All went well. Return new PID:
    Return DllStructGetData($tPROCESS_INFORMATION, "ProcessId")
    
    EndFunc   ;==>_RunBinary
    
    
    Func _RunBinary_FixReloc($pModule, $tData, $pAddressNew, $pAddressOld, $fImageX64)
    Local $iDelta = $pAddressNew - $pAddressOld ; dislocation value
    Local $iSize = DllStructGetSize($tData) ; size of data
    Local $pData = DllStructGetPtr($tData) ; addres of the data structure
    Local $tIMAGE_BASE_RELOCATION, $iRelativeMove
    Local $iVirtualAddress, $iSizeofBlock, $iNumberOfEntries
    Local $tEnries, $iData, $tAddress
    Local $iFlag = 3 + 7 * $fImageX64 ; IMAGE_REL_BASED_HIGHLOW = 3 or IMAGE_REL_BASED_DIR64 = 10
    While $iRelativeMove < $iSize ; for all data available
    $tIMAGE_BASE_RELOCATION = DllStructCreate("dword VirtualAddress; dword SizeOfBlock", $pData + $iRelativeMove)
    $iVirtualAddress = DllStructGetData($tIMAGE_BASE_RELOCATION, "VirtualAddress")
    $iSizeofBlock = DllStructGetData($tIMAGE_BASE_RELOCATION, "SizeOfBlock")
    $iNumberOfEntries = ($iSizeofBlock - 8) / 2
    $tEnries = DllStructCreate("word[" & $iNumberOfEntries & "]", DllStructGetPtr($tIMAGE_BASE_RELOCATION) + 8)
    ; Go through all entries
    For $i = 1 To $iNumberOfEntries
    $iData = DllStructGetData($tEnries, 1, $i)
    If BitShift($iData, 12) = $iFlag Then ; check type
    $tAddress = DllStructCreate("ptr", $pModule + $iVirtualAddress + BitAND($iData, 0xFFF)) ; the rest of $iData is offset
    DllStructSetData($tAddress, 1, DllStructGetData($tAddress, 1) + $iDelta) ; this is what's this all about
    EndIf
    Next
    $iRelativeMove += $iSizeofBlock
    WEnd
    Return 1 ; all OK!
    EndFunc   ;==>_RunBinary_FixReloc
    
    
    Func _RunBinary_AllocateExeSpaceAtAddress($hProcess, $pAddress, $iSize)
    ; Allocate
    Local $aCall = DllCall("kernel32.dll", "ptr", "VirtualAllocEx", _
    "handle", $hProcess, _
    "ptr", $pAddress, _
    "dword_ptr", $iSize, _
    "dword", 0x1000, _ ; MEM_COMMIT
    "dword", 64) ; PAGE_EXECUTE_READWRITE
    ; Check for errors or failure
    If @error Or Not $aCall[0] Then
    ; Try differently
    $aCall = DllCall("kernel32.dll", "ptr", "VirtualAllocEx", _
    "handle", $hProcess, _
    "ptr", $pAddress, _
    "dword_ptr", $iSize, _
    "dword", 0x3000, _ ; MEM_COMMIT|MEM_RESERVE
    "dword", 64) ; PAGE_EXECUTE_READWRITE
    ; Check for errors or failure
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) ; Unable to allocate
    EndIf
    Return $aCall[0]
    EndFunc   ;==>_RunBinary_AllocateExeSpaceAtAddress
    
    
    Func _RunBinary_AllocateExeSpace($hProcess, $iSize)
    ; Allocate space
    Local $aCall = DllCall("kernel32.dll", "ptr", "VirtualAllocEx", _
    "handle", $hProcess, _
    "ptr", 0, _
    "dword_ptr", $iSize, _
    "dword", 0x3000, _ ; MEM_COMMIT|MEM_RESERVE
    "dword", 64) ; PAGE_EXECUTE_READWRITE
    ; Check for errors or failure
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) ; Unable to allocate
    Return $aCall[0]
    EndFunc   ;==>_RunBinary_AllocateExeSpace
    
    
    Func _RunBinary_UnmapViewOfSection($hProcess, $pAddress)
    DllCall("ntdll.dll", "int", "NtUnmapViewOfSection", _
    "ptr", $hProcess, _
    "ptr", $pAddress)
    ; Check for errors only
    If @error Then Return SetError(1, 0, 0) ; Failure
    Return 1
    EndFunc   ;==>_RunBinary_UnmapViewOfSection
    
    
    Func _RunBinary_IsWow64Process($hProcess)
    Local $aCall = DllCall("kernel32.dll", "bool", "IsWow64Process", _
    "handle", $hProcess, _
    "bool*", 0)
    ; Check for errors or failure
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) ; Failure
    Return $aCall[2]
    EndFunc   ;==>_RunBinary_IsWow64Process
    
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  5. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,812
    45,404
    150
    #5 CODYQX4, Jul 13, 2011
    Last edited by a moderator: Apr 20, 2017
    The working solution:
    Code:
    using System;
    using System.Runtime.InteropServices;
    
    /* 
     * Title: CMemoryExecute.cs
     * Description: Runs an EXE in memory using native WinAPI. Very optimized and tiny.
     * 
     * Developed by: affixiate 
     * Release date: December 10, 2010
     * Released on: http://opensc.ws
     * Credits:
     *          MSDN (http://msdn.microsoft.com)
     *          NtInternals (http://undocumented.ntinternals.net)
     *          Pinvoke (http://pinvoke.net)
     *          
     * Comments: If you use this code, I require you to give me credits. Don't be a ripper! ;]
     */
    
    // ReSharper disable InconsistentNaming
    public static unsafe class CMemoryExecute
    {
        public struct STARTUPINFO
        {
            public uint cb;
            public string lpReserved;
            public string lpDesktop;
            public string lpTitle;
            public uint dwX;
            public uint dwY;
            public uint dwXSize;
            public uint dwYSize;
            public uint dwXCountChars;
            public uint dwYCountChars;
            public uint dwFillAttribute;
            public uint dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }
    
        /// <summary>
        /// Runs an EXE (which is loaded in a byte array) in memory.
        /// </summary>
        /// <param name="exeBuffer">The EXE buffer.</param>
        /// <param name="hostProcess">Full path of the host process to run the buffer in.</param>
        /// <param name="optionalArguments">Optional command line arguments.</param>
        /// <returns></returns>
        public static bool Run(byte[] exeBuffer, string hostProcess, string optionalArguments = "")
        {
            // STARTUPINFO
            STARTUPINFO StartupInfo = new STARTUPINFO();
            StartupInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
            StartupInfo.wShowWindow = SW_HIDE;
    
            var IMAGE_SECTION_HEADER = new byte[0x28]; // pish
            var IMAGE_NT_HEADERS = new byte[0xf8]; // pinh
            var IMAGE_DOS_HEADER = new byte[0x40]; // pidh
            var PROCESS_INFO = new int[0x4]; // pi
            var CONTEXT = new byte[0x2cc]; // ctx
    
            byte* pish;
            fixed (byte* p = &IMAGE_SECTION_HEADER[0])
                pish = p;
    
            byte* pinh;
            fixed (byte* p = &IMAGE_NT_HEADERS[0])
                pinh = p;
    
            byte* pidh;
            fixed (byte* p = &IMAGE_DOS_HEADER[0])
                pidh = p;
    
            byte* ctx;
            fixed (byte* p = &CONTEXT[0])
                ctx = p;
    
            // Set the flag.
            *(uint*)(ctx + 0x0 /* ContextFlags */) = CONTEXT_FULL;
    
            // Get the DOS header of the EXE.
            Buffer.BlockCopy(exeBuffer, 0, IMAGE_DOS_HEADER, 0, IMAGE_DOS_HEADER.Length);
    
            /* Sanity check:  See if we have MZ header. */
            if (*(ushort*)(pidh + 0x0 /* e_magic */) != IMAGE_DOS_SIGNATURE)
                return false;
    
            var e_lfanew = *(int*)(pidh + 0x3c);
    
            // Get the NT header of the EXE.
            Buffer.BlockCopy(exeBuffer, e_lfanew, IMAGE_NT_HEADERS, 0, IMAGE_NT_HEADERS.Length);
    
            /* Sanity check: See if we have PE00 header. */
            if (*(uint*)(pinh + 0x0 /* Signature */) != IMAGE_NT_SIGNATURE)
                return false;
    
            // Run with parameters if necessary.
            if (!string.IsNullOrEmpty(optionalArguments))
                hostProcess += " " + optionalArguments;
    
            if (!CreateProcess(null, hostProcess, IntPtr.Zero, IntPtr.Zero, false, CREATE_SUSPENDED, IntPtr.Zero, null, ref StartupInfo, PROCESS_INFO))
                return false;
    
            var ImageBase = new IntPtr(*(int*)(pinh + 0x34));
            NtUnmapViewOfSection((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, ImageBase);
            if (VirtualAllocEx((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, ImageBase, *(uint*)(pinh + 0x50 /* SizeOfImage */), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE) == IntPtr.Zero)
                Run(exeBuffer, hostProcess, optionalArguments); // Memory allocation failed; try again (this can happen in low memory situations)
    
            fixed (byte* p = &exeBuffer[0])
                NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, ImageBase, (IntPtr)p, *(uint*)(pinh + 84 /* SizeOfHeaders */), IntPtr.Zero);
    
            for (ushort i = 0; i < *(ushort*)(pinh + 0x6 /* NumberOfSections */); i++)
            {
                Buffer.BlockCopy(exeBuffer, e_lfanew + IMAGE_NT_HEADERS.Length + (IMAGE_SECTION_HEADER.Length * i), IMAGE_SECTION_HEADER, 0, IMAGE_SECTION_HEADER.Length);
                fixed (byte* p = &exeBuffer[*(uint*)(pish + 0x14 /* PointerToRawData */)])
                    NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, (IntPtr)((int)ImageBase + *(uint*)(pish + 0xc /* VirtualAddress */)), (IntPtr)p, *(uint*)(pish + 0x10 /* SizeOfRawData */), IntPtr.Zero);
            }
    
            NtGetContextThread((IntPtr)PROCESS_INFO[1] /* pi.hThread */, (IntPtr)ctx);
            NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, (IntPtr)(*(uint*)(ctx + 0xAC /* ecx */)), ImageBase, 0x4, IntPtr.Zero);
            *(uint*)(ctx + 0xB0 /* eax */) = (uint)ImageBase + *(uint*)(pinh + 0x28 /* AddressOfEntryPoint */);
            NtSetContextThread((IntPtr)PROCESS_INFO[1] /* pi.hThread */, (IntPtr)ctx);
            NtResumeThread((IntPtr)PROCESS_INFO[1] /* pi.hThread */, IntPtr.Zero);
    
    
            return true;
        }
    
        #region WinNT Definitions
    
        private const uint CONTEXT_FULL = 0x10007;
        private const int CREATE_SUSPENDED = 0x4;
        private const int MEM_COMMIT = 0x1000;
        private const int MEM_RESERVE = 0x2000;
        private const int PAGE_EXECUTE_READWRITE = 0x40;
        private const ushort IMAGE_DOS_SIGNATURE = 0x5A4D; // MZ
        private const uint IMAGE_NT_SIGNATURE = 0x00004550; // PE00
        
        private static short SW_SHOW = 5;
        private static short SW_HIDE = 0;
        private const uint STARTF_USESTDHANDLES = 0x00000100;
        private const uint STARTF_USESHOWWINDOW = 0x00000001;
    
    
        #region WinAPI
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, int[] lpProcessInfo);
    
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
    
        [DllImport("ntdll.dll", SetLastError = true)]
        private static extern uint NtUnmapViewOfSection(IntPtr hProcess, IntPtr lpBaseAddress);
    
        [DllImport("ntdll.dll", SetLastError = true)]
        private static extern int NtWriteVirtualMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, uint nSize, IntPtr lpNumberOfBytesWritten);
    
        [DllImport("ntdll.dll", SetLastError = true)]
        private static extern int NtGetContextThread(IntPtr hThread, IntPtr lpContext);
    
        [DllImport("ntdll.dll", SetLastError = true)]
        private static extern int NtSetContextThread(IntPtr hThread, IntPtr lpContext);
    
        [DllImport("ntdll.dll", SetLastError = true)]
        private static extern uint NtResumeThread(IntPtr hThread, IntPtr SuspendCount);
        #endregion
    
        #endregion
    }
    Note that you have to inject into %WINDIR%\Microsoft.NET\Framework\v2.0.50727\vbc.exe. It seems to be the only process that works with this code or "RunPE" variants. It must be a 32 bit exe you are injecting, and you must compile the .NET app that uses this as x86, not x64 or AnyCPU. This is important, it took me a year to learn theses conditions the hard way.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  6. maptiger

    maptiger MDL Novice

    Dec 15, 2009
    1
    0
    0
    Hi

    Thanks you "CODYQX4" for the code. Igot it to work but windows immediately closes the memory application.

    I have Windows 7 system. Can you please help me out for this.

    Regards
     
  7. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,812
    45,404
    150
    It seems that few apps can be injected, but the vbc.exe from .NET 2.0 is good. Also, you must compile the .NET application as x86, not AnyCPU or x64. Anything besides that and i don't know the context you are using it in.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  8. Josh Cell

    Josh Cell MDL Developer

    Jan 8, 2011
    3,519
    7,110
    120
    Yep, any valid PE console application can be injected with this code...

    If have an "Any CPU" compilation, the code will write a x64 tables in the memory, won't work...
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  9. BugB

    BugB MDL Novice

    Jul 25, 2014
    1
    0
    0
    Doesn't works for me

    I tried to use this code to run byte array of exe but it doesn't works