-
Ok. You can examine CheatEngine source, you will find a lot of interesting things.
In Olly, set debug options to break on new module (dll). Another quick method to stop debugger: make a call of MessageBox just before calling search function in your code, like
[code[call MessageBoxA
call <find value>[/code]
then BP on MessageBoxA in user32. After that, you can step by step trace your <find value> func
-
Original C++ Function
Here's the original C++ function
PHP Code:
// http://en.wikipedia.org/wiki/Boyer-Moore-Horspool_algorithm
LPBYTE PatchSearch(HMODULE hModule, LPBYTE searchCode, int size, BYTE wildcard) {
size_t skipLength[UCHAR_MAX + 1];
int scan;
int lastByte = size - 1;
while(searchCode[lastByte] == wildcard)
lastByte--;
int defaultSkip = lastByte;
for(scan = 0; scan < lastByte; scan++) {
if(searchCode[scan] == wildcard) {
defaultSkip = lastByte - scan;
}
}
if(defaultSkip > 1) defaultSkip--;
for(scan = 0; scan < (UCHAR_MAX + 1); scan++)
skipLength[scan] = defaultSkip;
for(scan = 0; scan < lastByte; scan++) {
if(searchCode[scan] != wildcard) {
skipLength[searchCode[scan]] = lastByte - scan;
}
}
MODULEINFO dllInfo;
GetModuleInformation(GetCurrentProcess(), hModule, &dllInfo, sizeof(dllInfo));
LPBYTE p = (LPBYTE)dllInfo.lpBaseOfDll;
LPBYTE searchEnd = (LPBYTE)dllInfo.lpBaseOfDll + dllInfo.SizeOfImage;
searchEnd -= lastByte + 1;
while(p <= searchEnd) {
scan = lastByte;
while(searchCode[scan] == wildcard || p[scan] == searchCode[scan]) {
if(scan == 0) return p;
scan--;
}
p += skipLength[p[lastByte]];
}
return NULL;
}
-
that code looks basic.
You just have to figure out what everything means.. and find same thing in delphi like..
UCHAR_MAX
you google this you find
#define UCHAR_MAX 255
so this line mean
size_t skipLength[255 + 1];
or
size_t skipLength[256];
then size_t could mean anything
then you look at this
skipLength[scan] = defaultSkip;
and then you see
int defaultSkip = lastByte;
so skipLength is int
int skipLength[256];
maybe problems with parameters too
like
LPBYTE searchCode
well.. LPBYTE is declared as
typedef byte* LPBYTE
then what is byte?
typedef unsigned char BYTE;
okay now you know BYTE means unsigned char.. and LPBYTE means unsigned byte pointer..
so we know
LPBYTE searchCode
is.. byte array of unsigned bytes..
byte[] searchCode //<- in C#.
we also now know..
BYTE wildcard is also unsigned char so,..
byte wildcard //<- in C#.
HMODULE hModule
typedef HINSTANCE HMODULE; //<-- see HMODULE mean HINSTANCE
typedef HANDLE HINSTANCE; //<- HINSTANCE mean HANDLE
typedef PVOID HANDLE; //<- HANDLE is PVOID
typedef void* PVOID; //<- PVOID is VOID * [void pointer]
Void pointer is a pointer that is pointing to any type of unknown data.. then you can cast it to anything you wish char,int,float, you must know what data you put in kind of pointer or else you might forget about it.
This doesn't explain much, but.
HMODULE and HINSTANCE = Base Address of DLL or EXE which is loaded in memory, it is a unsigned long pointer.
I think Delphi supports HMODULE and HINSTANCE.. or either one should work, if not it is just unsigned long pointer.. or from googling same as ^LongWord
Other than that nothing really to hard about that example.
Have to figure out how API works in delphi for GetModuleInformation it should be found in Win32API, I think this can be googled easily with "WIN32API GetModuleInformation Delphi" found example something like this
Okay it seems.. hModule should be in Delphi THandle
Lol delphi looks horrible something like this.. I don't know if this will work..
Code:
var
dllInfo: TModuleInfo;
begin
GetModuleInformation(GetCurrentProcess, hModule, @dllInfo, SizeOf(dllInfo));
end;
then pretty much
LPBYTE p = (LPBYTE)dllInfo.lpBaseOfDll;
LPBYTE searchEnd = (LPBYTE)dllInfo.lpBaseOfDll + dllInfo.SizeOfImage;
LPBYTE p is pointer to byte array which starts at dllInfo.lpBaseOfDll.
searchEnd is p which is where base address starts for dll and plus sizeOfImage of dll which gets the address where base address ends.
Hope it helps.. probably Dwar will do it all for you anyways. :D
-
If you look at the original post, you will see i did try to do much of what you said in figuring out the the delphi equivalent.
I've done something wrong in there, i think it's the pointer arithmetic and perhaps BaseDLL / size of image.
I'll review what i wrote and look at your suggestions.
Btw pkedpker... who are you from SubSpace??
-
Shit completely missed the first topic.. yeah this delphi is really alien to me.. You don't know me on subspace.. I used to play with Qualified as Pokemon 2001 other then that I didn't really know anyone else other then that asian girl Jaclyan.
I recently was trying to make a automatic continuum bot that flys around TW/EG (big zones) and kills like normal player from boredom.. I got very far.. managed to port the whole encryption from Continuum v0.40.. but these packets follow so much formats.. I did research some called Clusters some called Big Chunks/Small Chunks/Reliable Packets.. really pissed me off and I gave up on the project :p. I attempted to ignore these stupid packets.. only the ones i need.. like player positions and death packets etc.. but then I tried send packets back to server.. nothing happened.. Very strange never had this type of problem with any game.. But then again Continuum uses UDP protocol for all packet stuff.. maybe I did something wrong ehh.. I quit like you well..
But Continuum does give you this good feeling.. people shit talk and shit on you all day.. then you win.. and just leave to piss people off good feeling..
Also the feeling you can only get from subspace you get team killed.. then you play it cool.. and when the guy who team killed you least expects it.. kill him :D, he rages in private chat.. noob learn to play reported.. LOL. Then those people who really take the game seriously as ****, training everyday to hit invisible ships lol to learn shots and shit damn those people are committed.
Well I know no delphi sorry cannot help there.. but I tried to peice some code together might not even compile.
Delphi
Inc(p, skipLength[Pointer(Cardinal(p) + lastByte)^]);
As for this code
p += skipLength[p[lastByte]];
-
I look into that code after work (2nd day working for a new Web design company) as it's 1:30pm here.
And i remember your username from Continuum, did you make a couple of maps also back in the day?
-
Don't count on it compiling, I just pieced together some text from your source code.. not even understanding like what is Cardinal or how arrays work in Delphi.
@SS
Yeah I made a few maps for tw.. forgot which meh not important non ever got popular.. and who cares really lol.
Good job man webdesign you must be very good artist.
-
Artist no, i am more coder than designer...
One benefit of being Trenchwars's head web developer for a time while i was staff i suppose.
Update:
So after a bit of a coding session and bouncing ideas off people, i might have got the original function i posted working.
Still need to debug some more and do some sanity checks on the pointer and bytes found at that address for patching, but hey it doesn't crash now and looks like it's getting the correct pointer address!
Still going to look at memory mapping as it will more than likely be faster and more efficient.
-
Right so it most likely still needs work and checks, but here it is a working version of the original function i posted...
PHP Code:
Function SearchMemory(SearchDLL: hModule; wildcard: Byte; searchCode: Array of Byte; size: Integer) : Pointer;
Const
UCHAR_MAX = 255;
Var
scan,lastByte,defaultSkip,pID, searchEnd,SearchSuccess : Cardinal;
skipLength : ARRAY of Integer;
dllInfo : TModuleInfo;
p : pointer;
pbCurrent: PByte;
b: Byte;
begin
//WriteLog('------------------------------------------------------------------------------------');
//WriteLog('SearchMemory: Phase 1 - Builds skip length for chars that are not in search');
//The first loop builds the skip length for characters that aren't in the searched "string"
lastByte := size - 1;
while searchCode[lastByte] = wildcard do Dec(lastByte);
defaultSkip := lastByte;
//WriteLog('SearchMemory: Phase 2 - Building skip length');
//The second one builds the skip length for the characters in the string
scan := 0;
for scan:= 0 to lastByte - 1 do
begin
if searchCode[scan] = wildcard then defaultSkip := lastByte - scan;
end;
if defaultSkip > 1 then defaultSkip := defaultSkip - 1;
//WriteLog(Format('defaultSkip: %u', [scan]));
//WriteLog('SearchMemory: Phase 3 - Create Skiplength loop');
//Is just setting the default skip length
SetLength(skipLength, UCHAR_MAX);
for scan:=0 to UCHAR_MAX do
skipLength[scan] := defaultSkip;
//WriteLog('SearchMemory: Phase 4 - Searching, skipping bytes based on the skip length');
//Third loop searches for the string, skipping bytes based on the skip length
for scan := 0 to lastByte-1 do
begin
if searchCode[scan] <> wildcard then
begin
skipLength[searchCode[scan]] := lastByte - scan;
end;
end;
if GetModuleInformation(GetCurrentProcess, SearchDLL, @dllInfo, sizeof(dllInfo)) = FALSE then
begin
//WriteLog('SearchMemory: Phase 5 - GetModuleInformation failed...');
exit;
end
else
begin
//WriteLog('SearchMemory: Phase 5 - Im past GetModuleInformation...');
p := dllInfo.lpBaseOfDll;
//WriteLog(Format('SearchMemory: Checking dllInfo.lpBaseOfDll: %p', [p]));
searchEnd := Cardinal(dllInfo.lpBaseOfDll) + dllInfo.SizeOfImage;
searchEnd := searchEnd - (lastByte + 1);
//WriteLog(Format('SearchMemory: Checking StartAddr: %p, SearchEnd: %08X', [p, searchEnd]));
//WriteLog('------------------------------------------------------------------------------------');
while Cardinal(p) <= searchEnd do
begin
scan := lastByte;
while ((searchCode[scan] = wildcard) or (PByte(Cardinal(p)+scan)^ = searchCode[scan])) do
begin
if scan = 0 then
begin
result := P;
Inc(SearchSuccess);
Exit;
end;
scan := scan-1;
end;
p := Pointer(Cardinal(p)+skipLength[PByte(Cardinal(p)+lastByte)^]);
end;
if ( SearchSuccess = 0 ) then
begin
//WriteLog('ERROR: Search failed');
result := 0;
exit;
end;
if ( SearchSuccess > 1 ) then
begin
//WriteLog('ERROR: Search returned multiple results');
result := 0;
exit;
end;
result := 0;
end;
end;
-
Hey @Dwar
Tried to use that code but dont work (maybe because the dfm references).. would be nice if you could zip and send us this project. :D
ty