Home » Community » Forums » DirectX and XNA » [C++] Direct3D hooking sample
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic

Page:   1 2 »»

 Last Thread Next Thread 
 [C++] Direct3D hooking sample
Post New Topic  Post Reply 
Intro
This sample demonstrates the second technique that can be used to render content on-top of other Direct3D applications. The first technique, overlays, is rather general purpose; it is not tied to Direct3D. You can use overlays to render on-top of everything. This technique, on the other hand, is closely tied to Direct3D. Due to its special-purpose nature, you lose some benefits and gain others. What you lose is that you can only draw on-top of Direct3D9 applications. What you gain is that you become Direct3D itself, so you're not limited to just drawing anymore. You can do things like count the number of batches submitted per frame, the number of triangles, replace textures, etc.

In this sample, we use Windows hooks to inject our DLL code into a specific process - the target process - that uses Direct3D9. Our injected code replaces Direct3DCreate9 with our own function that calls the standard Direct3DCreate9, but returns our implementation of IDirect3D9, MyDirect3D9. MyDirect3D9 stores a pointer to the original IDirect3D9 interface, so you can do anything you like by forwarding the function calls you don’t want to change and rewriting the ones you want to.

The actual hooking is done using APIHijack, with very minor modifications to make it build under VC++ 2003 and 2005. Namely, a couple of reinterpret_cast’s here and there.

The sample is divided into 2 projects: A DLL containing interface implementations and APIHijack, and a launcher console application. Visual C++ 2003 and 2005 solutions are provided.

The launcher is a simple Unicode application that sets up the single piece of information that the DLL needs: The target process name. In order to make things simple, the launcher is passed the target process name (i.e. exe name) as a command-line argument. It then creates or updates a registry key, HKEY_CURRENT_USER\Software\Direct3D-Hook, to store the name in its default value. The non-Unicode DLL, whose DllMain is entered whenever a process is loaded, compares the name of the loaded process to that in the registry and hooks Direct3D if they’re the same. It also gives an info beep on hooking. The DLL was not build with Unicode because APIHijack isn't, and I'm not interested in converting it. Feel free to do so if you want.

I’ve only provided implementations for the interfaces IDirect3D9 and IDirect3DDevice9. You can implement any other interfaces if you like, provided that you modify the functions that create them to return a pointer to instances of your implementation. Keep in mind, though, that it’s a quite boring process. I nearly lost an arm and a leg writing the aforementioned implementations, even though I’ve copied the function declarators from the d3d9.h header file. You’ll understand when you see the code.

The IDirect3D9 interface implementation is rather minimal, so it forwards all function calls except:
1. Release. We call IDirect3D9::Release and check its return value. If its zero, we delete the MyDirect3D9 instance. If we don’t do this, we’ll leak memory.

2. CreateDevice. We create a normal device but return our own implementation of IDirect3DDevice9, MyDirect3DDevice9. The device implementation, again, forwards all of the function calls except:
a) Release, for the same reason as above.
b) EndScene. This is where we can do all the rendering we want. The sample renders a colored quad to the top-left of the render-target.

Limitations
Applications that manually load D3D9.dll via LoadLibrary, retrieve a pointer to Direct3DCreate9 using GetProcAddress and call it will NOT be hooked. All Direct3D SDK samples do this. If you really want to hook them, you can probably do it in another way, by providing your D3D9.dll and putting it in the same folder. I might try that out later.

Testing
To test the sample, I used 2 applications. A build of Direct3D tutorial #2, “Vertices”, was used first. It worked fine, and it is included in the sample. To test it in a real-world scenario, though, I used the brilliant, addictive game: “Egyptian Addiction”. Yes, this is free advertising. Go give that game a try, it rocks. No, it’s not developed by Egyptians.

The real-world test was useful in that it reminded me that I had to set the required render and texture stage states first. Don’t forget that there’s someone playing with the settings before you . The sample doesn’t restore the state after modifying it, assuming the hooked process sets its required states every time. This can break some applications where the application writers didn’t expect their states changing behind their back. You’ll need to cache all state changes on all the state changing calls, and revert to the cached ones after rendering if you’re dealing with such an application.

License
My code in this sample is public domain, do whatever you wish with it. I can’t say the same for the APIHijack library, however. The author does not mention any specific license in his code or article, so you’d probably want to contact him if you’re doing a commercial project.

PICTARS!!
Finally, screenshot time!


 User Rating: 1823   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

This is great and much needed since there have been so many "How do i's...".

PRAISE TO YAW!!!

 User Rating: 1737   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link



I've never had the time to look into API hooking in much detail, but I've always been curious how it actually worked. I shall be sure to have a look through your code as/when I get some time

Cheers!
Jack


Jack Hoxley [ Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]

 User Rating: 1947   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Niiiiiice, this is quality work. If I only had a dollar for each time I answered a "hooking" question, I would be a BAZILIONIONAIRE!!! Gotta love the tediousness of inheriting IDirect3DDevice9...there are only like 14 trillion member functions.


Dustin Franklin ( circlesoft :: KBase :: Mystic GD :: ApolloNL )

 User Rating: 1712   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by circlesoft
Niiiiiice, this is quality work. If I only had a dollar for each time I answered a "hooking" question, I would be a BAZILIONIONAIRE!!!

No need to be modest, we all know you already are!

Quote:
Gotta love the tediousness of inheriting IDirect3DDevice9...there are only like 14 trillion member functions.

Yes, seriously. I almost broke my fingers on this one.

 User Rating: 1823   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

I did something similar with IDirectPlay8Client. Took a while getting it to work but now i have nice send/recv sniffer for combat flight simulator 3 and all other games using directplay8client.



 User Rating: 746   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Wow, this is awesome. I intend to have some fun with this. I enjoyed hooking OpenGL and writing wallhacks for HL1 and its mods*. Let's see what I can do with this. And, kudos for typing out all those functions. There sure are a lot...

* Of course I don't play publically with the hacks. I rather happen to enjoy writing them, is all.

 User Rating: 1895   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

I'm wondering if there is some sort of image-analysis tool that can be built on top of this sort of technology.

If you could hook a commercial game and count the number of shaders used, number of passes, overdraw complexity and so on... would be an interesting thing to mess with if nothing else.

Make it work well and the hardware-nuts would love it - they spend enough time talking about clockspeeds and megahurtz that I'm sure they'll have good fun with a screenshot of the shader-complexity of a commercial game

Jack


Jack Hoxley [ Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]

 User Rating: 1947   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Quote:
Original post by jollyjeffers
I'm wondering if there is some sort of image-analysis tool that can be built on top of this sort of technology.

If you could hook a commercial game and count the number of shaders used, number of passes, overdraw complexity and so on... would be an interesting thing to mess with if nothing else.

Make it work well and the hardware-nuts would love it - they spend enough time talking about clockspeeds and megahurtz that I'm sure they'll have good fun with a screenshot of the shader-complexity of a commercial game

Jack

That would be quite easy...just hook into IDirect3DDevice9::SetVertexShader() and IDirect3DDevice9::SetPixelShader(). Then count up how many changes you have per frame. You can do *all* kinds of performance analysis like that.

p.s. IIRC the effect framework still uses Set*Shader() in its underlying implementation


Dustin Franklin ( circlesoft :: KBase :: Mystic GD :: ApolloNL )

 User Rating: 1712   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Maybe I'm missing something here, but isn't that exactly what PIX does?

 User Rating: 1895   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Wow! This is really cool!
You should make this an article =P

[Edited by - DirectXFreak on November 28, 2005 5:07:07 PM]

 User Rating: 1044   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by Promit
Maybe I'm missing something here, but isn't that exactly what PIX does?

D'oh...

I just tried that using PIX on GTA: San Andreas. Some sample stats:

DrawPrim............32
DrawIndexedPrim.....160
VB Locks............45
IB Locks............13
SetRenderState......163
SetTexture..........190
SetVertexShader.....6
SetPixelShader......0
SetRenderTarget.....12


Considering that this was a really simple scene (just inside the main characters house, very low complexity) I think those numbers are high.

 User Rating: 1712   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by Promit
Maybe I'm missing something here, but isn't that exactly what PIX does?

Yeah, essentially... I have to admit I haven't tried it, but you can't get PIX to generate an overdraw of the image, can you? deep pixel analysis yes, but not shader complexity and so on..?

The idea came from this thread. It'd be pretty awesome if you could somehow display the number of pixel shader arithmetic or texture instruction count per-pixel. Could make for a great performance debugging tool - the brighter the colours the more fill-rate related work you're doing etc...

Then again, hacking that in via hooking stands as much chance of breaking things as it does working

Oh, and the obvious advantage is that it'd be overlayed - giving immediate feedback rather than the capture full stream then analyse the data.

Jack


Jack Hoxley [ Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]

 User Rating: 1947   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Why might you need that many VB and IB locks per frame?
Was there a legendary particle system in the house or something?

------------------------------------
Development of Rock, Paper, Scissors - The Third Dimension

 User Rating: 1201   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by DrGUI
Why might you need that many VB and IB locks per frame?
Was there a legendary particle system in the house or something?


Yea, and this is inside a really simple house. I did some more investigating, and profiled a complex scene outside:

DIP Calls:  1300 - 2300 (:O !!!)
VB Locks: 120-145
IB Locks: 50-75

New VBs: 1-5
New IBs: 1-7

FPS: 10-20


Yea...so I wonder really what the frick is going on. Looks like someone at Rockstar needs to read the renown instancing slidedeck...


Dustin Franklin ( circlesoft :: KBase :: Mystic GD :: ApolloNL )

 User Rating: 1712   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

If I use that sample than AOE 3 hangs.
And nothing happened in COD 2.

 User Rating: 1025   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Oh my. This could be used for some serious hacking of applications. Really, you could trace exactly how the api is used - frankly I think it is pretty cool but I am surprised that MS allows this type of thing to be done.

I think I am going to try a few experiments with my own engine and see if this can be used for some type of runtime analysis of my rendering calls. Great work, I appreciate your effort (and typing abilities!).

Jason Zink :: DirectX MVP
"Intellectuals solve problems, geniuses prevent them." - Albert Einstein
Check out my game: Lunar Rift :: Dual-Paraboloid Mapping Article :: Parallax Occlusion Mapping Article :: Fast Silhouettes Article
Check out our free online D3D10 book: Programming Vertex, Geometry, and Pixel Shaders

 User Rating: 1505   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

Quote:
Original post by Jason Z
Oh my. This could be used for some serious hacking of applications. Really, you could trace exactly how the api is used - frankly I think it is pretty cool but I am surprised that MS allows this type of thing to be done.

I think so, since they full support the ultimate "hacking" application - PIX. PIX makes it easy to analyze exactly what an application is doing, D3D-wise. IMO, after doing some trials on commercial games, it is more helpful than the hooking approach for profiling.

 User Rating: 1712   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Holy Crap!

I just ran a test run of PIX on the latest build of my game. I tried using PIX long ago when it first came out and wasn't very impressed, but it has really evolved quite a bit from what I remember.

The object window alone is worth using, not to mention the frame rendering stream. So this will work with any D3D9 commercial application? I guess once you ship something you are essentially allowing everyone to see what you are doing - it kind of opens up the doors to smaller developers (like me!) to see what the big boys are doing.

Thats pretty cool.

Jason Zink :: DirectX MVP
"Intellectuals solve problems, geniuses prevent them." - Albert Einstein
Check out my game: Lunar Rift :: Dual-Paraboloid Mapping Article :: Parallax Occlusion Mapping Article :: Fast Silhouettes Article
Check out our free online D3D10 book: Programming Vertex, Geometry, and Pixel Shaders

 User Rating: 1505   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

Quote:
Original post by Jason Z
The object window alone is worth using, not to mention the frame rendering stream. So this will work with any D3D9 commercial application? I guess once you ship something you are essentially allowing everyone to see what you are doing - it kind of opens up the doors to smaller developers (like me!) to see what the big boys are doing.

Yea pretty much - they have worked on all commercial games I have tried it on (HL2, Farcry, GTA:SA). If you read a few posts above, I show some figures about GTA that are a little disturbing

 User Rating: 1712   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Hi there, thank you for this resource it should prove extremely useful however I have two questions if some one could please answer: (I am a beginner)

> Firstly when I download the sample files and run launcher.exe it says “usage: launcher filename” could some one just briefly interpret this describing how this application is used exactly. For example I have a game installed in my C:\ named abc.exe what is the command I would enter for the launcher to work and hook?

> Secondly can this method be used to interact with game textures for example changing them or recognising coordinates or does it simply draw directly above the game with no means of interaction?


Thank you.


 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by cykino
> Firstly when I download the sample files and run launcher.exe it says “usage: launcher filename” could some one just briefly interpret this describing how this application is used exactly. For example I have a game installed in my C:\ named abc.exe what is the command I would enter for the launcher to work and hook?

launcher abc.exe

Quote:
> Secondly can this method be used to interact with game textures for example changing them or recognising coordinates or does it simply draw directly above the game with no means of interaction?

You can do anything. I only demonstrated modifying the behavior of Present to draw a colored quad.

 User Rating: 1823   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Very cool man. Anyone know of a link that shows how do to these things in OpenGL as well?

 User Rating: 1464   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Ive tried to test this and I cannot seem to get it to work. I have no problems with the compilation. But when I launch Egyptian_Addiction.exe and then run Launcher.exe "Egyptian_Addiction.exe" nothing happens. Am I doing something in the wrong order?

EDIT: I read the OP just a little bit more and saw what I needed to do. It is working now.

Thanks,
Soul

[Edited by - DaSoul on January 21, 2006 11:34:37 AM]

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

The sample file is gone, NeXe is destroyed?! Doh!

I'm not back. I'm just visiting.

 User Rating: 1469   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link
Page:   1 2 »»
All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: