Archive for May 4th, 2008

Vb Net Article - Medal of Honour Allied Assault Basic Hacks

Medal of Honour Allied Assault Basic Hacks.

I got bored a while back and made some basic hacks for MoHAA.

I made a class (Well a few classes) that I used to read the console, send text to the console, and a few memory hacks.

I then stuck this into a global key hook and set up the hotkeys.

The classes are all contained inside Public Class MoHFunctions

Public Class WindowFunctions

<DllImport(“user32.dll”, SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As Int32) As Boolean

End Function

Private Enum WindowShowStyle As UInteger

Hide = 0

ShowMinimized = 2

Minimize = 6

ShowMinNoActivate = 7

ForceMinimized = 11

End Enum

Private Declare Auto Function FindWindow Lib “user32″ (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr

Public Shared Sub MinimiseWindow()

Dim MoHWnd As IntPtr = FindWindow(0, “Medal of Honor Allied Assult”)

ShowWindow(MoHWnd, WindowShowStyle.Minimize)

End Sub

End Class

That class is basically for minimising the MoHAA Window, I never got round to adding anything else to it. Maybe one day…

Now for a long class, the console stuff.

Public Class Console

<DllImport(“User32.dll”)> Private Shared Function EnumChildWindows(ByVal WindowHandle As IntPtr, ByVal Callback As EnumWindowProcess, ByVal lParam As IntPtr) As Boolean

End Function

<DllImport(“user32.dll”, CharSet:=CharSet.Auto)> Private Shared Sub GetClassName(ByVal hWnd As System.IntPtr, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer)

End Sub

Private Shared Function GetChildWindows(ByVal ParentHandle As IntPtr) As IntPtr()

Dim ChildrenList As New List(Of IntPtr)

Dim ListHandle As GCHandle = GCHandle.Alloc(ChildrenList)

Try

EnumChildWindows(ParentHandle, AddressOf EnumWindow, GCHandle.ToIntPtr(ListHandle))

Finally

If ListHandle.IsAllocated Then ListHandle.Free()

End Try

Return ChildrenList.ToArray

End Function

Private Shared Function EnumWindow(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean

Dim ChildrenList As List(Of IntPtr) = GCHandle.FromIntPtr(Parameter).Target

If ChildrenList Is Nothing Then Throw New Exception(“GCHandle Target could not be cast as List(Of IntPtr)”)

ChildrenList.Add(Handle)

Return True

End Function

Private Declare Auto Function SendMessage Lib “user32″ (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wparam As Integer, ByVal lparam As System.Text.StringBuilder) As IntPtr

Private Declare Auto Function SendMessage Lib “user32″ (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr

Private Declare Auto Function FindWindow Lib “user32″ (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr

Private Delegate Function EnumWindowProcess(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean

Private Const WM_GETTEXT = &HD

Private Const WM_GETTEXTLENGTH As Integer = &HE

Private Const WM_SETTEXT = &HC

Private Const WM_CHAR = &H102

These functions are to get a list of the windows inside of the MoHAA console, and to get the text from it.

Private Shared Function FindMoH() As IntPtr

FindMoH = FindWindow(“mohaa winconsole”, vbNullString)

End Function

This function gets the window handle for the MoHAA console, which is then used to get the consoles edit controls handle.

Now, for the sending to the console:

Public Shared Function SendText(ByVal Text As String) As Boolean

Dim handle As IntPtr = FindMoH()

If handle = 0 Then

MessageBox.Show(“Medal of Honor Allied Assult Console not found.”, “Error:”, MessageBoxButtons.OK, MessageBoxIcon.Error)

Return “Error;”

Exit Function

End If

For Each child As IntPtr In GetChildWindows(handle)

Dim sClassName As New System.Text.StringBuilder(“”, 256)

Call GetClassName(child, sClassName, 256)

If sClassName.ToString = “Edit” Then

Dim sb As New System.Text.StringBuilder(Text)

SendMessage(child, WM_SETTEXT, 0, sb)

SendMessage(child, WM_CHAR, 13, 1)

Return True

End If

Next

End Function

This finds the Edit control by looping through the handles until if finds one with the class name “Edit”. It then uses SendMessage to set the text in the window, and then sends the Return character to the window to set it

(child, WM_CHAR, 13, 1)

Reading text from the console isnt much different:

Public Shared Function ReadText() As String

ReadText = “”

Dim handle As IntPtr = FindMoH()

If handle = 0 Then

MessageBox.Show(“Medal of Honor Allied Assult Console not found.”, “Error:”, MessageBoxButtons.OK, MessageBoxIcon.Error)

Return “Error;”

Exit Function

End If

For Each child As IntPtr In GetChildWindows(handle)

Dim sClassName As New System.Text.StringBuilder(“”, 256)

Call GetClassName(child, sClassName, 256)

If sClassName.ToString = “Edit” Then

Dim conLength As IntPtr

conLength = SendMessage(child, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero)

Dim sbText As New System.Text.StringBuilder(conLength.ToInt32 + 1)

Dim ptrRet As IntPtr

ptrRet = SendMessage(child, WM_GETTEXT, conLength.ToInt32 + 1, sbText)

If Not sbText.ToString = “” Then

Return sbText.ToString

End If

End If

Next

End Function

This again loops through the handles, until it finds the edit control.

It then sends the GETTEXTLENGTH in order to get the length of the text in the console and then sends GETTEXT to the window to the length that was previously returned.

It then builds the string; if it’s not blank then it returns the value.

Now what can we actually do with these functions? Well to be honest, I didn’t use the ReadText function because I figured the only way to use it would be to check it on a loop, then if a specific string came up you could then do whatever, but I couldn’t be bothered with that…

Public Shared Sub SilentShot()

SendText(“echo Silent Shot”)

SendText(“+attackprimary; weapdrop”)

End Sub

Public Shared Sub Time()

SendText(“echo “ & Now.Hour & “:” & Now.Minute & “:” & Now.Second)

SendText(“locationprint 6 29 “ & Now.Hour & “:” & Now.Minute & “:” & Now.Second)

End Sub

Public Shared Sub Connect(ByVal Ip As String)

SendText(“connect “ & Ip)

End Sub

Public Shared Sub Specator()

SendText(“echo Gone Spectator”)

SendText(“spectator”)

End Sub

Public Shared Sub Reconnect()

SendText(“reconnect”)

End Sub

Now, that’s just some basic stuff, but you could create some more advanced scripts such as:

SendText(“+forward”)

System.Threading.Thread.Sleep(50)

SendText(“-forward”)

SendText(“+moveup”)

System.Threading.Thread.Sleep(400)

SendText(“-moveup”)

System.Threading.Thread.Sleep(10)

SendText(“+forward”)

System.Threading.Thread.Sleep(20)

SendText(“+moveup”)

System.Threading.Thread.Sleep(200)

SendText(“-moveup”)

SendText(“+forward”)

System.Threading.Thread.Sleep(200)

SendText(“+moveup”)

System.Threading.Thread.Sleep(100)

SendText(“-moveup”)

System.Threading.Thread.Sleep(20)

SendText(“+moveleft”)

SendText(“-forward”)

SendText(“-moveleft”)

Now I just came up with that and gave it a quick test, so I can’t guarantee that it works every time (It was just a bind that I made and converted, and it was made quickly so there ARE errors)

bind 9 “+forward;wait 50;-forward;+moveup;say jumped;wait 400;-moveup;wait 10;+forward;say forward;wait 20;+moveup;say jumped;+wait 200; -moveup;+forward;wait 200; say jumped;+moveup; wait 100; -moveup;wait 20;+moveleft;-forward;-moveleft;-moveup”

For example, one noticeable error: say jumped;+wait 200;

Now, off of the console stuff, and onto some fun stuff, memory editing!

Public Class Memory

<DllImport(“kernel32.dll”)> Private Shared Function WriteProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As Byte(), ByVal nSize As UIntPtr, <Runtime.InteropServices.Out()> ByRef lpNumberOfBytesWritten As IntPtr) As Boolean

End Function

My favourite APIJ, well not really but what you gonna do?

So, anyway, in the main part of the program we have a variable named MoHProchWnd, that’s where I store MoHAA’s PiD using the sub below

Public Shared Sub onLoad()

Try

Dim Processes() As System.Diagnostics.Process

Processes = System.Diagnostics.Process.GetProcessesByName(“MOHAA”)

Main.MoHProchWnd = Processes(0).Handle

Catch ex As Exception

Main.MoHProchWnd = 0

End Try

End Sub

So, anyway below is a basic function for enabling cheats in MoHAA (“Cvars”)

Public Shared Sub EnableCheats()

If Main.MoHProchWnd = 0 Then

onLoad()

End If

Dim bytes As Byte() = New Byte(0) {&H86}

WriteProcessMemory(Main.MoHProchWnd, New IntPtr(&H44F999), bytes, New UIntPtr(CType(bytes.Length, UInt32)), New IntPtr(0))

KeyHook.Cheats = True

End Sub

And then to disable them

Public Shared Sub DisableCheats()

If Main.MoHProchWnd = 0 Then

onLoad()

End If

Dim bytes As Byte() = New Byte(0) {&H85}

WriteProcessMemory(Main.MoHProchWnd, New IntPtr(&H44F999), bytes, New UIntPtr(CType(bytes.Length, UInt32)), New IntPtr(0))

KeyHook.Cheats = False

End Sub

And a quick example of what else can be done:

Public Shared Sub EnableThirdPerson()

If Main.MoHProchWnd = 0 Then

onLoad()

End If

Dim bytes As Byte() = New Byte(0) {&H1}

WriteProcessMemory(Main.MoHProchWnd, New IntPtr(&HECCAF0), bytes, New UIntPtr(CType(bytes.Length, UInt32)), New IntPtr(0))

KeyHook.ThirdPerson = True

Console.SendText(“cg_cameraverticaldisplacement -18″)

Console.SendText(“echo 3rd Person Camera Position Fixed”)

End Sub

Public Shared Sub DisableThirdPerson()

If Main.MoHProchWnd = 0 Then

onLoad()

End If

Dim bytes As Byte() = New Byte(0) {&H0}

WriteProcessMemory(Main.MoHProchWnd, New IntPtr(&HECCAF0), bytes, New UIntPtr(CType(bytes.Length, UInt32)), New IntPtr(0))

KeyHook.ThirdPerson = False

Console.SendText(“cg_cameraverticaldisplacement -2″)

Console.SendText(“echo 1st Person Camera Position Fixed”)

End Sub

That uses the console class to correct the camera position, and edits the programs memory to enable the third person – Note, that since it directly pokes an address, cheats do not need to be enabled to toggle 3rd person.

Now, onto the usage of these classes further. As I previously stated, I set this up on a global key hook. Below is the sub that I use to carry out the above functions.

Private Shared Sub KeyCheck()

If n0Down = True Then

If Cheats = True Then

Cheats = False

Memory.DisableCheats()

Else

Cheats = True

Memory.EnableCheats()

End If

ElseIf n1Down = True Then

If ThirdPerson = True Then

ThirdPerson = False

Memory.DisableThirdPerson()

Else

ThirdPerson = True

Memory.EnableThirdPerson()

End If

ElseIf n2Down = True Then

Console.SilentShot()

ElseIf n3Down = True Then

Console.Specator()

ElseIf n4Down = True Then

Console.Time()

ElseIf n5Down = True Then

Console.Reconnect()

ElseIf n6Down = True Then

Console.Connect(“213.251.176.208:28305″)

Console.SendText(“Echo Connecting to LCA V2 Sniper only”)

Console.SendText(“Echo IP: 213.251.176.208:28305″)

Exit Sub

ElseIf n7Down = True Then

Console.Connect(“213.251.176.208:12000″)

Console.SendText(“Echo Connecting to LCA Stalingrad Sniper only”)

Console.SendText(“Echo IP: 213.251.176.208:12000″)

ElseIf n8Down = True Then

Console.Connect(“217.79.181.142:27001″)

Console.SendText(“Echo Connecting to [NAG] Stalingrad Sniper only 1″)

Console.SendText(“Echo IP: 217.79.181.142:27001″)

ElseIf n9Down = True Then

Console.Connect(“213.133.101.46:27001″)

Console.SendText(“Echo Connecting to [NAG] Stalingrad Sniper only 2″)

Console.SendText(“Echo IP: 213.133.101.46:27001″)

ElseIf minusDown = True Then

WindowFunctions.MinimiseWindow()

End If

End Sub

As you can see, it just checks what key is down, and then if the specified one is, it carries out the function. n0 and n1 toggle the two memory functions by checking a Boolean to see if the function is enabled or not.

I was playing again earlier and thought about making a more accurate sniper rifle.

I tried to just make a bind:

bind MOUSE1 “+attacksecondary; +attackprimary; -attacksecondary”

However, due to the way that MoHAA works, this would not carry out the zoom out function. So, I looked through the cmdlist, and found the zoomoff function, and made a new bind:

bind MOUSE1 “+attacksecondary; +attackprimary; zoomoff”

Whilst this worked when playing on a local server, I tried it on another server and it did not work.

So now, I have not actually done this, but I would also hook the mouse, then if the mouse is clicked I would send these messages to console, after unbinding Mouse1 in game:

Console.SendText(“+attacksecondary”)

Console.SendText(“+attackprimary”)

Console.SendText(“-attacksecondary”)

But that however would do that for every single gun in the game, so I looked further for a console command that would give me the name of the gun currently in use. I searched both the cmdlist and the cvarslist, to no avail.

I then went searching in the memory, and found a number of helpful addresses:

010EEEF0 – Text[22] – The name of the gun as a string

010EEF40 – 4 Bytes – The gun as an integer

I decided that the best way to do it would be using the integer, and then a list of values to see what gun is currently in use. I tested all the weapons and created this list

Value/Weapon

1 - Papers

2 - Colt 45

3 - Walther P38

4 - Hi Standard Silenced

5 - M1 Garand

6 - Mauser KAR 98K

7 - KAR98 - Sniper

8 - Springfield

9 - Thompson

10 - MP40

11 - BAR

12 - StG 44

13 - Frag Grenade

14 - Stielhandgranate

15 - Bazooka

16 – Panzerschreck

Now, I can read the memory at that address, and if the current weapon is either 7 or 8, it will send the zoom in, shoot, zoom out function for a 100% accurate shot.