Log in

View Full Version : [D3D] some questions about game reversing


Silkut
April 23rd, 2007, 14:44
Hello all,

@admins: feel free to move this topic if it's location is not correct, I did read the FAQ, and I think no animals were hurt during this topic redaction.
Silver recommended me to post this publicly, to have more thoughts from pros and skilled reversers.


Since some days I started to think about D3D reverse in video game because a guy asked about what follows:
The original background is some korean MMORPG game, the Field Of View (FoV) is a bit too far (to his taste), making the game apparently lagging (I'm not telling this is exactly the cause of this issue). The idea was to modify the game to easily change this FoV (firstly to reduce it) as it isn't an option in settings. I wanted to help him and now, I'm more interested about the overall question.


So the guy started to seek variables responsible of FoV. He found one that apparently have a range value from 0 to 3. (I personnally didn't checked the code out). He tried to modify this value (with OllyDbg I guess) and then he found this modification didn't changed anything in the game.

The questions: Is the code integrity controled by routines ? Did the wanted modification was done on the right level (DX libraries, DX calls, variables..) ?

I contacted a friend who is game developper (note: he's not one of the korean game developpers, it was just to have his professional point of view), told the story and asked those questions.

He told about the patching that it was a very bad idea, in a first time because korean developpers surely implemented some home-made code integrity control, totally different from usual commercial apps hashes or checksums, to avoid cheat.
In a second time, the fact that the modification didn't worked is due to a lots of change in the matrix projection state with operations like LODs, etc... That sounds normal after all, that the patching failed if it's oftenly modified.

The gamedev believes in solving this problem by modifying the projection matrix on-the-fly when it's called, since it is responsible of far/near plane. That would make us able to do whatever we wants with the FoV. He told to look after lpD3DDevice->SetTransform().

Since the gamedev is not reverser, I asked Silver to give his advice, but clearly failed to properly present my problem as he misunderstood some details. He was not totally convinced about the tricks utility, though.

I would like your advice as it seems to be DX gurus out there (Maximus, Silver named you ). I lurked around and found piles of posts mentionning D3D, requiring Softice for easy debugging, also Silver's pure DX crackme about disassembled DX code aspect. I used to code with OpenGL and DirectX (samples and demo scenes, nothing very outstanding) but i'm not a pro reverser. The idea isn't to totally change the game, cheat on it or making my own omg-mmorpg-game. Just such introduction into D3D reversing and why not, exploring the rabbit hole. The home-made control is less interesting to my mind (particularly if I start reversing on a home-made DX app).

I hope this post is clear enough, don't hesitate to ask about details, I don't have the game code though, but every little DX game would be perfect I think. I'm still learning english, mistakes and typos must be common in my topic.

Regards.
Silkut~

omega_red
April 24th, 2007, 02:48
I'd say to start on some single-player game instead, since MMORPG clients are usually heavily protected from tampering (for obvious reasons). You may spend more time on circumventing the protections than your primary goal

Silver
April 24th, 2007, 04:32
To continue the discussion I'll just post my original reply to Silkut via pm:

Quote:
[Originally Posted by Silver]Hey Silkut. You should post this publicly, I think others would benefit as long as you don't name the target etc...

Quote:
the distance between the camera and the characters was so far it was making the game lagging, you know this issue right ?


Maybe. If there's a massively deep view frustum and the rear clip plane is miles away, AND (!) you have a low powered graphics card then yes, this might be the issue.

But it's just as likely that lag is caused by 10000 other issues. How did your friend figure out/decide the problem was this?


Quote:
As the gamedev said, it is due to a lots of changes in the matrix_proj state, like LOD, shading and lighting.


Hrm. That doesn't make sense - shading and lighting aren't directly relevant to the projection matrix.


Quote:
He believes (as i understood) that if we could change the matrix (responsible of far/near plane) on the fly when it's called, we could do everything we want.


Ok, he's talking about the projection matrix. It depends what you want to do, but I'm not convinced this will solve your problem. I think if the gamedev is telling you to do this to his own code then he knows something more about the problem than I do. It might help if you explain in detail...


Quote:
He also spoke about home made control unlike classic CRC32, that could explain the changes that didn't work


If I understand what you're saying, the coder added a checksum to his code and you think that's what stopped your patch from working?

I'm not sure, but I think it's more likely your patch did work but you didn't change the projection matrix correctly (or enough).


Quote:
My questions are, do you think that modify the matrix is a good idea


I think it's too hard for me to give you answers at the moment. I don't know enough about the problem or what you're trying to do to give you a proper answer.

Suggestion - why not repost this publicly, add more detail then we can get a decision going. Maximus seems to be a dx coder as well, he might be able to help...

Cheers!

Silkut
April 24th, 2007, 10:08
Hi, thanks omega_red. I already planed to practise on a home made DX app. Because the goal is only techniques about changing the FoV. I don't have the game anyway, it was more a starting point than a real target.

Any docs about that ? I'm currently on DXSDK documentation.

Maximus
April 28th, 2007, 07:18
Have you solved the problem, Silkut?
I do not think that altering the SetTransform() by itself can give you the result you need -you should better climb it for locating the far plane settings. This is because it might be called for various purposes -think to one of the nicest thing I ever seen (OGL), do you remember D3 'bathroom' where the mirror was exactly a rendered window?!

Silkut
April 28th, 2007, 11:34
Hello Maximus, thanks for the piece of advice.

I'm still on it, i'm looking for good samples to disass & study (started with DXbrowser sample but I'll check an old game without too much code protection, maybe deusex1).
I'll chase the far plane to see what happen then, the projection matrix was obviously the good direction, but not SetTransform().
Are you talking about this d3 scene ?
glideunderground.com/articles/doom3diary/img/bathroom.jpg
I only remember about the fact that I pretty pissed in my pant

I knew it was using GL rendering (some guys found GLSL after hacking it), did the DirectX requirement was only there for online xperience and i/o peripherals ?

EDIT: Hey, D3DXMatrixPerspectiveFov(LH|RH) could be the function to hack.
Code:
D3DXMATRIX * D3DXMatrixPerspectiveFovLH(
D3DXMATRIX * pOut,
FLOAT fovy,
FLOAT Aspect,
FLOAT zn,
FLOAT zf
);

Quote:

zn
[in] Z-value of the near view-plane.
zf
[in] Z-value of the far view-plane.


I had the bad surprise to fail launching the dx app under my VM that comes with sice ;'( I hope I can do without it. I'll try syser debugger.

Maximus
April 29th, 2007, 10:02
mmh... I tried syser time ago against DX applications to see how tough it was (a dx debugger fired on top of a DX application -I was delighted^^) but it didnt perform very well... however, it was 1.2 version, it was very unstable and bugged. I had to work much more to BSOD 1.5-6 so it's quite stable and, of course, it looks very neat
I am pretty curious to know how it works, keep informed.
edit----
ps: yep, that scene. I dont like playing 1st person shoot'em up, but I am a Carmak 'fan' from Wold3d times, which ran cool on my iAPX386sx 16Mhz

Silkut
July 4th, 2007, 11:38
Hi,
I recently progressed a bit about my quest of DirectX 9 reversing knowledge.

Fullscreen applications are painfull to debug because it freezes. As TheColonialน clearly explained in his tutorial concerning Silver's DX crackmeฒ we need to patch them. By studying the DirectX API structure and statically analyzing the application we can hunt the precious windowed flag and activate it (while deactivating the refreshRate flag as suggested in the MSDN articleณ).

In the same way we can study the math function I named in my last post, D3DXMatrixPerspectiveFov(LH|RH). I used a DirectX SDK example, so I had the debugging symbols to help with IDA. The two lasts parameters are defining the clipping plane. It tells where objects starts to be rendered and were they're no longer rendered due to the distance.

Quote:
D3DXMatrixPerspectiveFovLH

Builds a left-handed perspective projection matrix based on a field of view.
D3DXMATRIX * D3DXMatrixPerspectiveFovLH(
D3DXMATRIX * pOut,
FLOAT fovy,
FLOAT Aspect,
FLOAT zn,
FLOAT zf
);
Parameters
pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
fovy
[in] Field of view in the y direction, in radians.
Aspect
[in] Aspect ratio, defined as view space width divided by height.
zn
[in] Z-value of the near view-plane.
zf
[in] Z-value of the far view-plane.


I started to seek.
In the function window
Code:
0040B138 D3DXMatrixPerspectiveFovLH d3dx9_33


leading me to the data section
Code:
data:0040B138 ; __declspec(dllimport) __stdcall D3DXMatrixPerspectiveFovLH(x, x, x, x, x)
.idata:0040B138 extrn __imp__D3DXMatrixPerspectiveFovLH@20:dword
.idata:0040B138 ; DATA XREF: D3DXMatrixPerspectiveFovLH(x,x,x,x,x)r


Xrefs to this function
Code:
Up p SetupMatrices+F5 call _D3DXMatrixPerspectiveFovLH@20; D3DXMatrixPerspectiveFovLH(x,x,x,x,x)


And here we are, the code.
Code:

0040126D fld ds:__real@42c80000 ; load zf (far view plane)
.text:00401273 sub esp, 10h
.text:00401276 fstp [esp+130h+var_124]
.text:0040127A lea eax, [esp+130h+var_70]
.text:00401281 fld1 ; load original zn (near view plane)
.text:00401283 fst [esp+130h+var_128]
.text:00401287 fstp [esp+130h+var_12C]
.text:0040128B fld ds:__real@3f490fdb ; load aspect ratio
.text:00401291 fstp [esp+130h+var_130]
.text:00401294 push eax
.text:00401295 call _D3DXMatrixPerspectiveFovLH@20 ; D3DXMatrixPerspectiveFovLH(x,x,x,x,x)



According to the Intel Instruction Manual FLD is loading a floating point value, it helped a lot to figure that they were loading interesting things.
Since this application is already windowed I can debug it without display problems (and since i'm not familiar with IDA I debugged with Olly, erm..).

Code:
DS:[0040B1A8]=100.0000 // zf value

Code:
DS:[0040B1A4]=50.00000 // zn value


So we can see that objects draw before 50.0f are not displayed, and those after 100.0f are too far to be displayed (referring to some viewing logic).
NOTE: The usual value of zn is 1.0f but then it is not displayed as is into Olly, I modified it to be sure it was the right instruction.

It is without surprise the value attributed to zf we can see in the DXSDK sample cpp source, With Olly I'm able to modify it while debugging (and it runs fine). But how to modify it permanantly ? I see the FLD instruction refers to an address. Advices welcome there.

Okay, I took some example coming with the sources to easily figure out where to search. I'm now focusing on some commercial app (i.e. game) but I'm afraid I can't use an old game because I only know DirectX9, on the other side if the game comes with too much protection I'll dive into this instead pure DX stuff.

I think i'll go deeper.

[น] http://crackmes.de/users/silver/silvers_dx_crackme_1/solution/thecolonial
[ฒ] http://crackmes.de/users/silver/silvers_dx_crackme_1/
[ณ] http://msdn2.microsoft.com/en-us/library/bb172588.aspx

Silver
July 4th, 2007, 12:18
Quote:
I used a DirectX SDK example, so I had the debugging symbols to help with IDA


This isn't necessarily a good idea. The DX SDK samples use an object oriented framework, kind of like how MFC is an OO framework for win32. That means the samples are, quite frankly, full of crap code and setup you don't need.

You'll find using the samples will make life a lot harder than it should be for you. Can I suggest you google DirectX tutorials, grab some sample code that DOESN'T use the framework, compile that in debug and use those symbols instead? It will make your life easier.


Quote:
ut I'm afraid I can't use an old game because I only know DirectX9, on the other side if the game comes with too much protection I'll dive into this instead pure DX stuff.


Apart from shader setup and some technicalities, if you can understand D3D8 you can understand D3D9, and vice versa. DX7 and older, however, is a different kettle of fish.

<pedant>Also, please use D3D9 when you mean the 3D API part of DirectX 9. Most of the time it's obvious what you mean, but saying DirectX when you mean D3D (or DSound, DDraw etc) is like saying "I have a problem with formatting in Microsoft Office!". It'll save any confusion.<pedant>

Quote:
So we can see that objects draw before 50.0f are not displayed, and those after 100.0f are too far to be displayed (referring to some viewing logic)......< ... > But how to modify it permanantly


Probably the viewing frustum/clip planes, so look for the initial setup code. Hint: these figures are totally arbitrary and are relative to the camera position. Don't get too hung up on them. Have a look at IDirect3DDevice9::SetTransform().

(Note, I'm only guessing here, I didn't have time to study your code in detail, plus I suck at DirectX coding anyway )

blurcode
July 4th, 2007, 20:09
The following tool may be helpfull for debugging directx applications:
http://rapidshare.com/files/41067167/DXWnd.rar.html

Silkut
July 5th, 2007, 04:58
Hey,

@blurcode, Thanks for the tool. It is easier to use this than patching the windowed flag and the refreshRate flag as explained by TheColonial.

@Silver, I don't understand how the framework (I only see the object-oriented style ?!) is making things more difficult. I took the D3D9 tutorial 3 named Matrices. I compiled it with Visual Studio 8 both on Debug and Release. I also noticed that on debug it was full of crap, so I only used in the post above the release version. Since it is freshly compiled it's coming with an IDB file that IDA immediatly recognized. I used that to start.

You're right concerning D3D9 and DirectX 9, I was aware about the difference but forgot it at the moment, sorry.

Quote:
[...]Have a look at IDirect3DDevice9::SetTransform()[...]

I will certainly, but I was more focused on D3D9MatrixPerspectiveFov since Maximus said above SetTransform was not too much interesting in my case.

To sum up, I was looking for the function that could change the Fov because someone asked about how to change the FoV params. And permanant modification apart, I found it. Now I think I'll go deeper, or lurking around for interesting D3D functions, not sure yet. Maybe starting with a game. As you said D3D8 is not so different from D3D9, but the problem is I only have D3D7 and D3D9 games installed there.
This project is leading me to some D3D reverse knowledge, no particular goals at the moment.

Anyway I thank you for your advice and interest which are helpful, maybe Maximus will add interesting things.

Regards,
Silkut

dELTA
July 5th, 2007, 10:16
Let's save the tool here for archival reasons (renamed to .zip because I'm too lazy to change that board config setting ).

Interesting stuff as usual guys!

Silver
July 5th, 2007, 11:43
Quote:
I will certainly, but I was more focused on D3D9MatrixPerspectiveFov since Maximus said above SetTransform was not too much interesting in my case.


Yes, I think both Maximus and I were getting at the same thing. SetTransform just applies the transformation matrix - I was indicating that finding this call will give you a ptr to the location of the matrix, which you can then follow back to see where it's constructed. Maximus was also saying you need to go to where the matrix is constructed.

The reason I suggested using/following SetTransform rather than the D3DX utility functions that build matrices is because (a) the code doesn't have to use the D3DX utility function, it's easy to build the matrix yourself "manually", and (b) the D3DX calls could be used to set up any number of matrices that can be used at any arbitrary point as needed, whereas you can guarantee you're looking at the right matrix when it's a SetTransform parameter.

Quote:
I don't understand how the framework (I only see the object-oriented style ?!) is making things more difficult


Purely because the framework places certain restrictions on D3D setup and operation, and how code is structured. It leads to things being done in an odd order and a lot of extra code being linked in. Extra code = more unnecessary complication.

Maximus
July 6th, 2007, 08:02
Yes, i totally agree with Silver.
I can add very little to Silver's suggestions, as I were an 'hobbyst' at D3DIM, whereas he must have run mad a whole lot more with lost surfaces et similia

(@Silver: when will you release a shader's cm? )

Silver
July 6th, 2007, 08:24
Quote:
(@Silver: when will you release a shader's cm? )


I'm worried about giving people ideas on this . You gave me another idea too - just think, shader cm using non-managed surfaces to store data. As soon as you break the code with a debugger, the *hardware* dumps the surface due to lost device. Ouch. Bye bye any stored data.

Maximus
July 6th, 2007, 08:28
...@admins: place an EULA permission to read this thread to crackers only!!

EVIL

Silkut
November 30th, 2007, 17:40
I wrote a little thing that sum up what was previously said, plus some interesting things I discovered. It is only in french at the moment, just notice almost everything said in the file is available on this thread in english.
Thanks to Squallsurf and TiGa for last minute review.

http://navilinux.free.fr/rce/d3drce_silkut.pdf

I had good echoes until now, it's not perfect though.

dELTA
November 30th, 2007, 18:49
Nice work (even though I don't speak/read French). Distilling and archiving of interesting threads is always a good way to use and preserve the valuable knowledge discussed on messageboards.

Maximus
December 1st, 2007, 07:06
Nice!

My french is... not much better than Delta's one -well, maybe a little- and it seems a good work for what I am able to understand.

Congratulations, and keep writing, RCE needs it

TiGa
December 1st, 2007, 11:27
Who would have ever guessed that speaking French would be useful on the Internet one day?

Continues le bon travail Silkut, c'est tr่s int้ressant!

TiGa

JMI
December 1st, 2007, 11:31
d'accord!

Regards,

Silver
December 1st, 2007, 11:42
My French is also barely passable, but I could understand enough to get the gist of your PDF. Great work, well done for creating the pdf!