SRL Archive - SRL Member Goodies

Botting helper for other games [Plugin]


CynicRus

2012-08-05 11:39:15

Hi all. Let me introduce you to plugin for easy botting in other games with Simba.
Features:
  1. Reading values from process memory
  2. Writing into process memory
  3. Game window control
  4. Send key to Window
  5. Send text to game window
  6. Send mouse click to window
Functions description:
Window control:

Function GetWindowCaptionFromPid(Pid: integer):string;
Return window title by process id.

Function GetWindowHandle(WindowTitle: string):integer;
Return window handle by window title.

function GetWndHandleByPid(pid: integer):integer;
Return window handle by process id.

procedure MinimizeWindow(wnd: integer);
Minimizes an window of his handle

procedure RestoreWindow(wnd: integer);
Restores an window of his handle

procedure MaximizeWindow(wnd: integer);
Maximizes an window of his handle

procedure MoveWindow(wnd: integer; NewPos: TPoint;var OldPos: TPoint);
Move an window by handle.
Input:
- wnd: window handle
- NewPos: new window position coords
- OldPos: save current window coords
Memory reading:
 Function ReadFromMemory (WindowName,Address,Offset : integer): integer; 
Return integer value from memory address by window handle
input:
-WindowName: window handle
-Address: memory address
-Offset: need bytes count
Function ReadFloatFromMemory (WindowName,Address,Offset : integer): single;
Return float value from memory address by window handle
input:
-WindowName: window handle
-Address: memory address
-ASize: string length in bytes
function ReadStringFromMemory(WindowName,Address,ASize:integer): string;
Return string value from memory address by window handle
input:
-WindowName: window handle
-Address: memory address
-ASize: string length in bytes


function ReadMemoryFromPID (PID,Address,Offset : integer): integer;
Return integer value from memory address by process id
input:
-PID: process id
-Address: memory address
-Offset: need bytes count
Function ReadFloatFromPid (Pid,Address,Offset : integer): single;
Return float value from memory address by process id
input:
-PID: process id
-Address: memory address
-Offset: need bytes count

Function ReadStringFromPid (Pid,Address,Offset : integer): string;
Return string value from memory address by process id
input:
-PID: process id
-Address: memory address
-Offset: string length

Writing memory:

function WriteToMemory(WindowName :integer;Address: integer;Value : Array of Byte;CountBytes: Integer) : integer;
Writing bytes to memory by window handle.
input:
WindowName: window handle
Address: memory address
Value: value as bytes array
CountBytes: needed bytes count
unction WriteMemoryToPID(PID :integer;Address: integer;Value : Array of Byte;CountBytes: Integer) : integer;
Writing bytes to memory by window handle.
input:
PID: process id
Address: memory address
Value: value as bytes array
CountBytes: needed bytes count
Keyboard and mouse:

procedure ClickToWindow(Wnd: integer;Button: byte;x,y: integer);
Click on a point in the window.
Input:
Wnd: window handle
buttons: 0- one left click; 1 - right click; 2: double left click
x,y: x,y click coord.
procedure SendKeyToWindow(Wnd: integer; Key: byte; PressTime: integer);
Sends the key to window
Input:
wnd: window handle
Key: key code
PressTime: time, while key pressed
procedure SendTextToWindow(Wnd: integer; Text: string; PressTime: integer);
Sends the key to window
Input:
wnd: window handle
Text: some text to send in to window
PressTime: time, while key pressed

Applications:
function RunClient(PathToClient:string):boolean;
Run application, result true if app started.

procedure KillClient(pid: integer);
Kill application by process id.
Exported type for SRL adaptation:

type TCustomClient = record
CMSX1,CMSY1,CMSX2,CMSY2,CMSCX1,CMSCY1: integer;
end;
Procedure GetClientInfoFromWnd(Wnd: integer;var client: TCustomClient);
Fill custom client struct by window handle.

End description.

Written in lazarus, source aviables on GIT.
https://github.com/CynicRus/BottingHelper

Currently available only for Windows, in the future may be realized version for others platform.

Any suggestions or bug report print here.

Thanks for you advice.

The Best Regards From Cynic.

Justin

2012-08-05 11:41:30

Wow, amazing work. Keep it up!

Home

2012-08-05 13:07:03

Great work mate!

~Home

Janilabo

2012-08-05 13:13:26

Awesome work, as always, Cynic!
Keep these projects coming, cheers.

P.S. Your name looks very SMEXY with yellow color. ;)

~Jani

CynicRus

2012-08-06 03:12:02

GetWindowCaptionFromPid and GetWndHandleByPid fixed.

CynicRus

2012-08-06 06:46:50

Update plugin, add new features. Documentation updated.

Janilabo

2012-08-07 14:37:14

Thanks Cynic for documenting the commands. Helps a lot!
-Jani

nielsie95

2012-08-17 11:07:50

Looks good :) Any examples?

CynicRus

2012-08-18 02:12:53

As example you may see :

program BSAutoHealer;
{$loadlib bothelper.dll}
{$i SRL\SRL.simba}
Type TBSChar = record
DynHp,Hp,DynMp,Mp,CurrExp: integer;
end;
const
BaseCharAddr = $00AA2F38;//in that address located dinamicaly addres to Character struct(i think);
BaseStatAddr = $00AA7A80;
var
BSChar: TBSChar;
BSPid: integer;
X,Y: integer;
OldExp,GainedExp,GainedLvl,KillsCounter,RestoredHp,RestoredMP: integer;
HealPot,ManaPot: integer;
NKFlag: integer; //No Kill flag
function GetDynHP(pid: integer): integer;
var
i: integer;
begin
//read dynamicaly character address
i:=ReadFromMemoryFromPID(pid,BaseCharAddr,4);
//read hp value and return this
result:=ReadFromMemoryFromPID(pid,i+(9*4)+$188,4);
end;

function GetHP(pid: integer): integer;
var
i: integer;
begin
//read dynamicaly character address
i:=ReadFromMemoryFromPID(pid,BaseCharAddr,4);
//read hp value and return this
result:=ReadFromMemoryFromPID(pid,i+(8*4)+$188,4);
end;

function GetDynMP(pid: integer): integer;
var
i: integer;
begin
//read dynamicaly character address
i:=ReadFromMemoryFromPID(pid,BaseCharAddr,4);
//read mp value and return this
result:=ReadFromMemoryFromPID(pid,i+($b*4)+$188,4);
end;

function GetMP(pid: integer): integer;
var
i: integer;
begin
//read dynamicaly character address
i:=ReadFromMemoryFromPID(pid,BaseCharAddr,4);
//read mp value and return this
result:=ReadFromMemoryFromPID(pid,i+($a*4)+$188,4);
end;

function GetCurrExp(pid: integer): integer;
var
i: integer;
begin
//read dynamicaly character address
i:=ReadFromMemoryFromPID(pid,BaseCharAddr,4);
//read exp value and return this
result:=ReadFromMemoryFromPID(pid,i+$598,4);
end;
Procedure UpdateStats;
var
xp: integer;
begin
OldExp:=BSChar.CurrExp;
BSChar.DynHp:=GetDynHp(BSPid);
BSChar.DynMp:=GetDynMp(BSPid);
BSChar.Hp:=GetHp(BSPid);
BSChar.Mp:=GetMp(BSPid);
BSChar.CurrExp:=GetCurrExp(BSPid);
if OldExp<BSChar.CurrExp then
KillsCounter:=KillsCounter+1;//Kill mob counter
if OldExp = BSChar.CurrExp then
begin
if NKFlag = 0 then NKFlag:=1 else NKFlag:=NKFlag+1;
end;
if not NKFlag>0 then
begin
if BSChar.CurrExp>0 then
xp:=BSChar.CurrExp-OldExp
else begin
xp:=0;
GainedLvl:=GainedLvl+1;
end;
GainedExp:=GainedExp+xp;
end;
end;
Procedure SetupBS;
begin
BSPid:=GetProcessIdByName('Client.exe');
if BSPid <> 0 then
begin
//Fill unchanged fields
BSChar.Hp:=GetHp(BSPid);
BSChar.Mp:=GetMp(BSPid);
//Fill dynamicaly fields
BSChar.DynHp:=GetDynHp(BSPid);
BSChar.DynMp:=GetDynMp(BSPid);
BSChar.CurrExp:=GetCurrExp(BSPid);
//fill dtms
HealPot:= DTMFromString('mfgEAAHicE2JgYPjCxMDwFYg/QTGI/R2IPwPxOyB+DcRvgfgjVO4nEP9BUvMeSs9jZmBYCMSLgHgpFK8G4rVAvB6KNwPxFijeBMQbgXgnEO+C0nuBeHm+HBhzWjsyfL/TwPD5ajHD1RRPhv0G8gxTZgYynJ4qx3B9vQvDxaVWDE9PpDDEsjIztPZ5M2yt5mVIB7oDREcAaWoBRiphTAAAKmg1cg==');
ManaPot:= DTMFromString('mVAEAAHicE2BgYFBkZmBQhmJVIJZHwtLMEHk1INYEYi0gloOKSwKxEhDPBeLFQLwciNcA8RIk9log3gzE24B4OxBvgNJbgXgTEO8E4r8vpzIINE9m4LR2ZGCtPsrw/8cqBt7EHDCbMbyXgTF2BsOVde4MjMZBDIyGAQyMXhUMjAqmDPf3hDEwajgyUAoYKcToAAAwNh+8');
end else
begin
WriteLn('Blood and Soul client not finded!');
TerminateScript;
end;
end;

Procedure Heal;
var
DiffHp,Hp: integer;
begin
Hp:=BSChar.DynHp;
DiffHp:=BSChar.Hp-BSChar.DynHp;
if FindDTM(HealPot, X, Y, MIX1, MIY1, MIX2, MIY2) then
begin
Mouse(x, y, 4, 4, False);//FindDTM gives (x, y) as the coordinates of the DTM we made it look for.
Wait(1000);
UpdateStats();
if Hp>=BSChar.DynHp then begin
WriteLn('Something wrong-(')
TerminateScript;
end
else
begin
restoredHp:=restoredHp+DiffHp;
end;
end;
end;

Procedure Mana;
var
DiffMp,Mp: integer;
begin
Mp:=BSChar.DynMp;
DiffMp:=BSChar.Mp-BSChar.DynMp;
if FindDTM(ManaPot, X, Y, MIX1, MIY1, MIX2, MIY2) then
begin
Mouse(x, y, 4, 4, False);//FindDTM gives (x, y) as the coordinates of the DTM we made it look for.
Wait(1000);
UpdateStats();
if Mp>=BSChar.DynMp then begin
WriteLn('Something wrong-(')
TerminateScript;
end
else
begin
restoredMp:=restoredMp+DiffMp;
end;
end;
end;

Procedure CheckStats;
begin
UpdateStats;
if BSChar.DynHp<BSChar.Hp then
NKFlag:=0;
if BSChar.DynMp<BSChar.Mp then
NKFlag:=0;
if BSChar.DynHp<(BSChar.Hp/2) then
Heal;
if BSChar.DynMp<(BSChar.Mp/2) then
Mana;
end;

Procedure PrintVars;
begin
WriteLn('My Hits:'+#32+toStr(BSChar.DynHp)+'/'+toStr(BSChar.Hp));
WriteLn('My Mana:'+#32+toStr(BSChar.DynMp)+'/'+toStr(BSChar.Mp));
WriteLn('I gained:'+toStr(GainedExp)+#32+'exp');
WriteLn('I kill'+toStr(KillsCounter)+#32 + 'mobs');
WriteLn('I healed'+toStr(restoredHp));
WriteLn('I restore'+toStr(restoredMp)+#32+'mana');
WriteLn('I gained:'+toStr(GainedLvl)+#32+'lvls');
end;
begin
SetupBS;
repeat
CheckStats;
PrintVars;
until false;
end.

Flight

2012-09-06 06:34:09

CynicRus maybe you can help me. Where are you getting your memory addresses from? Is there some way to debug all the addresses from a specific window?

CynicRus

2012-09-06 07:07:25

I use Cheat Engine 6.2 for this. Use this program to search for a value in memory is very simple. It can also be used an ArtMoney.
http://www.youtube.com/watch?v=vHg9ickNkCA - that Cheat engine tutorial.

http://www.youtube.com/watch?v=sWYpmWNF3kg - that ArtMoney tutorial

Gala

2012-09-07 14:21:32

From: CynicRus
As example you may see :

program BSAutoHealer;
{$loadlib bothelper.dll}
{$i SRL\SRL.simba}
Type TBSChar = record
DynHp,Hp,DynMp,Mp,CurrExp: integer;
end;
const
BaseCharAddr = $00AA2F38;//in that address located dinamicaly addres to Character struct(i think);
BaseStatAddr = $00AA7A80;
var
BSChar: TBSChar;
BSPid: integer;
X,Y: integer;
OldExp,GainedExp,GainedLvl,KillsCounter,RestoredHp,RestoredMP: integer;
HealPot,ManaPot: integer;
NKFlag: integer; //No Kill flag
function GetDynHP(pid: integer): integer;
var
i: integer;
begin
//read dynamicaly character address
i:=ReadFromMemoryFromPID(pid,BaseCharAddr,4);
//read hp value and return this
result:=ReadFromMemoryFromPID(pid,i+(9*4)+$188,4);
end;

function GetHP(pid: integer): integer;
var
i: integer;
begin
//read dynamicaly character address
i:=ReadFromMemoryFromPID(pid,BaseCharAddr,4);
//read hp value and return this
result:=ReadFromMemoryFromPID(pid,i+(8*4)+$188,4);
end;

function GetDynMP(pid: integer): integer;
var
i: integer;
begin
//read dynamicaly character address
i:=ReadFromMemoryFromPID(pid,BaseCharAddr,4);
//read mp value and return this
result:=ReadFromMemoryFromPID(pid,i+($b*4)+$188,4);
end;

function GetMP(pid: integer): integer;
var
i: integer;
begin
//read dynamicaly character address
i:=ReadFromMemoryFromPID(pid,BaseCharAddr,4);
//read mp value and return this
result:=ReadFromMemoryFromPID(pid,i+($a*4)+$188,4);
end;

function GetCurrExp(pid: integer): integer;
var
i: integer;
begin
//read dynamicaly character address
i:=ReadFromMemoryFromPID(pid,BaseCharAddr,4);
//read exp value and return this
result:=ReadFromMemoryFromPID(pid,i+$598,4);
end;
Procedure UpdateStats;
var
xp: integer;
begin
OldExp:=BSChar.CurrExp;
BSChar.DynHp:=GetDynHp(BSPid);
BSChar.DynMp:=GetDynMp(BSPid);
BSChar.Hp:=GetHp(BSPid);
BSChar.Mp:=GetMp(BSPid);
BSChar.CurrExp:=GetCurrExp(BSPid);
if OldExp<BSChar.CurrExp then
KillsCounter:=KillsCounter+1;//Kill mob counter
if OldExp = BSChar.CurrExp then
begin
if NKFlag = 0 then NKFlag:=1 else NKFlag:=NKFlag+1;
end;
if not NKFlag>0 then
begin
if BSChar.CurrExp>0 then
xp:=BSChar.CurrExp-OldExp
else begin
xp:=0;
GainedLvl:=GainedLvl+1;
end;
GainedExp:=GainedExp+xp;
end;
end;
Procedure SetupBS;
begin
BSPid:=GetProcessIdByName('Client.exe');
if BSPid <> 0 then
begin
//Fill unchanged fields
BSChar.Hp:=GetHp(BSPid);
BSChar.Mp:=GetMp(BSPid);
//Fill dynamicaly fields
BSChar.DynHp:=GetDynHp(BSPid);
BSChar.DynMp:=GetDynMp(BSPid);
BSChar.CurrExp:=GetCurrExp(BSPid);
//fill dtms
HealPot:= DTMFromString('mfgEAAHicE2JgYPjCxMDwFYg/QTGI/R2IPwPxOyB+DcRvgfgjVO4nEP9BUvMeSs9jZmBYCMSLgHgpFK8G4rVAvB6KNwPxFijeBMQbgXgnEO+C0nuBeHm+HBhzWjsyfL/TwPD5ajHD1RRPhv0G8gxTZgYynJ4qx3B9vQvDxaVWDE9PpDDEsjIztPZ5M2yt5mVIB7oDREcAaWoBRiphTAAAKmg1cg==');
ManaPot:= DTMFromString('mVAEAAHicE2BgYFBkZmBQhmJVIJZHwtLMEHk1INYEYi0gloOKSwKxEhDPBeLFQLwciNcA8RIk9log3gzE24B4OxBvgNJbgXgTEO8E4r8vpzIINE9m4LR2ZGCtPsrw/8cqBt7EHDCbMbyXgTF2BsOVde4MjMZBDIyGAQyMXhUMjAqmDPf3hDEwajgyUAoYKcToAAAwNh+8');
end else
begin
WriteLn('Blood and Soul client not finded!');
TerminateScript;
end;
end;

Procedure Heal;
var
DiffHp,Hp: integer;
begin
Hp:=BSChar.DynHp;
DiffHp:=BSChar.Hp-BSChar.DynHp;
if FindDTM(HealPot, X, Y, MIX1, MIY1, MIX2, MIY2) then
begin
Mouse(x, y, 4, 4, False);//FindDTM gives (x, y) as the coordinates of the DTM we made it look for.
Wait(1000);
UpdateStats();
if Hp>=BSChar.DynHp then begin
WriteLn('Something wrong-(')
TerminateScript;
end
else
begin
restoredHp:=restoredHp+DiffHp;
end;
end;
end;

Procedure Mana;
var
DiffMp,Mp: integer;
begin
Mp:=BSChar.DynMp;
DiffMp:=BSChar.Mp-BSChar.DynMp;
if FindDTM(ManaPot, X, Y, MIX1, MIY1, MIX2, MIY2) then
begin
Mouse(x, y, 4, 4, False);//FindDTM gives (x, y) as the coordinates of the DTM we made it look for.
Wait(1000);
UpdateStats();
if Mp>=BSChar.DynMp then begin
WriteLn('Something wrong-(')
TerminateScript;
end
else
begin
restoredMp:=restoredMp+DiffMp;
end;
end;
end;

Procedure CheckStats;
begin
UpdateStats;
if BSChar.DynHp<BSChar.Hp then
NKFlag:=0;
if BSChar.DynMp<BSChar.Mp then
NKFlag:=0;
if BSChar.DynHp<(BSChar.Hp/2) then
Heal;
if BSChar.DynMp<(BSChar.Mp/2) then
Mana;
end;

Procedure PrintVars;
begin
WriteLn('My Hits:'+#32+toStr(BSChar.DynHp)+'/'+toStr(BSChar.Hp));
WriteLn('My Mana:'+#32+toStr(BSChar.DynMp)+'/'+toStr(BSChar.Mp));
WriteLn('I gained:'+toStr(GainedExp)+#32+'exp');
WriteLn('I kill'+toStr(KillsCounter)+#32 + 'mobs');
WriteLn('I healed'+toStr(restoredHp));
WriteLn('I restore'+toStr(restoredMp)+#32+'mana');
WriteLn('I gained:'+toStr(GainedLvl)+#32+'lvls');
end;
begin
SetupBS;
repeat
CheckStats;
PrintVars;
until false;
end.


Sry I can't decide, but is this for Wow? I haven't played it but I read "mana" and stuff. Doesn't blizzard force you to download some anti bot software?

Your example really pushed me to try it out myself, thanks man :)

Flight

2012-10-21 12:41:11

Hmm I'm having a bit of trouble with mine, CynicRus. I'm trying to read the integer from my address "2A26D7AC". According to my memory editor this address should have a current value of, let's say, "30511447677888". When I read this address in Simba with your plugin I get a value of "182647888"; quite a big difference. Am I going wrong some where?


program MemoryReader;
{$loadlib bothelper.dll}

const
BaseAddr = $2A26D7AC;

var
BSPid: integer;

procedure CalcXCoord;
var
i: integer;
begin
BSPid:=GetProcessIdByName('javaw.exe');
if BSPid <> 0 then
begin
i := ReadFromMemory(BSPid, BaseAddr, 8);
Writeln(ToStr(i));
end;
end;


begin
CalcXCoord;
end.

Perhaps I have const "BaseAddr" incorrectly defined or I'm not using GetProcessIdByName / ReadFromMemory right?

CynicRus

2012-10-22 05:46:01

Use ReadMemoryFromPid. Because you get PID with GetProcessIdByName, use ReadFromMemory only if you have the window handle. In this case, you are trying to read the value of the window, which is not. And at the memory address is everything.

program MemoryReader;
{$loadlib bothelper.dll}

const
BaseAddr = $2A26D7AC;

var
BSPid: integer;

procedure CalcXCoord;
var
i: integer;
begin
BSPid:=GetProcessIdByName('javaw.exe');
if BSPid <> 0 then
begin
i := ReadMemoryFromPid(BSPid, BaseAddr, 8);
Writeln(ToStr(i));
end;
end;


begin
CalcXCoord;
end.
Cheers, Cynic.

Flight

2012-10-22 06:12:43

From: CynicRus
Use ReadMemoryFromPid. Because you get PID with GetProcessIdByName, use ReadFromMemory only if you have the window handle. In this case, you are trying to read the value of the window, which is not. And at the memory address is everything.

Cheers, Cynic.


Sounds good, but now I'm getting an Access Violation error at this line:
i := ReadMemoryFromPid(BSPid, BaseAddr, 8);

Running as administrator as well; any ideas?

CynicRus

2012-10-22 06:14:54

In Java - dynamically memory model. So it is quite natural that you are able to access an address that does not exist. In Java applications, the address space is changed after each restart.

Flight

2012-10-22 06:19:41

From: CynicRus
In Java - dynamically memory model. So it is quite natural that you are able to access an address that does not exist. In Java applications, the address space is changed after each restart.


Oh darn it, that's not what I was hoping to hear. :S Thanks again, CynicRus.

CynicRus

2012-10-22 06:31:12

No problem. You can try to calculate the offset from the base address, but this is not guaranteed in Java.