|
-
Nov 11th, 2004, 10:42 AM
#1
Thread Starter
New Member
Detecting Memory Access/Execution
Is there any way to detect if a certain code instruction in memory has been executed? And if it has been executed, I want to run one of my own functions in my program. Someone explained to me that SetUnhandledExceptionFilter in the Win32 API could be used to detect any changes made to memory, but he wasn't sure if it could be used to detect execution of certain part of memory. And I'm also not too sure how to use that function anyways, as I can't seem to find too many examples of its use.
So my question is, can I detect when an assembly code instruction in memory has been executed using that function or perhaps some other way entirely?
It ocurred to me that this somehow must be possible, considering debuggers are able to set breakpoints at certain points in memory. I just am not sure how to go about coding that sort of thing. All I would need to do is sort of set up a breakpoint at a memory location and execute my code instead of stopping execution of the program entirely.
Any help with this would be GREATLY appreciated.
-
Nov 11th, 2004, 10:55 AM
#2
You could replace the instruction with a interrupt 3. That sets off any attached debuggers, which could be your program.
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Nov 11th, 2004, 11:06 AM
#3
Thread Starter
New Member
I see. Well I remember reading somewhere about using 0xCC as the replacement instruction as it said it was the standard with debuggers. Is that interrupt 3? Or is that simply 0x03? I'm not just not really sure about this. I thought I had tried using 0xCC, and it was crashing, but I'm not quite sure I was handling the "exception" correctly.
So once I do replace the instruction with that interrupt, how would I go about setting off the code in my program?
-
Nov 11th, 2004, 11:39 AM
#4
Err, no idea. Look it up in the Intel specs.
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Nov 12th, 2004, 05:54 AM
#5
Thread Starter
New Member
Alright, well somone else suggested using VirtualProtect to block access to the specific area. That would cause an exception that I could possibly handle and then set off my code and use VirtualProtect again to fix the problem and continue executing.
The problem here is, I'm rather clueless on the details of structured error handling. I've done some reading on the subject, particularly the article here: http://www.microsoft.com/msj/0197/ex...exception.aspx
It goes fairly in-depth. I've tried to use some of that code, but it ends up crashing trying to implement the handler in the first place. I don't even have to use VirtualProtect to force the exception. Just trying to use the code to have a handler is causing a crash.
Here is the gist of my code:
Code:
EXCEPTION_DISPOSITION __cdecl OnEvent(struct _EXCEPTION_RECORD *ExceptionRecord,
void *EstablisherFrame,
struct _CONTEXT *ContextRecord,
void *DispatcherContext);
void OnAmxxAttach() {
// Setup handler for forwards
handler = (unsigned long)OnEvent;
__asm {
push handler // Address of handler function
push fs:[0] // Address of previous handler
mov fs:[0], esp // Install new EXECEPTION_REGISTRATION
}
// Reset forwards
forwardEventRoundStart = 0;
// Add natives to AMXX
MF_AddNatives(cshack_Natives);
// Get starting game DLL memory address
#ifdef __linux__
gameDllAddress = (unsigned long)dlopen(GAMEDLL_NAME, RTLD_NOW);
#else
gameDllAddress = (unsigned long)LoadLibrary(GAMEDLL_NAME);
#endif
}
void OnAmxxDetach() {
__asm {
mov eax, [esp] // Get pointer to previous record
mov fs:[0], EAX // Install previous record
add esp, 8 // Clean our EXECEPTION_REGISTRATION off stack
}
}
EXCEPTION_DISPOSITION __cdecl OnEvent(struct _EXCEPTION_RECORD *ExceptionRecord,
void *EstablisherFrame, struct _CONTEXT *ContextRecord,
void *DispatcherContext) {
//MF_ExecuteForward(forwardEventRoundStart);
//unsigned long ddd;
//VirtualProtect((LPVOID)0x000841CA, 2, PAGE_EXECUTE, &ddd);
return ExceptionContinueExecution;
}
Let me explain some of this. I'm writing a module for a server-side mod of Half Life called Amx Mod X. OnAmxxAttach I suppose would be equivalent to the entry point or when the server is started up, and OnAmxxDetach would be when the server is shut down. As you can see I have a preprocessor directive for linux, so yes this code will eventually be run on linux too. But I'll worry about the linux portion of error handling later. Right now I'm concentrating on Win32.
Some of the variables in my code are declared elsewhere, so that's not an issue either. My main concern is the use of the exception handler here. I have commented out the code I wish to set off when the exception occurs. But the code as it stands will crash without any error messages.
Something else I've been thinking about is that the code I'm trying to "debug" is in another DLL completely. So the exception would technically occur within that DLL and not in my program. Is that assumption correct? If so, then is what I'm trying to do the correct way of handling such an exception? Or am I just not able to handle the exception at all?
-
Nov 12th, 2004, 10:35 AM
#6
Forget VirtualProtect, it can only protect a whole page at a time, which is around 512k. You can't pinpoint a specific instruction that way.
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Nov 13th, 2004, 06:37 AM
#7
Thread Starter
New Member
Ok, maybe I need to rethink what I am doing here. I'll forget about VirtualProtect then. Back to the idea of using Interrupt 3...
I have verified that 0xCC is equivalent to int3. So if I do replace an instruction, how would I do that exactly here? Because I have already tried this. I'm thinking I'm not handling the excepton correctly, but I really don't know.
Let's say I have this block of ASM:
Code:
100841C7 8B5500 mov edx,[ebp+00h]
100841CA 8BCD mov ecx,ebp
100841CC FF92F0000000 call [edx+000000F0h]
100841D2 DB4540 fild dword ptr [ebp+40h]
100841D5 85C0 test eax,eax
100841D7 A134BA1610 mov eax,[L1016BA34]
100841DC D820 fsub dword ptr [eax]
100841DE D84538 fadd dword ptr [ebp+38h]
100841E1 D81DF0720F10 fcomp dword ptr [L100F72F0]
100841E7 DFE0 fnstsw ax
100841E9 0F8425020000 jz L10084414
100841EF F6C441 test ah,41h
100841F2 0F8A72080000 jpe L10084A6A
100841F8 68A4291210 push SSZ101229A4_World_triggered__Round_Start__
100841FD E83EE60200 call SUB_L100B2840
I'm using PE Explorer as for my dissassembly work btw... And I think that's more code than necessary, but anyways I want to detect when that first instruction is executed, which happens to be mov edx,[ebp+00h].
So I replace these bytes "8B5500" with "CCCCCC" ? That's what I've tried doing. But like I said I'm unsure of my exception handling methods...
Code:
int forwardEventRoundStart;
LPTOP_LEVEL_EXCEPTION_FILTER OldUnhandledExceptionFilter;
long __stdcall OnEvent(LPEXCEPTION_POINTERS ExceptionPointers);
void OnPluginsLoaded() {
// Register forwards
forwardEventRoundStart = MF_RegisterForward("event_round_start", ET_IGNORE, FP_DONE);
// Check for forwards in plugins
if (IsPublicFound("event_round_start")) {
UTIL_PatchMemory_Byte(0x000841C7, (char)0xCC);
UTIL_PatchMemory_Byte(0x000841C8, (char)0xCC);
UTIL_PatchMemory_Byte(0x000841C9, (char)0xCC);
}
}
long __stdcall OnEvent(LPEXCEPTION_POINTERS ExceptionPointers) {
if (ExceptionPointers->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT
&& ExceptionPointers->ExceptionRecord->ExceptionAddress == (void *)0x000841C7) {
MF_ExecuteForward(forwardEventRoundStart);
UTIL_PatchMemory_Byte(0x000841C7, (char)0x00);
UTIL_PatchMemory_Byte(0x000841C8, (char)0x55);
UTIL_PatchMemory_Byte(0x000841C9, (char)0x8B);
return EXCEPTION_CONTINUE_EXECUTION;
}
return((*OldUnhandledExceptionFilter)(ExceptionPointers));
}
UTIL_PatchMemory_Byte is a utility function that I wrote elsewhere that does just what it says using a combination of VirtualProtect and directly setting the particular memory location with the value I provide. I'm fairly certain my problem has nothing to do with that function as I've used it elsewhere in my project and I've had no problems with it.
The system I am working with does the following and I'm doing this for the Half-Life based game of Counter-Strike. I'm working with a server-side mod called AMX Mod X. It has a plugin and a module system. The plugins are scripted in another language called Small while the modules (which are written in C/C++) provide scripting functions for the plugins to use. The modules can also provide forwarded functions which is what I'm trying to do.
So OnPluginsLoaded is called when all the scripted plugins have been loaded into memory. So what I'm doing is registering a forward for the plugins to use called "event_round_start". And then it checks to see if "event_round_start" is defined in any of the plugins. If it is I patch bytes in the Counter-Strike server game DLL, the bytes that represent the ASM instruction that I want to hook.
Then OnEvent is my exception handler for when it encounters those patched bytes I mentioned. I'm not entirely sure I have implemented this correctly. Anyways, when the exception occurs I want to execute my forwarded function in any plugins that have it defined via MF_ExecuteForward provided the AMX Mod X module API. And then I patched those bytes to their original state so they can be executed normally again.
However there are problems with this, other than the obvious of getting crashes with the way I've implemented this. I'd like the forwarded function in the plugins to be called at any time. With the way I have it now, they would only be called one time. Is there a way to hook an ASM instruction and have my code be able to called more than one time? Also there is the issue I want to have more than one forwarded function too. So if one ASM instruction is called I call one function in my code, but if another instruction is executed at different memory address, then different function in my code would be called. This whole thing is like setting up some way to catch or hook events, except the events are when a particular ASM instruction is executed.
Btw, I'm using normal hardcoded numbers for right now until I figure this out. Once I do get it handled, I will be using #defines and such for this.
Some of what I just wrote might be confusing here and my head certainly hurts writing all of this, so I'll clarify anything that needs to be. I've been working with this sort of thing for awhile now, and I just can't seem to figure it out yet.
AMX Mod X is also open source btw, so if you are interested in helping me out but don't still don't have idea what I was saying previously in this post, check out www.amxmodx.org. I'll try to clarify anything about it that I possibly can. I would greatly appreciate help with this.
EDIT: If necessary, I'm willing to share my entire source if it will help.
Last edited by Dual Reality; Nov 13th, 2004 at 11:03 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|