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 


Reliably hook a game's engine

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
Mal1t1a
Cheater
Reputation: 0

Joined: 03 Jan 2010
Posts: 40

PostPosted: Tue Jun 03, 2014 7:25 pm    Post subject: Reliably hook a game's engine Reply with quote

Before you read

I want to make this as clear as day: NOTHING THAT I AM DOING INVOLVES WRITING TO THE ACTUAL PROCESS. I AM NOT MANIPULATING MEMORY AND THE ENTIRE GAME IS SERVER-SIDE.

Introduction

Okay, it's been awhile since I last posted about hooking into a game's memory to inject a .dll, that I never did get to finish. Harddrive failure, and there was no chance at recovering the lost data (tried with spinrite and alternatives). So I gave up on it, so I thought. I've come back to the hacking scene as my programming skills need to be sharpened. I've been thinking about this for awhile, and a .dll injection seems like the only way to go, because a timer just doesn't do it. I need to know exactly when something changes exactly AFTER it changes and exactly BEFORE it changes again.

Background experience

I'm experienced at reverse engineering games and applications, but I'm by no means a pro. I can navigate pretty fluidly around the basics like the back of my hand. What I mean by this is identifying the memory type, and finding it. Sometimes this is very tricky, what with pointers and memory types that should be one thing but turn out to be another. Various game events, one of which I want to hook is object specific updates.

My goal

My goal is to create a basic A.I., which I have been working on in VB.NET using a timer that updates every milisecond, recording the execution time of the A.I. and adjusts itself to the computation speed so it doesn't create lag, and providing an accurate "Thought rate" or "Processing rate". This process get's very cpu intensive due to the extent of the amount of "ReadProcessMemory" calls being made to get a fresh "game state". Sometimes it takes anywhere from 1 - 5 SECONDS. To play this game you need to have a reaction time less than 1000ms (more like 100ms ~ 250ms) and even then it doesn't mean you'll win. I want to battle it against the A.I. that is already implemented inside of the game. All of this to watch my own A.I. grow and become better and better.

Code history and snippets

My current code is heavily based in VB.NET because that's what I grew up learning, it's the easiest to understand, and it's pretty fast to code in. I HAVE to use structured send and post messages in order to do a simple tasks like mouse operation (move and click), and keyboard operation (hold key, release key, press key, and use modifiers). I've already put in a ton of hours of work to try to get a small library of functions and methods to simulate "gameplay".

Something as simple as sending a "Mouse Move and Click" seems to be very bloated:

Code:

  Public Sub SendMouseMoveClick(ByVal ProcessName As String, ByVal Spot As Point, ByVal mkButton As IntPtr)
        Dim hWnd As IntPtr = GetProcessWindowHandle(ProcessName)
        If mkButton = MK_LBUTTON Then
            SendMessage(hWnd, WM_MOUSEACTIVATE, hWnd, MakeLParam(1, WM_LBUTTONDOWN))

            SendMessage(hWnd, WM_SETCURSOR, WM_MOUSEMOVE, MakeLParam(1, WM_MOUSEMOVE))
            SendMessage(hWnd, WM_MOUSEMOVE, WM_MOUSEMOVE, MakeLParam(Spot.X, Spot.Y))

            SendMessage(hWnd, WM_SETCURSOR, WM_LBUTTONDOWN, MakeLParam(1, WM_LBUTTONDOWN))
            SendMessage(hWnd, WM_LBUTTONDOWN, mkButton, MakeLParam(Spot.X, Spot.Y))

            SendMessage(hWnd, WM_SETCURSOR, WM_MOUSEMOVE, MakeLParam(1, WM_MOUSEMOVE))
            SendMessage(hWnd, WM_MOUSEMOVE, WM_MOUSEMOVE, MakeLParam(Spot.X, Spot.Y))

            SendMessage(hWnd, WM_SETCURSOR, WM_LBUTTONUP, MakeLParam(1, WM_LBUTTONUP))
            SendMessage(hWnd, WM_LBUTTONUP, 0, MakeLParam(Spot.X, Spot.Y))
        ElseIf mkButton = MK_RBUTTON Then
            SendMessage(hWnd, WM_MOUSEACTIVATE, hWnd, MakeLParam(1, WM_RBUTTONDOWN))

            SendMessage(hWnd, WM_SETCURSOR, WM_MOUSEMOVE, MakeLParam(1, WM_MOUSEMOVE))
            SendMessage(hWnd, WM_MOUSEMOVE, WM_MOUSEMOVE, MakeLParam(Spot.X, Spot.Y))

            SendMessage(hWnd, WM_SETCURSOR, WM_RBUTTONDOWN, MakeLParam(1, WM_RBUTTONDOWN))
            SendMessage(hWnd, WM_RBUTTONDOWN, mkButton, MakeLParam(Spot.X, Spot.Y))

            SendMessage(hWnd, WM_SETCURSOR, WM_MOUSEMOVE, MakeLParam(1, WM_MOUSEMOVE))
            SendMessage(hWnd, WM_MOUSEMOVE, WM_MOUSEMOVE, MakeLParam(Spot.X, Spot.Y))

            SendMessage(hWnd, WM_SETCURSOR, WM_RBUTTONUP, MakeLParam(1, WM_RBUTTONUP))
            SendMessage(hWnd, WM_RBUTTONUP, 0, MakeLParam(Spot.X, Spot.Y))
        End If
    End Sub


As you can see, it's alot of messages being sent for something that should just be a WM_MOUSEMOVE, WM_(L|R)BUTTONDOWN, and WM_(L|R)BUTTONUP. I used spy++ to intercept these messages and I tried many MANY different variants; all of which failed. The game only in-takes specific messages in a specific order as a specific type. For example, I can't POST any of these messages or the game will not understand. Maybe I approached this wrong but this method does in-fact, work.

Same goes with the keyboards messages. The game only in-takes a "Send" message, in this order and with the bits of the message changed accordingly:

WM_KEYDOWN
WM_CHAR
WM_KEYUP

so I created these methods to emulate:

Code:

Public Sub SendHoldKey(ByVal hWnd As IntPtr, ByVal vKey As Integer, Optional ByVal scanCodeValue As Integer = &H1C, Optional ByVal repeatCount As Integer = 0)
        Dim scanCode As Integer = scanCodeValue << 16           'shift 16 bits
        Dim extended As Integer = 0 << 24           'shift 16 + 8 bits
        Dim reserved As Integer = 0                 'Not to be used so no need to shift all zeroes.
        Dim contextCode As Integer = 0 << 29        'shift 16 + 8 + 1 + 4
        Dim previousState As Integer = 0 << 30      'shift 16 + 8 + 1 + 4 + 1
        Dim transitionState As Integer = 0 << 31    'shift 16 + 8 + 1 + 4 + 1 + 1

        Dim lParam As Integer = repeatCount + _
                                scanCode + _
                                extended + _
                                reserved + _
                                contextCode + _
                                previousState + _
                                transitionState
        SendMessage(hWnd, WM_KEYDOWN, vKey, lParam)
    End Sub

    Public Sub SendCharKey(ByVal hWnd As IntPtr, ByVal vKey As Integer, Optional ByVal scanCodeValue As Integer = &H1C, Optional ByVal repeatCount As Integer = 0)
        Dim scanCode As Integer = scanCodeValue << 16           'shift 16 bits
        Dim extended As Integer = 0 << 24           'shift 16 + 8 bits
        Dim reserved As Integer = 0                 'Not to be used so no need to shift all zeroes.
        Dim contextCode As Integer = 0 << 29        'shift 16 + 8 + 1 + 4
        Dim previousState As Integer = 0 << 30      'shift 16 + 8 + 1 + 4 + 1
        Dim transitionState As Integer = 0 << 31    'shift 16 + 8 + 1 + 4 + 1 + 1

        Dim lParam As Integer = repeatCount + _
                                scanCode + _
                                extended + _
                                reserved + _
                                contextCode + _
                                previousState + _
                                transitionState
        SendMessage(hWnd, WM_CHAR, vKey, lParam)
    End Sub
    Public Sub SendReleaseKey(ByVal hWnd As IntPtr, ByVal vKey As Integer, Optional ByVal scanCodeValue As Integer = &H1C, Optional ByVal repeatCount As Integer = 0)
        Dim scanCode As Integer = scanCodeValue << 16           'shift 16 bits
        Dim extended As Integer = 0 << 24           'shift 16 + 8 bits
        Dim reserved As Integer = 0                 'Not to be used so no need to shift all zeroes.
        Dim contextCode As Integer = 0 << 29        'shift 16 + 8 + 1 + 4
        Dim previousState As Integer = 1 << 30      'shift 16 + 8 + 1 + 4 + 1
        Dim transitionState As Integer = 1 << 31    'shift 16 + 8 + 1 + 4 + 1 + 1

        Dim lParam As Integer = repeatCount + _
                                scanCode + _
                                extended + _
                                reserved + _
                                contextCode + _
                                previousState + _
                                transitionState

        PostMessage(hWnd, WM_KEYUP, vKey, lParam)
    End Sub


The keyboard code snippets appear to work flawlessly, where-as the mouse code snippets work "PROPERLY" only when my cursor is over the game's window. It still "mostly" works when it's not. It's been awhile since I fiddled with that bit of code and used spy++, but I remember trying to use WM_SETFOCUS and WM_ACTIVATE as per what spy++ reported. I think my tests were unsuccessful. I'll have to revisit them again sometime soon.

What I'm asking for
How can I inject a .DLL file to read memory changes, and change the variables in the .DLL's memory accordingly so.

Knowledge of whether or not my approach to this is proper.

A coding partner (if you want to join in on this project, but I don't expect anyone to want to join).

what I'm NOT asking for
Hacks.
Cheats.
Memory manipulation.
Anything that deals with Writing routines.


Last edited by Mal1t1a on Tue Jun 03, 2014 9:36 pm; edited 4 times in total
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 Jun 03, 2014 7:29 pm    Post subject: Reply with quote

We do not discuss multiplayer cheating / hacking on this site.
http://forum.cheatengine.org/faq.php#0

Regardless of your intent, you named the game and the intent involves things that break the ToS of the game which break the rules here as well. So we do not allow discussion of things like this here.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Mal1t1a
Cheater
Reputation: 0

Joined: 03 Jan 2010
Posts: 40

PostPosted: Tue Jun 03, 2014 9:37 pm    Post subject: Reply with quote

atom0s wrote:
We do not discuss multiplayer cheating / hacking on this site.
http://forum.cheatengine.org/faq.php#0

Regardless of your intent, you named the game and the intent involves things that break the ToS of the game which break the rules here as well. So we do not allow discussion of things like this here.


Okay, I stripped the direct relations, how about now? Also I'm not playing Multiplayer.
Back to top
View user's profile Send private message
zm0d
Master Cheater
Reputation: 7

Joined: 06 Nov 2013
Posts: 423

PostPosted: Wed Jun 04, 2014 4:43 am    Post subject: Reply with quote

When you inject a DLL into a process, you are modifying the processes memory. Also you write the DLL to the target process.

Mal1t1a wrote:
what I'm NOT asking for
Hacks.
Cheats.
Memory manipulation.
Anything that deals with Writing routines.
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: Wed Jun 04, 2014 11:58 am    Post subject: Reply with quote

Given your goal some things I would really point out to you for speed:

1. Injection is better than stand-alone.

If the game has no anti-cheat to worry about I would inject into the game for direct memory access. You will have much faster reads since you can directly read the memory instead of using an API call.

Along with this, you can directly inject input into the game while you are injected into it. And with that, you can have the game minimized entirely and use a form of IPC to send input from an external program as well.

2. Fixing Slow ReadProcessMemory Calls

An ideal way to read memory is in chunks instead of single calls. If you read a chunk in, you can cast it to a structure which is a ton faster than reading certain values 1 by 1. If you are reading 1 by 1 you are creating a lot of overhead and unneeded calls, which in turn slows down the process of getting all the data you need.

Being injected also makes this easy since you can cast the memory directly to a structure removing all the middle-man API calls and such too.

3. Ditch Vb.NET

Simply put, get rid of it. It is a horrible language that is barely holding on.
If you want to stay in the realm of .NET, I would recommend C#

If you want to start getting more in depth with game hacking with hooking, injection, and so on, I would recommend C/C++ then. You can do injection with .NET languages as well but its a lot more work.

Any language that can access the system API can be used for game hacking though, so the choice is yours, that is just my opinion.

Quote:
How can I inject a .DLL file to read memory changes, and change the variables in the .DLL's memory accordingly so.


Going along with what I just said, I do not recommend trying to learn how to do DLL injection in .NET languages. It is a hefty amount of work that gets overall annoying and just not really worth it. I would recommend moving into a language where injection is much more common, such as:
- C / C++
- ASM
- Delphi
- etc.

Once you understand and are comfortable with one of these languages, there are several methods you can use to do DLL injection.
- CreateRemoteThread
- Manual Mapping
- SetWindowsHookEx
- IAT injection to force your library to load.
- Code injection to overwrite the OEP of the process to jump to a cave to load your DLL.
- System wide registry entry which forces your DLL to load into every process.

And so on. There are a lot of ways to get a DLL into a process.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
zm0d
Master Cheater
Reputation: 7

Joined: 06 Nov 2013
Posts: 423

PostPosted: Thu Jun 05, 2014 2:32 am    Post subject: Reply with quote

Also may be interesting for the more experienced coder -> "Reflective DLL Injection":

Info:
http://www.harmonysecurity.com/files/HS-P005_ReflectiveDllInjection.pdf

Example (from last page in the upper PDF):
https://github.com/stephenfewer/ReflectiveDLLInjection
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking All times are GMT - 6 Hours
Page 1 of 1

 
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