From: Jerome on
Thanx Bruce, it helped me to fix the exact same problem :)
After many hours i could not figure out why WriteProcessMemory worked with one EXE but not with another one.

so i just used :

-----------------------
BOOL res = VirtualProtect(ppfn, pfnLen, PAGE_READWRITE, &oldprotect);
if(res && oldprotect != NULL)
{
res = WriteProcessMemory( GetCurrentProcess(), ppfn, &pfnNew, pfnLen, NULL);
res = VirtualProtect(ppfn, pfnLen, oldprotect, 0);
}
-----------------------

It's probably not the good way to do it, but it works like a charm ;)



Bruce. wrote:

Re: Hooking exit process
20-Mar-08

"Volodymyr M. Shcherbyna" <v_scherbina(a)online.mvps.org> wrote in message
news:%232yLtRqiIHA.5968(a)TK2MSFTNGP04.phx.gbl...

That helped!! I'm now able to set my replacement ExitProcess from the "bad"
exe.

So that leaves me with the question, why did I have a "bad" exe and a "good"
exe?

By playing with that API I could tell that the memory for the bad exe was
set to PAGE_READONLY, while the good exe was set to PAGE_READWRITE.

VirtualProtect allowed me to alter the bad one to PAGE_READWRITE and then I
could write it.

Anyone have any idea why there would be a difference from one exe to the
next exe?

Thanks Roger and Volodymyr, and everyone else!

Bruce.

Previous Posts In This Thread:

On Wednesday, March 19, 2008 6:04 PM
Bruce. wrote:

Hooking exit process
As a continuation of my other thread here, I am now trying to hook
ExitProcess() so a routine up in my dll will be called at the time the exe
is unloading BEFORE the DllMain is called with DLL_PROCESS_DETACH is called.

I used the example code from

http://www.jamajm.com/e-books/cpprichter/HTML/ch22j.htm

which shows how to hook ExitProcess. I pasted that code in a test exe and
it works very nicely. MyExitProcess() code is always called when the exe
exits. Perfect so far.

So I pasted the code in to my dll and MyExitProcess() is never called. The
registering of the hook seems to work perfectly, but it never gets called.

I have tried scanning for both the exe name and the dll name, and neither
works. In both cases it finds the right entry, installs the hook, but
MyExitProcess in the dll is never called when the exe exits.

Any idea what I'm doing wrong? Why would hooking ExitProcess in this code
work in an exe but not in a dll loaded by that exe?

Bruce.

On Wednesday, March 19, 2008 10:07 PM
Bruce. wrote:

Re: Hooking exit process
"Bruce." <noone(a)example.net> wrote in message
news:eVZx50giIHA.5088(a)TK2MSFTNGP02.phx.gbl...

The mystery deepens. I have 2 exe's. exeOld and exeNew. exeOld has been
around for probably 15 years. exeNew I just made. Both call my dll that
registers a ExitProcess hook in DllMain.

When I run exeNew, the hook is called when the exe unloads. When I run
exeOld, the hook is never called when the exe exits. Same exact dll in both
cases.

I now have about 99.99% of the code in both exes commented out yet the
problem remains. Something is different between the 2 exe's but so far it
has me stumped.

Bruce.

On Wednesday, March 19, 2008 11:27 PM
Alexander Grigoriev wrote:

See my post in the previous thread.
See my post in the previous thread. You better avoid hooking; these hacks
will one day bite you in the rear.

In DLL_DETACH_PROCESS on ExitProcess you cannot do any meaningful teardown.
You don't actually need any. You only need to tell that your DllMain is
called in response to ExitProcess, and in this case just return. Your thread
will die in peace then. Only in case of explicit FreeLibrary you'll need to
stop your thread, which will unload the DLL.

"Bruce." <noone(a)example.net> wrote in message
news:eVZx50giIHA.5088(a)TK2MSFTNGP02.phx.gbl...

On Thursday, March 20, 2008 5:13 AM
Bruce. wrote:

Re: Hooking exit process
it is not dying in peace. The thread stops running as soon as
DLL_DETACH_PROCESS is called and never again runs to completion. My thread
never completes.

Bruce.

On Thursday, March 20, 2008 5:26 AM
Bruce. wrote:

Re: Hooking exit process
On your actual question, my first try would be:
- logging all the addresses patched by your hook
- running under a debugger
- place a breakpt at Kernel32!ExitProcess
- work back up the stack to find out how you got there

Thanks Riger. I am running in the debugger. How to I place a break at
Kernel32!ExitProcess? I don't know what module that's in?

Bruce.

On Thursday, March 20, 2008 6:08 AM
Volodymyr M. Shcherbyna wrote:

Why in the first place you're trying to get this information using hackery
Why in the first place you're trying to get this information using hackery
approach? In kernel mode driver you can use documented API:
PsSetCreateProcessNotifyRoutine && PsSetLoadImageNotifyRoutine to setup
callback for processes creation / termination. Depends on task, but you can
do a small driver to process processes creation / termination (you also is
able to get notifications for threads) and pass it to user mode if
neccessary.

--
V.
This posting is provided "AS IS" with no warranties, and confers no
rights.
"Bruce." <noone(a)example.net> wrote in message
news:%23SUh5xmiIHA.1212(a)TK2MSFTNGP05.phx.gbl...

On Thursday, March 20, 2008 9:15 AM
Bruce. wrote:

Re: Hooking exit process
<roger.orr(a)gmail.com> wrote in message
news:6f61f3f1-5f44-4568-a193-7f67a21cd66d(a)c65g2000hsa.googlegroups.com...

Thanks so much Roger. There's so much of this I never would have been able
to figure out on myself.

That experiment yields these call stacks. Here is my program callled
HookExitProcess that calls (my dll) dba32dll.dll and it installs the
ExitProcess hook. When run I get this:

kernal32.dll!ExitProcess
dba32dll.dll!MyExitProcess
HookExitProcess.exe!__crtExitProcess
HookExitProcess.exe!doexit
HookExitProcess.exe!exit
HookExitProcess.exe!main

So, you can see that dll32dll did in fact installi the hook and my routine
MyExitProcess is part of the call stack.

However, here is my other older program, called dba.exe. It does exactly
the same thing, calling dba32dll, and I've watched it successfully install
the hook. Yet my exit routine is not part of the call stack.

kernal32.dll!ExitProcess
dba.exe!__crtExitProcess
dba.exe!doexit
dba.exe!exit
dba.exe!main

Could someone be resetting the hook after I set it?

Bruce.

On Thursday, March 20, 2008 9:19 AM
Bruce. wrote:

Re: Hooking exit process
I do appreciate your reply and suggestion, but writing a driver is WAY
beyond my level of expertise.

Bruce.

On Thursday, March 20, 2008 9:28 AM
Alexander Grigoriev wrote:

You should not wait for the thread to complete.
You should not wait for the thread to complete. When handling
DLL_DETACH_PROCESS on ExitProcess (lpReserved!=NULL), do nothing, just
return.

On Thursday, March 20, 2008 9:30 AM
Volodymyr M. Shcherbyna wrote:

Time to fix all bugs and possible drawbacks of your current solution (imagine
Time to fix all bugs and possible drawbacks of your current solution
(imagine your software deployed for thousands of machines) will be less and
less smaller then writing + testing a small nt driver using a documented and
fully supported approach.

--
V.
This posting is provided "AS IS" with no warranties, and confers no
rights.
"Bruce." <noone(a)example.net> wrote in message
news:udG88zoiIHA.5504(a)TK2MSFTNGP05.phx.gbl...

On Thursday, March 20, 2008 10:26 AM
Bruce. wrote:

Re: Hooking exit process
Whether I wait or not, the thread does not complete. I need it to complete
to maintain the integrity of the objects it is accessing.

Bruce.

On Thursday, March 20, 2008 10:32 AM
Bruce. wrote:

Re: Hooking exit process
<roger.orr(a)gmail.com> wrote in message
news:3bdc4adb-5cac-4b67-b0ab-1a8b63d24eb6(a)i29g2000prf.googlegroups.com...
On Mar 20, 1:15 pm, "Bruce." <no...(a)example.net> wrote:



Roger, you're a genious. The code I "borrowed" from that web site wasn't
checking the return of WriteProcessMemory(). Well, guess what, it's failing
but only in 1 of my 2 exes.

BOOL fStatus = WriteProcessMemory( GetCurrentProcess(), ppfn, &pfnNew,
sizeof( pfnNew ), NULL );
if( !fStatus )
{
rc = GetLastError();
}

In the case of the bad exe (99.9% of which has been commented out), fStatus
is false and rc is 998. 998 is:

error 998, Invalid access to memory location, ERROR_NOACCESS

In the good exe, fStatus is true.

So why does the write succeed in one of my test programs but fail in the
other? Do programs have rights?

Bruce.

On Thursday, March 20, 2008 11:54 AM
Bruce. wrote:

Re: Hooking exit process
<roger.orr(a)gmail.com> wrote in message
news:a8316775-e5ad-4afb-8b8f-01b78e5a8a14(a)e10g2000prf.googlegroups.com...
On Mar 20, 2:32 pm, "Bruce." <no...(a)example.net> wrote:


Here are the comparison between the exe that works and the one that doesn't
as displayed by the debugger.

doesn't work: ppfn 0x0041902c __imp__ExitProcess@4 int (void)* *
does work: ppfn 0x0043a364 __imp__ExitProcess@4 int (void)* *

It's looking like for some darn reason I don't have rights to write my own
memory. I can't think of any other reason to get an error 998. The API
says I must have PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the
process.

My call is simply:

WriteProcessMemory( GetCurrentProcess(), ppfn, &pfnNew, sizeof( pfnNew ),
NULL );

How can I check if I have those rights, comparing the working program with
the failing program? If I don't have those rights, how do I get them?

Bruce.

On Thursday, March 20, 2008 12:06 PM
Volodymyr M. Shcherbyna wrote:

Use VirtualProtect (...)-- V.
Use VirtualProtect (...)

--
V.
This posting is provided "AS IS" with no warranties, and confers no
rights.

On Thursday, March 20, 2008 1:06 PM
Volodymyr M. Shcherbyna wrote:

Most likely, your code did not log the errors which were returned by
Most likely, your code did not log the errors which were returned by
WriteMemory, so you never noticed that it fails ;)

--
V.
This posting is provided "AS IS" with no warranties, and confers no
rights.
<roger.orr(a)gmail.com> wrote in message
news:53be1cb1-f2a3-4ea2-9769-506baffb3c5e(a)e10g2000prf.googlegroups.com...
On Mar 20, 4:06 pm, "Volodymyr M. Shcherbyna"
<v_scherb...(a)online.mvps.org> wrote:

You live and learn.

I've used WriteProcessMemory before and never had any problems.
It worked for all the code and data I've tried it on.

I've just tried - and it fails if the target is a readonly page,
although it is OK for execute_read.

I'd always assumed before that WriteProcessMemory() sorted
the page protection out behind the scenes.

Regards,
Roger.

On Thursday, March 20, 2008 1:36 PM
Bruce. wrote:

Re: Hooking exit process
"Volodymyr M. Shcherbyna" <v_scherbina(a)online.mvps.org> wrote in message
news:%232yLtRqiIHA.5968(a)TK2MSFTNGP04.phx.gbl...

That helped!! I'm now able to set my replacement ExitProcess from the "bad"
exe.

So that leaves me with the question, why did I have a "bad" exe and a "good"
exe?

By playing with that API I could tell that the memory for the bad exe was
set to PAGE_READONLY, while the good exe was set to PAGE_READWRITE.

VirtualProtect allowed me to alter the bad one to PAGE_READWRITE and then I
could write it.

Anyone have any idea why there would be a difference from one exe to the
next exe?

Thanks Roger and Volodymyr, and everyone else!

Bruce.

On Thursday, March 20, 2008 4:17 PM
Bruce. wrote:

Re: Hooking exit process
"Volodymyr M. Shcherbyna" <v_scherbina(a)online.mvps.org> wrote in message
news:eEwngJniIHA.3400(a)TK2MSFTNGP03.phx.gbl...

Would this work in my environment? We distribute an API in the form of a
DLL (it's much more but let's keep it simple). Whatever solution you
envision here can not entail requiring our customers to modify their
programs. And we have no way of knowing what the program names of what they
write are. They could be console, GUI, COM, C, VB, exe, dll, whatever.

Bruce.

On Thursday, March 20, 2008 9:59 PM
Alexander Grigoriev wrote:

After ExitProcess is called, there is no concept of "objects integrity".
After ExitProcess is called, there is no concept of "objects integrity".
Your process is under last rites and is about to stop breathing. Forget
about the thread, it's a goner. It's as if your process was killed by
TerminateProcess.

"Bruce." <noone(a)example.net> wrote in message
news:ObL6aZpiIHA.5088(a)TK2MSFTNGP02.phx.gbl...

On Friday, March 21, 2008 6:14 AM
Bruce. wrote:

Re: Hooking exit process
"Alexander Grigoriev" <alegr(a)earthlink.net> wrote in message
news:eeLQ1hviIHA.3740(a)TK2MSFTNGP03.phx.gbl...

Hooking ExitProcess did 99% of what I wanted. The counts and objects are
now being cleaned up properly when normally exiting a program.

If a user decides to use the task manager to kill the process, then yes,
things can go wrong, but at least the normal case is handled now.

Bruce.

On Friday, March 21, 2008 5:40 PM
Ben Voigt [C++ MVP] wrote:

Bruce.
Bruce. wrote:

Your library would, at startup, open a device created by the driver and
issue an IOCTL. The driver would then set a callback for the termination of
that process.

Or just forget about the process exit notify routine, leak the open handle
to the driver's device. At process termination it will get closed
automatically, your driver will get notified.

Note that you can do the same thing in user mode using pipes or any other
IPC mechanism which notifies one end when the other closes... and you don't
even need admin rights for this.

On Saturday, March 22, 2008 12:05 AM
Pavel Lebedinsky [MSFT] wrote:

In the read/execute case, WriteProcessMemory automatically changesprotection
In the read/execute case, WriteProcessMemory automatically changes
protection to writeable. My guess is that this was done to make life
easier for debuggers (e.g. setting breakpoints).

This behavior however is not documented so you should not depend
on it. Just use VirtualProtect in all cases.

--
This posting is provided "AS IS" with no warranties, and confers no
rights.

On Saturday, March 22, 2008 10:06 AM
roger.or wrote:

Re: Hooking exit process
On Mar 20, 3:27=A0am, "Alexander Grigoriev" <al...(a)earthlink.net> wrote:

I agree.

What tidy up is actually needed (other than the thread itself?)

There may be better ways than trying to get the thread to do it.

On your actual question, my first try would be:
- logging all the addresses patched by your hook
- running under a debugger
- place a breakpt at Kernel32!ExitProcess
- work back up the stack to find out how you got there

Regards,
Roger.

On Saturday, March 22, 2008 10:06 AM
roger.or wrote:

Re: Hooking exit process
On Mar 20, 9:26=A0am, "Bruce." <no...(a)example.net> wrote:
t

I guess you're not using windbg then :-)
It is bp kernel32!ExitProcess in that debugger.

Format is module ! entry

In VS 2005 ensure you've selected DLL exports:
Tools -> Options -> Debugging -> Native
Click Load DLL exports

Then type:
ExitProcess,,kernel32
into the breakpoint location.

Regards,
Roger.

On Saturday, March 22, 2008 10:06 AM
roger.or wrote:

Re: Hooking exit process
On Mar 20, 1:15=A0pm, "Bruce." <no...(a)example.net> wrote:


Possibly - but unlikely.
More likely is
a) You're not actually successfully writing the hook
b) The old program is getting the entry point another way

If you disassemble the code in __crtExitProcess
you should be able to see where it goes.

You'll probably see something like:

__crtExitProcess:
push dword ptr[esp+4]
call __crtCorExitProcess
pop ecx
push dword ptr [esp+4]
call dword ptr [_imp__ExitProcess (41D1C4h)]

And the contents of the word at 0x41D1C4 will be the address
of ExitProcess -- this is the word you should have modified earlier.
Does the instrumented patching code give you the same address?
Set a data breakpoint on this address to catch writers.

Regards,
Roger.

PS You've still not said what you need to do in the closedown.
Might be better to investigate that, rather than going
further along this route..

On Saturday, March 22, 2008 10:06 AM
roger.or wrote:

Re: Hooking exit process
Yes they do, but you usually have rights on yourself...

I'd carefully check the address you are trying to write to.

Regards
Roger.

On Saturday, March 22, 2008 10:06 AM
roger.or wrote:

Re: Hooking exit process
On Mar 20, 4:06=A0pm, "Volodymyr M. Shcherbyna"
<v_scherb...(a)online.mvps.org> wrote:

You live and learn.

I've used WriteProcessMemory before and never had any problems.
It worked for all the code and data I've tried it on.

I've just tried - and it fails if the target is a readonly page,
although it is OK for execute_read.

I'd always assumed before that WriteProcessMemory() sorted
the page protection out behind the scenes.

Regards,
Roger.

On Saturday, March 22, 2008 10:06 AM
roger.or wrote:

Re: Hooking exit process
On 20 Mar, 17:06, "Volodymyr M. Shcherbyna"
<v_scherb...(a)online.mvps.org> wrote:

I've just been lucky :-)

I use it to write to:-
+ Read/Write memory I've allocated in the target process
+ Read/Execute code in target process

and these both work.
Still puzzled that read only doesn't work when read/execute does
- may be a wierd Intel protection mask issue.

Roger.

On Thursday, January 14, 2010 12:33 PM
Jerome wrote:

VirtualProtect solution
Thanx Bruce, it helped me to fix the exact same problem :)
After many hours i could not figure out why WriteProcessMemory worked with one EXE but not with another one.

so i just used :

-----------------------
BOOL res = VirtualProtect(ppfn, pfnLen, PAGE_READWRITE, &oldprotect);
if(res && oldprotect != NULL)
{
res = WriteProcessMemory( GetCurrentProcess(), ppfn, &pfnNew, pfnLen, NULL);
res = VirtualProtect(ppfn, pfnLen, oldprotect, 0);
}
-----------------------

It's probably not the good way to do it, but it works like a charm ;)


Submitted via EggHeadCafe - Software Developer Portal of Choice
Database Scale-Out Strategies for Web Apps
http://www.eggheadcafe.com/tutorials/aspnet/ac17210f-fef3-4fa1-8395-c0f6ed092c90/database-scaleout-strate.aspx
 | 
Pages: 1
Prev: VirtualProtect solution
Next: Hooking exit process