Is it possible to run an executable from memory, is a question that has turned up several times on the board. With intent to find out if it is possible i have made a deep dive in the process of creating a process. The attachment is the result of creating a process from a file on the disk. Normaly you start it with kernel API CreateProcess. The code only works on win2K.

I have turned the code out and in and came to the conclusion that it is not possible to run an executable from memory. You have to use the nativ API NtCreateSection to map the file into memory and the only way to do that is via a disk file.

If someone has another opinion please tell me. Feel free to play about with the code to try to map from memory.

Best regards
Posted on 2003-10-02 14:58:45 by minor28
im sure its possible, it just requires a fair bit of work
Posted on 2003-10-02 15:17:20 by evlncrn8
Hi minor28, when I'm right you have to get rid from the PE-Format fist, bevor you can run it.
When the pure source leaded in the memory it might be possible let it run with the MP instruction. - Am I right ?

Greets
Posted on 2003-10-03 15:13:25 by Bubu-Boy
I think it should be possible under Win9X, since you can access ring-0 and tweak anything you want. Under NT or XP, though, there are more restrictions. Since I don't know much about how NT based versions work, I'd rather trust minor28's opinion... if there is no native API call to create a process without disk access, it can't be done.

However, you could always create a temporary file, write to it, and then create the process... but that would be cheating :grin:

EDIT: Perhaps there is a way using handle -1 (paging file). Are there any native calls to create a section from a file mapping handle rather than a file handle?
Posted on 2003-10-03 15:25:51 by QvasiModo
if you strip of the PE header then you wont know where the OEP is...

also you loose the memory rights to the program...

also you will loos where the date ,code and other sections are located...

so just for that you would have to record everything or store the header some where..


after that you have to adjust the import table and any other parts of the code that call jmp dword ptr...

which can be a pain...

what most people are looking for is a way to properly load the exe into memory so that it has its own heap and stack and so that it can be executed with out code modding..

oh and a side note... the memory access of a file on xp can befully write able and execute able with out messing up the program but on win 9x you are not allowed to in all areas...

this is true because i made a WriteProcessMemory Replacement and i originally got the file size and unprotected the whole exe in memory... xp had no problems but win 98 se did..
Posted on 2003-10-03 15:29:45 by devilsclaw
Hi devilsclaw - thats sounds interisting.
Perhaps you upload your code. - I would like to test it to.

Greets Bubu-Boy
Posted on 2003-10-03 15:50:01 by Bubu-Boy
well the theory would be (not sure this would be as easy for an exe but should work for a dll)...

virtualalloc memory block of the size of the image (from the pe header)
build up the image in the virtualalloc mem block from the section information
find the iat, and fill the imports, use the .reloc information in the dll to rebase
the image you have now loaded in memory patching the va's it lists with the base
adjustment (using the virtualalloc mem block start as the base), that should
in theory work, the only downside is that possibly loading resources mightnt work
but code should... also remember to virtualprotect the sections (after doing all the work above) to the states specified in the section info from the pe header, then
call the entrypoint with the 3 parameters typical for dll_process_attach... for an
exe its slightly trickier but im sure its doable, regardless of the system being 9x or 2k/xp/nt, and i really dont think you'd have to use ring 0 for it either, if the system can do it, why cant you? ;).. again, for an exe it'd require a different strategy

might try and do some code for it later on after i've finished my current project
Posted on 2003-10-03 16:36:45 by evlncrn8
But maybe you do need ring-0... after all, the kernel runs in that ring. And under Win9X, the kernel runs on ring-3 but it can access ring-0 anytime with VxD or other means, so we have no guarantee that a full PE loader can be implemented in ring-3. By full I mean resources working, and all that.
However, there ould be a way to efficiently simulate it... maybe with some heavy API hooks it can be done reasonably well.
Posted on 2003-10-04 11:24:44 by QvasiModo
I have tryed virtual allocated memory and global allocated memory with the expanded image. Not working. The nearest I have come is the attached example (this has been on the board this summer)

The dialog.exe reside as as rcdata resource in the EXERES app. From loaded resource the dialog image is expanded into a global allocated memory. EXERES then pushes the parameters for WriteProcessMemory and pushes the returnaddress to the entrypoint of the dialog.exe. Next a jump to kernel function WriteProcessMemory. The function replaces the EXERES code in process memory with the dialog.exe code. The return goes to entrypoint of dialog.exe. The dialog.exe starts executing but the dialog never shows up. I suppose the exe is not properly registrated. You can't fool windows.

I think I have tryed the most. You can't run an exe from memory. If someone has another opinion then prove it.

Best regards
Posted on 2003-10-05 13:23:25 by minor28
hi,

if the file dont have resources, it can be done without problems.

you will have the code running normally, but the 'new' process dont exists to windows - its just a program running a new thread in allocated memory.

ancev
Posted on 2003-10-06 20:21:58 by ancev
this has all been discussed before, more than one time.

As ancev says, as long as the exe doesn't have resources (and a couple things that are not so standard), it's pretty easy to execute a PE yourself - but it will not appear as a new process and there's all sorts of catches.

If you find a non-dirty/ring0 (use of NT Native API accepted, though) way to more properly run a piece of code from memory (ie, create a new process), don't hesitate to post info =)
Posted on 2003-10-09 16:35:56 by f0dder
Yes f0dder, I know the item has been on the board several times before but I wouldn't say discussed. What I have seen is questions if it is possible and answers that you have to code your own PE-loader, jump table problems and so on. No really constructive discussion how to create a new process from an memory image.

The subject is interesting. I am now in kernel-mode trying to find out the secrecy of creating a new process. As you know documentation is insufficient and I have a lot to learn.

I take it that the key between an exe image and its process is the mapping by create section.

I have seen the expressions "non-dirty" and "dirty" before. What does "non-dirty" and "dirty" mean? I don't want to post dirty things.

Best regards
Posted on 2003-10-10 01:05:10 by minor28
minor28,

take a look in elicz site... maybe you can discover how create a process taking a look in how he create remote thread

ancev
Posted on 2003-10-10 17:52:55 by ancev
Ok, I will have a look at elicz site.

Now I have moved the Create Section procedure from user-mode to kernel-mode. The Create Section procedure is executed in CrSec.sys

Regards

edit: I still don't know what "non-dirty" means.
Posted on 2003-10-11 15:57:38 by minor28
"dirty" means that it's not reliable, in other words that it could be changed by Microsoft in any patch. So non-dirty means using only official API's and semi-official API's like the NT native API (Microsoft can't change this because some programs by other people depend on them).
Posted on 2003-10-12 07:52:58 by Qweerdy
As matters now stand I have done following.

A. RUNNING FROM DISK

In user mode:
1. Loading a file object attribute structure with data
2. Creating a driver service passing data needed for open file function.

In kernel mode:
3. Retrieving file handle by calling ntoskrn.exe!ObOpenObjectByName. I have not succeeded with the ObDereferenceObject function but it works without. Is it important with this function?
4. Passing the file handle to user mode

In user mode:
5. Create section and so on till the exe is running.

This works.


Now my intention was to switch ObOpenObjectByName to ObOpenObjectByPointer.

B. RUNNING FROM MEMORY

In user mode:
1. Open the exe file
2. Allocate memory
3. Read exe file into memory giving a pointer to address of MZ
4. Creating a driver service passing pointer

In kernel mode:
5. Calling ntoskrn.exe!ObOpenObjectByPointer

The return value is STATUS_OBJECT_TYPE_MISMATCH.
This indicates that it is not possible to create an object from memory but I am not sure yet.

I would appraciate id?as.

Regards
Posted on 2003-10-15 13:57:25 by minor28
Hi minor28

> ObOpenObjectByName to ObOpenObjectByPointer.
>5. Calling ntoskrn.exe!ObOpenObjectByPointer
>The return value is STATUS_OBJECT_TYPE_MISMATCH.

I'm not sure but the problem here might be one that occurs when dealing with several kernel functions which require a pointer to an OBJECT (be it thread, event, mutex...), rather than a HANDLE, which is what is generally returned with several other kernel functions that actually *create* the thread, event, mutex...

To convert the Handle to a Object you need to call ObReferenceObjectByHandle.
ObReferenceObjectByHandle increments the reference count of the object, so requires ObDereferenceObject to lower it's reference count when finished with it.

I'm not sure about your ObOpenObjectByName, but it may also return a handle, and ObOpenObjectByPointer requires an object pointer I believe.


I've had to do this for both Events and Threads. For example, a convenient way of synchronizing communication between a user app and driver thread (remote or otherwise) is to use a Named Event using IoCreateNotificationEvent. This function returns an event HANDLE, but to use the event in other functions you need to convert it to a direct OBJECT pointer with ObReferenceObjectByHandle first. i.e.

[size=12]

invoke RtlInitUnicodeString, offset pUNICODE_STRING, offset EventName
invoke IoCreateNotificationEvent, offset pUNICODE_STRING, offset EventHandle
invoke ObReferenceObjectByHandle, [EventHandle], EVENT_ALL_ACCESS,\
NULL, KernelMode, offset pEventObject, NULL

; we've converted an EventHandle to an EventObject,
; now it can be used in other functions...

; (if you don't need the handle you can delete it since we
; have a pointer to the actual object structure now)
; invoke ZwClose, [EventHandle] ; (will call ObDereferenceObject)

; IoCreateNotificationEvent creates an event in the signalled state,
; set it to unsignalled
invoke KeInitializeEvent, [pEventObject], NotificationEvent, FALSE

;...

; elsewhere we can wait for the Event to be signalled from user
; mode with OpenEvent / SetEvent...
; (note that driver created named events must be placed in the
; system directory \BaseNamedObjects\<eventname> to match
; any User event name (automatically placed in that directory))


;...in a PsCreateSystemThread created thread far, far away...
invoke KeReadStateEvent, _pEventObject ; returns 0 = non-signalled

; Wait indefinitely for User mode to wake up this thread by
; signalling event...
invoke KeWaitForSingleObject, _pEventObject, Executive, \
KernelMode, TRUE, NULL

; after returning, event is in signalled state
invoke KeReadStateEvent, _pEventObject ; returns 1 = signalled

;...

invoke ObDereferenceObject, _pEventObject

;(PsTerminateSystemThread required if thread created
; in system context)
[/SIZE]


You might also go through the same process with threads of converting a thread handle to a thread object pointer if you wanted to use a function such as KeSetPriorityThread for example.


DO make sure you call ObDereferenceObject wherever necessary to avoid memory leaks. The system *might* clean up for you but I've had some slow lockups while developing that might be tied to this. I believe ObDereferenceObject returns the current reference count, but I haven't been able to see it de-reference down to '0', the current reference count in various places in my code seems higher than I would have expected by any associated calls to ObReferenceObjectByHandle or prior creation calls.

As a side-bar to this, there is an undocumented function called ObGetObjectPointerCount that also returns the current reference count on an object (matches that returned by ObDereferenceObject). However, I could not directly Invoke the function ObGetObjectPointerCount and had to call its address directly by using MmGetSystemRoutineAddress first.

Good luck with this, it will be interesting to see the results.

Regards,
Kayaker
Posted on 2003-10-15 23:56:59 by Kayaker
Hi

ObOpenObjectByName makes an internal call to ObReferenceObjectByHandle thus you have to decrement the reference count. Earlier the return value of ObReferenceObjectByHandle was -1h which I assumed was an error. Now it returns 1. I don't know if it's a succees or error. Most kernel mode functions return 0 (equ STATUS_SUCCESS)at success. 1 could be "ERROR_INVALID_FUNCTION".

This is a function in CrSec.sys:
_GetHandleFromName proc uses ebx esi edi FileHandleAddr:dword,DesiredAccess:dword,\

oaAddr:dword,iosbAddr:dword,namesize:dword

LOCAL FO:FILE_OBJECT
LOCAL filehandle:dword

mov FO._Type,IO_TYPE_OPEN_PACKET
mov FO._Size,50h
mov FO.FileName._Length,0
mov FO.FileName.Buffer,1

lea eax,filehandle
push eax ;File handle
lea eax,FO
push eax ;Pointer to File object structure
push DesiredAccess ;Desired access
push KernelMode ;Access mode (not sure. KernelMode=0)
push 0 ;Object type (nor sure)
push FILE_ANY_ACCESS ;Access state (nor sure. FILE_ANY_ACCESS=0)
push oaAddr ;Pointer to object attributes
call ObOpenObjectByName
.if eax==0
mov eax,filehandle
mov ecx, FileHandleAddr
mov [ecx],eax
push FO.DeviceObject
call ObDereferenceObject
.endif
ret

_GetHandleFromName endp

I haven't found any documentation so I have tryed a lot. First I'm not sure FILE_OBJECT is the correct sturcture. FO._Size only works with the value 50h no matter which exe file is started. I can understand the FO.FileName._Length equ 0, but not why FO.FileName.Buffer must be 1. I am also unsure about the second, third and fourth argument. All are 0 so it doesn't matter. However the function delivers a file handle and the exe i running.

Now to the try to execute from memory.

Swithing commenting of lines 161-166 to lines 155-159 in CreateProcess.asm and lines 134-139 to 127-131 in CrSec.asm turns CreateProcess.exe to start Dialog.exe from memory.

This is a function in CrSec.sys:
_GetHandleFromPointer proc uses ebx esi edi FileHandleAddr:dword,DesiredAccess:dword,\

oaAddr:dword,iosbAddr:dword,pMem:dword

LOCAL FO:FILE_OBJECT
LOCAL filehandle:dword

mov FO._Type,IO_TYPE_OPEN_PACKET
mov FO._Size,50h
mov FO.FileName._Length,0
mov FO.FileName.Buffer,1
mov eax,pMem
mov FO.SectionObjectPointer,eax

; lea eax,filehandle
; push eax ;File handle
; push KernelMode ;Access mode
; push 0 ;Object type
; push DesiredAccess ;Desired access
; push FILE_ANY_ACCESS ;Access state
; push 0 ;Flags
; lea eax,FO
; push eax ;Pointer to object structure

lea eax,filehandle
push eax ;File handle
lea eax,FO
push eax ;Pointer to File object structure
push DesiredAccess ;Desired access
push KernelMode ;Access mode (not sure. KernelMode=0)
push 0 ;Object type (nor sure)
push FILE_ANY_ACCESS ;Access state (nor sure. FILE_ANY_ACCESS=0)
push oaAddr ;Pointer to object attributes
call ObOpenObjectByPointer
.if eax==0
mov eax,filehandle
mov ecx, FileHandleAddr
mov [ecx],eax
push FO.DeviceObject
call ObDereferenceObject
.endif

ret

_GetHandleFromPointer endp

The commented argument are as I have found them from an article on a Google seach. But whatever I do it will crach, not a blue screen but rebooting. The same arguments as ..ByName gives a return value of "STATUS_OBJECT_TYPE_MISMATCH".

Now I have got stuck and would be glad for suggestions.

Best regards.
Posted on 2003-10-18 16:42:24 by minor28
Hi

There does seem to be some confusion with the definition of ObOpenObjectByPointer. This may help, it is defined as the following in
Building NT File System Drivers, A Developer's Guide, O'Reilly. Rajeev Nagar

[size=12]

In the description of the ZwCreateSection() routine, I mentioned the existence
of an Object Manager routine that can be used to obtain a handle to an object
in the context of any arbitrary process, given a pointer to that object.
This routine is called ObOpenObjectByPointer() and is defined as follows:

NTSTATUS
ObOpenObjectByPointer(
IN PVOID Object,
IN ULONG HandleAttributes,
IN PACCESS_STATE PassedAccessState OPTIONAL,
IN ACCESS_MASK DesiredAccess OPTIONAL,
IN POBJECT_TYPE ObjectType OPTIONAL,
IN KPROCESSOR_MODE AccessMode,
OUT PHANDLE Handle
) ;

Typically, you can pass in NULL for PassedAccessState and for
the ObjectType. Be careful to request only the type of access in
the DesiredAccess argument permitted by the original open operation
(from which you obtained a pointer to the object). The HandleAttributes
can be obtained from the previous invocation to
ObReferenceObjectByHandle(). That routine returns Handlelnformation,
which in turn contains the returned Handle-Attributes.

There is also a routine called ObReferenceObjectByPointer(),
which simply increments the object reference count for the
specified object. This function is defined in the Windows NT IPS kit
as follows:

NTSTATUS
ObReferenceObjectByPointer(
IN PVOID Object,
IN ACCESS_MASK DesiredAccess OPTIONAL,
IN POBJECT_TYPE ObjectType OPTIONAL,
IN KPROCESSOR_MODE AccessMode, };
[/size]


I might be off base here but one thing I noticed with your code, if I'm reading it right, is about using the pMem location of the MZ header (this is a pointer to SECTION_OBJECT_POINTERS I believe?) in a Locally declared FILE_OBJECT structure as opposed to a Global one. From this you generate a FileHandle by using either ObOpenObjectByName or ObOpenObjectByPointer which is used back in usermode by NtCreateSection, then immediately deleted. The FileHandle identifies the file from which to create the section object (the executable image).

Since memory locations of LOCAL variables can be overwritten once out of the proc, even if this is in kernel mode, it seems to me the Section object defined by the FILE_OBJECT structure (and which the FileHandle refers to), may be invalid, both in permanency and perhaps in context. Handles can come and go, but I would think the underlying object must be a permanent structure for its lifetime.

If you are running your created section image from disk (the successful part), is the FileHandle actually necessary with NtCreateSection?, or does it simply act as if the FileHandle is zero (as defined) - the VMM creates a section object backed by the paging file (piece of shared memory) rather than by a named file in the file system.

Cheers,
Kayaker
Posted on 2003-10-19 01:10:37 by Kayaker
Hi Kayaker

Thanks for your help. The parameters of the ObOpenObjectByPointer is similar to the one I found on the Google seach. However I follow the advice in the quoted text. I replace the two CrSec functions __GetHandleFromName and _GetHandleFromPointer with following function.
_GetHandle proc uses ebx esi edi FileHandleAddr:dword,DesiredAccess:dword,\

handle:dword,obj:dword

LOCAL hi[8]:dword ;Reservation of sufficient memory for HandleInformation struct
LOCAL pObject:dword
LOCAL filehandle:dword

lea eax,hi
push eax ;OUT HandleInformation OPTIONAL
lea eax,pObject
push eax ;OUT *Object
push KernelMode ;IN AccessMode
push 0 ;IN ObjectType OPTIONAL
push 0 ;IN DesiredAccess
push handle ;IN Handle
call ObReferenceObjectByHandle
.if eax==0
mov eax,pObject
mov ecx,obj
mov [ecx],eax
lea eax,filehandle
push eax ;OUT Handle
push KernelMode ;IN AccessMode,
push 0 ;IN ObjectType OPTIONAL,
push DesiredAccess ;IN DesiredAccess OPTIONAL,
push 0 ;IN PassedAccessState OPTIONAL
push hi ;IN HandleAttributes
push pObject ;IN Object
call ObOpenObjectByPointer
.if eax==0
mov eax,filehandle
mov ecx, FileHandleAddr
mov [ecx],eax
push pObject
call ObDereferenceObject
.endif
.endif
ret

_GetHandle endp
. This function can be used for both disk file and memory file. First part, the call to ObReferenceObjectByHandle (DesiredAccess is insignificant) gives the pointer to the object, The second part ObOpenObjectByPointer (DesiredAccess is important) gives the correct value of the filehandle. The third part ObDereferenceObject decrement the reference counter. Perhaps you have to decrement twice because the two firs calls each increment the reference counter. I haven't found the structure of the Handle Information thus I reservate 8 dwords of memory (Any one know?).

To run the executable from disk still succeeds. If you switch hFile (file handle) to hMem (handle of allocated memory) the driver delivers an object pointer of 0h and a FileHandle of 0h. The error message from NtCreateSection is STATUS_INVALID_FILE_FOR_SECTION. I have tested several combinations of access and handles. No one works.

I might be off base here but one thing I noticed with your code, if I'm reading .......... must be a permanent structure for its lifetime.

As far as I know the only thing I need is a valid FileHandle with the correct access rights. The CreateProcess pass the address of FileHandle to the driver and the driver deliver a value to the address. There is no need for an outBuffer from the driver.

If you are running your created section image from disk (the successful part), is the FileHandle actually necessary with NtCreateSection?, or does it simply act as if the FileHandle is zero (as defined) - the VMM creates a section object backed by the paging file (piece of shared memory) rather than by a named file in the file system.

The FileHandle is necessary and important. It must be a file handle with correct access rights. For example if you push hFile coded with the GENERIC_READ access the error message is STATUS_ACCESS_DENIED and a file handle of 0 the error message is STATUS_INVALID_FILE_FOR_SECTION.

My conclusion is that object manager functions might be a wrong track. Is my conclusion right or wrong? Does somebody have any id?as or hints, let's hear it.

I attach the revised asm-files.

Best regards
Posted on 2003-10-20 13:37:47 by minor28