SRL Archive - Research & Development Lounge

Read memory for simba[Plugin]


CynicRus

2012-07-29 06:30:11

Hi all. Let me introduce for you read memory plugin for Simba.

The plugin is created for read a values ​​from a process memory. Search process is going by window title or exename. Writing into memory implemented.

See Dll in attachment, source aviable on a GIT:
https://github.com/CynicRus/memrw

Using example:

Type TMapCoord = record
x,y,z: single;
end;
Type TEverQuest2Char = record
DynHp,Hp,DynMp,Mp: integer;
NickName: string;
Coord: TMapCoord;
end;
var
Everquest2: integer;
MyChar: TEverQuest2Char;
MyCoord: TMapCoord;
procedure ReadEverquest2;
begin
EverQuest2:=GetProcessIdByName('EverQuest2.exe');
if Everquest2 <> 0 then
begin
MyCoord.x:= ReadFloatFromPid(EverQuest2,$0225C714,4);
MyCoord.z:= ReadFloatFromPid(EverQuest2,$0225C718,4);
MyCoord.y:= ReadFloatFromPid(EverQuest2,$0225C71C,4);
MyChar.DynHp:= ReadFromMemoryFromPID(EverQuest2,$022417CC,4);
MyChar.Hp:= ReadFromMemoryFromPID(EverQuest2,$022417D0,4);
MyChar.DynMp:= ReadFromMemoryFromPID(EverQuest2,$022417D8,4);
MyChar.Mp:= ReadFromMemoryFromPID(EverQuest2,$022417DC,4);
MyChar.NickName:=ReadStringFromPID(EverQuest2,$0225740C,6);
MyChar.Coord:=MyCoord;
end;
end;
begin
ReadEverquest2;
WriteLn('Game PID = ' + #32 + toStr(Everquest2));
WriteLn(toStr('My name is:'+#32+MyChar.NickName));
WriteLn('My health:'+#32+toStr(MyChar.DynHp)+'/'+toStr(MyChar.Hp));
WriteLn('My mana:'+#32+toStr(MyChar.DynMp)+'/'+toStr(MyChar.Mp));
WriteLn('My world position now:'+#13#10+'x ='+FloatToStr(MyChar.Coord.x)+#13#10+'y ='+FloatToStr(MyChar.Coord.y)+#13#10+'z ='+FloatToStr(MyChar.Coord.z));
end.
PS: Now,I will return to development a form designer:)

Justin

2012-07-29 06:35:28

Very nice work here!

putonajonny

2012-07-29 07:22:42

This looks really good, I already wondered if this was possible :)

Wizzup?

2012-07-29 07:24:04

Heh. What kind of game is this exactly? And how did you get the place of the HP in the memory?

CynicRus

2012-07-29 07:36:17

http://www.youtube.com/watch?v=uEVE0niPzrk - i find needed addres with Cheat Engine;
You can use for all native games i think. But I'm not sure about the address space of Java.

CynicRus

2012-07-29 07:40:09

When I finish with the designer - I shall add a record into memory, then theoretically you can do Simba trainers.

litoris

2012-07-29 10:09:08

From: CynicRus
When I finish with the designer - I shall add a record into memory, then theoretically you can do Simba trainers.


So, we could read item names and all?

Home

2012-07-29 10:42:25

This looks awesome! Great job mate!


Edit: Tested with Solitaire, works great :)

Rep +!

~Home

P1ng

2012-07-29 11:03:21

Cynic out of nowhere with a couple of amazing additions! Love your contributions so far mate :) +rep

Brandon

2012-07-29 11:09:45

From: CynicRus
When I finish with the designer - I shall add a record into memory, then theoretically you can do Simba trainers.


Not possible for runescape though.. Memory editing is server-sided. Unless you mean grabbing the bytes then using it in a script then that's totally possible.

I wrote a memory editor a while back.. It's bad but it is good enough to find memory locations given the bytes.. I used it in my avast crack:


#include <fstream>
#include <iterator>
#include <algorithm>

using namespace std;

int main()
{
typedef istream_iterator<unsigned char> input_iter_t;
typedef ostream_iterator<unsigned char> output_iter_t;

const off_t SIZE = 7;
char before[SIZE] = { 0x55, 0x53, 0x45, 0x52, 0x45, 0x4E, 0x56 }; //Search for UserEnv.dll
char after[SIZE] = { 0x42, 0x54, 0x43, 0x72, 0x61, 0x63, 0x6B }; //Replace it with BTCrack.dll

fstream f("ashBase.dll", ios::binary | ios::in | ios::out);

if (search(input_iter_t(f), input_iter_t(), before, before + SIZE) != input_iter_t())
{
f.seekp(-SIZE, ios::cur); //I don't like this
f.write(after, SIZE); //overwrite the found memory with the bytes specified by "after"
}
}


So.. how can this be useful? Well if you loop it over and over and over while keeping track of all found locations in a datastructure, you can dynamically find the location of ANYTHING.

I like the idea though.. But your'e going to have a lot of work. It's like writing a hex editor that keeps track of everything. That's what cheat engine does.

CynicRus

2012-07-29 12:15:32

Updated. Add functions:

function GetProcessIdByName(procname: string):integer;
function WriteToMemory(WindowName :integer;Address: integer;Value : Array of Byte;CountBytes: Integer) : integer;
To Brandon:I'm not trying to create a second, I'm trying to expand the functionality of Simba for more convenient use in other games. If I understood you correctly.

CynicRus

2012-07-29 13:54:56

Updated. Add function for reading and writing memory from Process.

CynicRus

2012-07-30 09:28:49

Simply example for using that:

program new;
{$loadlib rwmem.dll}
var
trnForm:TForm;
lblPid,lblpvalue,lblHandle,lblhvalue,lblval,lbl1val,lbladdr2,lbladdr2val: TLabel;
TButton0: TButton;
Values: array of byte;//Values for memory writing
WinMine: integer;//WinMine PID
MineHandle: integer;//WinMine window handle
Addr1,Addr2: integer;


const
default = 'Comic Sans MS';

{Trainer procedures}
Procedure InitAndFill;
begin
SetLength(Values,1);
Values[0]:=StrToInt('$90');
Addr1:=StrToInt('$1003830');
Addr2:=StrToInt('$1002ff5');
WinMine:=GetProcessIdByName('WinMine.exe');
lblpvalue.Caption:=IntToStr(WinMine);
MineHandle:=GetWindowName('Minesweeper');
lblhvalue.CAPTION:=IntToStr(MineHandle);
lbl1val.CAPTION:=IntToStr(ReadFromMemory(MineHandle,addr1,1));
lbladdr2val.CAPTION:=IntToStr(ReadFromMemory(MineHandle,addr2,1));
end;

procedure Patch(Sender: TObject);
begin
WriteMemoryToPID(WinMine,Addr1,Values,1);
WriteMemoryToPID(WinMine,Addr2,Values,1);
lbl1val.CAPTION:=ToStr(ReadFromMemoryFromPID(WinMine,addr1,1));
lbladdr2val.CAPTION:=ToStr(ReadFromMemoryFromPID(WinMine,addr2,1));
end;


procedure InitForm;
begin
//trnForm\\
trnForm:=TForm.Create(nil);
with trnForm do
begin
Caption:='MineSweeper';
Left:=401;
Top:=201;
Width:=217;
Height:=149;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lblPid\\
lblPid:=TLabel.Create(trnForm);
with lblPid do
begin
Parent:=trnForm;
Caption:='Minesweeper PID:';
Left:=13;
Top:=7;
Width:=95;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lblpvalue\\
lblpvalue:=TLabel.Create(trnForm);
with lblpvalue do
begin
Parent:=trnForm;
Caption:='lblpvalue';
Left:=150;
Top:=7;
Width:=49;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lblHandle\\
lblHandle:=TLabel.Create(trnForm);
with lblHandle do
begin
Parent:=trnForm;
Caption:='MS handle:';
Left:=12;
Top:=25;
Width:=60;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lblhvalue\\
lblhvalue:=TLabel.Create(trnForm);
with lblhvalue do
begin
Parent:=trnForm;
Caption:='lblhvalue';
Left:=130;
Top:=25;
Width:=49;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lblval\\
lblval:=TLabel.Create(trnForm);
with lblval do
begin
Parent:=trnForm;
Caption:='Address 1 value:';
Left:=12;
Top:=42;
Width:=86;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lbl1val\\
lbl1val:=TLabel.Create(trnForm);
with lbl1val do
begin
Parent:=trnForm;
Caption:='lbl';
Left:=130;
Top:=42;
Width:=14;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lbladdr2\\
lbladdr2:=TLabel.Create(trnForm);
with lbladdr2 do
begin
Parent:=trnForm;
Caption:='Address 2 value:';
Left:=11;
Top:=58;
Width:=86;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lbladdr2val\\
lbladdr2val:=TLabel.Create(trnForm);
with lbladdr2val do
begin
Parent:=trnForm;
Caption:='Addr2val';
Left:=130;
Top:=58;
Width:=48;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//TButton0\\
TButton0:=TButton.Create(trnForm);
with TButton0 do
begin
Parent:=trnForm;
Caption:='Modify';
Left:=11;
Top:=76;
Width:=75;
Height:=25;
OnClick:=@Patch;
Font.Name:='Arial Rounded MT Bold';
Font.Color:=clPurple;
Font.Size:=12;
end;
end;

procedure SafeInitForm;
var
v: TVariantArray;
begin
setarraylength(V, 0);
ThreadSafeCall('InitForm', v);
end;


procedure ShowFormModal;
begin
trnForm.ShowModal;
end;


procedure SafeShowFormModal;
var
v: TVariantArray;
begin
SetArrayLength(V, 0);
ThreadSafeCall('ShowFormModal', v);
end;


begin
SafeInitForm;
InitAndFill;
SafeShowFormModal;
end.

Hazzah

2012-07-30 17:05:09

From: CynicRus
Simply example for using that:

program new;
{$loadlib rwmem.dll}
var
trnForm:TForm;
lblPid,lblpvalue,lblHandle,lblhvalue,lblval,lbl1val,lbladdr2,lbladdr2val: TLabel;
TButton0: TButton;
Values: array of byte;//Values for memory writing
WinMine: integer;//WinMine PID
MineHandle: integer;//WinMine window handle
Addr1,Addr2: integer;


const
default = 'Comic Sans MS';

{Trainer procedures}
Procedure InitAndFill;
begin
SetLength(Values,1);
Values[0]:=StrToInt('$90');
Addr1:=StrToInt('$1003830');
Addr2:=StrToInt('$1002ff5');
WinMine:=GetProcessIdByName('WinMine.exe');
lblpvalue.Caption:=IntToStr(WinMine);
MineHandle:=GetWindowName('Minesweeper');
lblhvalue.CAPTION:=IntToStr(MineHandle);
lbl1val.CAPTION:=IntToStr(ReadFromMemory(MineHandle,addr1,1));
lbladdr2val.CAPTION:=IntToStr(ReadFromMemory(MineHandle,addr2,1));
end;

procedure Patch(Sender: TObject);
begin
WriteMemoryToPID(WinMine,Addr1,Values,1);
WriteMemoryToPID(WinMine,Addr2,Values,1);
lbl1val.CAPTION:=ToStr(ReadFromMemoryFromPID(WinMine,addr1,1));
lbladdr2val.CAPTION:=ToStr(ReadFromMemoryFromPID(WinMine,addr2,1));
end;


procedure InitForm;
begin
//trnForm\\
trnForm:=TForm.Create(nil);
with trnForm do
begin
Caption:='MineSweeper';
Left:=401;
Top:=201;
Width:=217;
Height:=149;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lblPid\\
lblPid:=TLabel.Create(trnForm);
with lblPid do
begin
Parent:=trnForm;
Caption:='Minesweeper PID:';
Left:=13;
Top:=7;
Width:=95;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lblpvalue\\
lblpvalue:=TLabel.Create(trnForm);
with lblpvalue do
begin
Parent:=trnForm;
Caption:='lblpvalue';
Left:=150;
Top:=7;
Width:=49;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lblHandle\\
lblHandle:=TLabel.Create(trnForm);
with lblHandle do
begin
Parent:=trnForm;
Caption:='MS handle:';
Left:=12;
Top:=25;
Width:=60;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lblhvalue\\
lblhvalue:=TLabel.Create(trnForm);
with lblhvalue do
begin
Parent:=trnForm;
Caption:='lblhvalue';
Left:=130;
Top:=25;
Width:=49;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lblval\\
lblval:=TLabel.Create(trnForm);
with lblval do
begin
Parent:=trnForm;
Caption:='Address 1 value:';
Left:=12;
Top:=42;
Width:=86;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lbl1val\\
lbl1val:=TLabel.Create(trnForm);
with lbl1val do
begin
Parent:=trnForm;
Caption:='lbl';
Left:=130;
Top:=42;
Width:=14;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lbladdr2\\
lbladdr2:=TLabel.Create(trnForm);
with lbladdr2 do
begin
Parent:=trnForm;
Caption:='Address 2 value:';
Left:=11;
Top:=58;
Width:=86;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//lbladdr2val\\
lbladdr2val:=TLabel.Create(trnForm);
with lbladdr2val do
begin
Parent:=trnForm;
Caption:='Addr2val';
Left:=130;
Top:=58;
Width:=48;
Height:=16;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
//TButton0\\
TButton0:=TButton.Create(trnForm);
with TButton0 do
begin
Parent:=trnForm;
Caption:='Modify';
Left:=11;
Top:=76;
Width:=75;
Height:=25;
OnClick:=@Patch;
Font.Name:='Arial Rounded MT Bold';
Font.Color:=clPurple;
Font.Size:=12;
end;
end;

procedure SafeInitForm;
var
v: TVariantArray;
begin
setarraylength(V, 0);
ThreadSafeCall('InitForm', v);
end;


procedure ShowFormModal;
begin
trnForm.ShowModal;
end;


procedure SafeShowFormModal;
var
v: TVariantArray;
begin
SetArrayLength(V, 0);
ThreadSafeCall('ShowFormModal', v);
end;


begin
SafeInitForm;
InitAndFill;
SafeShowFormModal;
end.


I'm not very good with stuff like this, but would it be possible to create Adventure Quest + AQWorlds + MechQuest bots with this. Fairly certain they are all flash and I know AQ can be hacked with Cheat engine (I think it crashes if you try to change values though).

Brandon

2012-07-30 18:15:45

From: Hazzah
I'm not very good with stuff like this, but would it be possible to create Adventure Quest + AQWorlds + MechQuest bots with this. Fairly certain they are all flash and I know AQ can be hacked with Cheat engine (I think it crashes if you try to change values though).


He doesn't have memory recording functionality in this so it won't allow you to minimalize memory values found or use them like cheat engine.
CheatEngine:

Search for value.
Record all addresses found.
Do something in game.
Search for new value
Record all new address found that match up with the old record. Delete old record list.

Repeat that procedure until desired (usually until it's clear which to change).
WriteProcessMemory…

And yes those games do allow memory editing. They can't block it unless they do server side checks (but they don't).

If he implements records then I think I can find some uses for this.

CynicRus

2012-07-31 01:06:08

Brandon: Record into memory is implemented now.

WriteMemoryToPID
WriteToMemory

CynicRus

2012-08-01 14:21:12

Plugin updated. A lot of bug fixed. Test script updated, git updated too. Enjoy!

dweg

2012-08-03 00:06:48

I will work on getting the basics of this for runescape. I know the health and prayer points, as well as skills can be read this way (they work in cheat engine). i believe inventory can also be read, with the items giving their id (like 526 for bones).

this can revolutionize simba forever. no more DTMS!

CynicRus

2012-08-03 04:25:22

From the DTM can not refuse, but is useful in many cases. However, direct reading values &#8203;&#8203;from memory should be as an alternative.

nokkasiili

2012-08-03 09:09:12

From: dweg
I will work on getting the basics of this for runescape. I know the health and prayer points, as well as skills can be read this way (they work in cheat engine). i believe inventory can also be read, with the items giving their id (like 526 for bones).

this can revolutionize simba forever. no more DTMS!


Memory positions in java change once on while

CynicRus

2012-08-03 09:25:42

Not sure about Java, but in the native applications you can always repeat a search chain the necessary values &#8203;&#8203;from an base address.