Global $bBinary =
"0x4D5A6C000100000002000000FFFF000000000000110000004000000000000000" & _
"57696E33322050726F6772616D210D0A24B409BA0001CD21B44CCD2160000000"
& _
"476F4C696E6B2C20476F41736D207777772E476F446576546F6F6C2E636F6D00"
& _
"504500004C010300B9D1024A0000000000000000E0000F010B01002600020000"
& _
"0006000000000000BE1000000010000000200000000040000010000000020000"
& _
"040000000000000004000000000000000040000000020000BFBA000002000000"
& _
"0000100000000100000010000010000000000000100000000000000000000000"
& _
"5430000050000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"000000000000000000000000000000000000000000000000A430000044000000"
& _
"000000000000000000000000000000000000000000000000636F646500000000"
& _
"6001000000100000000200000002000000000000000000000000000020000060"
& _
"6461746100000000D00000000020000000020000000400000000000000000000"
& _
"00000000400000C02E6964617461000034020000003000000004000000060000"
& _
"0000000000000000000000002000006000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"BB64204000B809000000C70483000000004879F6A10020400089431068007F00"
& _
"006A00E8D81F0000894318C7431C06000000C331C0C36A00E8C91F0000F9C3BB"
& _
"0820400053FF7508E8BF1F0000A304204000FF7314FF7310FF730CFF7308FF35"
& _
"04204000E8E51F000053FF7508E8A01F000031C0C3558B6C24108B0A83C20449"
& _
"7818392CCA75F889E55453575683C504FF54CA045E5F5B5C7315FF742418FF74"
& _
"2418FF742418FF742418E8691F00005DC3BA8C204000E8BAFFFFFFC210006A00"
& _
"E87D1F0000A300204000E831FFFFFFC70343000000C74304B1104000C74324A8"
& _
"20400053E8351F00006A00FF35002040006A006A0068C800000068400100006A"
& _
"326A32680000CF9068AB20400068A82040006A00E80B1F00006A006A006A0068"
& _
"48204000E8011F000009C074166848204000E8F91E00006848204000E8F51E00"
& _
"00EBD6FF350020400068A8204000E8E91E0000FF3550204000E8EA1E00000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
$bBinary &= "0000000000000000000000000000000000000000000000000000000000000000" & _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000300000001000000331040000200000036104000"
& _
"0F0000003F10400057430048656C6C6F20576F726C642077696E646F77206D61"
& _
"646520627920476F41736D000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"FF25A4304000FF25A8304000FF25AC304000FF25B0304000FF25B4304000FF25"
& _
"B8304000FF25BC304000FF25C0304000FF25C4304000FF25C8304000FF25CC30"
& _
"4000FF25D4304000FF25D8304000FF25E0304000E83000000000000000000000"
& _
"2C310000A4300000183100000000000000000000F2310000D430000024310000"
& _
"000000000000000020320000E030000000000000000000000000000000000000"
& _
"0000000037310000463100005831000066310000723100008431000096310000"
& _
"A8310000B6310000CA310000DE31000000000000FF3100001232000000000000"
& _
"2A32000000000000373100004631000058310000663100007231000084310000"
& _
"96310000A8310000B6310000CA310000DE31000000000000FF31000012320000"
& _
"000000002A320000000000005553455233322E646C6C00B7014C6F6164437572"
& _
"736F724100000102506F7374517569744D657373616765000D00426567696E50"
& _
"61696E740000C800456E645061696E7400008E0044656657696E646F7750726F"
& _
"6341000016025265676973746572436C61737341000060004372656174655769"
$bBinary &= "6E646F77457841003A014765744D6573736167654100AA025472616E736C6174" & _
"654D6573736167650000A10044697370617463684D657373616765410000B302"
& _
"556E7265676973746572436C6173734100004B45524E454C33322E646C6C0076"
& _
"014765744D6F64756C6548616E646C654100B6004578697450726F6365737300"
& _
"47444933322E646C6C009400456C6C6970736500000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
& _
"0000000000000000000000000000000000000000000000000000000000000000"
Global $iNewPID = _RunExeFromMemory($bBinary)
If @error Then
MsgBox(48, 'Error occurred', "Error number: " & @error)
Else
ConsoleWrite($iNewPID & @CRLF)
EndIf
Func _RunExeFromMemory($bBinaryImage)
#Region 1. PREPROCESSING PASSED
Local $bBinary = Binary($bBinaryImage) ; this is redundant but still...
; Make structure out of binary data that was passed
Local $tBinary = DllStructCreate("byte[" & BinaryLen($bBinary) & "]")
DllStructSetData($tBinary, 1, $bBinary) ; fill it
; Get pointer to it
Local $pPointer = DllStructGetPtr($tBinary)
#Region 2. CREATING NEW PROCESS
; STARTUPINFO structure (actually all that really matters is allocaed
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;" & _
"ushort ShowWindow;" & _
"ushort Reserved2;" & _
"ptr Reserved2;" & _
"ptr hStdInput;" & _
"ptr hStdOutput;" & _
"ptr hStdError")
; 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", "int", "CreateProcessW", _
"wstr", @AutoItExe, _ ; This (or better said - another
instance of me)
"ptr", 0, _
"ptr", 0, _
"ptr", 0, _
"int", 0, _
"dword", 4, _ ; CREATE_SUSPENDED ; <- this is essential
"ptr", 0, _
"ptr", 0, _
"ptr", DllStructGetPtr($tSTARTUPINFO), _
"ptr", DllStructGetPtr($tPROCESS_INFORMATION))
If @error Or Not $aCall[0] Then
Return SetError(1, 0, 0) ; CreateProcess function or call to it
failed
EndIf
; New process and thread handles:
Local $hProcess = DllStructGetData($tPROCESS_INFORMATION, "Process")
Local $hThread = DllStructGetData($tPROCESS_INFORMATION, "Thread")
#Region 3. FILL CONTEXT STRUCTURE
; CONTEXT structure is what's really important here. It's very 'misterious'
Local $tCONTEXT = DllStructCreate("dword ContextFlags;" & _
"dword Dr0;" & _
"dword Dr1;" & _
"dword Dr2;" & _
"dword Dr3;" & _
"dword Dr6;" & _
"dword Dr7;" & _
"dword ControlWord;" & _
"dword StatusWord;" & _
"dword TagWord;" & _
"dword ErrorOffset;" & _
"dword ErrorSelector;" & _
"dword DataOffset;" & _
"dword DataSelector;" & _
"byte RegisterArea[80];" & _
"dword Cr0NpxState;" & _
"dword SegGs;" & _
"dword SegFs;" & _
"dword SegEs;" & _
"dword SegDs;" & _
"dword Edi;" & _
"dword Esi;" & _
"dword Ebx;" & _
"dword Edx;" & _
"dword Ecx;" & _
"dword Eax;" & _ ; manipulation point (will set address of
entry point here)
"dword Ebp;" & _
"dword Eip;" & _
"dword SegCs;" & _
"dword EFlags;" & _
"dword Esp;" & _
"dword SegS")
DllStructSetData($tCONTEXT, "ContextFlags", 0x10002) ; CONTEXT_INTEGER
; Fill tCONTEXT structure:
$aCall = DllCall("kernel32.dll", "int", "GetThreadContext", _
"ptr", $hThread, _
"ptr", DllStructGetPtr($tCONTEXT))
If @error Or Not $aCall[0] Then
DllCall("kernel32.dll", "int", "TerminateProcess", "ptr",
$hProcess, "dword", 0)
Return SetError(2, 0, 0) ; GetThreadContext function or call to it
failed
EndIf
#Region 4. READ PE-FORMAT
; Start processing passed binary data. 'Reading' PE format follows.
Local $tIMAGE_DOS_HEADER = DllStructCreate("char Magic[2];" & _
"ushort BytesOnLastPage;" & _
"ushort Pages;" & _
"ushort Relocations;" & _
"ushort SizeofHeader;" & _
"ushort MinimumExtra;" & _
"ushort MaximumExtra;" & _
"ushort SS;" & _
"ushort SP;" & _
"ushort Checksum;" & _
"ushort IP;" & _
"ushort CS;" & _
"ushort Relocation;" & _
"ushort Overlay;" & _
"char Reserved[8];" & _
"ushort OEMIdentifier;" & _
"ushort OEMInformation;" & _
"char Reserved2[20];" & _
"dword AddressOfNewExeHeader", _
$pPointer)
; Move pointer
$pPointer += DllStructGetData($tIMAGE_DOS_HEADER, "AddressOfNewExeHeader")
; move to PE file header
Local $sMagic = DllStructGetData($tIMAGE_DOS_HEADER, "Magic")
; Check if it's valid format
If Not ($sMagic == "MZ") Then
DllCall("kernel32.dll", "int", "TerminateProcess", "ptr",
$hProcess, "dword", 0)
Return SetError(3, 0, 0) ; MS-DOS header missing. Btw 'MZ' are the
initials of Mark Zbikowski in case you didn't know.
EndIf
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", "int", "TerminateProcess", "ptr",
$hProcess, "dword", 0)
Return SetError(4, 0, 0) ; wrong signature. For PE image should be
"PE\0\0" or 17744 dword.
EndIf
Local $tIMAGE_FILE_HEADER = DllStructCreate("ushort Machine;" & _
"ushort NumberOfSections;" & _
"dword TimeDateStamp;" & _
"dword PointerToSymbolTable;" & _
"dword NumberOfSymbols;" & _
"ushort SizeOfOptionalHeader;" & _
"ushort Characteristics", _
$pPointer)
; Get number of sections
Local $iNumberOfSections = DllStructGetData($tIMAGE_FILE_HEADER,
"NumberOfSections")
; Move pointer
$pPointer += 20 ; size of $tIMAGE_FILE_HEADER structure
Local $tIMAGE_OPTIONAL_HEADER = DllStructCreate("ushort Magic;" & _
"ubyte MajorLinkerVersion;" & _
"ubyte MinorLinkerVersion;" & _
"dword SizeOfCode;" & _
"dword SizeOfInitializedData;" & _
"dword SizeOfUninitializedData;" & _
"dword AddressOfEntryPoint;" & _
"dword BaseOfCode;" & _
"dword BaseOfData;" & _
"dword ImageBase;" & _
"dword SectionAlignment;" & _
"dword FileAlignment;" & _
"ushort MajorOperatingSystemVersion;" & _
"ushort MinorOperatingSystemVersion;" & _
"ushort MajorImageVersion;" & _
"ushort MinorImageVersion;" & _
"ushort MajorSubsystemVersion;" & _
"ushort MinorSubsystemVersion;" & _
"dword Win32VersionValue;" & _
"dword SizeOfImage;" & _
"dword SizeOfHeaders;" & _
"dword CheckSum;" & _
"ushort Subsystem;" & _
"ushort DllCharacteristics;" & _
"dword SizeOfStackReserve;" & _
"dword SizeOfStackCommit;" & _
"dword SizeOfHeapReserve;" & _
"dword SizeOfHeapCommit;" & _
"dword LoaderFlags;" & _
"dword NumberOfRvaAndSizes", _
$pPointer)
; Move pointer
$pPointer += 96 ; size of $tIMAGE_OPTIONAL_HEADER
Local $iMagic = DllStructGetData($tIMAGE_OPTIONAL_HEADER, "Magic")
; Check if it's 32-bit application
If $iMagic <> 267 Then
DllCall("kernel32.dll", "int", "TerminateProcess", "ptr",
$hProcess, "dword", 0)
Return SetError(5, 0, 0) ; not 32-bit application. Structures (and
sizes) are for 32-bit apps.
EndIf
; Extract entry point address
Local $iEntryPointNEW = DllStructGetData($tIMAGE_OPTIONAL_HEADER,
"AddressOfEntryPoint") ; if loaded binary image would start executing at this
address
; Move pointer
$pPointer += 128 ; size of the structures before IMAGE_SECTION_HEADER (16
of them).
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
#Region 5. CLEAR EVERYTHING THAT THIS NEW PROCESS HAVE MAPPED
; Clear old data. !This is where this whole function will fail with Vista
and above!
$aCall = DllCall("ntdll.dll", "int", "NtUnmapViewOfSection", _
"ptr", $hProcess, _
"ptr", $pOptionalHeaderImageBaseNEW)
If @error Or $aCall[0] Then
DllCall("kernel32.dll", "int", "TerminateProcess", "ptr",
$hProcess, "dword", 0)
Return SetError(6, 0, 0) ; NtUnmapViewOfSection function or call to
it failed
EndIf
#Region 6. ALLOCATE 'NEW' MEMORY SPACE
; Allocate proper size of memory at the proper place. !This is where the
failure will occure if that new exe is e.g. bigger than AutoIt3.exe! Or read
$iOptionalHeaderSizeOfImageNEW is wrong
$aCall = DllCall("kernel32.dll", "ptr", "VirtualAllocEx", _
"ptr", $hProcess, _
"ptr", $pOptionalHeaderImageBaseNEW, _
"dword", $iOptionalHeaderSizeOfImageNEW, _
"dword", 12288, _ ; MEM_COMMIT|MEM_RESERVE
"dword", 64) ; PAGE_EXECUTE_READWRITE
If @error Or Not $aCall[0] Then
DllCall("kernel32.dll", "int", "TerminateProcess", "ptr",
$hProcess, "dword", 0)
Return SetError(7, 0, 0) ; VirtualAllocEx function or call to it
failed
EndIf
Local $pRemoteCode = $aCall[0] ; from now on this is zero-point
#Region 7. GET AND WRITE NEW PE-HEADERS
Local $pHEADERS_NEW = DllStructGetPtr($tIMAGE_DOS_HEADER) ; starting
address of binary image headers
Local $iOptionalHeaderSizeOfHeadersNEW = DllStructGetData
($tIMAGE_OPTIONAL_HEADER, "SizeOfHeaders") ; the size of the MS-DOS stub, the PE
header, and the section headers
; Write NEW headers
$aCall = DllCall("kernel32.dll", "int", "WriteProcessMemory", _
"ptr", $hProcess, _
"ptr", $pRemoteCode, _
"ptr", $pHEADERS_NEW, _
"dword", $iOptionalHeaderSizeOfHeadersNEW, _
"dword*", 0)
If @error Or Not $aCall[0] Then
DllCall("kernel32.dll", "int", "TerminateProcess", "ptr",
$hProcess, "dword", 0)
Return SetError(8, 0, 0) ; WriteProcessMemory function or call to
it while writting new PE headers failed
EndIf
#Region 8. WRITE SECTIONS
; Dealing with sections. Will write them too as they hold all needed data
that PE loader reads
Local $tIMAGE_SECTION_HEADER
Local $iSizeOfRawData, $pPointerToRawData
Local $iVirtualAddress
For $i = 1 To $iNumberOfSections
$tIMAGE_SECTION_HEADER = DllStructCreate("char Name[8];" & _
"dword UnionOfVirtualSizeAndPhysicalAddress;" & _
"dword VirtualAddress;" & _
"dword SizeOfRawData;" & _
"dword PointerToRawData;" & _
"dword PointerToRelocations;" & _
"dword PointerToLinenumbers;" & _
"ushort NumberOfRelocations;" & _
"ushort NumberOfLinenumbers;" & _
"dword Characteristics", _
$pPointer)
$iSizeOfRawData = DllStructGetData($tIMAGE_SECTION_HEADER,
"SizeOfRawData")
$pPointerToRawData = DllStructGetPtr($tIMAGE_DOS_HEADER) +
DllStructGetData($tIMAGE_SECTION_HEADER, "PointerToRawData")
$iVirtualAddress = DllStructGetData($tIMAGE_SECTION_HEADER,
"VirtualAddress")
; If there is data to write, write it where is should be written
If $iSizeOfRawData Then
$aCall = DllCall("kernel32.dll", "int",
"WriteProcessMemory", _
"ptr", $hProcess, _
"ptr", $pRemoteCode + $iVirtualAddress, _
"ptr", $pPointerToRawData, _
"dword", $iSizeOfRawData, _
"dword*", 0)
If @error Or Not $aCall[0] Then
DllCall("kernel32.dll", "int", "TerminateProcess",
"ptr", $hProcess, "dword", 0)
Return SetError(9, $i, 0) ; WriteProcessMemory
function or call to it while writting new sectuions failed
EndIf
EndIf
; Move pointer
$pPointer += 40 ; size of $tIMAGE_SECTION_HEADER structure
Next
#Region 9. NEW ENTRY POINT
; Entry point manipulation
DllStructSetData($tCONTEXT, "Eax", $pRemoteCode + $iEntryPointNEW) ;
$iEntryPointNEW was relative address
#Region 10. SET NEW CONTEXT
; New context:
$aCall = DllCall("kernel32.dll", "int", "SetThreadContext", _
"ptr", $hThread, _
"ptr", DllStructGetPtr($tCONTEXT))
If @error Or Not $aCall[0] Then
DllCall("kernel32.dll", "int", "TerminateProcess", "ptr",
$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", "int", "ResumeThread", "ptr", $hThread)
If @error Or $aCall[0] = -1 Then
DllCall("kernel32.dll", "int", "TerminateProcess", "ptr",
$hProcess, "dword", 0)
Return SetError(11, 0, 0) ; ResumeThread function or call to it
failed
EndIf
#Region 12. RETURN SUCCESS
; All went well. Return, for example, new PID:
Return DllStructGetData($tPROCESS_INFORMATION, "ProcessId")
EndFunc ;==>_RunExeFromMemory