Swoorup Posted October 4, 2011 Share Posted October 4, 2011 (edited) I found your how the bit change when pressing the F5 key. I am thinking that if the parameter are of small size they are passed directly. Whereas large data are pushed onto the stack. Is this true? Secondly, this one is for my mod. I found the opcode which keeps passing value to the minute variable on every game minute. So I want to put my hook here so that my function gets accessed whenever a game minute is changed. How can I do that sir, If I dont want to replace the opcode as that would cause the game minute not to be displayed or stopped or else the game would crash. How would I place the hook without destroying the original functions. I saw that both Squiddy's and yours change the code itself! Anyways Thank you so much for helping! I will be putting all of my learning in the upcoming mod ECS. I owe you alot!! Edited October 4, 2011 by Swoorup Link to comment Share on other sites More sharing options...
K^2 Posted October 4, 2011 Share Posted October 4, 2011 Squiddy's code tries to preserve original functionality while adding a hook, but you have to be very careful with that. One of the functions he ended up having patched to make sure it still works. Basically, you have to get down to assembly level, look at the code of the original function, and look for a good place to add your own code. It's a pain, and there is no universal way of doing this. Ok, in general, there are three ways of passing parameters to a function. 1) Push them onto stack. 2) Set registers. 3) Allocate some memory for parameters and pass address to that memory by either 1 or 2. There is a reason why C/C++ compilers usually chose method 1 unless asked specifically for an alternative. Lets take a very simple function and take it apart command by command. int add(int x, int y){int c;c=x+y;return c;} Compiles to this. 004012D0 /$ 55 PUSH EBP004012D1 |. 89E5 MOV EBP,ESP004012D3 |. 83EC 04 SUB ESP,4004012D6 |. 8B45 0C MOV EAX,DWORD PTR SS:[EBP+C]004012D9 |. 0345 08 ADD EAX,DWORD PTR SS:[EBP+8]004012DC |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX004012DF |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]004012E2 |. C9 LEAVE004012E3 \. C3 RETN The first two instructions are a classic prologue. It's useful to recognize this, because almost any function entry point will have these two instructions. Hopefully, you'll see why in a moment. Lets start with the call, though. Suppose, I want to add numbers 2 and 3. I will first push 3, then push 2, and finally call add(). The call instruction itself pushes one more value onto the stack, which is the return address. When you issue RETN instruction, that address will be used to go back and execute the next instruction after the CALL that started the function in the first place. So when the function is called, the stack looks something like this from top to bottom. [return_address, 2, 3]. Each one is 4 bytes. The ESP register contains a pointer that points to the top element in the stack. So at this very moment at address SS:[ESP] you'll find return_address. What does the prologue do? Well, first instruction pushes EBP onto the stack. Reason for that should also become clear in a moment. So the stack is now [old_EBP, return_address, 2, 3], and ESP points to old_EBP. Second instruction of prologue moves current ESP value to EBP. So now EBP points to old_EBP. Consequently, EBP+4 points to return_address, EBP+8 to 2, and EBP+12 to 3. Third instruction in the function is also very typical. It sets up room for local variables. Yes! These also go onto the stack. The instruction simply subtracts 4 from ESP, giving you 4 bytes of space. This is the stack now. [___ , old_EBP, return_address, 2, 3] The blank space doesn't contain anything yet. Notice that EBP still points to old_EBP. In fact, no matter what we do with ESP from now on, EBP will remain there for the duration of the function. Next 3 lines are what this function is all about and why all of the above work was necessary. MOV EAX,DWORD PTR SS:[EBP+C] Take value at EBP+12 and store it in EAX, so we just moved 3 to EAX. ADD EAX,DWORD PTR SS:[EBP+8] Add value from EBP+8 and add it to the EAX. EAX now contains 2+3=5. MOV DWORD PTR SS:[EBP-4],EAX Take EAX and store its value at EBP-4. What's at EBP-4? Well, that's the blank space that was left right after the prologue. The next line is redundant in this particular function. This is due to lack of optimization in the compiler. We move the value we got in the blank space back to EAX. (Why? Because return value is usually passed through EAX.) Finally, the epilogue. This particular compiler (MinGW g++) produced the C9 instruction, LEAVE. This is actually a shorthand fro two instructions that follow. In more classical Assembly programming they are stated explicitly. (Partly because some old CPUs executed LEAVE slower than the expanded version.) This is the equivalent. MOV ESP, EBPPOP EBP This is basically the exact reversal of the prologue. First instruction points ESP at old_EBP on the stack. Second instruction pops that value. So EBP is now old_EBP, and ESP is advanced to point at return_address. Finally, RETN is executed. That instruction pops a value from ESP, which is return_address, and sends the program to that location. Ok, why did I bother going through all this in such detail? Several points. First, about the variables. When you are coding a function, you have two types of named variables. Variables that were passed as parameters and variables that were declared locally. (You also have globals, etc, but lets forget about added complexity for a moment.) When you are programming, you don't really distinguish between the two types. You use them in expressions the same way. Well, the compiler does basically the same thing. Each named variable has an address associated with. Since both parameters and local variables reside on the stack, these are all stack addresses. Furthermore, they are all addresses relative to EBP. In this example, you have the following variables: x: EBP+8 y: EBP+12 c: EBP-4 Hidden in there are two unnamed variables at EBP and EBP-4. You can access these, and that's basically how buffer overflow attacks work, but that's rarely practical from programming perspective. So what this really does for you is makes the values that were passed as parameters persist as variables with constant address. If you were to pass in parameters as register values, you wouldn't be able to use these registers until you unloaded off the parameters in some temporary storage, which would probably end up on the stack anyways. Passing them on the stack already saves you the trouble. Of course, when you're writing the program in assembly and you are going for optimization, a simple function like above could be written completely differently. Consider this implementation that does exactly the same thing. ADD EAX, EBXRETN And instead of MOV EAX, aPUSH EAXMOV EAX, bPUSH EAXCALL add complete the call like this. MOV EAX, aMOV EBX, bCALL add You've just made this function call run about ten times faster. And some compilers will do this optimization for you, among many other useful tricks to speed things up. But this comes at the price of complexity in the compiler, making functions that much harder to identify during debugging, and making your code extremely platform-specific. Sometimes it's worth the trouble. Generally, it is not. I hope that helps clear up a few things. Prior to filing a bug against any of my code, please consider this response to common concerns. Link to comment Share on other sites More sharing options...
Swoorup Posted October 5, 2011 Share Posted October 5, 2011 Thank you a lot sir. This is helping me very much. Take a look at 57D5B5 and 57D5BF. They are the same, Can I patch one of them to call my function? Also I change 57D5A3, and both of above to all NOP. It created a bizzare atmosphere and extreme thunder which will strike the player and even flip his car throwing him at a very large distance. Link to comment Share on other sites More sharing options...
K^2 Posted October 5, 2011 Share Posted October 5, 2011 It's part of floating point computation. You'd mess up whatever algebra is going on. What you might be able to do is move part of that computation to your own code, but then you need to first figure out what exactly that code does compute. Because floating point computations ran on a co-processor traditionally, they are not as straight forward in x86 architecture as integer ones, so that might not be the best choice. But if you can sort through it, then that works. Prior to filing a bug against any of my code, please consider this response to common concerns. Link to comment Share on other sites More sharing options...
Swoorup Posted October 5, 2011 Share Posted October 5, 2011 (edited) Call we write them directly? Suppose I replaced it with a Call display function of Squiddy's then, in Call display function Can I do this: Display Functions:flmult dword ptr[.....] Start Squidy's Functions Edited October 5, 2011 by Swoorup Link to comment Share on other sites More sharing options...
K^2 Posted October 5, 2011 Share Posted October 5, 2011 This should work as long as you don't perform ANY floating point computations in your code. If you do, you'll mess up the floating point registers, and operation in original code will still be incomplete. Also, notice that you are replacing a group of 6 bytes with 5 bytes. You'll want to use Squiddy's original form of the ChangeFunctionCall and pass 1 as the parameter for number of NOPs you want. Prior to filing a bug against any of my code, please consider this response to common concerns. Link to comment Share on other sites More sharing options...
Swoorup Posted October 5, 2011 Share Posted October 5, 2011 Okay after a hour of searching I found out that it can be done by storing the register values at a stack before and then at the end of function we can reload the stack values to the register and then place the replaced opcode. But my question is which code in C++ can write an ASM or byte code at the end of the functions? Wow, I have not know anything before two weeks anything about C or ASM, Now I have learnt so much! Thanks for all your words Link to comment Share on other sites More sharing options...
K^2 Posted October 5, 2011 Share Posted October 5, 2011 You can add assembly instructions straight to your C/C++ function. It works a little differently depending on compiler. In VC++, you simply prefix the line with __asm. Prior to filing a bug against any of my code, please consider this response to common concerns. Link to comment Share on other sites More sharing options...
Swoorup Posted October 5, 2011 Share Posted October 5, 2011 (edited) I managed to reduced Squiddy's code vastly to just display a simple text. I also changed the hooking procedure and deleted the patch! But I get errors in compiling the Display function. Especially the asm opcode! void Display(){gFont->PrintString(160.0f, 166.0f, "This is a test only");_asm{fmul dword ptr [0069A0B8h]}} It gives improper operand. I saw the ASM declaration from elsewhere which would compile in VS 2010, but its just not compiling! The hooking procedure: ChangeFunctionCall(0x57D5BF, (DWORD)&Display, 1); //ChangeFunctionCall(0x5FA0D8, (DWORD)&Display, 0); //BYTE jmp[] = { 0xEB, 0x15 }; //PatchCode(0x5FA0DD, 2, (void*)jmp) Again thank you! EDIT: I got it working by doing this _asm{ mov eax, 0069A0B8h fmul dword ptr [eax]} I dont know what effect it would do or why it does work. But it looks that value of eax will be replaced again as it is local. Thank you so much sir, for the every help you gave it to me. It was just yesterday I took my first step on hooking! Edited October 5, 2011 by Swoorup Link to comment Share on other sites More sharing options...
K^2 Posted October 5, 2011 Share Posted October 5, 2011 It's odd, but if it works, run with it. What are you writing, anyways? Prior to filing a bug against any of my code, please consider this response to common concerns. Link to comment Share on other sites More sharing options...
Swoorup Posted October 6, 2011 Share Posted October 6, 2011 I have to do a lot of hacks for the Vice city for the ECS mod. The mod is public for discussion so I am gonna explain my problems sir.: Firstly we are combining Vice City and Liberty City in the mod where the game will be set in 1993 incorporating huge changes in both the cities with a way R* could have made. Apart from the story line and setting we planned to make VC directly above LC floating in the air. It was done due a limitation which no one was able to hack: the Paths Spawn area(Spawning them outside original bounds is almost impossible), though the path node limit has already been hacked. Also to go with our plan, we need physical and visual water at both of the cities along with the helicopter height limit(How much can the helicopter go up), so I did the dynamic water hack by just editing the memory address of water level but there seems to be some problem with the visual water. Also the same thing was done for the helicopter height limit at both the cities. Currently, one cannot view Vice city just by looking at the sky , That was solved by Almost610 by simply editing some flags of IDE lines and placing a zon over there. Most of the physical problems we have faced that would cause the development to be halted have been solved already. I was doing all the solutions in VB.net via writeprocessmemory! Now I will be coding them in C++. There are still some left to do hack. They are: i. Visual water level for Vice City ,its just not showing up(Currently we are using our own textures for it). ii. Hack the radar by loading a set of Vice city radar textures and Liberty City radar texture dynamically ( I am not sure but I think it can be achieved by reloading the functions which load the radar) iii. Menu map ( I have thought the same solution like the radar) iv. HUD ( I need to learn programming with DirectX first) Link to comment Share on other sites More sharing options...
K^2 Posted October 6, 2011 Share Posted October 6, 2011 Might be easier to write your own radar and map and render them via custom DirectX code. People have done DirectX hooks for Vice for a long time, so it shouldn't be too much of a problem. By far the simplest solution would be to write your own d3d8.dll. I recall somebody mentioning that this hack does work for Vice. Of course, you need to understand D3D8 programming first, but if you need it for HUD anyways, you might as well. Once you intercepted renderer with custom d3d8.dll, it also resolves many of your headaches. For one thing, you'll actually get a call every time VC engine goes to render a frame, so any per-frame operations can be done there. You even get a choice to go for pre-frame or post-frame processing. You can also render your own geometry. If you really want, you can render completely custom water with any dx8 effects you want. Hell, you could write your own renderer with DX11 effects if you want, but that would be a lot of work. Point is, DirectX is probably your next step. And it will definitely be useful for you in many other projects. I know I have an empty custom d3d9 code sitting somewhere. Let me see if I have one for d3d8 as well. Prior to filing a bug against any of my code, please consider this response to common concerns. Link to comment Share on other sites More sharing options...
Swoorup Posted October 6, 2011 Share Posted October 6, 2011 I had it in my mind too. But it turns out to be too much work and learning too. I have to make the radar in a way it gets rendered above the 3D game world and below the icons and markers which the normal radar would consist of. Also more to that I would have to learn how the player velocity's affect the radar as it zooms in and out. Currently, I am just in-fact predicting the time it would take. Can this be done by placing the radar hook in a loop in between the one rendering the world and the other rendering the markers and icons simply? I thought it would take a very long time. So temporarily I would perhaps just disable the radar only. Thank you sir, I think now that's how ENB works too by injecting or either intercepting the post and the pre-fames? Sir, if you have them please do submit it, I had been looking on Squiddy's HUD code to learn how it works, but I could not even compile it. If I could compile and learn how it hooks, I think I would start DirectX programming by playing with it and also correct its major problems! Thank you sir, for each and every info you have given. You are full of wisedom! Link to comment Share on other sites More sharing options...
K^2 Posted October 6, 2011 Share Posted October 6, 2011 With custom d3d8.dll you'd have a great amount of control over how things are rendered. Most games will switch from 3D rendering to 2D rendering by changing projection matrix. You can monitor calls that set projection matrix, and use that to tell you when the game's done rendering 3D stuff. But I was thinking more of disabling game's HUD all together, including the radar, and custom-rendering everything. You should be able to get active markers from game's script. Then you can zoom the radar and display markings in any way you wish. You can even add some really creative additions, like 3D map on the radar, GPS navigation, etc. Advance programming, all that, but there is no reason why you can't add to it as you go along. I'm looking at squiddy's code now. What he wrote for d3d8 intercept is exactly what you need. I'd seriously recommend getting his permission to use his code as a base. It will save you a ton of trouble. As far as compiling it, you might need to have DirectX SDK installed. I'll try compiling it a bit later and see if I can come up with some advice on that. Prior to filing a bug against any of my code, please consider this response to common concerns. Link to comment Share on other sites More sharing options...
Swoorup Posted October 6, 2011 Share Posted October 6, 2011 Did you compile it successfully sir? I am currently downloading the SDK. I will have a look at it. But I am running to this problem at function pointer declaration: void (*Render2DStuffptr)()=0x4A6190; No matter whatever I try I keep failing. I looked for several tutorials and non of them have declared like this. Its a direct extract from what you have told earlier. The error states that value of type "int" cannot be used to initialize an entity of type "void (*) ()" Its a void function with no parameters passed to it. I have read through the whole forum about D3D and there are things that are may be fully documented! Link to comment Share on other sites More sharing options...
K^2 Posted October 6, 2011 Share Posted October 6, 2011 The error states correctly. I'm not entirely sure how it slipped by squiddy's compiler. Try this: void (*Render2DStuffptr)(void)=(void(*)(void))0x4A6190; Prior to filing a bug against any of my code, please consider this response to common concerns. Link to comment Share on other sites More sharing options...
Swoorup Posted October 6, 2011 Share Posted October 6, 2011 (edited) Wow, It does not gives any error now. I still have to compile and test it soon. I will get back to you!!! Thank you sir! EDIT: I was not able to display the hack I get crashes every time. Squiddy has converted the printstring parameter from unicode to char. How did he do so? I made the ASI which also includes floating point computation! Also the ASM code works beautifully, though I have used floating point computations, it didnot affect anything sir I download the SDK. There are C headers and cpp files over there. But I cant install the SDK. It always gives me an error. BTW its Directx9.0c summer update SDK. It includes all the needed files that the HUD source has requested but I just cant install from the installer EDIT EDIT: I linked the Directx files with VS 2010 but I could not get it to work. Still it produces about 10-15 errors that I find hard to debug though. Then I had a copy of VS 6.0 because my college used to teach me VB 6.0 and then I linked all the DX files and it worked! But Still dont know how to give a start! Edited October 7, 2011 by Swoorup Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now