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 


Trouble using signature outside of CE

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

Joined: 30 Mar 2016
Posts: 16

PostPosted: Thu Jul 06, 2017 9:05 am    Post subject: Trouble using signature outside of CE Reply with quote

Hi there,

I'm currently having some trouble with a signature I have located. I'm looking to fetch the address for a text string "HOTBAR.DAT" in memory. I know that I can find this in CE using the signature:

48 4F 54 42 41 52 2E 44 41 54 00 00 00 00 00 00 30 9F

No matter how many times I restart the game, putting that byte array into the "Find Memory" tool in CE always returns the correct position.

The problem I'm having is translating that over to my external application. I have countless other signature patterns just like this one in my application (C# based) which uses a SigScan class to fetch my memory addresses for use in the app - it has worked flawlessly for all signatures I have found EXCEPT this one.

For some reason it cannot find the above signature and I can't work out for the life of me why. I can locate it every time (even without wildcards) in CE (i also wrote an aobscan LUA script in CE to test and that works fine also) so it should translate to my scanner, but it doesn't.

Is there something I may be missing? I have attached a copy of the memory view to this post.



sigscan.PNG
 Description:
 Filesize:  676.94 KB
 Viewed:  11311 Time(s)

sigscan.PNG


Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

Joined: 09 May 2003
Posts: 25287
Location: The netherlands

PostPosted: Thu Jul 06, 2017 11:14 am    Post subject: Reply with quote

perhaps your signature scanner only scans modules
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8517
Location: 127.0.0.1

PostPosted: Thu Jul 06, 2017 1:25 pm    Post subject: Reply with quote

Also double check that your scanner is scanning pages with the proper protections. What you showed only has Read/Write protections, make sure your scanner isn't ignoring it.
_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
logicallysynced
Newbie cheater
Reputation: 0

Joined: 30 Mar 2016
Posts: 16

PostPosted: Thu Jul 06, 2017 5:05 pm    Post subject: Reply with quote

atom0s wrote:
Also double check that your scanner is scanning pages with the proper protections. What you showed only has Read/Write protections, make sure your scanner isn't ignoring it.


Sorry for asking probably an obvious question, but would you be able to point me in the right direction to make sure the SigScan class isn't ignoring that?

And I'm not sure how to check if SigScan is only scanning modules?

I appreciate any suggestions/feedback you can give
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8517
Location: 127.0.0.1

PostPosted: Thu Jul 06, 2017 6:05 pm    Post subject: Reply with quote

You would have to post the code you are using for us to be able to help determine that.
_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
logicallysynced
Newbie cheater
Reputation: 0

Joined: 30 Mar 2016
Posts: 16

PostPosted: Thu Jul 06, 2017 7:13 pm    Post subject: Reply with quote

atom0s wrote:
You would have to post the code you are using for us to be able to help determine that.


The scanner code is as follows:
Code:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using FFXIVAPP.Memory.Events;
using FFXIVAPP.Memory.Models;
using NLog;

namespace FFXIVAPP.Memory
{
    public sealed class Scanner
    {
        #region Logger

        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

        #endregion

        /// <summary>
        /// </summary>
        /// <param name="pSignatures"> </param>
        public void LoadOffsets(IEnumerable<Signature> pSignatures)
        {
            IsScanning = true;

            Func<bool> d = delegate
            {
                var sw = new Stopwatch();
                sw.Start();
                if (MemoryHandler.Instance.ProcessModel?.Process == null)
                {
                    return false;
                }
                var signatures = new List<Signature>(pSignatures);
                LoadRegions();
                if (signatures.Any())
                {
                    foreach (var signature in signatures)
                    {
                        if (signature.Value == string.Empty)
                        {
                            // doesn't need a signature scan
                            Locations[signature.Key] = signature;
                            continue;
                        }
                        signature.Value = signature.Value.Replace("*", "?"); // allows either ? or * to be used as wildcard
                    }
                    signatures.RemoveAll(a => Locations.ContainsKey(a.Key));
                    FindExtendedSignatures(signatures);
                }
                foreach (var kvp in Locations)
                {
                    Logger.Log(LogLevel.Info, $"Signature [{kvp.Key}] Found At Address: [{((IntPtr) kvp.Value).ToString("X")}]");
                }
                sw.Stop();

                RaiseSignaturesFound(Logger, Locations, sw.ElapsedMilliseconds);

                IsScanning = false;

                return true;
            };
            d.BeginInvoke(null, null);
        }

        /// <summary>
        /// </summary>
        private void LoadRegions()
        {
            try
            {
                _regions = new List<UnsafeNativeMethods.MEMORY_BASIC_INFORMATION>();
                var address = new IntPtr();
                while (true)
                {
                    var info = new UnsafeNativeMethods.MEMORY_BASIC_INFORMATION();
                    var result = UnsafeNativeMethods.VirtualQueryEx(MemoryHandler.Instance.ProcessHandle, address, out info, (uint) Marshal.SizeOf(info));
                    if (0 == result)
                    {
                        break;
                    }
                    if (0 != (info.State & MemCommit) && 0 != (info.Protect & Writable) && 0 == (info.Protect & PageGuard))
                    {
                        _regions.Add(info);
                    }
                    else
                    {
                        MemoryHandler.Instance.RaiseException(Logger, new Exception(info.ToString()));
                    }
                    address = IntPtr.Add(info.BaseAddress, info.RegionSize.ToInt32());
                }
            }
            catch (Exception ex)
            {
                MemoryHandler.Instance.RaiseException(Logger, ex, true);
            }
        }

        private void FindExtendedSignatures(IEnumerable<Signature> signatures)
        {
            const int bufferSize = 0x1200;
            const int regionIncrement = 0x1000;
            var moduleMemorySize = MemoryHandler.Instance.ProcessModel.Process.MainModule.ModuleMemorySize;
            var baseAddress = MemoryHandler.Instance.ProcessModel.Process.MainModule.BaseAddress;
            var searchEnd = IntPtr.Add(baseAddress, moduleMemorySize);
            var searchStart = baseAddress;
            var lpBuffer = new byte[bufferSize];
            var notFound = new List<Signature>(signatures);
            var temp = new List<Signature>();
            var regionCount = 0;
            while (searchStart.ToInt64() < searchEnd.ToInt64())
            {
                try
                {
                    IntPtr lpNumberOfBytesRead;
                    var regionSize = new IntPtr(bufferSize);
                    if (IntPtr.Add(searchStart, bufferSize)
                              .ToInt64() > searchEnd.ToInt64())
                    {
                        regionSize = (IntPtr) (searchEnd.ToInt64() - searchStart.ToInt64());
                    }
                    if (UnsafeNativeMethods.ReadProcessMemory(MemoryHandler.Instance.ProcessHandle, searchStart, lpBuffer, regionSize, out lpNumberOfBytesRead))
                    {
                        foreach (var signature in notFound)
                        {
                            var idx = FindSuperSig(lpBuffer, SigToByte(signature.Value, WildCardChar));
                            if (idx < 0)
                            {
                                temp.Add(signature);
                                continue;
                            }
                            var baseResult = new IntPtr((long) (baseAddress + regionCount * regionIncrement));
                            var searchResult = IntPtr.Add(baseResult, idx + signature.Offset);

                            signature.SigScanAddress = new IntPtr(searchResult.ToInt64());

                            Locations.Add(signature.Key, signature);
                        }
                        notFound = new List<Signature>(temp);
                        temp.Clear();
                    }
                    regionCount++;
                    searchStart = IntPtr.Add(searchStart, regionIncrement);
                }
                catch (Exception ex)
                {
                    MemoryHandler.Instance.RaiseException(Logger, ex, true);
                }
            }
        }

        /// <summary>
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="pattern"></param>
        /// <returns></returns>
        private int FindSuperSig(byte[] buffer, byte[] pattern)
        {
            var result = -1;
            if (buffer.Length <= 0 || pattern.Length <= 0 || buffer.Length < pattern.Length)
            {
                return result;
            }
            for (var i = 0; i <= buffer.Length - pattern.Length; i++)
            {
                if (buffer[i] != pattern[0])
                {
                    continue;
                }
                if (buffer.Length > 1)
                {
                    var matched = true;
                    for (var y = 1; y <= pattern.Length - 1; y++)
                    {
                        if (buffer[i + y] == pattern[y] || pattern[y] == WildCardChar)
                        {
                            continue;
                        }
                        matched = false;
                        break;
                    }
                    if (!matched)
                    {
                        continue;
                    }
                    result = i;
                    break;
                }
                result = i;
                break;
            }
            return result;
        }

        /// <summary>
        ///     Convert a hex string to a binary array while preserving any wildcard characters.
        /// </summary>
        /// <param name="signature">A hex string "signature"</param>
        /// <param name="wildcard">The byte to treat as the wildcard</param>
        /// <returns>The converted binary array. Null if the conversion failed.</returns>
        private byte[] SigToByte(string signature, byte wildcard)
        {
            var pattern = new byte[signature.Length / 2];
            var hexTable = new[]
            {
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
            };
            try
            {
                for (int x = 0, i = 0; i < signature.Length; i += 2, x += 1)
                {
                    if (signature[i] == wildcard)
                    {
                        pattern[x] = wildcard;
                    }
                    else
                    {
                        pattern[x] = (byte) (hexTable[char.ToUpper(signature[i]) - '0'] << 4 | hexTable[char.ToUpper(signature[i + 1]) - '0']);
                    }
                }
                return pattern;
            }
            catch
            {
                return null;
            }
        }

        #region Event Raising

        public event EventHandler<SignaturesFoundEvent> SignaturesFoundEvent = delegate { };

        private void RaiseSignaturesFound(Logger logger, Dictionary<string, Signature> signatures, long processingTime)
        {
            SignaturesFoundEvent?.Invoke(this, new SignaturesFoundEvent(this, logger, signatures, processingTime));
        }

        #endregion

        #region Property Bindings

        private static Scanner _instance;
        private Dictionary<string, Signature> _locations;

        public static Scanner Instance
        {
            get { return _instance ?? (_instance = new Scanner()); }
            set { _instance = value; }
        }

        public Dictionary<string, Signature> Locations
        {
            get { return _locations ?? (_locations = new Dictionary<string, Signature>()); }
            private set
            {
                if (_locations == null)
                {
                    _locations = new Dictionary<string, Signature>();
                }
                _locations = value;
            }
        }

        #endregion

        #region Constants

        private const int WildCardChar = 63;
        private const int MemCommit = 0x1000;
        private const int PageNoAccess = 0x01;
        private const int PageReadwrite = 0x04;
        private const int PageWritecopy = 0x08;
        private const int PageExecuteReadwrite = 0x40;
        private const int PageExecuteWritecopy = 0x80;
        private const int PageGuard = 0x100;

        private const int Writable = PageReadwrite | PageWritecopy | PageExecuteReadwrite | PageExecuteWritecopy | PageGuard;

        #endregion

        #region Declarations

        private List<UnsafeNativeMethods.MEMORY_BASIC_INFORMATION> _regions;

        public bool IsScanning { get; set; }

        #endregion
    }
}


The full implementation can be found on github under Icehunter/ffxivapp-memory (cant post links).
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8517
Location: 127.0.0.1

PostPosted: Fri Jul 07, 2017 11:10 am    Post subject: Reply with quote

The code is using VirtualQueryEx to dump the regions, but is enforcing specific region flags to be met. Try altering the region flag checks to allow other types of memory to be included. His code is made specifically for FFXIV so the memory regions that his addresses are going to be in are possibly only ever in the types that he is checking.
_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
logicallysynced
Newbie cheater
Reputation: 0

Joined: 30 Mar 2016
Posts: 16

PostPosted: Fri Jul 07, 2017 11:26 am    Post subject: Reply with quote

atom0s wrote:
The code is using VirtualQueryEx to dump the regions, but is enforcing specific region flags to be met. Try altering the region flag checks to allow other types of memory to be included. His code is made specifically for FFXIV so the memory regions that his addresses are going to be in are possibly only ever in the types that he is checking.


It's probably worth noting that I am using this for FFXIV as well.

I assume what you are referring to is this line here:

Code:

if (0 != (info.State & MemCommit) && 0 != (info.Protect & Writable) && 0 == (info.Protect & PageGuard))



But I have already tried nullifying this statement and still get the same results.

Something I also tried was manually setting the searchStart and searchEnd variables to ranges close to where i can see the signature in CE, and when I do this the C# scanner finds it straight away. So I'm not really sure where that leaves me..

Is it possible this while statement

Code:

var baseAddress = MemoryHandler.Instance.ProcessModel.Process.MainModule.BaseAddress;
var searchEnd = IntPtr.Add(baseAddress, moduleMemorySize);
var searchStart = baseAddress;

while (searchStart.ToInt64() < searchEnd.ToInt64())


is taking the scanner out of the scope of the allocated memory?
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8517
Location: 127.0.0.1

PostPosted: Fri Jul 07, 2017 11:58 am    Post subject: Reply with quote

Ah I did miss that. Yes, that is specifically enforcing it to scan the modules static memory area. You would want to instead have it search the systems min/max address range which you can obtain via GetSystemInfo.
http://www.pinvoke.net/default.aspx/kernel32.getsysteminfo

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

Joined: 30 Mar 2016
Posts: 16

PostPosted: Fri Jul 07, 2017 12:08 pm    Post subject: Reply with quote

atom0s wrote:
Ah I did miss that. Yes, that is specifically enforcing it to scan the modules static memory area. You would want to instead have it search the systems min/max address range which you can obtain via GetSystemInfo.
http://www.pinvoke.net/default.aspx/kernel32.getsysteminfo


Considering the returned min/max range from that GetSystemInfo is between 1000 and 7FFFFFFEFFFF (8DADB7FFF after subtracting the baseaddress of the main module), that range is huge and i think overflows the buffer quite quickly. Do you know of a way to break it down further?

EDIT

I realised that the _regions list generated from VirtualQueryEx was actually unimplemented. When i put that list into a foreach loop and used it to iterate my scanner of the regions, it found the signature straight up.

Thanks for all your help, I couldn't have figured it out without you Very Happy
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