This is a pretty easy way to reverse console commands. And since it's modifying the .data section of the game code it should be 100% undetected. (Unless VAC start doing CVAR consistency checks)
NOTE: BY FOLLOWING THIS TUTORIAL YOU ARE AGREEING TO POST EVERY SINGLE ADDRESS YOU FIND. OR FACE TEH LAW. Lols not really. But it would be great and very kind of you if you could. I'll rep you for it
Apps used.
1. L.Spiro's Memory Hacking Software. HERE
2. OllyDBG HERE
3. A compiler HERE
First things first, as there is no console you need to use your own way to send commands to the game. Like this..
As most commands are cheat protected you need to remove that protection. There are 2 you need to remove.
"%s cannot be changed"
006461F1 |. 74 47 JE SHORT 172_iw4m.0064623A
To
006461F1 |. EB 47 JMP SHORT 172_iw4m.0064623A
In C++ that would be:
Code:
Assign key
Patch protections
Do command
Unpatch protections
Then to set it back to normal do the same
if(GetAsyncKeyState(VK_F1)&1) //sets fog off
{
WriteProcessMemory(GetCurrentProcess(),(void*)0x0064600B,(PBYTE)"\x00",1,0);
WriteProcessMemory(GetCurrentProcess(),(void*)0x006461F1,(PBYTE)"\xEB",1,0);
SendCommandToConsole(1,1,"r_fog 0");
WriteProcessMemory(GetCurrentProcess(),(void*)0x6461F1,(PBYTE)"\x74",1,0);
WriteProcessMemory(GetCurrentProcess(),(void*)0x64600B,(PBYTE)"\x01",1,0);
}
if(GetAsyncKeyState(VK_F2)&1) //sets fog on
{
WriteProcessMemory(GetCurrentProcess(),(void*)0x0064600B,(PBYTE)"\x00",1,0);
WriteProcessMemory(GetCurrentProcess(),(void*)0x006461F1,(PBYTE)"\xEB",1,0);
SendCommandToConsole(1,1,"r_fog 1");
WriteProcessMemory(GetCurrentProcess(),(void*)0x6461F1,(PBYTE)"\x74",1,0);
WriteProcessMemory(GetCurrentProcess(),(void*)0x64600B,(PBYTE)"\x01",1,0);
}
Compile that in a DLL and start MW2. Then also start up MHS and file > open process and attach it to iw4mp.exe
Go into a PRIVATE SERVER!!! then go back into MHS. Press the first magnifying glass under found addresses. Make sure the data type is Byte and the value is 1. Press OK.
Go back into MW2 and press F1 (Setting the fog to 0)
Go back into MHS and this time press the button with the 2 magnifying glasses (the second one) make sure the value to find is 0 and search type is Exact Value.
Then go back to MW2 and press F2 (Setting the fog to 1)
Go back into MHS and do the same as before but this time set the value to find to 1.
Repeat this over and over until you're left with just a few values. If one of them is 064xxxx0 then you've found what you're looking for. There should be 2 ALWAYS take the first which should be -10 bytes from the second one. If there is more than 2 add them all to the right window. If there is way more than than 2 or so keep searching.
Right click the value you have on the right and click modify selected enter 0 as your "Cur Value" and click OK.
Go back to MW2 and see if the fog has gone. If so then you have found the address you need. YAY
To use those addresses in a C++ project do this
Code:
*(__int8*)0xaddress = 0; //rfog 0
Code:
*(__int8*)0xaddress = 1; //rfog 1
That's it really. Some commands are 4 bytes long and some are floats. Up to you to figure it out. Basically if you are able to set a value to higher than 255 it's not 1 byte long.
Also before anyone comments on why I patch the cvar protections then unpatch them straight after sending the command it's because i'm unsure if VAC is enabled in private servers. Also Steam complains when changing servers if any of the .code memory is edited.
Good work dave! Think this would fit into the topic. If not move it into a new thread pls.
I've tried finding a sig to access some cvars dynamically cause of the stupid updates.
Therefore i put a memory bp on access at the cvars address e.G. 640AF40 for forceLaserOn
After i fired up ida and searched for the value 7D8A50. Following came up
Code:
.text:00445870 push offset aForceLaserSigh ; "Force laser sights on in all possible p"...
.text:00445875 push 4
.text:00445877 push 0
.text:00445879 push offset aLaserforceon ; "laserForceOn"
.text:0044587E call sub_4DCBB0
.text:00445883 fld ds:flt_724CEC
.text:00445889 add esp, 10h
.text:0044588C push offset aTheMaximumRang ; "The maximum range of a laser beam"
.text:00445891 push 4 ; int
.text:00445893 sub esp, 0Ch
.text:00445896 fstp [esp+14h+var_C]
.text:0044589A mov dword_7D8A50, eax <- here
If we put a nicely signature on the track we could access our cvar as long as the signature fits.
Havnt tried it yet due i am limited @ time atm but wouldnt that method even work after an gameupdate?
Could somebody updload an old version of the iw4mp.exe so i can have a look if the cvar addresses are
accessed through the same way?
Here are some other researches
Code:
//r_fog 64010D0 is the addy
0054F84E 8B15 5CDB9E06 MOV EDX,DWORD PTR DS:[69EDB5C] ; iw4mp.06401DE0
0054F854 807A 10 00 CMP BYTE PTR DS:[EDX+10],0
.text:005116D0 sub esp, 18h
.text:005116D3 movzx ecx, word ptr [ecx]
.text:005116D6 mov edx, [esp+18h+arg_0]
.text:005116DA push ebx
.text:005116DB push ebp
.text:005116DC push esi
.text:005116DD mov esi, dword_69EDB5C <- here
//conMinicon 6406490 is the addy
0043000B 8B15 ACA37E00 MOV EDX,DWORD PTR DS:[7EA3AC] ; iw4mp.06406480
00430011 807A 10 00 CMP BYTE PTR DS:[EDX+10],0
.text:00419A1A push 0
.text:00419A1C push 0
.text:00419A1E mov dword_9F8E78, eax
.text:00419A23 push offset aCon_minicon ; "con_minicon"
.text:00419A28 call sub_4DCBB0
.text:00419A2D fld ds:flt_724CEC
.text:00419A33 add esp, 40h
.text:00419A36 push offset aTheMinimumTime ; "The minimum time that the subtitles are"...
.text:00419A3B push 1 ; int
.text:00419A3D sub esp, 0Ch
.text:00419A40 fstp [esp+14h+var_C]
.text:00419A44 mov dword_7EA3AC, eax <- here
//drawfriendlytagsthruwalls 6406C60 is the addy
004B953C A1 2CA19B01 MOV EAX,DWORD PTR DS:[19BA12C]
004B9544 8078 10 00 CMP BYTE PTR DS:[EAX+10],0
.text:00496110 mov eax, dword_19BA12C <- here
.text:00496115 cmp byte ptr [eax+10h], 0
.text:00496119 push esi
.text:0049611A mov esi, [esp+4+arg_0]
.text:0049611E jz short loc_496147
.text:00496120 mov ecx, [esi+158h]
.text:00496126 mov edx, dword_1A80054
.text:0049612C mov [ecx+314Ch], edx
.text:00496132 mov eax, [esi+158h]
.text:00496138 add eax, 314Ch
__________________
“For every complex problem, there is an answer that is short, simple and wrong.”
“Pessimism is safe, but optimism is a lot faster!”
Good work dave! Think this would fit into the topic. If not move it into a new thread pls.
I've tried finding a sig to access some cvars dynamically cause of the stupid updates.
Therefore i put a memory bp on access at the cvars address e.G. 640AF40 for forceLaserOn
After i fired up ida and searched for the value 7D8A50. Following came up
Code:
.text:00445870 push offset aForceLaserSigh ; "Force laser sights on in all possible p"...
.text:00445875 push 4
.text:00445877 push 0
.text:00445879 push offset aLaserforceon ; "laserForceOn"
.text:0044587E call sub_4DCBB0
.text:00445883 fld ds:flt_724CEC
.text:00445889 add esp, 10h
.text:0044588C push offset aTheMaximumRang ; "The maximum range of a laser beam"
.text:00445891 push 4 ; int
.text:00445893 sub esp, 0Ch
.text:00445896 fstp [esp+14h+var_C]
.text:0044589A mov dword_7D8A50, eax <- here
If we put a nicely signature on the track we could access our cvar as long as the signature fits.
Havnt tried it yet due i am limited @ time atm but wouldnt that method even work after an gameupdate?
Could somebody updload an old version of the iw4mp.exe so i can have a look if the cvar addresses are
accessed through the same way?
Here are some other researches
Code:
//r_fog 64010D0 is the addy
0054F84E 8B15 5CDB9E06 MOV EDX,DWORD PTR DS:[69EDB5C] ; iw4mp.06401DE0
0054F854 807A 10 00 CMP BYTE PTR DS:[EDX+10],0
.text:005116D0 sub esp, 18h
.text:005116D3 movzx ecx, word ptr [ecx]
.text:005116D6 mov edx, [esp+18h+arg_0]
.text:005116DA push ebx
.text:005116DB push ebp
.text:005116DC push esi
.text:005116DD mov esi, dword_69EDB5C <- here
//conMinicon 6406490 is the addy
0043000B 8B15 ACA37E00 MOV EDX,DWORD PTR DS:[7EA3AC] ; iw4mp.06406480
00430011 807A 10 00 CMP BYTE PTR DS:[EDX+10],0
.text:00419A1A push 0
.text:00419A1C push 0
.text:00419A1E mov dword_9F8E78, eax
.text:00419A23 push offset aCon_minicon ; "con_minicon"
.text:00419A28 call sub_4DCBB0
.text:00419A2D fld ds:flt_724CEC
.text:00419A33 add esp, 40h
.text:00419A36 push offset aTheMinimumTime ; "The minimum time that the subtitles are"...
.text:00419A3B push 1 ; int
.text:00419A3D sub esp, 0Ch
.text:00419A40 fstp [esp+14h+var_C]
.text:00419A44 mov dword_7EA3AC, eax <- here
//drawfriendlytagsthruwalls 6406C60 is the addy
004B953C A1 2CA19B01 MOV EAX,DWORD PTR DS:[19BA12C]
004B9544 8078 10 00 CMP BYTE PTR DS:[EAX+10],0
.text:00496110 mov eax, dword_19BA12C <- here
.text:00496115 cmp byte ptr [eax+10h], 0
.text:00496119 push esi
.text:0049611A mov esi, [esp+4+arg_0]
.text:0049611E jz short loc_496147
.text:00496120 mov ecx, [esi+158h]
.text:00496126 mov edx, dword_1A80054
.text:0049612C mov [ecx+314Ch], edx
.text:00496132 mov eax, [esi+158h]
.text:00496138 add eax, 314Ch
Just a side note on how he's getting the value that Dave is getting, while using OllyDbg to get the address:
This can be done through code, as I've just explained to Dave via IRC. *( PDWORD )0x19BA12C (for the last example), will return the address that Dave's method is finding. As such:
Code:
*( PBYTE )*( PDWORD )0x19BA12C = 1;
This does it all automatically. However, I would recommend doing some checks to make sure that the pointer is valid, before you go nuts and start modifying. Meaning:
Just a side note on how he's getting the value that Dave is getting, while using OllyDbg to get the address:
This can be done through code, as I've just explained to Dave via IRC. *( PDWORD )0x19BA12C (for the last example), will return the address that Dave's method is finding. As such:
Code:
*( PBYTE )*( PDWORD )0x19BA12C = 1;
This does it all automatically. However, I would recommend doing some checks to make sure that the pointer is valid, before you go nuts and start modifying. Meaning:
Yeah. It was all a deep thought out plan to manipulate the pros into finding a better and much easier way to do it. I SUCCEEDED
Thanks guys. Will save me (and everyone) alot of time.
__________________
http://i49.tinypic.com/j993tj.png
CSS hax: 0% AAO hax: 0%
Gaying up my signature with pointless progress meters in a vain attempt to show off: 100%
Yeah. It was all a deep thought out plan to manipulate the pros into finding a better and much easier way to do it. I SUCCEEDED
Thanks guys. Will save me (and everyone) alot of time.
don't you just love it when a plan comes together? ahaha the good ol a-team
Yeah. It was all a deep thought out plan to manipulate the pros into finding a better and much easier way to do it. I SUCCEEDED
Thanks guys. Will save me (and everyone) alot of time.
I wouldnt have found these without ur tutorial man.. U lay down the basics
__________________
“For every complex problem, there is an answer that is short, simple and wrong.”
“Pessimism is safe, but optimism is a lot faster!”
hey this looks nice, im trying to do this myself, but it doesnt seem to work when im disabling the protection.
first, im using ollybdg obviously to find the lines you specified, this is pretty much my first time ever getting into "hacking" games so i tried real hard to comprehend, so what i got was that there were columns im suppose to match up in my iw4mp.exe that i opend with ollydbg.
so first, i look for the first column "00646009", i got close, infact so close at 00646000 all the way to 00646010, it has almost everything in between except the 9 in the last digit...
so i instead try looking to match the third column, i first search for referenced strings called "cheat protected" which i found, so i look all around those lines and find two that match up both of the last columns (first one didnt match as i already tried looking and couldnt find that column number at all), i change the letters and numbers like you said from 1 to 0.
then i went to change the "%s cannot be changed". i pretty much followed the same process and found:
CPU Disasm
Address Hex dump Command Comments
00646C71 /74 47 JE SHORT 00646CBA
as you can see it matches pretty well except the first and last column, i couldnt find anything around the referenced string "cannot be changed" with what you specified: "172_iw4m.0064623A" it matches the je short, but the numbers and letters after that obviously dont match...
so i changed it to JMP anyway, and coincidentally the 74 47 changes to EB 47 like you said it should too
not completely satisfied i try debugging anyway, and without a doubt it it froze up when it started running...
what am i doing wrong?
and btw, apparently my .exe has a console that opens up when i run? im actually using a cracked version of the game i got from thepiratebay (lol), so idk if thats any different.
with that said as well, would i need to send commands to the game via c++ even though i already have a console in which i can send commands directly?
heres of pic of the console :S
anyway, im pretty damn new at this sorry if im doing anything wrong, if you could (as i will myself) get me started with this hacking stuff? is there anything i should read prior to doing this tut? because obviously its missing lots of info i had to figure out myself
We strive to provide all our services for free and not interrupt your visit with overly intrusive advertisements or restrictions - support us by disabling your ad blocker or whitelisting our site.