Hooking DirectWrite

c++ / delphi package - dll injection and api hooking
manjeetk
Posts: 32
Joined: Thu Apr 07, 2011 6:40 am

Hooking DirectWrite

Post by manjeetk »

Hi,

We are trying to capture the text of IE9 browser’s windows on Vista/Windows7, but we come to know that IE9 and Firefox are using the new graphics libraries i.e. DirectWrite and Direct2D, so my question is:

Is MadShi supports hooking DirectWrite/Direct2D for capturing the text of a window?

If Yes, could you please let us know which API of DirectWrite/Direct2D need to hook for capturing the windows text and how. Is there any example/demo code?
madshi
Site Admin
Posts: 10765
Joined: Sun Mar 21, 2004 5:25 pm

Re: Hooking DirectWrite

Post by madshi »

There's a Direct3D hooking demo in the madCodeHook 2.x demo folder. Unfortunately I've not found the time to convert it to madCodeHook 3.0 yet. Anyway, you can download the 2.x demos here:

http://madshi.net/mch2Demos.rar

Look for the files named "HookDirect3D.*". The hook dll itself should not differ between madCodeHook 2.x and 3.0, only the dll injection APIs have changed.

I've no experience with DirectWrite/Direct2D, but the basic principle should be the same as when hooking Direct3D, so I'm pretty sure it should work just fine. I've no idea which exact DirectWrite/Direct2D APIs you need to hook, though. That's your job to find out... :wink:
manjeetk
Posts: 32
Joined: Thu Apr 07, 2011 6:40 am

Re: Hooking DirectWrite

Post by manjeetk »

Hi,

Thanks for the demo application.

With the help of demo project, we are able to hook "DWriteCreateFactory" method of DirectWrite.
Now, we are trying to hook "CreateTextLayout" of "IDWriteFactory" interface. Below is the code snippet.

Code: Select all

PVOID GetInterfaceMethod(PVOID intf, DWORD methodIndex)
{
  return *(PVOID*)(*(DWORD*)intf + methodIndex * 4);
}


HRESULT (WINAPI *CreateTextLayoutNext)(const WCHAR *string,
                                                   UINT32  stringLength,
                                                   IDWriteTextFormat *textFormat,
                                                   FLOAT  maxWidth,
                                                   FLOAT  maxHeight,
                                                   IDWriteTextLayout **textLayout);

HRESULT WINAPI CreateTextLayoutCallback(const WCHAR *string,
                                                    UINT32  stringLength,
                                                    IDWriteTextFormat *textFormat,
                                                    FLOAT  maxWidth,
                                                    FLOAT  maxHeight,
                                                    IDWriteTextLayout **textLayout)
{
     //DESCRIPTION: Wrapper function for prohooked CreateTextLayout functions

     if(NULL != string)
     {
           //Process information.
     }

     //Pass on the call to the original function.
     HRESULT hRetVal = CreateTextLayoutNext(string,
                                                        stringLength,
                                                       textFormat,
                                                       maxWidth,
                                                       maxHeight,
                                                       textLayout);
    return hRetVal;
}

HRESULT (WINAPI *DWriteCreateFactoryNext)(DWRITE_FACTORY_TYPE factoryType, REFIID iid, IUnknown **factory);

HRESULT WINAPI DWriteCreateFactoryCallback(DWRITE_FACTORY_TYPE factoryType, REFIID iid, IUnknown **factory)
{
     HRESULT hRetVal = DWriteCreateFactoryNext(factoryType, iid, factory);
     if(!hRetVal)
     {
           
           if(!CreateTextLayoutNext)
           {
                if(__uuidof(IDWriteFactory) == iid)
                {
                     HookCode(GetInterfaceMethod(*factory, 18), CreateTextLayoutCallback, (PVOID*) &CreateTextLayoutNext);

                     //IDWriteFactory *pDWriteFactory = reinterpret_cast<IDWriteFactory *>(*factory);
                     //if(pDWriteFactory)
                     //HookCode(GetInterfaceMethod(pDWriteFactory, 15), CreateTextLayoutCallback, (PVOID*) &CreateTextLayoutNext);
                }
           } 
           else
                RenewHook((PVOID*) &CreateTextLayoutNext);
     }

     return hRetVal;
}


HookAPI("Dwrite.dll", "DWriteCreateFactory", DWriteCreateFactoryCallback, (PVOID*) &DWriteCreateFactoryNext);


In Above code, we are trying with method index as 18 but we are not sure about index we are using to hook "CreateTextLayout".

Please let us know what is wrong with above code? as we are not able to hook "CreateTextLayout".

Looking for your help.
madshi
Site Admin
Posts: 10765
Joined: Sun Mar 21, 2004 5:25 pm

Re: Hooking DirectWrite

Post by madshi »

What happens? Do you get a crash? Or does your hook simply not fire? Does HookCode return true or false?

One bug in your code: The interface methods all have a hidden "self" or "this" parameter. See the HookDirect3D demo.
manjeetk
Posts: 32
Joined: Thu Apr 07, 2011 6:40 am

Re: Hooking DirectWrite

Post by manjeetk »

Regarding the bug, we have resolved it as per HookDirect3D Demo details.

Hook code returns false. Our hook is not firing. In 64 bit IE we are getting crash but in 32 bit IE no crash and no hook firing.
madshi
Site Admin
Posts: 10765
Joined: Sun Mar 21, 2004 5:25 pm

Re: Hooking DirectWrite

Post by madshi »

IUnknown has 3 methods of its own, so the correct index is 18 and not 15. If HookCode still fails, what does GetLastError say?
manjeetk
Posts: 32
Joined: Thu Apr 07, 2011 6:40 am

Re: Hooking DirectWrite

Post by manjeetk »

HookCode return False and Getlasterror says "0->operation completed successfully"

I am still not sure about the index. do you know how to get index for interface method?
madshi
Site Admin
Posts: 10765
Joined: Sun Mar 21, 2004 5:25 pm

Re: Hooking DirectWrite

Post by madshi »

In order to get the correct index, you just count the number of methods in the order they are declared. You need to count the methods of the interfaces the target interface inherited from, too, though. So you need to count the 3 methods in IUnknown, which gets you to index 18 instead of 15.

Does GetInterfaceMethod return a seemingly valid address? And HookCode returns 0?
manjeetk
Posts: 32
Joined: Thu Apr 07, 2011 6:40 am

Re: Hooking DirectWrite

Post by manjeetk »

How to make sure that address return by GetInterfaceMethod IsValid Address?
madshi
Site Admin
Posts: 10765
Joined: Sun Mar 21, 2004 5:25 pm

Re: Hooking DirectWrite

Post by madshi »

Well, which address is it? You could check whether it appears to lie inside of a valid dll file by using ProcessExplorer. And HookCode returns 0, 1 or -1?
manjeetk
Posts: 32
Joined: Thu Apr 07, 2011 6:40 am

Re: Hooking DirectWrite

Post by manjeetk »

As you can see in our code above, we are sending "*factory" pointer of IDWriteFactory interface to GetInterfaceMethod(*factory, 18) method and trying to hook 18 index method of IDWriteFactory interface i.e. "CreateTextLayout"

In this case, we are assuming the address we are getting in "*factory" is vtable start address and same we are passing in GetInterfaceMethod.

In 32 bit IE, we are not getting any crash and no hooking i.e. hookcode returns 0.
In 64 bit IE, we are getting crash. (we are using 8 bit in address calculation of GetInterfaceMethod *(PVOID*)(*(DWORD*)intf + methodIndex * 8 ))
madshi
Site Admin
Posts: 10765
Joined: Sun Mar 21, 2004 5:25 pm

Re: Hooking DirectWrite

Post by madshi »

I would suggest to concentrate on 32bit first. GetInterfaceMethod will probably not work like this for 64bit, I would guess. You'd probably have to use ULONG_PTR instead of DWORD. Anyway, you didn't answer any of the questions in my previous comment.
manjeetk
Posts: 32
Joined: Thu Apr 07, 2011 6:40 am

Re: Hooking DirectWrite

Post by manjeetk »

Hi,

Regarding the comments:
which address is it?
As i said in the comment, we are sending "*factory" pointer of IDWriteFactory interface to GetInterfaceMethod(*factory, 18) method and trying to hook 18 index method of IDWriteFactory interface i.e. "CreateTextLayout"

In this case, we are assuming the address we are getting in "*factory" is vtable start address and same we are passing in GetInterfaceMethod.

You could check whether it appears to lie inside of a valid dll file by using ProcessExplorer?
I don't know what it means but i can see Dwrite.dll is listing in IE's DLL in ProcessExplorer.

HookCode returns 0, 1 or -1?
Hook Code always return 0 in our case.
madshi
Site Admin
Posts: 10765
Joined: Sun Mar 21, 2004 5:25 pm

Re: Hooking DirectWrite

Post by madshi »

manjeetk wrote:As i said in the comment, we are sending "*factory" pointer of IDWriteFactory interface to GetInterfaceMethod(*factory, 18) method and trying to hook 18 index method of IDWriteFactory interface i.e. "CreateTextLayout"
You asked "How to make sure that address return by GetInterfaceMethod IsValid Address?". And I replied by asking "Well, which address is it?". I think it's a pretty simple question. I want to hear: "It's 0x12345678", or something like that.
manjeetk wrote:I don't know what it means but i can see Dwrite.dll is listing in IE's DLL in ProcessExplorer.
In ProcessExplorer you can check which dlls are using which address ranges. You can check whether the address returned by GetInterfaceMethod lies inside of the address range of one of the dlls listed by ProcessExplorer.
manjeetk
Posts: 32
Joined: Thu Apr 07, 2011 6:40 am

Re: Hooking DirectWrite

Post by manjeetk »

Hi,

Following are the details:
DLL : dwrite.dll
DLL Method we hooked : DWriteCreateFactory
Interface : IDWriteFactory
Interface Method we are trying to hook : CreateTextLayout

CreateTextLayout Method's Address : 0x7080E961 we are getting using GetInterfaceMethod.

As per ProcessExplorer:
dwrite DLL Base Address : 0x70800000
Size : 0x10A000
Post Reply