Prev: VirtualProtect solution
Next: Hooking exit process
From: Jerome on 14 Jan 2010 12:34 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 |