As a test app for exploring the PE format, and just because I think it's funny that this is possible under windows XP, I wrote a small program that can move itself completely into another process. Relocations and imports are then fixed up appropriately, so it's really a kind of PE loader. Eventually I want to use it as a easy to use API hooking platform.
It really works great most of the time, even when moving the program around every process on my PC, but it always seems to crash when I try to move into EXPLORER.EXE for the second time. First time works fine. Any theories on why this would happen? It's kinda got me stumped.

The program is on my site (click the www button) btw.
Posted on 2003-01-11 07:03:54 by Qweerdy
I haven't found yet why your program crashes but you are doing some dangerous stuff in your code. You're copying the whole image from memory to the newly allocated memory. This also means you're copying the unitialized data section which is not uninitialized anymore but filled with values. It shouldn't really matter in your program but if you would use it on some other program it should be able to assume uninitialized data is set to zero on startup. A real loader would load each section seperately, and set the access (readonly, readwrite, execute, etc) per section. You would also get in trouble when values in the .data section have changed before you copy it.
But still, since your program is quite simple (well not the code, but the structure of the (data) sections, imports, etc. that is) it should work. I'll look into it later when I have some more time.

Thomas
Posted on 2003-01-11 13:34:45 by Thomas
Hi Queerdy,

examining with ntsd its easy to see that your code crashes being called from user32. Looks like a windows proc having vanished.

When I took a closer look at the source, I see you avoid finishing the message loop with PostQuitMessage. Why? Since your code executes in its own thread, it should be save (and should done) to leave the loop. In any case, doing a VirtualFree in WM_DESTROY is hazardous (WM_DESTROY is surely not the last message your wndproc receives).

I changed your source accordingly and inserted a "uses esi edi ebx" in your wndproc (because CopyProcess seems to change esi at least). After that it seemed to run with explorer.



WndProc proc uses esi edi ebx hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CREATE


and


.elseif eax==102
invoke SendMessage,hList,LB_GETCURSEL,0,0
.if eax!=LB_ERR
invoke SendMessage,hList,LB_GETITEMDATA,eax,0
invoke CopyProcess,eax,0 ;addr DoSomething
;; invoke RemoteExitProcess,0
invoke DestroyWindow, hWnd
.endif


and



.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
invoke RemoteExitProcess,0


japheth
Posted on 2003-01-11 16:07:11 by japheth
Thomas:

It shouldn't really matter in your program but if you would use it on some other program it should be able to assume uninitialized data is set to zero on startup.

I don't really see the use in merging random processes, the current code does impose some restrictions on the program being copied. In fact it actually depends on the values of some (uninitialized) globals being the same in source and destination process.

japheth:

Thanks!!! Now I understand why it didn't work at first. Strange that it only happened in explorer.exe during my tests!
The aditional RemoteExitProcess after the message loop is not needed though, since I already call RemoteExitProcess after the WinProc returns.
Posted on 2003-01-12 05:45:41 by Qweerdy