Results 1 to 7 of 7

Thread: Detecting Memory Access/Execution

  1. #1

    Thread Starter
    New Member
    Join Date
    Oct 2004
    Location
    Florida
    Posts
    10

    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.

  2. #2
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    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.

  3. #3

    Thread Starter
    New Member
    Join Date
    Oct 2004
    Location
    Florida
    Posts
    10
    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?

  4. #4
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    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.

  5. #5

    Thread Starter
    New Member
    Join Date
    Oct 2004
    Location
    Florida
    Posts
    10
    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?

  6. #6
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    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.

  7. #7

    Thread Starter
    New Member
    Join Date
    Oct 2004
    Location
    Florida
    Posts
    10
    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
  •  



Click Here to Expand Forum to Full Width