Hooking DrawTextExW issue.

Jan 27, 2013 at 3:08 PM
Edited Jan 27, 2013 at 3:18 PM

 

Im hooking DrawTextExW to get some text from a process. And using this code:
 [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] delegate int DDrawTextExW(IntPtr hdc, StringBuilder lpchText, int cchText, ref RECT lprc, uint dwDTFormat, ref DRAWTEXTPARAMS lpDTParams); // just use a P-Invoke implementation to get native API access from C# (this step is not necessary for C++.NET) [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)] static extern int DrawTextExW(IntPtr hdc, StringBuilder lpchText, int cchText, ref RECT lprc, uint dwDTFormat, ref DRAWTEXTPARAMS lpDTParams); // this is where we are intercepting all file accesses! int DrawTextExW_Hooked(IntPtr hdc, StringBuilder lpString, int cchText, ref RECT lpRect, uint uFormat, ref DRAWTEXTPARAMS lpDTParams) { try { if (lpString.ToString() != "") { //For Debugging Interface.ReportException(new Exception(lpString.ToString())); for (int i = 0; i < Zones.Length; i++) { if (Zones[i].WithinZone(lpRect, HookMode)) { Main This = (Main)HookRuntimeInfo.Callback; DrawTextW_Record text = new DrawTextW_Record(); text.Text = lpString.ToString(); text.rect = new Rectangle(lpRect.Left, lpRect.Top, lpRect.Right - lpRect.Left, lpRect.Bottom - lpRect.Top); text.ZoneIndex = i; text.uFormat = uFormat; text.Called = DateTime.Now;// DrawTextW_Record.LastID++; text.LastUpdate = text.Called; Zones[i].AddText(text); } } } } catch (Exception ExtInfo) { Interface.ReportException(ExtInfo); } //call original API... return DrawTextExW(hdc, lpString, cchText, ref lpRect, uFormat, ref lpDTParams); }
I used the same code for when i hooked DrawTextW(which works) but this one does not. I can see the text when looking at APIMonitor so I should get an exception thrown in my application when the output gets hooked:

Output From APIMonitor:

4:00:17.237 PM 1 program.exe DrawTextExW ( 0xab015a82, "bigbee19", -1, 0x0039efb4, DT_CALCRECT | DT_NOPREFIX, NULL ) 13 0.0000233230325

4:00:17.237 PM 1 program.exe DrawTextExW ( 0xac015a82, "bigbee19", -1, 0x0039ec0c, DT_CALCRECT | DT_NOPREFIX, NULL ) 13 0.0000201230326�

4:00:17.237 PM 1 gdigraphdriver.dll DrawTextExW ( 0x54015afd, "bigbee19", -1, 0x0039ecf4, DT_CALCRECT | DT_NOPREFIX, NULL ) 13 0.0000201230327�

4:00:17.237 PM 1 gdigraphdriver.dll DrawTextExW ( 0x54015afd, "bigbee19", -1, 0x0039ecf4, DT_NOPREFIX, NULL ) 13 0.0000359

the text updates every 4 seconds and when it updates, DrawTextExW gets called in the main application twice and then in gdigraphdriver twice, since none of these 4 calls is registered is there a problem with the Deadlock barrier? or maybe do you see any issues with my code?

Any help is appreciated so throw all your ideas at me because i need to fix this!�

 

//TopHat2

Coordinator
Jan 29, 2013 at 1:39 AM

Hmm not sure - but if you grab the latest EasyHook source, and enable both Managed and Unmanaged debugging when attaching to your target process you can enable the disassembly view and step through the hook (i.e. F11 on return DrawTextExW). Note to step into the assembly you must have the disassembly window active while stepping through the C# code.

When you step into the DrawTextExW original function you can then debug the deadlock barrier easily - however I doubt this is the issue, in fact if you breakpoint the start of your hook you will probably find that it does not get called by your "return DrawTextExW".

Feb 4, 2013 at 11:38 AM
Edited Feb 4, 2013 at 11:39 AM
spazzarama wrote:
however I doubt this is the issue, in fact if you breakpoint the start of your hook you will probably find that it does not get called by your "return DrawTextExW".
Sorry for being unclear, the problem isn't that it's getting called multiple times, the problem is that my hook almost never (and when it does it's completely irrelevant information) gets called when i can clearly see DrawTextExW being used in API Monitor. The behavior i expect is that my hook gets triggered 4 times, 2 times when it's called in program.exe and 2 times when it's called in gdigraphdriver.dll but is doesn't.

It would be great if you could look in to it since i haven't done so much lo- level programming and even less low-level debugging. PM me and i'll give your more information about the target process, and all of my source code
Coordinator
Feb 7, 2013 at 9:15 PM
I'll try to check your example code this weekend.

Have you tried not using a StringBuilder and instead pass IntPtr and then Marshal.PtrToStringAnsi(...) ?
Coordinator
Feb 8, 2013 at 10:59 PM
Working fine for me... I excluded your loop code and simply wrote the text back to the process monitor example.

I did notice that I had to hook before starting the API monitor however. Try adding a breakpoint in your hook and debug what is happening.

Of course it could be something specific to the application you are trying to hook also.