Log in

View Full Version : Does someone knows how to emulate CreateRemoteThread on win9x ?


tsehp
December 24th, 2000, 13:58
hi,
I'm not talking about installing some code into an already existing thread for a win9x process, because the thread I have to create will be killed after I use it for the iat rebuilder tracer.
If someone have info about this, thanks to mail me or write it on the msgboard.
TIA

Alexey Solodovnikov
December 24th, 2000, 14:25
Hi +Tsehp,
As I saw you work ever in Christmas time That's great!

Marry Christmas and Happy New Year, man. And good luck to
you and your IAT rebuilder

Lord Soth
December 24th, 2000, 20:22
Hiya +tsehp,

The way I see it, you basically only have
two options. The one is to somehow inject
code into the process space (temporarily),
that will call CreateThread itself, which will create a new thread for the process itself.
Then you really wouldn't care about the
changes you made to the code (or if you do
care, you can restore it..).
For all purposed intended, I think a new
thread would serve you right.
The other option would be to somehow use
internal kernel functions and structures
to allocate another thread block for the
process space. I'm not certain there is any
place you can find such information. I don't
remember seeing such a thing at pietriek's.
However, with some reversing, you might be
able to figure out how createprocess does
the magic, and try to perform it yourself.
I know it's a lot of work, but if you REALLY
need this, you might think about putting
the time for it.
This is a daunting project. Of course this
is not just allocation of memory and stuff.
You have to have a TCB, msg queue, stack
area, what not. You even have to somehow
notify vmm32 of your new thread.
Don't ask me how, that's as far as my knowledge goes

cya buddy
good luck

Lord Soth
December 24th, 2000, 20:25
> However, with some reversing, you might be
> able to figure out how createprocess does
> the magic, and try to perform it yourself.

That should've been CreateThread.
Oops :-)

LS

Morlac
December 24th, 2000, 21:04
Hi all,

+Tsehp, i cant say that i understand why you want to emulate the function. I checked the msdn i have and it says that CreateRemoteThread() is available for Win98 or later.
Check this out( from the MSDN):
QuickInfo
Windows: Requires Windows 98 or later.
Windows CE: Unsupported.
Header: Declared in winbase.h.
Import Library: Use kernel32.lib.

Perhaps i dont understand.
Regards,
Morlac.

tsehp
December 25th, 2000, 05:23
Quote:
Alexey Solodovnikov (12-24-2000 03:25):
Hi +Tsehp,
As I saw you work ever in Christmas time That's great!

Marry Christmas and Happy New Year, man. And good luck to
you and your IAT rebuilder


Hi alex, If I worked that christmas evening I would say that my app would be more than damaged, anyway I have a little text file for you,
generated from AZPR latest version , included for download.

Have a good work on next asprotect version

Merry christmas

tsehp
December 25th, 2000, 05:27
Quote:
Lord Soth (12-24-2000 09:25):
> However, with some reversing, you might be
> able to figure out how createprocess does
> the magic, and try to perform it yourself.

That should've been CreateThread.
Oops :-)

LS


Hi lord, thanks for your reply, I've found another way to do it, if you ask me by mail I'll tell you if the solution works, will be trying today.
merry christmas.

tsehp
December 25th, 2000, 05:33
Quote:
Morlac (12-24-2000 10:04):
Hi all,

+Tsehp, i cant say that i understand why you want to emulate the function. I checked the msdn i have and it says that CreateRemoteThread() is available for Win98 or later.
Check this out( from the MSDN):
QuickInfo
Windows: Requires Windows 98 or later.
Windows CE: Unsupported.
Header: Declared in winbase.h.
Import Library: Use kernel32.lib.

Perhaps i dont understand.
Regards,
Morlac.


I don't understand me too, because I've already found what you say, and I found also some other msdn links that say the opposite, just look at this, extracted from :http://msdn.microsoft.com/library/default.asp
at the end :
Requirements
Windows NT/2000: Requires Windows NT 3.1 or later.
Windows 95/98: Unsupported.
Header: Declared in Winbase.h; include Windows.h.
Library: Use Kernel32.lib.

A guy said that this api is used in office 2000, I'll check with softice,
otherwise I already have a kind of solution, when I'll be finished the app will be sent to beta testers.
best regards,

Predator [PC/pGC]
December 25th, 2000, 07:06
Hey Alexey ;-)

Erovin
December 25th, 2000, 17:17
My last 3 MSDN kits have stated clearly that CreateRemoteThread is UNSUPPORTED on Win95 and Win98. I needed the same thing for a trainer I made. I wanted my thread to run in the same process space as the game. I spent a lot of time and the only satisfactory thing I found was to use SetWindowsHookEx with WH_GETMESSAGE. With this I could send messages to the app and have my own code get access to the entire memory space of the process.

There are 2 drawbacks with this approach: (1) it requires some fancy DLL manipulations and (2) if the app is not a "real" Windoze app with a message loop and a window procedure then it won't work at all.

tsehp
December 25th, 2000, 17:46
yes you're right.
I tried another way :
createprocess and get the primary hThread, freeze it and change it's context for my injected code with writeprocessmemory, sometimes it works sometimes not, if the threads eip is too low, I just crash it, no way to allocate more mem from another process to inject my code elsewhere and have plenty of space for my tracer dll. I'm waiting for a final answer from the Owl and then maybe give up the win9x port of my tool. It's plenty working on win2k, such a shame but I'm afraid that this iat rebuilder will be available only on this system with the tracing feature Maybe someone have another idea, who knows ?

+Tsehp

tsehp
December 25th, 2000, 17:52
Quote:
Lord Soth (12-24-2000 09:22):
Hiya +tsehp,

The way I see it, you basically only have
two options. The one is to somehow inject
code into the process space (temporarily),
that will call CreateThread itself, which will create a new thread for the process itself.

I'd like to, but I have to use the app's primary thread to do it, and if it doesn't have some free space, I just crush it's code and damage it.
Even if I manage to create another thread, I can't get back it's handle for my main app in another process to copy my dll... So I'm oblidged to use the main thread, if there's not enough mem allocated for it for my dll (about 5 mem pages) I'm just blocked on this. So much simple and stable on win2k / nt4
too bad

kill3xx
December 25th, 2000, 19:45
Quote:
+Tsehp (12-25-2000 06:46):
yes you're right.
I tried another way :
createprocess and get the primary hThread, freeze it and change it's context for my injected code with writeprocessmemory, sometimes it
....
+Tsehp

without undocumented/exotics solution.. this one works fine for me..

1) put your createthread, etc, stuff in a MMF with bInheritHandle=true
+ some signiling/syncronization code (events,etc..)
+ restore EP code
2) setup a small stub that'll do :
a) MapViewOfFile (inheritable handle)
b) save registers, etc..
c) jmp into ur code

3) createprocess + CREATE_SUSPENDED + bInheritHandles=true
4) ReadProcessMemory to the original EP code into the MMF
5) WriteProcessMemory to overwrite the EP with your stub
6) ResumeThread
wait on hThread and syncronization objs to signaling u that all is ok.. a side bonus is that the MMF is also suitable for IPC (u can save ur listener thread/window handle, etc..)

merry xmas,

kill3xx

garph0
December 26th, 2000, 06:53
I wrote a proggie just like kill3xx says... do you remember my injector threads ?
it works fine, if you want it drop me a line

regards

garph0

garph0
December 26th, 2000, 06:54
uh, it works well also with a running target

garph0

The Owl
December 26th, 2000, 07:23
Quote:

createprocess and get the primary hThread, freeze it and change it's context for my injected code with writeprocessmemory, sometimes it works sometimes not, if the threads eip is too low, I just crash it


ok, if only this is a problem, then i suggest you take a look at not only the target thread's (E)IP but CS/SS/(E)SP as well ;-). then you'll find out what it really means that win9x still relies on 16 bit code at times. the solution for this will be to change all of these 4 registers to their proper values. CS/SS you can grab from your own process, however ESP will be less than trivial as you would have to find out the ESP value before the stack switch occured to the 16 bit stack... needs reverse engineering. or maybe you can make use of the current 16 bit SS:SP (just be careful with stack operations), or you can try to resume/suspend the target thread in a loop until you find it in win32 context.

tsehp
December 26th, 2000, 08:23
Quote:
garph0 (12-25-2000 19:53):
I wrote a proggie just like kill3xx says... do you remember my injector threads ?
it works fine, if you want it drop me a line

regards

garph0

hi,
that's very nice of you, it's tempting but if I want to have a chance to learn something on this case, I'm oblidged to continue my own way !
My actual method is at this point :
suspend the target thread, get a pointer to its stack, save it into my process, write about 600 bytes of code containing some tools :
a first loadlibrarya for my dll, then a new thread will be automatically created by win9x, but inside the target's context.
my actual problem is that I have to change the eip of target context to make it start my own code but it crashes, I'm trying to trace the win9x resumethread api but it's kind of long , maybe someone knows the last interrupt this function uses before the usual Iret that leads to the new eip into the target's thread resumed at this time.
But this technique works, I've succeded to load the dll just once, that was a lucky shot.
best regards

tsehp
December 26th, 2000, 08:28
Quote:
kill3xx (12-25-2000 08:45):
Quote:
+Tsehp (12-25-2000 06:46):
yes you're right.
I tried another way :
createprocess and get the primary hThread, freeze it and change it's context for my injected code with writeprocessmemory, sometimes it
....
+Tsehp

without undocumented/exotics solution.. this one works fine for me..

1) put your createthread, etc, stuff in a MMF with bInheritHandle=true
+ some signiling/syncronization code (events,etc..)
+ restore EP code
2) setup a small stub that'll do :
a) MapViewOfFile (inheritable handle)
b) save registers, etc..
c) jmp into ur code

3) createprocess + CREATE_SUSPENDED + bInheritHandles=true
4) ReadProcessMemory to the original EP code into the MMF
5) WriteProcessMemory to overwrite the EP with your stub
6) ResumeThread
wait on hThread and syncronization objs to signaling u that all is ok.. a side bonus is that the MMF is also suitable for IPC (u can save ur listener thread/window handle, etc..)

merry xmas,

kill3xx

I almost did the same, but didn't put the code to inject into a mmf, I directly use a function pointer to copy the compiled code into the target, like I did on win2k with the remote created thread, it's more simple, despite you must use function pointers inside this code and resolve first the function you want to call with a getprocaddress, but the mmf is avoided.
my actual problem is that I change the esp and eip of freezed thread into a context that is a copy of the original one, but when I resume it crashed, I'm working on this at this time, when this will be fixed that should work fine.

The iat rebuilder will be ported to win9x, I actually managed to resolve all the target's that was provided on this mb + all asprotect and vboxed apps !!!! the challenge is worth the work.
best regards,

+Tsehp

tsehp
December 26th, 2000, 19:10
Quote:
The Owl (12-25-2000 20:23):
Quote:

createprocess and get the primary hThread, freeze it and change it's context for my injected code with writeprocessmemory, sometimes it works sometimes not, if the threads eip is too low, I just crash it


ok, if only this is a problem, then i suggest you take a look at not only the target thread's (E)IP but CS/SS/(E)SP as well ;-). then you'll find out what it really means that win9x still relies on 16 bit code at times. the solution for this will be to change all of these 4 registers to their proper values. CS/SS you can grab from your own process, however ESP will be less than trivial as you would have to find out the ESP value before the stack switch occured to the 16 bit stack... needs reverse engineering. or maybe you can make use of the current 16 bit SS:SP (just be careful with stack operations), or you can try to resume/suspend the target thread in a loop until you find it in win32 context.

as always I choosed the easiest solution
But I don't start stop the thread, just watch for its context every 100ms and check for esp>0x400000, but on win9x, the app window must have focus for the thread to evolve so I will be forced to make it modal, and it's working, good old win 3.x and msdos days...

kill3xx
December 26th, 2000, 20:11
Hi,
Quote:
+Tsehp (12-25-2000 21:28):
target, like I did on win2k with the remote created thread, it's more simple, despite you must use function pointers inside this code and resolve first the function you want to call with a getprocaddress, but the mmf is avoided.

well.. u'r right from a HLL perspective (C,C++,etc..) i understand that using a dll is simpler since u've not to deal with relocation, delta-ofs, etc.. i use mmf it 'coz when i need this kind of "services" i prefer to code everything in asm and are more suitable for my IPC needs.. anyway u can simply replace 2a) MapViewOf.. with LoadLibrary 2c) with GetProcAddress + jmp/call and all works flowless (btw in the above list i've forgotten to list 7-PostThreadMessage to force wakeup) ..

Quote:

my actual problem is that I change the esp and eip of freezed thread into a context that is a copy of the original one, but when I resume it crashed, I'm working on this at this time, when this will be fixed that should work fine.

as The Owl has pointed out there'r some things u've to deal with when u want to use the stack of a suspended remote thread (perphaps u can also use some TDB/TIB stack related fields and GetThreadSelectorEntry to infer if the thread is in a suitable state)
but i've to admit that i'm wondering why u want to absolutelely play with the stack ..maybe a WriteProcessMemory copy-on-write/page protection issue ?

Best regards,

kill3xx

tsehp
December 27th, 2000, 16:22
at this time, I succeeded with the remote thread, I only have actually a few bug inside the state machine to fix but it's installed.
I tried to use the most simple way to emulate createremoteThread, here are the steps:
1-prepare an injector, should be less than 1024 bytes, gets byt parameters the name of dll to load and function pointer to getmodulehandle and getprocaddress, it also contains char* for loadlibrary, freelibrary and other needed api's to inject your code
2-wait for the target thread to reach an esp higher than 0x400000 then freeze it, you must have a valid handle to it, to get it, start yourself the app to tweak with createprocess and get the handle from systeminfo structure.
3-put your injector higher than the actual esp-4, then change the frozen thread's eip to it's oep and resume the thread.
4-the injector does a loadlibrary of your dll and then must wait for your work to finish to clean itself, you can use a flag that will be set by the dll you injected.
5-the dll is freed, your injector sets the flag and your main app freezes the thread again, cleans the injector and restore original eip and starts the thread again.

It's more simple that I thought, even if a simple implement of createremotethread would have done the job more easily, maybe done on windoze me 2005 who knows ?

I'm about to finish the win9x port for iat rebuilder now, got to fix some tracer bugs and that should work as good as on win2k, I'll write it here.

best regards,

+Tsehp