-
PUSH / MOV or CALL to data from another file?
If its possible then I would like to know how to do something like this (in assembly):
mov edi, "data in another file"
or
push "text in another file"
Lets say I have client.exe and I have some text in myfile.bin (inside there are some lines of text). Is it possible to do push myfile.bin (some data inside it)?
I might not make any sense but I am wondering if there is a simple way to this or if there is simple way to put that file to memory and than push address of data inside of that file. And if its possible then will it slow down game a lot?
-
Re: PUSH / MOV or CALL to data from another file?
I understand what you are asking... I put an "International" version of my "Butchered" client into discussion, but nobody seemed very interested in it.
It does, exactly that.
Every string used in the client is compared to a text file. If the address is listed in the text file then the text string is replaced with the line of text indicated in the text file.
Eg:-
Code:
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
; English Language Translation File for Butchered PT
; By bobsobol.
;______________________________________________________________________________
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
; !!! NEVER DO THIS !!!
;1572072 = "Ver: 2b Eng"
;
; This will replace the string you are looking to, but also several other
;strings which you did NOT intend to.
; Always find the originating location, NOT the destination buffer which ends
; up being displayed.
6191640 = "Ver: 2b Eng"
; ^^ Like this !!!
; Note... because the call is to wsprintf(), it doesn't matter if you don't
; include the same number of formatting arguements.
;______________________________________________________________________________
6197848 = "Connecting to Server..."
6197820 = "Connection Failed!"
6197792 = "Please enter login details!"
6197764 = "Invalid user name or password!"
6196572 = "Continue this adventure?"
6186476 = "¦¢" ;This character only displays correctly in the Korean code page.
; The logic (in the EXE) which generates it, is badly coded anyway, and
; better alternatives exist in every code page. Either way, I do intend to fix
; the code which uses this "string", but may replace it's use all together.
; This is a bad example... but as far as I can tell APIs are NOT used to move
; this string.
1566976 = "Logging out..."
; There are other examples where this happens, and I will attempt to replace
; the manual byte move code with lstrcpy() API as and when I find them.
;______________________________________________________________________________
; The following are good examples of patching, but format badly becuase the
; game is not yet written to cope with international strings. This, I shall
; attempt to fix in the main EXE, since it cannot be done correctly for EVERY
; language without making such changes.
6119336 = "Damage: /n"
6119324 = "Speed: /n"
6119300 = "Critical: /n"
6119276 = "Weight: /n"
6119252 = "Block: /n"
6119228 = "Durability: /n"
If you search for that thread you will see I implement two libraries to achieve this. One is written in assembler and maps over the API calls for standard string handling functions... the other is written in a high level language (freeBasic in the release but I have a prototype C implementation) specifically so that I can utilise memory heaps and / or malloc() functions without having to write them in assembler, and utilise standard Line Input / cin >> / stdio type file handling without implementing those functions in Assembler.
freeBasic allows for multi-dimensional dynamic arrays of Variant String datatypes with ZString content, where I'm concluding that char * is not sufficient high level memory management to gain advantage over writing in assembler, and I will have to pick ATL, MFC, VCL or some such library to manage strings and their memory management sensibly and safely in C, or write a custom "StringArray" or "LinkedListOfStrings" Class / Classes to make it practical.
-
Re: PUSH / MOV or CALL to data from another file?
Are you talking about your thread "Beta Technical Demonstration - Translation without Hexing the EXE"?
Today RZ working really slow for me and I can't find what I am looking for.
From quick look at it i think you are patching memory, like in simple hack? This would slow game?
Is it possible to move item table, exp table, monster table etc. outside the client/server.exe using your method?
I think I am looking for different method (if it exist ;)), like:
load myfile.bin to memory and than
push myfile.bin_address + 100
or
mov edi, myfile.bin
I am not sure what I am looking for yet because uncle google can't help me =P
I still need to do some more reading (you have some interesting thread there). Thanks for help.
-
Re: PUSH / MOV or CALL to data from another file?
a) Like some "NoCD" Hacks or off-line RPG "Trainer" type hacks, yes. Not like most PT hacks.
b) Yes, it presently slows the game, mostly at loading, but also because GDI32:TextOut() is called too frequently. But the patching of existing APIs isn't the bit you are concerned about... it's the "loading stuff from another file" part that you want. :wink:
c) Yes, I'd like to make all those tables external from the main executable too, and it's not that hard to implement, but more complex than the simple examples you are giving.
Three options for successful implementation:-
1) If you are writing your assembler in the game.exe you can utilise the fopen(), fread() and fclose() routines included in the C stdio library linked into it. You should be able to find something like a malloc() routine to create your memory buffer too.
2) If you are making an external DLL in a high level language, you can use any facilities available to the language you write in, but must be able to pass back to the main program pointers to the location of these memories (it's likely to be different on each machine or configuration the game runs on, so not determinable at build time.
3) If you are still writing in Assembler and creating a DLL with the appropriate routines, then you will need to implement file handling routines yourself from the existing API exported from the Win32 platform SDK.
Option 1 seems the smallest, neatest and possibly cleanest solution. Option 2 the easiest (but you will add a large overhead to the memory footprint of the game, just as my example does). Option 3 is probably the hardest, it will add less overhead than option 2, but will not be able to reliably access the routines existing in the main game.exe as they are not exported for run-time linking by external modules... you could try to modify the export table of the PE to make them so, but it seems a lot of faff.
Also, please remember that many (or most) of the games internal securities are concerned with ensuring that these tables are built into the executable and do not change at any point after the executable was built. So you are going to have to completely change those securities... most simply by disabling them and opening the game to much easier cheating.
-
Re: PUSH / MOV or CALL to data from another file?
Thank you for answer,
I think I know what I will use. fopen() look like best option right now (its simple and clean).
It will go like this:
open file
read number of bytes
get space in memory
copy file to memory
I can write that in C++ but can't imagine that in assembly yet =P
And I am not sure how to address space that PT will think as Item Table.
Patching memory like in simple hack is out of question... those always slow down game.
DLL is no good too :/ its just another gate for hacks... when xtrap was detecting some dll loaders I just used d3d9.dll to load my hack.dll. So I prefer to assemble it in client/server.exe.
When come to security issues I think the biggest one would be that changed client side ITEM TABLE could crash server.exe, but I am counting on DC4 =P or later on some *CLSAFE_ITEM_TABLE_CODE ;)
External tables would speed up development and thats a huge + :)
-
Re: PUSH / MOV or CALL to data from another file?
Quote:
Originally Posted by
Vormav
Thank you for answer,
I think I know what I will use. fopen() look like best option right now (its simple and clean).
It will go like this:
open file
read number of bytes
get space in memory
copy file to memory
Order is wrong, should be:-
- Open file
- Get space in memory
- Read number of bytes into that memory buffer
- Close file
see fread() syntax, if you can write it in C, I'm guessing that is a simple typo, but I'll mention just in case.
Quote:
Originally Posted by
Vormav
I can write that in C++ but can't imagine that in assembly yet =P
And I am not sure how to address space that PT will think as Item Table.
Simple, once you know where your table is going to be loaded (fopen() with mode "rb") you need all the pointers to the table start (or first fields) to point to that address. You will have to store that in an otherwise unused, fixed location DWord, and use relative addressing in the table lookup routines.
The "relative addressing" OpCodes are bigger than their "direct" versions. So, instead of Mov ECX,TableStart, you need to LEA ECX,ptrTableStart
Quote:
Originally Posted by
Vormav
Patching memory like in simple hack is out of question... those always slow down game.
If it's done in Olly and saved to the Exe, that's not necessarily so... however, you are adding file access, and that will increase load up time however you do it, so where you do it is important. I should do mine after the initial splash has shown... you should probably do the same.
Quote:
Originally Posted by
Vormav
DLL is no good too :/ its just another gate for hacks...when xtrap was detecting some dll loaders I just used d3d9.dll to load my hack.dll. So I prefer to assemble it in client/server.exe.
I don't agree with that either, since you already point out that it's not possible to write Win32 app without DLL dependencies, and any one of those can be replaced with a proxy that adds more dependencies as well as the original functionality.
What is a security hole is that CLSAFE_CODE checks the tables in the executable memory space when you log in... if you put them in a file CLSAFE_CODE does not change when tables content is changed.
Quote:
Originally Posted by
Vormav
When come to security issues I think the biggest one would be that changed client side ITEM TABLE could crash server.exe, but I am counting on DC4 =P or later on some *CLSAFE_ITEM_TABLE_CODE ;)
If you place Item Table outside EXE you have bypassed DC4, you can't count on it at all any longer. But mis-matched tables crashes the client, not the server.
Quote:
Originally Posted by
Vormav
External tables would speed up development and thats a huge + :)
Here, I fully agree. The only reason haven't devoted more time to it because discussion with Server admins brings up such strong reservations about it... and with very good reason.
More useful than DC4 or CLSAFECODE would be requiring an SSL / PGP or RSA signed table file... unsigned file cannot load, modified file doesn't match it's signature, public key in the game.exe, private key from the server / web server. (it's still breakable)
-
Re: PUSH / MOV or CALL to data from another file?
When I was saying "read number of bytes" I wanted to say "SEEK_END" ;)
Anyway, I will start doing some tests at monday.
As for security I can't tell yet if external TABLE can break security, as long as client TABLE is compared to server TABLE there should be DC4 when they are not matching... probably even if it contain code where server is... probably :)
Quote:
Originally Posted by
bobsobol
The "relative addressing" OpCodes are bigger than their "direct" versions. So, instead of Mov ECX,TableStart, you need to LEA ECX,ptrTableStart
Yeah thats it, but I hope that PT will understand than table when somewhere else :)
-
Re: PUSH / MOV or CALL to data from another file?
I'm seeing some Sandurr fans over here. :B
-
Re: PUSH / MOV or CALL to data from another file?
Why bring up that name? It seems completely off-topic to me. I could be wrong, you know I don't follow his work any more than I follow Dexterrs' and only hear gossip. They don't contribute here, and I don't hack (or even play) other peoples servers or clients, (unless they ask me to) so what they do is a mystery to me.
But I see no connection between this discussion and that individual.
-
Re: PUSH / MOV or CALL to data from another file?
I don't see the point of talking about "him" too...
Maybe he did same thing on his server? I don't know and I don't care...
OK bobsobol my assembly master ;)
does:
MOV EBP,DWORD PTR DS:[ECX*4+600F3C]
in 600F3C there is JMP 04483084
and in 04483084 there is same thing that is in 600F3C
IS equal to:
MOV EBP,DWORD PTR DS:[ECX*4+600F3C]
??
PS. Do you know some good place to start code I have? Right now Is starting where PT "start" is... and I need place to free memory too, on quit I guess.
--EDIT--
I need to rethink this... I am not sure how to force PT to read ITEM TABLE from file loaded to memory. I have offset but ITEM TABLE is not reading from it.
I need to change current memory address to address existing in memory when file is loaded but its not 'static' so I need to rethink this =P If only there where a way to load this file to the same space... like memory-mapped file.
-
Re: PUSH / MOV or CALL to data from another file?
Hmm... Well, "one liners" are particularly difficult in low level, but thankfully we are still talking CISC, not RISC.
First off, let me say "I don't think this is what you are really looking for." Now I will explain what I think you have got.
Lines like MOV EBP,DWORD PTR DS:[ECX*4+600F3C] are usually followed (maybe not immediately) with a JMP EBP, or CALL EBP, and act like a low level form of Switch Case / Select Case logic. But sometimes they are a form of memcpy(), where you MOV EBP,DWORD PTR DS:[ECX*4+600F3C] then MOV DWORD PTR DS:[ECX*4+SomeOtherBaseAddress],EBP then INC ECX and CMP ECX with the SizeOf and if less JMP back.
Here's how the switch code usually works:-
Code:
.Switch:
MOV ECX, Case ;maybe POP ECX as an Arg value in this routine.
CMP ECX, Case3
JG CaseDefault
MOV EBP,[ECX*4+.JumpTable]
JMP EBP
.Case1:
;some code
JMP .End
.Case2:
;some code
JMP .End
.Case3:
;some code
JMP .End
.CaseDefault:
;some code
JMP .End
.End:
Ret
.JumpTable
DW .Case1, .Case2, .Case3, .CaseDefault, 0
That's how I'd write it in Assembler... as opposed to the disassembly listing. The optimisation routines of a C compiler will probably jumble things around a bit, and may well JMP SHORT to another JMP, if the optimiser deems that the quickest option to execute, or smallest code. (depending on how complex the routines in each case are, and whether you have the compiler set to optimise size or speed) That's when the PTR to another JMP comes in. DWord is usually assumed as the consumer is a 32-bit Register, EBP... so you don't normally specify it explicitly. DS: is completely irrelevant since your not writing 16-bit code where DS (Data Segment) CS (Code Segment) and ES (Extra Segment) are relevant, in a 32-bit environment, all these segments are always 0.
Olly will list DS: (optionally) because some of the older 32-bit assemblers which evolved with the Intel 16-bit architecture (MASM and TASM etc.) will still think in 16-bit "real mode" terms even when they are told to produce a 32-bit "Flat" (>= i386 and with no segment pages) binary. (such as used in Windows PE Executables, and Linux ELF32 executables.)
What you want is to find some code which uses the C libraries malloc() routine, to utilise that, or to hit the Kernel32 VirtualAlloc() / VirtualFree(), HeapCreate() / HeapDestroy(), or LocalAlloc() / LocalFree() routines directly. These are the routines which the standard C (libc, msvcrt in PTs case, etc) .lib file linked into PT provides C programmers with a standard (platform independent) malloc() routine to handle for them.
A good place to look, is the code which loads SMDs, TGAs and BMPs. This allocates memory, and then loads a file into that memory... the SMD is complicated by the fact that it looks for a .ASE file to turn into an SMD first. PT has a wrapper which covers loading all the assets, including sounds and music, keeping a hash table of each file name and discarding the least used asset when it runs out of memory.
Q: Why don't all OS's (Windows especially) just implement malloc() in the Kernel?
A: System Stability (what Microsoft calls Security). malloc() doesn't much care if the memory is real, virtual, paged, pageable, static etc... the OS wants to know how volatile this memory is, and a smart C library will determine this for the C programmer at compile time.
Are you going to keep it throughout your programs life, or are you just going to load it, parse it, display it and then destroy it... C programmers don't want to care about that, but it makes a big difference to the performance and interoperability of multiple applications running on the same OS.
Additionally... it may be of interest to you that all allocated memory is unallocated by the NT kernel when the application (and all it's threads) are terminated. It's bad practice, but the commonality of programmers forgetting to deallocate memory they allocated was why Win9x had to be rebooted so often to prevent it slowing down and crashing where NT never did. PT is particularly bad in this respect, and if you can still run the client on a 9x system I suggest you take a look at how much free memory you had before you ran it, and after you quit it. Last time I tried the difference was astonishing. :wink:
You may want to "do it properly", but it's worth noting that PT doesn't, so you aren't compromising much if you don't bother to deallocate your memory.
-
Re: PUSH / MOV or CALL to data from another file?
Write a dll. Use LoadLibrary inside the client to load it. In olly, select View and you'll see your dll there. Now, you can push data from your dll.
I may be wrong, but I think somethings doesnt work. I mean, change game.exe offsets or the registers should result in Access Violation.
@About sandurr
As far as I can see, you want to grab the item table from game.exe and make a items.dat like him did. Or I am wrong? I was just kidding, dont take it seriously.
-
Re: PUSH / MOV or CALL to data from another file?
And he wants to do it from a file that's not a DLL... You may have missed that bit.
I agree, that a DLL with the tables exported from it would be the quickest and most efficient method. But Vormav expresses concerns about introducing more means of "injecting" into his program.
+ If the DLL is "signed" it should be as secure as any other "signed" binary file.
- You can't stop a DLL executing it's entry point upon loading it... so you'd have to check the signature before loading.
+ & - You don't have to LoadLibrary() if you re-link the PE file as I showed in "Adding Code to PT Client and Server via DLL", but then you don't get the chance to check it's signature before loading... afterwards, "the cat is out of the bag" and you're "shutting the door after the horse has bolted". (The entry point code can mask a fake signature)
So while I agree with your view Lelejau, Vormavs' argument is valid.
Re: Sandurr, it seems neither of us where aware of this. A .dat file is not a disguised .dll I presume? Did he "sign" the table files?
-
Re: PUSH / MOV or CALL to data from another file?
The item table is just the same. The only diffrence, it is in a separated .dat file. But the item table structure is the same. (Until now, :P Maybe sandurr changes it too, like he did to all Priston tale. )
-
Re: PUSH / MOV or CALL to data from another file?
Thanks guys,
I think I am getting closer to finish this.
Let me 'materialize' my problem now.
Item table addressing memory-mapped file by using:
Code:
MOV ECX,600F48
LEA EAX,DWORD PTR DS:[ESI+600F6C]
MOV ECX,DWORD PTR DS:[ESI+600F80]
etc...
When I am loading file to memory I don't know where it will be.
So i do something like this:
Code:
MOV DWORD PTR DS:[600F48],EAX
LEA EBX,DWORD PTR DS:[EAX+24]
MOV DWORD PTR DS:[600F6C],EBX
LEA EBX,DWORD PTR DS:[EAX+34]
MOV DWORD PTR DS:[600F7C],EBX
etc...
This will give me offsets to some places (in my file located in memory) in ITEM TABLE that PT functions are scanning.
Address 600F48 is not holding item table data but address of table loaded to memory.
If I had a way to go to physical address located in EAX I am sure this would work.
If table start is in 060D0020
than I could do:
and problem would be slowed =O
...but I don't know how to force assembler to do:
Code:
...
416A96 MOV ECX,600F48
...
600F48 60D0020
In 600F48 assembler will move "600F48" instead of jumping and getting data of that address. I also can't do:
Code:
...
416A96 MOV ECX,600F48
...
600F48 JMP 60D0020
because JMP will not be executed.
This look funny but I hope you guys can understand me :)
-
Re: PUSH / MOV or CALL to data from another file?
I dont unsertand you problem.
-
Re: PUSH / MOV or CALL to data from another file?
Quote:
Originally Posted by
Vormav
Thanks guys,
I think I am getting closer to finish this.
Let me 'materialize' my problem now.
Item table addressing memory-mapped file by using:
Code:
MOV ECX,600F48
LEA EAX,DWORD PTR DS:[ESI+600F6C]
MOV ECX,DWORD PTR DS:[ESI+600F80]
etc...
When I am loading file to memory I don't know where it will be.
That's fine, but a memory mapped file isn't a file loaded into memory, it's a file treated as though it where a memory range. And the location in memory you want it mapped is one of the parameters you must pass when mapping the file (or part of it) into memory.
File Mapping (Windows)
Quote:
Originally Posted by
Vormav
So i do something like this:
Code:
MOV DWORD PTR DS:[600F48],EAX
LEA EBX,DWORD PTR DS:[EAX+24]
MOV DWORD PTR DS:[600F6C],EBX
LEA EBX,DWORD PTR DS:[EAX+34]
MOV DWORD PTR DS:[600F7C],EBX
etc...
This will give me offsets to some places (in my file located in memory) in ITEM TABLE that PT functions are scanning.
Address 600F48 is not holding item table data but address of table loaded to memory.
That looks smashing. Spot on idea.
Quote:
Originally Posted by
Vormav
If I had a way to go to physical address located in EAX I am sure this would work.
If table start is in 060D0020
than I could do:
and problem would be slowed =O
...but I don't know how to force assembler to do:
Code:
...
416A96 MOV ECX,600F48
...
600F48 60D0020
In 600F48 assembler will move "600F48" instead of jumping and getting data of that address. I also can't do:
Code:
...
416A96 MOV ECX,600F48
...
600F48 JMP 60D0020
because JMP will not be executed.
This look funny but I hope you guys can understand me :)
Okay... you are stuck on direct vs. indirect addressing.
MOV ECX,600F48
Now ECX = 600F48
MOV EAX, 600F48
LEA ECX, EAX
Now ECX contains the address stored at memory location 600F48. ^_^
Also:-
MOV ECX, DWord Ptr [600F48]
Now ECX contains the address pointed to by memory at location 600F48.
Speed, size and availability of registers will determine the method you use.
---EDIT---
I warn you, that's off the top of my head, and it's been -4 INSIDE my house for the last week and a half, I have no heating and am running low on supplies and sleep. :s
-
Re: PUSH / MOV or CALL to data from another file?
Quote:
Originally Posted by
bobsobol
Okay... you are stuck on direct vs. indirect addressing.
MOV ECX,600F48
Now ECX = 600F48
MOV EAX, 600F48
LEA ECX, EAX
Now ECX contains the address stored at memory location 600F48. ^_^
Also:-
MOV ECX, DWord Ptr [600F48]
Now ECX contains the address pointed to by memory at location 600F48.
Speed, size and availability of registers will determine the method you use.
---EDIT---
I warn you, that's off the top of my head, and it's been -4 INSIDE my house for the last week and a half, I have no heating and am running low on supplies and sleep. :s
I must say you confused me =P again:
My EAX contain random address of ITEM TABLE (item table going to EAX).
Lets see:
MOV ECX,600F48 <- ECX = 600F48 and because 600F48 is empty ECX = 0
MOV EAX, 600F48 <- EAX = 600F48 and because 600F48 is empty EAX = 0 and now I lost ITEM TABLE address...
LEA ECX, EAX <- since this is impossible i assuming that you wanted to say LEA ECX, [EAX] so now ECX = 0 because EAX is 0 at this point
MOV ECX, DWord Ptr [600F48] <- now ECX = 600F48
in the end:
EAX = 0
ECX = 600F48
or I am doing something terribly wrong =P
When PT doing something like this:
MOV ECX,600F48
I need data there (inside 600F48, because is empty) "Stone Axe" or "00 01 01 01" etc.
but because MOV DWORD PTR DS:[600F48],EAX is equal to 600F48 = address of EAX my MOV ECX,600F48 will do MOV ECX, address of EAX so (for example) ECX = 4490020...
PS. if is "-4 INSIDE" than open up some 3D game and get close to CPU ;)
-
Re: PUSH / MOV or CALL to data from another file?
Okay... I just did some practical tests.
In a client (1872) the .RData (import section of PE) is @ 5BD000
MOV ECX,005BD000
ECX = 005BD000
---------
MOV ECX, DWORD [005BD000]
ECX = 75E57C42 (which is the location of the RegOpenKeyExA routine from AdvAPI32.dll, and the DWord stored at location 005BD000)
----------
LEA ECX,[005BD000]
ECX = 5BD000
==========
I'm confused by the final result, because that makes it identical to a MOV, and that's not how it's documented at all. But I have to say, I very rarely resort to using LEA (Load Effective Address). I prefer to use [] relative addressing.
Your table is not much different to the import table. The biggest difference is that Olly has no idea how to label it's contents.
Explanation: I had no idea how EAX was being used in the code you are looking at, I just used it as an example, since you should be able to LEA the contents of memory pointed to by an address in another register... but as I say, I rarely use it. (there are lots of rarely used instructions in Complex Instruction Set CISC CPU architectures)
Also. Please be careful of the term "empty". You should only come across the term "empty" in relation to digital storage you are when dealing with objects. Usually Variant Typed Objects.
Memory is never "empty" (unless it's an address that has no memory module / chip physically plugged in) and registers are never "empty".
Containing the value 0 is not empty. It may mean 0, False, Null, Nil, Failed, Error or "End of [List | Array]" but it should never mean "empty". (Well, maybe if it's representing how much water is in a cup... or such. Even so, it's better to say there is exactly 0 units of water in the cup.)
Specifically, this is very confusing with VB Variant variables (actually objects / custom types) of type Bool, since a Boolean value should only ever hold one of two possible states. They should either be "True" or "False", "On" or "Off", "Positive" or "Negative", "Yes" or "No, 1 or 0. But in VB it can be "True", "False", "Empty" or "Error" which, by definition, makes it far from "Boolean", as they are 4 state variables, not 2 state ones; even if you ignore their extended attributes.
This is very confusing for people moving to, or from VB or VBScript (ASP etc) and anything else.
Quote:
MOV ECX, DWord Ptr [600F48] <- now ECX = 600F48
Should only be the case if the value of the DWord stored at address 00600F48h is 00600F48h. o.O
-
Re: PUSH / MOV or CALL to data from another file?
Right now I am doing beta test (on game.exe).
I patched 3 functions that are called when you login into server. Those functions checking item table.
PT can load my file to memory and count items in that file.
However there is a problem when next function is doing this again (this time is checking every second item O.o + its checking some other parts of items)
Problem is here:
EAX contain my content of external file but when this is executed:
Code:
MOV EDX,DWORD PTR DS:[EAX-7C]
EAX-7C = start of my external file in memory and EDX = 01010100, 01010200, 01010300 etc. (this is actually correct, same thing happening on unmodified exe)
01010100, 01010200, 01010300 etc. is number at the beginning of every item in table, its also offset to memory-mapped file (empty space in .data).
My questions is... WTH? is this?
I will probably load this space to memory and than change EDX into space in memory but before I will do that maybe someone can tell me something more about those magic numbers in front of every item.
-
Re: PUSH / MOV or CALL to data from another file?
They are the UID.
They are the item ID the server and client recognise by... not the WA101 or what-ever NameID.
The NameID is used by the server to look up in OpenItem, and by the client to find "assets" (Icons, ground and worn meshes) but the numeric ID / UID is used like as a key value for most other lookups. I think the GameSave file stores both, and I suspect both are in any packet concerning items. (dropped, picked up, in WH / shop etc)
The code actually indicates the type of item as well... there's info hereabouts in posts, but not exactly a "guide" or "tutorial".
Comes up in questions about "off hand" items and "item holding animation" for items which you hold in your hands (bow, crossbow, wand, stave, axe, sword, longsword etc each have different held item animation).
Gregoo would probably be able to give a more complete (correct) answer, as I know he's done stuff with customs... I never have. I only want the standard base items to work. XD
It should really be covered in the guide "How to add items to table without replace" (or WHY) but I didn't read that very thoroughly and don't remember seeing it mentioned. (I could have just skipped over it)
-
1 Attachment(s)
Re: PUSH / MOV or CALL to data from another file?
OK I got my proof of concept (item table in game.exe is deleted) =P
I loaded item from external file (nvm error, its because I did not patch img function).
http://forum.ragezone.com/attachment...1&d=1291928345
Now I should build my offset table (adding items will be very easy) but before I will do that I need to fix security function (I disable it for now =P)... Its function that check item table every 10 sec and if something is wrong its forcing game.exe to quit.
offset to that problem is 00492909 in game.exe I uploaded in other thread.
http://forum.ragezone.com/attachment...nswer-game.rar
Function look like this:
Code:
004927A0 /$ A1 C0C95F00 MOV EAX,DWORD PTR DS:[5FC9C0]
004927A5 |. 81EC 80000000 SUB ESP,80
004927AB |. 85C0 TEST EAX,EAX
004927AD |. C705 A84C1003 >MOV DWORD PTR DS:[3104CA8],0
004927B7 |. 0F84 98000000 JE game.00492855
004927BD |. 53 PUSH EBX
004927BE |. 8B1D D4625C00 MOV EBX,DWORD PTR DS:[<&USER32.wsprintfA>; USER32.wsprintfA
004927C4 |. 55 PUSH EBP
004927C5 |. 8B2D 34625C00 MOV EBP,DWORD PTR DS:[<&KERNEL32.lstrcpy>; kernel32.lstrcpyA
004927CB |. 56 PUSH ESI
004927CC |. B8 C0C95F00 MOV EAX,game.005FC9C0
004927D1 |. 57 PUSH EDI
004927D2 |. 8B3D 3C615C00 MOV EDI,DWORD PTR DS:[<&KERNEL32.lstrcat>; kernel32.lstrcatA
004927D8 |. 8BF0 MOV ESI,EAX
004927DA |. 8D9B 00000000 LEA EBX,DWORD PTR DS:[EBX]
004927E0 |> 8B8C24 9400000>/MOV ECX,DWORD PTR SS:[ESP+94]
004927E7 |. 8508 |TEST DWORD PTR DS:[EAX],ECX
004927E9 |. 74 5A |JE SHORT game.00492845
004927EB |. 8B56 FC |MOV EDX,DWORD PTR DS:[ESI-4]
004927EE |. A1 A8456B00 |MOV EAX,DWORD PTR DS:[6B45A8]
004927F3 |. 52 |PUSH EDX
004927F4 |. 50 |PUSH EAX
004927F5 |. 8D4C24 18 |LEA ECX,DWORD PTR SS:[ESP+18]
004927F9 |. 51 |PUSH ECX
004927FA |. FFD3 |CALL EBX
004927FC |. 83C4 0C |ADD ESP,0C
004927FF |. 68 44595D00 |PUSH game.005D5944 ; ASCII "
"
00492804 |. 8D5424 54 |LEA EDX,DWORD PTR SS:[ESP+54]
00492808 |. 52 |PUSH EDX
00492809 |. FFD5 |CALL EBP
0049280B |. 8D4424 10 |LEA EAX,DWORD PTR SS:[ESP+10]
0049280F |. 50 |PUSH EAX
00492810 |. 68 88351003 |PUSH game.03103588
00492815 |. FFD7 |CALL EDI
00492817 |. 8D4C24 50 |LEA ECX,DWORD PTR SS:[ESP+50]
0049281B |. 51 |PUSH ECX
0049281C |. 68 E81E1003 |PUSH game.03101EE8
00492821 |. FFD7 |CALL EDI
00492823 |. A1 AC4C1003 |MOV EAX,DWORD PTR DS:[3104CAC]
00492828 |. 8B0D A84C1003 |MOV ECX,DWORD PTR DS:[3104CA8]
0049282E |. 40 |INC EAX
0049282F |. 41 |INC ECX
00492830 |. A3 AC4C1003 |MOV DWORD PTR DS:[3104CAC],EAX
00492835 |. 2BC1 |SUB EAX,ECX
00492837 |. 83C0 02 |ADD EAX,2
0049283A |. 890D A84C1003 |MOV DWORD PTR DS:[3104CA8],ECX
00492840 |. A3 A44C1003 |MOV DWORD PTR DS:[3104CA4],EAX
00492845 |> 8B4E 2C |MOV ECX,DWORD PTR DS:[ESI+2C]
00492848 |. 83C6 2C |ADD ESI,2C
0049284B |. 85C9 |TEST ECX,ECX
0049284D |. 8BC6 |MOV EAX,ESI
0049284F |.^75 8F \JNZ SHORT game.004927E0
00492851 |. 5F POP EDI
00492852 |. 5E POP ESI
00492853 |. 5D POP EBP
00492854 |. 5B POP EBX
00492855 |> 33C0 XOR EAX,EAX
00492857 |. 81C4 80000000 ADD ESP,80
0049285D \. C2 0400 RETN 4
00492860 > A1 3C4D1003 MOV EAX,DWORD PTR DS:[3104D3C]
00492865 . 40 INC EAX
00492866 . 3D BC020000 CMP EAX,2BC
0049286B . A3 3C4D1003 MOV DWORD PTR DS:[3104D3C],EAX
00492870 . 7D 03 JGE SHORT game.00492875
00492872 . 33C0 XOR EAX,EAX
00492874 . C3 RETN
00492875 > 53 PUSH EBX
00492876 . 56 PUSH ESI
00492877 . 33F6 XOR ESI,ESI
00492879 . 57 PUSH EDI
0049287A . C705 3C4D1003 >MOV DWORD PTR DS:[3104D3C],0
00492884 . 33D2 XOR EDX,EDX
00492886 . B9 40096000 MOV ECX,game.00600940
0049288B . EB 03 JMP SHORT game.00492890
0049288D 8D49 00 LEA ECX,DWORD PTR DS:[ECX]
00492890 > 8B01 MOV EAX,DWORD PTR DS:[ECX]
00492892 . 85C0 TEST EAX,EAX
00492894 . 74 05 JE SHORT game.0049289B
00492896 . 0FAFC2 IMUL EAX,EDX
00492899 . 03F0 ADD ESI,EAX
0049289B > 83C1 1C ADD ECX,1C
0049289E . 42 INC EDX
0049289F . 81F9 AC0A6000 CMP ECX,game.00600AAC
004928A5 .^7C E9 JL SHORT game.00492890
004928A7 . 33C9 XOR ECX,ECX
004928A9 . B8 C40F6000 MOV EAX,game.00600FC4
004928AE . 8BFF MOV EDI,EDI
004928B0 > 8B50 84 MOV EDX,DWORD PTR DS:[EAX-7C]
004928B3 . 85D2 TEST EDX,EDX
004928B5 . 74 14 JE SHORT game.004928CB
004928B7 . 8B58 B8 MOV EBX,DWORD PTR DS:[EAX-48]
004928BA . 8B78 68 MOV EDI,DWORD PTR DS:[EAX+68]
004928BD . 03FB ADD EDI,EBX
004928BF . 0378 BC ADD EDI,DWORD PTR DS:[EAX-44]
004928C2 . 03FA ADD EDI,EDX
004928C4 . 0338 ADD EDI,DWORD PTR DS:[EAX]
004928C6 . 0FAFF9 IMUL EDI,ECX
004928C9 . 03F7 ADD ESI,EDI
004928CB > 8B90 98020000 MOV EDX,DWORD PTR DS:[EAX+298]
004928D1 . 85D2 TEST EDX,EDX
004928D3 . 74 24 JE SHORT game.004928F9
004928D5 . 8B98 14030000 MOV EBX,DWORD PTR DS:[EAX+314]
004928DB . 8BB8 7C030000 MOV EDI,DWORD PTR DS:[EAX+37C]
004928E1 . 03FB ADD EDI,EBX
004928E3 . 03B8 D0020000 ADD EDI,DWORD PTR DS:[EAX+2D0]
004928E9 . 03B8 CC020000 ADD EDI,DWORD PTR DS:[EAX+2CC]
004928EF . 03FA ADD EDI,EDX
004928F1 . 8D51 01 LEA EDX,DWORD PTR DS:[ECX+1]
004928F4 . 0FAFFA IMUL EDI,EDX
004928F7 . 03F7 ADD ESI,EDI
004928F9 > 05 28060000 ADD EAX,628
004928FE . 83C1 02 ADD ECX,2
00492901 . 3D ECDB6A00 CMP EAX,game.006ADBEC
00492906 .^7C A8 JL SHORT game.004928B0
00492908 . 5F POP EDI
00492909 . 81FE 9A8DFBA9 CMP ESI,A9FB8D9A
0049290F . 5E POP ESI
00492910 . 5B POP EBX
00492911 . 74 0A JE SHORT game.0049291D
00492913 . 6A 65 PUSH 65
00492915 . E8 F6B10C00 CALL game.0055DB10
0049291A . 83C4 04 ADD ESP,4
0049291D > B8 01000000 MOV EAX,1
00492922 . C3 RETN
Problem is in red... CMP ESI,A9FB8D9A I just doing force jump from 00492911 to 0049291D.
I would prefer that part enabled because if check is every 10 sec than this function must be important part of security but I don't understand how number A9FB8D9A is created (this number IS different on other versions of game.exe, its some kind of checksum?).
For now I am planing to build offset table, move items UID table outside game.exe, and fix functions (a lot of manual work ;)) and maybe in future additional tool to add items to table.
-
Re: PUSH / MOV or CALL to data from another file?
Okay... IMS that number is all the bytes in the table added together with no overflow checking. (but I could be wrong, it could even be a different function in different game.exe)
Regardless, you do want to implement some function of this nature.
The function needs to know:-
- Start byte
- Length of table
- Correct table checksum value
This would be a good opportunity to replace it with MD5 / SHA1 checksum, but the easiest way for you to do that would probably be to import that function from a DLL. There are lots of free implementations of these (very secure checksums) in C that could be made into a DLL... however, if the checking routine is external, it's very easy for a hacker to replace it with one that doesn't check, and just returns the right checksum.
Additionally, you have identified that the checksum is stored in the .text section... this helps prevent it being changed... but if it isn't changed, then your game.exe is locked to only one item-table file, and the only way to correct it is with Olly, or a hex editor.
You could store the checksum in the file, and change cmp ESI,[OffsetInMemoryLoadedFromFile] and I would suggest the start of the file, so that it doesn't move when items are added.
Alternatively, you could write a program which knows your game.exe and will allow developers to "patch" the exe directly.
Another alternative, may be to get the checksum from the games server, maybe as a web page request. (and I know you are good with those) The problem then, is that a URL can be spoofed, and the API to get a web page can be patched easily.
Which ever method you choose, the easier you make it for Devs, the easier you make it for hackers. Because if we can do it easily, so can they... and there-in lies the problem.
This is a lot of why more people haven't followed this method.
Now; this may be upsetting to hear, but... if all the functions which access the item table and return a value for an item or simply okay the table where exported to a DLL which is linked in the game.exe header, the format of the item table could be completely changed. It could even be a SQLite table. The checksum could be embedded in the DLL and the calculation could be one of a number of different functions selectable at compile time... the DLL it's self could then be compressed and encrypted, obscuring the checksum.
I'm not sure if that idea appeals to you, or that it is even any more secure than any of the others I list. There are probably other ways you could go too.
The programs which hack item details also disable this function the way you have, only at the point they are injected into the game.
GameGuard could block this, and the current version is supposedly harder to disable... XTrap doesn't, but could do, if the game companies paid for that service... but most of them don't.
As you may know, the reason I am loathe to implement a checksum in the string patching libraries, is because a single universal checksum will be broken very quickly. The only way I can imagine individual servers protecting their client for any amount of time is if each one implements a different encryption / signature (checksum) function for their set-up.
Take heart, however, in the fact that the method you are attempting to replace has been broken by every item hacker in PT already. So you can't possibly do any worse unless you leave it disabled as it is now. XD
It may also be worth noting that the function you have disabled is part of the memory which makes up the CLSafeCode... so if you keep the checksum there, it will block a modified checksum client saved to disk, and force hackers to patch the executable only after logging in... as they traditionally do. If you move it out of the main executable, then they can change the checksum on disk and not have to inject a DLL after the game has already connected and got the character details. :s
-
Re: PUSH / MOV or CALL to data from another file?
I've been thinking about it for a while now and I see only small problem with current items security on PT. When I was playing PT I remember they "activated" something on server and range hack was not working (some md5 etc check? But they enable it only for one day, maybe server could not handle it), however knowing where item is I could create my not existing item WP999 and change into existing WP110 using only memory editor, this is working even now. So only security issue I see here is that someone will be able to edit weapon length. If you have some examples of "hack item details" you are talking about than I would like to hear what they where doing because any damage edit will end up with DC4. So only name of item is unprotected?
So lets say I will use MD5 to check item_table.dat and if its incorrect then game will quit (MD5 can be in game.exe, people can't connect with edited .exe anyway). Thats 1st security, after that file is in memory so I need some way to protect memory from point X to Y. For some reason function that I was showing you is not protecting game.exe from item swap (only names of items?). Thats odd (its running every 10 sec)... So I need something better, any suggestions?
I have Item table that start in memory address X and end in Y... so if someone edit it he will get DC/game will quit.
I don't know any
DontTouchMeOrIWillTerminateYou() functions that will protect my memory.
And It would be good to know if I can protect files from modification.
PS. nvm DLL... IMHO important functions should be in game.exe
-
Re: PUSH / MOV or CALL to data from another file?
The names of items come from the server. They exist in the client, but if they are wrong, blank, in a different language etc. makes absolutely no difference. Change the name in OpenItem, and that's what the user sees.
Same applies to all the stats, speed, attack power, damage, health, manna and stamina restore rate etc.
What can user change in item table to his benefit? Not a lot. The item number, and that will lead to a different mesh and icon and no details coming from server... except "You are using an unknown item, please disconnect.", so hacker has to ignore that request to disconnect anyway.
As for getting a different mesh and icon, you can change the smd file for the same item code and not be told to disconnect, and still have an attack range larger than an entire field. XD
That checksum is very simple calculation, and I'm not convinced that it helps a lot.
The only "DontTouchMeOrIWillTerminateYou()" functions come from XTrap or GameGuard... or you can declare your own game.exe to be it's own JIT debugger, and set debug interrupts on write / execute every memory range that is sensitive, responding with TerminateProcess(0).
Essentially, imagine your game.exe required OllyDbg to launch it... it won't start without it. Olly has every memory range set with log functionality enabled in it's .udd file, and it's entire UI is broken so that any trapped event causes the whole lot to crash. That's what you need.
Sandurrs PT clients are already half way there. But that's not very easy to figure out, is only half of the puzzle and would be stealing. VirtualDub is an open source project and, at least in earlier versions, included a built in debugger which trapped illegal instructions and out of range memory accesses and disassembled a fair portion of the code where the error occurred displaying it, and part of the stack in a custom error message. It did this, partly because the developer created VDub for a Collage project, and partly because it relies heavily on external filters written by third parties as .dll files (renamed to .vdf).
I don't know how to do what I have described... which is why I point you to several examples of where it (or something similar) has already been done.
Best of luck to you. :wink: