Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


[C#]Trainer Code Injection (Example)
Goto page 1, 2  Next
 
Post new topic   This topic is locked: you cannot edit posts or make replies.    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
ej52
Cheater
Reputation: 0

Joined: 29 Mar 2011
Posts: 39
Location: Mother City

PostPosted: Wed Mar 30, 2011 8:31 pm    Post subject: [C#]Trainer Code Injection (Example) Reply with quote

Hey all

I only started coding game trainers yesterday so please feel free to tell me
if i am doing something wrong or if there is a better way of doing it Smile

This is just a quick example on how to create a "code cave" and inject code, using C#.

I am using the memory functions from Darkjohn20's thread called "C# Trainer Tutorial (With Example)"
which is located in the "Cheat Engine Tutorials" Section, i just added a few functions to create the "code cave".

Here is the code i added ...

MemoryAPI Class:
Code:

[Flags]
public enum AllocType
{
    Commit = 0x1000,
    Reserve = 0x2000,
    Decommit = 0x4000,
}
[Flags]
public enum Protect
{
    Execute = 0x10,
    ExecuteRead = 0x20,
    ExecuteReadWrite = 0x40,
}
[Flags]
public enum FreeType
{
    Decommit = 0x4000,
    Release = 0x8000,
}


Code:

[DllImport("kernel32.dll")]
public static extern Int32 VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, AllocType flAllocationType, Protect flProtect);
[DllImport("kernel32.dll")]
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, FreeType dwFreeType);


Memory Class:
Code:

public void Alloc(out int Addr, int Size)
{
    Addr =  MemoryAPI.VirtualAllocEx(m_hProcess, IntPtr.Zero, Size, MemoryAPI.AllocType.Commit, MemoryAPI.Protect.ExecuteReadWrite);
}
public bool Dealloc(int Addr)
{
    return MemoryAPI.VirtualFreeEx(m_hProcess, (IntPtr)Addr, 0, MemoryAPI.FreeType.Release);
}


As you can see iv'e created two public functions Alloc() and Dealloc() which act exactly the same as the equivalent functions in AA.

Here is a AA script i did for instant build with FarmFrenzy 3 IceAge ...

Code:

[ENABLE]
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)

newmem:

originalcode:
fst dword ptr [esi+00000354]
mov dword ptr [esi+00000354],(float)20
exit:
jmp returnhere

00545943:
jmp newmem
nop
returnhere:

[DISABLE]
dealloc(newmem)
00545943:
fst dword ptr [esi+00000354]


Here is the exact same AA script in C# Very Happy
Note this example does not have any error checking ...

Code:

int newmem = 0;

private void EnableHack()
{
    Process[] process = Process.GetProcessesByName("FarmFrenzy3_Arctica.wrp"); //Find FarmFrenzy3_Arctica.wrp.exe
    oMemory.ReadProcess = process[0]; //Sets the Process to Read/Write From/To
    oMemory.Open(); //Open Process
    oMemory.Alloc(out newmem, 0x800); //New memory allocation "code cave"

    int ad1 = Addr.ToDec("00545943"); //Static address
    int ad2 = newmem; //newmem
    int ad3 = ad2 + 0x06; //newmem + 6 bytes (see bv2 below)
    int ad4 = ad2 + 0x10; //newmem + 10 bytes (see bv3 below)

    byte[] bv1 = Jmp(Addr.ToHex(ad2), Addr.ToHex(ad1), true); //jmp newmem nop (jmp newmem = 5 bytes, so add a nop)
    byte[] bv2 = { 0xD9, 0x96, 0x54, 0x03, 0x00, 0x00 }; //fst dword ptr [esi+00000354]
    byte[] bv3 = { 0xC7, 0x86, 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x41 }; //mov [esi+00000354],41A00000
    byte[] bv4 = Jmp(Addr.ToHex(ad1 + 0x06), Addr.ToHex(ad4), false); //jmp 00545949 (ad1 + 6 bytes)

    int bytes; //Holds how many bytes were written by Write()

    oMemory.Write((IntPtr)ad1, bv1, out bytes);
    oMemory.Write((IntPtr)ad2, bv2, out bytes);
    oMemory.Write((IntPtr)ad3, bv3, out bytes);
    oMemory.Write((IntPtr)ad4, bv4, out bytes);

    oMemory.CloseHandle(); //Close Memory Handle
}

private void DisableHack()
{
    Process[] process = Process.GetProcessesByName("FarmFrenzy3_Arctica.wrp"); //Find FarmFrenzy3_Arctica.wrp.exe
    oMemory.ReadProcess = process[0]; //Sets the Process to Read/Write From/To
    oMemory.Open(); //Open Process
    oMemory.Dealloc(newmem); //Release newmem "code cave"

    int ad1 = Addr.ToDec("00545943"); //Static address
    byte[] bv1 = { 0xD9, 0x96, 0x54, 0x03, 0x00, 0x00 }; //fst dword ptr [esi+00000354]

    int bytes; //Holds how many bytes were written by Write()

    oMemory.Write((IntPtr)ad1, bv1, out bytes);

    oMemory.CloseHandle(); //Close Memory Handle
}

private byte[] Jmp(string to, string from, bool nop)
{
    return Jmp(Convert.ToInt32("0x" + to, 16), Convert.ToInt32("0x" + from, 16), nop);
}

private byte[] Jmp(int to, int from, bool nop)
{
    string dump = (to - from - 5).ToString("X"); //Get original bytes

    if (dump.Length == 7) //Make sure we have 4 bytes
        dump = "0" + dump;

    dump = dump + "E9"; //Add JMP
    if (nop)
        dump = "90" + dump; //Add NOP if needed

    byte[] hex = new byte[dump.Length / 2];
    for (int i = 0; i < hex.Length; i++)
    {
        hex[i] = Convert.ToByte(dump.Substring(i * 2, 2), 16); //Set each byte to 2 chars
    }
    Array.Reverse(hex); //Reverse byte array for use with Write()

    return hex;
}


The byte arrays for bv2 and bv3 in EnableHack(), and bv1 in DisableHack() i got from running the AA script and checking the bytes in Memory View.

Hope this can help a few of you C# coders, if any1 needs me to explain anything further jst ask Smile

Regards
Ej52


Last edited by ej52 on Thu Mar 31, 2011 1:44 pm; edited 4 times in total
Back to top
View user's profile Send private message
Krähne
Expert Cheater
Reputation: 0

Joined: 06 Jun 2010
Posts: 108
Location: Inside of my Kernel

PostPosted: Wed Mar 30, 2011 9:12 pm    Post subject: Reply with quote

Nice code, Very useful. btw is also valid use the String.Format for show to hex format.

Something like:

Code:
byte[] Buffer = new byte[4] { 0xAA, 0xBB, 0xCC, 0xDD };
string HexResult = String.Empty;

HexResult = String.Format("{0:X4}", BitConverter.ToInt32(Buffer, 0));

_________________
Excuse me if you don't understand what I just said, but "english" isn't my native language.
Back to top
View user's profile Send private message MSN Messenger
ej52
Cheater
Reputation: 0

Joined: 29 Mar 2011
Posts: 39
Location: Mother City

PostPosted: Sun Apr 10, 2011 6:46 am    Post subject: Reply with quote

@DaasCook thx 4 the comment, i have used String.Format in the opcde library Smile
_________________
Hitler dNt HiDe WaT mOtHa NaTurE pRoViDe ... Razz
Back to top
View user's profile Send private message
Pingo
Grandmaster Cheater
Reputation: 8

Joined: 12 Jul 2007
Posts: 571

PostPosted: Sun Apr 10, 2011 6:01 pm    Post subject: Reply with quote

You should make some functions for this. So you wont be using as much code.

That same injection could be as small as this
Inject(Jump_From, Next_Instruction, "Injection");
and to deallocate
DeAllocate(Jump_From);

Another thing you might want to look into is codeshifting. That code would only work for static addresses like 00545943

_________________
Back to top
View user's profile Send private message
ej52
Cheater
Reputation: 0

Joined: 29 Mar 2011
Posts: 39
Location: Mother City

PostPosted: Sun Apr 10, 2011 6:24 pm    Post subject: Reply with quote

Hey Pingo

Sorry i can't reply 2 ur PM yet Sad

This code was jst a quick example b4 i started coding the library.

The library has a method 4 nearly ever opcode instruction and
it automatically works out all the offsets by itself.

Simple example ...

Code:

int cave = mem.Alloc(0x400); //Create code cave of 1kb

mem.Mark(0x012E1850); //Start writing at this address
mem.Call(cave); //call "cave"
mem.Nop(); //nop
mem.Mark(cave); //Start writing to the code cave
mem.Fst(new mAddr(mReg.ESI, 0x354)); //fst [esi+00000354]
mem.Mov(new mAddr(mReg.ESI, 0x354), 20f); //mov [esi+00000354],(float)20
mem.Ret(); //ret

mem.Write(); //Write all the above instructions


This library makes it easy 2 convert AA scripts into .Net game trainers.
I am still workin on a few methods but hope 2 release the library soon Smile

_________________
Hitler dNt HiDe WaT mOtHa NaTurE pRoViDe ... Razz
Back to top
View user's profile Send private message
Pingo
Grandmaster Cheater
Reputation: 8

Joined: 12 Jul 2007
Posts: 571

PostPosted: Sun Apr 10, 2011 7:20 pm    Post subject: Reply with quote

Looking better. I dont think you'l need to specify the byte size when allocating. It'l get rounded up to a next page i think.

How are you storing these instruction in the mem class? Then using mem.Write();
Are you adding them to a byte array?

_________________
Back to top
View user's profile Send private message
ej52
Cheater
Reputation: 0

Joined: 29 Mar 2011
Posts: 39
Location: Mother City

PostPosted: Mon Apr 11, 2011 12:00 am    Post subject: Reply with quote

Yea you are right about the byte size when allocating, did'nt read the docs properly Razz

Yes this library has 1 main class which has methods 2 handle everything
Process, Memory and Opcodes Very Happy

Ever instruction gets added 2 a List<AOB> (Which can be retrieved 4 debugging Smile)
and writes them all when u call mem.Write().

AOB struct only has 2 properties Addr and Aob which should be self explanatory Razz

_________________
Hitler dNt HiDe WaT mOtHa NaTurE pRoViDe ... Razz
Back to top
View user's profile Send private message
Pingo
Grandmaster Cheater
Reputation: 8

Joined: 12 Jul 2007
Posts: 571

PostPosted: Mon Apr 11, 2011 4:36 am    Post subject: Reply with quote

Remember jump bytes written from one address isnt the same for another.
from 012E1850 to 1F000000 wont be the same as
from 013E1850 to 1F000000
to jump its Cave - Address - 5
to jump back its Next_Instruction - Cave - 5
You probably already know this but just incase you didnt.

_________________
Back to top
View user's profile Send private message
ej52
Cheater
Reputation: 0

Joined: 29 Mar 2011
Posts: 39
Location: Mother City

PostPosted: Mon Apr 11, 2011 5:26 am    Post subject: Reply with quote

Yip i am aware of who 2 calculate the AOB for jumps
and the library calculates all the offsets automatically
thts why you dnt have 2 include the address in every
function, you just hav to mark the address where you
want 2 start writing ... mem.Mark(0x012E1850);

_________________
Hitler dNt HiDe WaT mOtHa NaTurE pRoViDe ... Razz
Back to top
View user's profile Send private message
Pingo
Grandmaster Cheater
Reputation: 8

Joined: 12 Jul 2007
Posts: 571

PostPosted: Mon Apr 11, 2011 6:13 am    Post subject: Reply with quote

ah ic. How did you calculate the next instruction address? I couldnt figure that out.
Cause the jump requires 5 bytes but the next instruction might be 3 bytes away. So you'd need to go to the instruction after that to avoid a crash.
Thats why i use Jump_From, Next_Instruction.
Got any suggestions?

_________________
Back to top
View user's profile Send private message
ej52
Cheater
Reputation: 0

Joined: 29 Mar 2011
Posts: 39
Location: Mother City

PostPosted: Mon Apr 11, 2011 6:52 am    Post subject: Reply with quote

If you look at my prev example i used "call" and "ret" instead of jumps
as the "ret" instruction automatically returns 2 the original code.

Code:

int cave = mem.Alloc(0x400); //Create code cave of 1kb

mem.Mark(0x012E1850); //Start writing at this address
mem.Call(cave); //call "cave"
mem.Nop(); //nop
mem.Mark(cave); //Start writing to the code cave
mem.Fst(new mAddr(mReg.ESI, 0x354)); //fst [esi+00000354]
mem.Mov(new mAddr(mReg.ESI, 0x354), 20f); //mov [esi+00000354],(float)20
mem.Ret(); //ret

mem.Write(); //Write all the above instructions


I used to use it like this with jumps ...

Code:

int start = 0x012E1850;
int cave = mem.Alloc(0x400); //Create code cave of 1kb

mem.Mark(start); //Start writing at this address
mem.Jmp(cave); //call "cave"
mem.Nop(); //nop
mem.Mark(cave); //Start writing to the code cave
mem.Fst(new mAddr(mReg.ESI, 0x354)); //fst [esi+00000354]
mem.Mov(new mAddr(mReg.ESI, 0x354), 20f); //mov [esi+00000354],(float)20
mem.Jmp(start + 6); //jump to start address + 6bytes (jmp + nop = 6)

mem.Write(); //Write all the above instructions


As you can see you would still have to manually set the address to
return to the original code with jumps, but i am workin on automating
the offsets for that aswell Smile

_________________
Hitler dNt HiDe WaT mOtHa NaTurE pRoViDe ... Razz


Last edited by ej52 on Mon Apr 11, 2011 2:25 pm; edited 1 time in total
Back to top
View user's profile Send private message
Pingo
Grandmaster Cheater
Reputation: 8

Joined: 12 Jul 2007
Posts: 571

PostPosted: Mon Apr 11, 2011 9:35 am    Post subject: Reply with quote

I might go try again. Could your class convert something like this.

Code:
[Enable]
alloc(Cave,128)
Cave:
mov ecx,[esi+4c]
mov [Cave-8],ecx
mov ecx,[Cave-4]
mov [ecx+Cave+40],esi
cmp ecx,50
je Cave+1f
add ecx,04
jmp Cave+24
mov ecx,0
mov [Cave-4],ecx
mov ecx,[Cave-8]
mov ecx,[esi+4c]
fld dword ptr [esi+5c]
jmp game.exe+Next_Offset

game.exe+Start_Offset:
jmp Cave

[Disable]
dealloc(Cave)
game.exe+Start_Offset:
db 8b 4e 4c d9 46 5c

moving values in and out of the cave

_________________
Back to top
View user's profile Send private message
ej52
Cheater
Reputation: 0

Joined: 29 Mar 2011
Posts: 39
Location: Mother City

PostPosted: Mon Apr 11, 2011 10:33 am    Post subject: Reply with quote

Yip it can, heres what it will look like in C# Smile

Code:

int cave = mem.Alloc(128);

mem.Mark(Start_Offset);
mem.Jmp(cave);
mem.Mark(cave);
mem.Mov(mReg.ECX, new mAddr(mReg.ESI, 0x4C));
mem.Mov(new mAddr(cave - 8), mReg.ECX);
mem.Mov(mReg.ECX, new mAddr(cave-4));
mem.Mov(new mAddr(mReg.ECX, cave + 0x40), mReg.ESI);
mem.Cmp(mReg.ECX, (byte)0x50);
mem.Jmp(mCond.Equal, cave + 0x1F); //jumps to ( mov ecx,0 )
mem.Add(mReg.ECX, (byte)4);
mem.Jmp(cave + 0x24); //jumps to ( mov [cave-4],ecx )
mem.Mov(mReg.ECX, 0);
mem.Mov(new mAddr(cave - 4), mReg.ECX);
mem.Mov(mReg.ECX, new mAddr(cave - 8));
mem.Mov(mReg.ECX, new mAddr(mReg.ESI, 0x4C));
mem.Fld(new mAddr(mReg.ESI, 0x5C));
mem.Jmp(Start_Offset + 5); //jumps to original instruction code


As you can see the last offset you will have 2 calculate yourself
or just get it from the memory view in CE.

As i said b4 this library just makes it easier to convert AA into .Net
its upto the user 2 set the correct addresses and offsets.

As for deallocating the code cave there is a method for tht 2
Code:

mem.Dealloc(cave);

_________________
Hitler dNt HiDe WaT mOtHa NaTurE pRoViDe ... Razz
Back to top
View user's profile Send private message
Pingo
Grandmaster Cheater
Reputation: 8

Joined: 12 Jul 2007
Posts: 571

PostPosted: Tue Apr 12, 2011 8:54 am    Post subject: Reply with quote

Pure sweetness! Let me know when you're at the testing stage. I'll try it.
_________________
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8587
Location: 127.0.0.1

PostPosted: Tue Apr 12, 2011 3:22 pm    Post subject: Reply with quote

Here is a method of injecting ASM using FASM as a base:
http://www.gamedeception.net/threads/14333-FasmManaged

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   This topic is locked: you cannot edit posts or make replies.    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites