 |
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
VirtualMind Newbie cheater
Reputation: 0
Joined: 04 Apr 2015 Posts: 20
|
Posted: Sun May 17, 2015 5:56 pm Post subject: AOB Wildcard scan in C#? |
|
|
i have codded a memory scanner to scan AOB and replace. pretty much like what CE does.
tho i can't figure out how to do a wildcard scan, does CE does a scan for that wildcard bytes from 1 - 255 integers? and from 0x0A to 0x0D ?
if so do i need to make a scan for every single byte in my code?
|
|
Back to top |
|
 |
atom0s Moderator
Reputation: 205
Joined: 25 Jan 2006 Posts: 8585 Location: 127.0.0.1
|
Posted: Sun May 17, 2015 9:07 pm Post subject: |
|
|
Here is a C# class I wrote that handles wildcards using the well known FindPattern method:
Code: | /**
* sigScan C# Implementation - Written by atom0s [aka Wiccaan]
* Class Version: 2.0.0
*
* [ CHANGE LOG ] -------------------------------------------------------------------------
*
* 2.0.0
* - Updated to no longer require unsafe or fixed code.
* - Removed unneeded methods and code.
*
* 1.0.0
* - First version written and release.
*
* [ CREDITS ] ----------------------------------------------------------------------------
*
* sigScan is based on the FindPattern code written by
* dom1n1k and Patrick at GameDeception.net
*
* Full credit to them for the purpose of this code. I, atom0s, simply
* take credit for converting it to C#.
*
*/
namespace YourNamespaceNameHere.Classes
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
public class SigScan
{
/// <summary>
/// ReadProcessMemory
///
/// API import definition for ReadProcessMemory.
/// </summary>
/// <param name="hProcess">Handle to the process we want to read from.</param>
/// <param name="lpBaseAddress">The base address to start reading from.</param>
/// <param name="lpBuffer">The return buffer to write the read data to.</param>
/// <param name="dwSize">The size of data we wish to read.</param>
/// <param name="lpNumberOfBytesRead">The number of bytes successfully read.</param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[Out] byte[] lpBuffer,
int dwSize,
out int lpNumberOfBytesRead
);
/// <summary>
/// m_vDumpedRegion
///
/// The memory dumped from the external process.
/// </summary>
private byte[] m_vDumpedRegion;
/// <summary>
/// m_vProcess
///
/// The process we want to read the memory of.
/// </summary>
private Process m_vProcess;
/// <summary>
/// m_vAddress
///
/// The starting address we want to begin reading at.
/// </summary>
private IntPtr m_vAddress;
/// <summary>
/// m_vSize
///
/// The number of bytes we wish to read from the process.
/// </summary>
private Int32 m_vSize;
#region "sigScan Class Construction"
/// <summary>
/// SigScan
///
/// Main class constructor that uses no params.
/// Simply initializes the class properties and
/// expects the user to set them later.
/// </summary>
public SigScan()
{
this.m_vProcess = null;
this.m_vAddress = IntPtr.Zero;
this.m_vSize = 0;
this.m_vDumpedRegion = null;
}
/// <summary>
/// SigScan
///
/// Overloaded class constructor that sets the class
/// properties during construction.
/// </summary>
/// <param name="proc">The process to dump the memory from.</param>
/// <param name="addr">The started address to begin the dump.</param>
/// <param name="size">The size of the dump.</param>
public SigScan(Process proc, IntPtr addr, int size)
{
this.m_vProcess = proc;
this.m_vAddress = addr;
this.m_vSize = size;
}
#endregion
#region "sigScan Class Private Methods"
/// <summary>
/// DumpMemory
///
/// Internal memory dump function that uses the set class
/// properties to dump a memory region.
/// </summary>
/// <returns>Boolean based on RPM results and valid properties.</returns>
private bool DumpMemory()
{
try
{
// Checks to ensure we have valid data.
if (this.m_vProcess == null)
return false;
if (this.m_vProcess.HasExited)
return false;
if (this.m_vAddress == IntPtr.Zero)
return false;
if (this.m_vSize == 0)
return false;
// Create the region space to dump into.
this.m_vDumpedRegion = new byte[this.m_vSize];
int nBytesRead;
// Dump the memory.
var ret = ReadProcessMemory(
this.m_vProcess.Handle, this.m_vAddress, this.m_vDumpedRegion, this.m_vSize, out nBytesRead
);
// Validation checks.
return ret && nBytesRead == this.m_vSize;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// MaskCheck
///
/// Compares the current pattern byte to the current memory dump
/// byte to check for a match. Uses wildcards to skip bytes that
/// are deemed unneeded in the compares.
/// </summary>
/// <param name="nOffset">Offset in the dump to start at.</param>
/// <param name="btPattern">Pattern to scan for.</param>
/// <param name="strMask">Mask to compare against.</param>
/// <returns>Boolean depending on if the pattern was found.</returns>
private bool MaskCheck(int nOffset, IEnumerable<byte> btPattern, string strMask)
{
// Loop the pattern and compare to the mask and dump.
return !btPattern.Where((t, x) => strMask[x] != '?' && ((strMask[x] == 'x') && (t != this.m_vDumpedRegion[nOffset + x]))).Any();
// The loop was successful so we found the pattern.
}
#endregion
#region "sigScan Class Public Methods"
/// <summary>
/// FindPattern
///
/// Attempts to locate the given pattern inside the dumped memory region
/// compared against the given mask. If the pattern is found, the offset
/// is added to the located address and returned to the user.
/// </summary>
/// <param name="btPattern">Byte pattern to look for in the dumped region.</param>
/// <param name="strMask">The mask string to compare against.</param>
/// <param name="nOffset">The offset added to the result address.</param>
/// <returns>IntPtr - zero if not found, address if found.</returns>
public IntPtr FindPattern(byte[] btPattern, string strMask, int nOffset)
{
try
{
// Dump the memory region if we have not dumped it yet.
if (this.m_vDumpedRegion == null || this.m_vDumpedRegion.Length == 0)
{
if (!this.DumpMemory())
return IntPtr.Zero;
}
// Ensure the mask and pattern lengths match.
if (strMask.Length != btPattern.Length)
return IntPtr.Zero;
// Loop the region and look for the pattern.
for (int x = 0; x < this.m_vDumpedRegion.Length; x++)
{
if (this.MaskCheck(x, btPattern, strMask))
{
// The pattern was found, return it.
return new IntPtr((int)this.m_vAddress + (x + nOffset));
}
}
// Pattern was not found.
return IntPtr.Zero;
}
catch (Exception)
{
return IntPtr.Zero;
}
}
/// <summary>
/// ResetRegion
///
/// Resets the memory dump array to nothing to allow
/// the class to redump the memory.
/// </summary>
public void ResetRegion()
{
this.m_vDumpedRegion = null;
}
#endregion
#region "sigScan Class Properties"
public Process Process
{
get { return this.m_vProcess; }
set { this.m_vProcess = value; }
}
public IntPtr Address
{
get { return this.m_vAddress; }
set { this.m_vAddress = value; }
}
public Int32 Size
{
get { return this.m_vSize; }
set { this.m_vSize = value; }
}
#endregion
}
} |
_________________
- Retired. |
|
Back to top |
|
 |
VirtualMind Newbie cheater
Reputation: 0
Joined: 04 Apr 2015 Posts: 20
|
Posted: Mon May 18, 2015 11:24 am Post subject: |
|
|
atom0s wrote: | Here is a C# class I wrote that handles wildcards using the well known FindPattern method:
Code: | /**
* sigScan C# Implementation - Written by atom0s [aka Wiccaan]
* Class Version: 2.0.0
*
* [ CHANGE LOG ] -------------------------------------------------------------------------
*
* 2.0.0
* - Updated to no longer require unsafe or fixed code.
* - Removed unneeded methods and code.
*
* 1.0.0
* - First version written and release.
*
* [ CREDITS ] ----------------------------------------------------------------------------
*
* sigScan is based on the FindPattern code written by
* dom1n1k and Patrick at GameDeception.net
*
* Full credit to them for the purpose of this code. I, atom0s, simply
* take credit for converting it to C#.
*
*/
namespace YourNamespaceNameHere.Classes
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
public class SigScan
{
/// <summary>
/// ReadProcessMemory
///
/// API import definition for ReadProcessMemory.
/// </summary>
/// <param name="hProcess">Handle to the process we want to read from.</param>
/// <param name="lpBaseAddress">The base address to start reading from.</param>
/// <param name="lpBuffer">The return buffer to write the read data to.</param>
/// <param name="dwSize">The size of data we wish to read.</param>
/// <param name="lpNumberOfBytesRead">The number of bytes successfully read.</param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[Out] byte[] lpBuffer,
int dwSize,
out int lpNumberOfBytesRead
);
/// <summary>
/// m_vDumpedRegion
///
/// The memory dumped from the external process.
/// </summary>
private byte[] m_vDumpedRegion;
/// <summary>
/// m_vProcess
///
/// The process we want to read the memory of.
/// </summary>
private Process m_vProcess;
/// <summary>
/// m_vAddress
///
/// The starting address we want to begin reading at.
/// </summary>
private IntPtr m_vAddress;
/// <summary>
/// m_vSize
///
/// The number of bytes we wish to read from the process.
/// </summary>
private Int32 m_vSize;
#region "sigScan Class Construction"
/// <summary>
/// SigScan
///
/// Main class constructor that uses no params.
/// Simply initializes the class properties and
/// expects the user to set them later.
/// </summary>
public SigScan()
{
this.m_vProcess = null;
this.m_vAddress = IntPtr.Zero;
this.m_vSize = 0;
this.m_vDumpedRegion = null;
}
/// <summary>
/// SigScan
///
/// Overloaded class constructor that sets the class
/// properties during construction.
/// </summary>
/// <param name="proc">The process to dump the memory from.</param>
/// <param name="addr">The started address to begin the dump.</param>
/// <param name="size">The size of the dump.</param>
public SigScan(Process proc, IntPtr addr, int size)
{
this.m_vProcess = proc;
this.m_vAddress = addr;
this.m_vSize = size;
}
#endregion
#region "sigScan Class Private Methods"
/// <summary>
/// DumpMemory
///
/// Internal memory dump function that uses the set class
/// properties to dump a memory region.
/// </summary>
/// <returns>Boolean based on RPM results and valid properties.</returns>
private bool DumpMemory()
{
try
{
// Checks to ensure we have valid data.
if (this.m_vProcess == null)
return false;
if (this.m_vProcess.HasExited)
return false;
if (this.m_vAddress == IntPtr.Zero)
return false;
if (this.m_vSize == 0)
return false;
// Create the region space to dump into.
this.m_vDumpedRegion = new byte[this.m_vSize];
int nBytesRead;
// Dump the memory.
var ret = ReadProcessMemory(
this.m_vProcess.Handle, this.m_vAddress, this.m_vDumpedRegion, this.m_vSize, out nBytesRead
);
// Validation checks.
return ret && nBytesRead == this.m_vSize;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// MaskCheck
///
/// Compares the current pattern byte to the current memory dump
/// byte to check for a match. Uses wildcards to skip bytes that
/// are deemed unneeded in the compares.
/// </summary>
/// <param name="nOffset">Offset in the dump to start at.</param>
/// <param name="btPattern">Pattern to scan for.</param>
/// <param name="strMask">Mask to compare against.</param>
/// <returns>Boolean depending on if the pattern was found.</returns>
private bool MaskCheck(int nOffset, IEnumerable<byte> btPattern, string strMask)
{
// Loop the pattern and compare to the mask and dump.
return !btPattern.Where((t, x) => strMask[x] != '?' && ((strMask[x] == 'x') && (t != this.m_vDumpedRegion[nOffset + x]))).Any();
// The loop was successful so we found the pattern.
}
#endregion
#region "sigScan Class Public Methods"
/// <summary>
/// FindPattern
///
/// Attempts to locate the given pattern inside the dumped memory region
/// compared against the given mask. If the pattern is found, the offset
/// is added to the located address and returned to the user.
/// </summary>
/// <param name="btPattern">Byte pattern to look for in the dumped region.</param>
/// <param name="strMask">The mask string to compare against.</param>
/// <param name="nOffset">The offset added to the result address.</param>
/// <returns>IntPtr - zero if not found, address if found.</returns>
public IntPtr FindPattern(byte[] btPattern, string strMask, int nOffset)
{
try
{
// Dump the memory region if we have not dumped it yet.
if (this.m_vDumpedRegion == null || this.m_vDumpedRegion.Length == 0)
{
if (!this.DumpMemory())
return IntPtr.Zero;
}
// Ensure the mask and pattern lengths match.
if (strMask.Length != btPattern.Length)
return IntPtr.Zero;
// Loop the region and look for the pattern.
for (int x = 0; x < this.m_vDumpedRegion.Length; x++)
{
if (this.MaskCheck(x, btPattern, strMask))
{
// The pattern was found, return it.
return new IntPtr((int)this.m_vAddress + (x + nOffset));
}
}
// Pattern was not found.
return IntPtr.Zero;
}
catch (Exception)
{
return IntPtr.Zero;
}
}
/// <summary>
/// ResetRegion
///
/// Resets the memory dump array to nothing to allow
/// the class to redump the memory.
/// </summary>
public void ResetRegion()
{
this.m_vDumpedRegion = null;
}
#endregion
#region "sigScan Class Properties"
public Process Process
{
get { return this.m_vProcess; }
set { this.m_vProcess = value; }
}
public IntPtr Address
{
get { return this.m_vAddress; }
set { this.m_vAddress = value; }
}
public Int32 Size
{
get { return this.m_vSize; }
set { this.m_vSize = value; }
}
#endregion
}
} |
|
i don't quit understand this, aren't wildcard suppose to be '??" and there should be no value?
i tried to type in "Nothing" as wildcard and added it as xxx?xxx but nope 0 results and nothing was wrote to memory.
|
|
Back to top |
|
 |
atom0s Moderator
Reputation: 205
Joined: 25 Jan 2006 Posts: 8585 Location: 127.0.0.1
|
Posted: Mon May 18, 2015 5:32 pm Post subject: |
|
|
Using the above code I posted, you would use a dead byte as the wildcard, such as 0xFF. The mask would contain a single ? for its position.
So for example if you have:
Code: | 009E63BA - 53 - push ebx
009E63BB - 56 - push esi
009E63BC - 57 - push edi
009E63BD - A1 00B09E00 - mov eax,[009EB000] : [A0AC5072]
009E63C2 - 31 45 FC - xor [ebp-04],eax
009E63C5 - 33 C5 - xor eax,ebp
009E63C7 - 50 - push eax
|
Your signature would be for this:
53 56 57 A1 ?? ?? ?? ?? 31 45 FC 33 C5 50
Using the above code, you would use:
Code: |
var sigscan = new SigScan(YourProcObject.Handle, SomeBaseAddress, SomeSize);
var addr = sigscan.FindPattern(new byte[] { 0x53, 0x56, 0x57, 0xA1, 0x0xFF, 0x0xFF, 0x0xFF, 0x0xFF, 0x31, 0x45, 0xFC, 0x33, 0xC5, 0x50 }, "xxxx????xxxxxx", 4);
|
In this case I used 0xFF as the wildcard bytes, since they have to exist in the pattern but can be anything since the mask states that their position in the pattern is a wildcard.
With this, the mask has x and ? representing 1 byte each in the pattern. This means that:
0x53 = x
0x56 = x
0x57 = x
0xA1 = x
0xFF = ?
0xFF = ?
0xFF = ?
0xFF = ?
0x31 = x
0x45 = x
0xFC = x
0x33 = x
0xC5 = x
0x50 = x
_________________
- Retired. |
|
Back to top |
|
 |
VirtualMind Newbie cheater
Reputation: 0
Joined: 04 Apr 2015 Posts: 20
|
Posted: Tue May 19, 2015 7:52 pm Post subject: |
|
|
atom0s wrote: | Using the above code I posted, you would use a dead byte as the wildcard, such as 0xFF. The mask would contain a single ? for its position.
So for example if you have:
Code: | 009E63BA - 53 - push ebx
009E63BB - 56 - push esi
009E63BC - 57 - push edi
009E63BD - A1 00B09E00 - mov eax,[009EB000] : [A0AC5072]
009E63C2 - 31 45 FC - xor [ebp-04],eax
009E63C5 - 33 C5 - xor eax,ebp
009E63C7 - 50 - push eax
|
Your signature would be for this:
53 56 57 A1 ?? ?? ?? ?? 31 45 FC 33 C5 50
Using the above code, you would use:
Code: |
var sigscan = new SigScan(YourProcObject.Handle, SomeBaseAddress, SomeSize);
var addr = sigscan.FindPattern(new byte[] { 0x53, 0x56, 0x57, 0xA1, 0x0xFF, 0x0xFF, 0x0xFF, 0x0xFF, 0x31, 0x45, 0xFC, 0x33, 0xC5, 0x50 }, "xxxx????xxxxxx", 4);
|
In this case I used 0xFF as the wildcard bytes, since they have to exist in the pattern but can be anything since the mask states that their position in the pattern is a wildcard.
With this, the mask has x and ? representing 1 byte each in the pattern. This means that:
0x53 = x
0x56 = x
0x57 = x
0xA1 = x
0xFF = ?
0xFF = ?
0xFF = ?
0xFF = ?
0x31 = x
0x45 = x
0xFC = x
0x33 = x
0xC5 = x
0x50 = x |
at the usage part. i see that i need an address to read from.
but what if i wanted to use the scanner to find that address?
|
|
Back to top |
|
 |
atom0s Moderator
Reputation: 205
Joined: 25 Jan 2006 Posts: 8585 Location: 127.0.0.1
|
Posted: Wed May 20, 2015 12:50 am Post subject: |
|
|
The address and size is where the scanner should look within. Typically that will be the base address of the application + the size of that module.
_________________
- Retired. |
|
Back to top |
|
 |
popescu400 How do I cheat?
Reputation: 0
Joined: 27 Jun 2015 Posts: 5
|
Posted: Fri Aug 12, 2016 12:34 pm Post subject: |
|
|
atom0s wrote: | The address and size is where the scanner should look within. Typically that will be the base address of the application + the size of that module. |
I tried your code... and I think I made it work... but I still have 2 problems
1) can't find a good base address...
2) can't find a good WriteProcessMemory function which can write the AOB I want directly to the one found in addr
Edit: I just want to search an AOB in the entire game and change to another. Also, there may be more results..
|
|
Back to top |
|
 |
|
|
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
|
|