Skip to main content
GameDev.net gamedev.net
🔒 Locked

win32 SetTimer injection

Started by thedustbustr Jan 22, 2007 at 1:26 AM 2 replies 1.9k views
Original Post
thedustbustr
thedustbustr
If you saw the previous thread about minesweeper code injection, this is similar. Minesweeper has a counting timer that increments every second. This timer is controlled through the win32 api. Functions SetTimer and KillTimer control the timer, and after the timeout (1 second here) a WM_TIMER event is generated which is caught by the message queue in minesweeper. So I want to inject simple code to kill the old timer and inject a new timer with the same timerid, so I can effectively change the timeout on the fly without minesweeper knowing. So I need to inject code to call KillTimer then call SetTimer with new paramaters. Blah blah, it ends up being 10 lines or so, whatever, I'll jump to a code cave or something. The question is, where is the best place to jump from, and what is the most elegant way to do this? Is there a way to temporarily hook execution or break from execution from wherever winmine is currently executing, and run my code, then go back? All I can figure is that I can hijack the windows message loop, and use a static variable to make sure it only gets executed once. So I'll insert a jump to code cave like so, then jump back eventually. To line up the instructions I'll probably have to export this whole loop to the cave but I can handle that. here's a paraphrase of the mainloop which seems like a good place to inject
loop:
goto code cave
return from code cave
...
call user32.TranslateAcceleratorW
...
call user32.TranslateMessage
...
call user32.DispatchMessage
...
goto loop
So I think I know enough to do all this, but before I bother, I want to make sure it's the best way, because this feels like a huge cludge. So yeah this ended up being a lot of words for not that big of a problem, sorry :( Thanks for your help, Dustin Appendix: the code to reconfigure the timer in case it is relevant (I dont really think it is but I'm a huge reverse engineering noob so I'll post it just in case). Note that it probably doesn't even work but that's something I will work through once I find a place to inject it.
cave:
//static bool finished=0;
//if (finished != 0) jmp back_to_mainloop
//finished=1;
push 1					;TimerID=1
push dword ptr ds:[1005b24]		;hWnd=minesweeper
call dword ptr ds:[user32.KillTimer]

push 0					;Timerproc=NULL (no callback)
push 7D0				;2000ms intervals
push 1					;TimerID=1
push dword ptr ds:[1005B24] 		;hWnd=minesweeper
mov dword ptr ds:[1005164],ebx		; don't know why but the original code has this
                                        ; don't think it is necessary but i will spend some effort
                                        ; tracing ebx and this addr to see if its necessary
call dword ptr ds:[user32.SetTimer]
jmp back_to_mainloop
[Edited by - thedustbustr on January 22, 2007 1:43:39 AM]
thedustbustr
thedustbustr
Upon further investigation, the cludgy technique I described above looks as if it will not work. It requires a static local variable, which afaik is implemented in assembly via a global variable. I can't inject global variables because that stuff is assigned an offset at compile time.

So I'm back to square one - I have no idea how to do this 'live'.
LessBread
LessBread
Have you considered intercepting the WM_TIMER message using SetWindowsHookEx, a dll and a launching program?

"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
thedustbustr
thedustbustr
No, I'll look into it, thanks.

I really want to avoid a launching program, I'd prefer to be able to do a live injection. If I have a launching program, I could just patch the SetTimer call and not have to deal with any of this. But then I lose flexibility, such as on-the-fly clock speed adjustment.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.