[Source] C# Sig / Pattern Scanner menu

User Tag List

Results 1 to 8 of 8
  1. #1
    mazer's Avatar Active Member
    Reputation
    55
    Join Date
    Sep 2007
    Posts
    87
    Thanks G/R
    11/27
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Source] C# Sig / Pattern Scanner

    Here's a basic example showing how to implement a memory scanner using C#.
    The code demonstrates the fundamental concepts of pattern scanning in memory and is kept simple for educational purposes.
    It includes example patterns for structures like ObjectManager, PlayerGUID, Camera etc. (tested on version 1.15.5.58555).


    I've also attached a fixed version of sigmaker (from GitHub - nvapi/sigmaker: Signature maker plugin for IDA 9.X) that works with IDA Free 9.0.
    Check out the GitHub page for instructions on how to use it.


    This is just a basic implementation to show how it works - you'll want to add proper error handling and optimization for any serious use.

    How to use: Run WowClassic, login and run scanner.

    Code:
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Linq;
    
    
    /// <summary>
    /// Configuration class that holds process name and signature patterns to scan for
    /// </summary>
    public class SignatureConfig
    {
        public string ProcessName { get; set; }
        public List<SignaturePattern> Patterns { get; set; }
    }
    
    
    /// <summary>
    /// Represents a pattern to search for in memory, using IDA-style pattern syntax
    /// </summary>
    public class SignaturePattern
    {
        // Name of the pattern for identification
        public string Name { get; set; }
    
    
        // Pattern in IDA-style format (e.g., "4C 8B 3D ? ? ? ?")
        public string IdaPattern { get; set; }
    
    
        /// <summary>
        /// Converts an IDA-style pattern into a byte array and mask
        /// The mask uses 'x' for exact match and '?' for wildcard bytes
        /// </summary>
        /// <returns>Tuple containing the pattern bytes and mask string</returns>
        public (byte[] Pattern, string Mask) ConvertIdaPattern()
        {
            var parts = IdaPattern.Split(' ');
            var pattern = new List<byte>();
            var mask = "";
    
    
            foreach (var part in parts)
            {
                if (part == "?")
                {
                    pattern.Add(0);    // Add placeholder byte for wildcards
                    mask += "?";       // Mark as wildcard in mask
                }
                else
                {
                    pattern.Add(Convert.ToByte(part, 16));  // Convert hex string to byte
                    mask += "x";                           // Mark as exact match in mask
                }
            }
    
    
            return (pattern.ToArray(), mask);
        }
    }
    
    
    class MemoryScanner
    {
        // Import Windows API function to read process memory
        [DllImport("kernel32.dll")]
        static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead);
    
    
        // Configuration for WoW Classic memory scanning
        private static SignatureConfig Config = new SignatureConfig
        {
            ProcessName = "WowClassic", //tested on 1.15.5.58555
            Patterns = new List<SignaturePattern>
            {
                // Various memory signatures for game structures
                new SignaturePattern {
                    Name = "ObjectManager",
                    IdaPattern = "4C 8B 3D ? ? ? ? 45 33 F6"
                },
                new SignaturePattern
                {
                    Name = "PlayerGUID",
                    IdaPattern = "48 8D 0D ? ? ? ? E8 ? ? ? ? 48 83 BC 24 ? ? ? ? ? 7C ? 48 8B 4C 24"
                },
                new SignaturePattern
                {
                    Name = "PlayerTargetGUID",
                    IdaPattern = "0F 10 05 ? ? ? ? C7 05"
                },
                new SignaturePattern
                {
                    Name = "MouseOverGUID",
                    IdaPattern = "0F 11 05 ? ? ? ? 0F 10 07"
                },
                new SignaturePattern
                {
                    Name = "ZoneText",
                    IdaPattern = "4C 8B 0D ? ? ? ? 8B C0"
                },
                new SignaturePattern
                {
                    Name = "Camera",
                    IdaPattern = "48 8B 0D ? ? ? ? B3"
                },
                new SignaturePattern
                {
                    Name = "FrameBase",
                    IdaPattern = "4C 8B 35 ? ? ? ? BF"
                }
            }
        };
    
    
        /// <summary>
        /// Scans a process's memory for a given pattern
        /// </summary>
        /// <param name="process">Target process to scan</param>
        /// <param name="pattern">Byte pattern to search for</param>
        /// <param name="mask">Pattern mask ('x' for exact match, '?' for wildcard)</param>
        /// <returns>Tuple containing the found address and pointer offset</returns>
        public static (IntPtr signatureAddress, int pointerOffset) ScanProcessMemory(Process process, byte[] pattern, string mask)
        {
            try
            {
                // Get process memory information
                IntPtr baseAddress = process.MainModule.BaseAddress;
                int moduleSize = process.MainModule.ModuleMemorySize;
    
    
                // Read the entire module memory into a buffer
                byte[] buffer = new byte[moduleSize];
                int bytesRead;
                ReadProcessMemory(process.Handle, baseAddress, buffer, moduleSize, out bytesRead);
    
    
                return FindPattern(buffer, pattern, mask, baseAddress);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
                return (IntPtr.Zero, 0);
            }
        }
    
    
        /// <summary>
        /// Searches for a pattern in a memory buffer
        /// </summary>
        /// <param name="buffer">Memory buffer to search in</param>
        /// <param name="pattern">Pattern to search for</param>
        /// <param name="mask">Pattern mask</param>
        /// <param name="baseAddress">Base address of the memory region</param>
        /// <returns>Tuple containing the found address and pointer offset</returns>
        private static (IntPtr address, int pointerOffset) FindPattern(byte[] buffer, byte[] pattern, string mask, IntPtr baseAddress)
        {
            // Scan through the buffer
            for (int i = 0; i < buffer.Length - pattern.Length; i++)
            {
                bool found = true;
                // Check each byte of the pattern
                for (int j = 0; j < pattern.Length; j++)
                {
                    // Skip wildcard bytes ('?'), otherwise compare exactly
                    if (mask[j] != '?' && pattern[j] != buffer[i + j])
                    {
                        found = false;
                        break;
                    }
                }
    
    
                if (found)
                {
                    // Extract the pointer offset from the found pattern
                    int offset = BitConverter.ToInt32(buffer, i + 3);
                    return (baseAddress + i, offset);
                }
            }
    
    
            return (IntPtr.Zero, 0);
        }
    
    
        static void Main()
        {
            // Find the target process
            Process process = Process.GetProcessesByName(Config.ProcessName).FirstOrDefault();
            if (process == null)
            {
                Console.WriteLine($"Process '{Config.ProcessName}' nicht gefunden.");
                return;
            }
    
    
            var baseAddress = process.MainModule.BaseAddress;
    
    
            // Scan for each configured pattern
            foreach (var sigPattern in Config.Patterns)
            {
                // Convert IDA pattern to byte pattern and mask
                var (pattern, mask) = sigPattern.ConvertIdaPattern();
                var (signatureAddress, pointerOffset) = ScanProcessMemory(process, pattern, mask);
    
    
                if (signatureAddress != IntPtr.Zero)
                {
                    // Calculate and output the final address relative to base address
                    long finalAddress = signatureAddress.ToInt64() + pointerOffset + 7 - baseAddress.ToInt64();
                    Console.WriteLine($"{sigPattern.Name}: 0x{finalAddress:X}");
                }
                else
                {
                    Console.WriteLine($"{sigPattern.Name}: nicht gefunden");
                }
            }
    
    
            Console.ReadLine();
        }
    }
    Additional patterns found with Sigmaker. I used the shortest while crossreferencing different builds of classic
    Code:
    Top 5 Signatures out of 18 xrefs for 1438AC7C8 ObjectManager:
    XREF Signature #1  @ 141D21E44: 4C 8B 3D ? ? ? ? 45 33 F6
    XREF Signature #2  @ 141D23440: 48 8B 15 ? ? ? ? 4C 8B E1
    XREF Signature #3  @ 141D24A4E: 4C 8B 3D ? ? ? ? 4C 89 35
    XREF Signature #4  @ 141D24A55: 4C 89 35 ? ? ? ? 4D 85 FF
    XREF Signature #5  @ 141D24B0E: 48 8B 3D ? ? ? ? 48 8B 1C C8
    Top 2 Signatures out of 2 xrefs for 1437F1F40 PlayerGUID:
    XREF Signature #1  @ 14198415C: 48 8D 0D ? ? ? ? E8 ? ? ? ? 48 83 BC 24 ? ? ? ? ? 7C ? 48 8B 4C 24
    XREF Signature #2  @ 14198748D: 48 8D 0D ? ? ? ? E8 ? ? ? ? 48 8B 1D ? ? ? ? 48 8B 3D ? ? ? ? 48 C1 E7
    Top 5 Signatures out of 29 xrefs for 1435D6778 PlayerTargetGUID:
    XREF Signature #1  @ 1405BD528: 0F 10 05 ? ? ? ? C7 05
    XREF Signature #2  @ 1405BAB78: 4C 8B 0D ? ? ? ? 48 C1 E8
    XREF Signature #3  @ 1405BBB01: 48 8B 05 ? ? ? ? 49 39 01
    XREF Signature #4  @ 1405BCBE7: 48 8D 15 ? ? ? ? 41 83 E6
    XREF Signature #5  @ 1405BD433: 4C 8B 05 ? ? ? ? 40 F6 C5
    Top 5 Signatures out of 13 xrefs for 14390C4E0 MouseOverGUID:
    XREF Signature #1  @ 141D5C58D: 0F 11 05 ? ? ? ? 0F 10 07
    XREF Signature #2  @ 1421853A2: 0F 10 05 ? ? ? ? 48 83 45
    XREF Signature #3  @ 141D5C4EB: 48 8D 0D ? ? ? ? 48 0F 44 D9
    XREF Signature #4  @ 1405BAA1F: 48 39 05 ? ? ? ? 75 ? 48 8B 02
    XREF Signature #5  @ 141E09442: 48 39 15 ? ? ? ? 75 ? 48 8B 46
    Top 5 Signatures out of 13 xrefs for 14390B728 ZoneText:
    XREF Signature #1  @ 1419870C5: 4C 8B 0D ? ? ? ? 8B C0
    XREF Signature #2  @ 141D2DCC2: 4C 8B 35 ? ? ? ? 48 8B F0
    XREF Signature #3  @ 141D2DEA9: 48 8B 2D ? ? ? ? C7 44 24
    XREF Signature #4  @ 141D64DCC: 48 8B 05 ? ? ? ? 48 85 C0 74 ? 40 38 38
    XREF Signature #5  @ 141D2C6DE: 48 8B 2D ? ? ? ? 48 8D 0D ? ? ? ? 45 33 C0
    Top 5 Signatures out of 109 xrefs for 1437EDAD8 Camera:
    XREF Signature #1  @ 14193B1E4: 48 8B 0D ? ? ? ? B3
    XREF Signature #2  @ 14187C369: 48 8B 35 ? ? ? ? 83 78
    XREF Signature #3  @ 141C937DA: 4C 8B 35 ? ? ? ? 39 B7
    XREF Signature #4  @ 141C70182: 4C 8B 3D ? ? ? ? 33 F6
    XREF Signature #5  @ 1405BCDC1: 48 8B 35 ? ? ? ? 48 85 C0
    Top 5 Signatures out of 250 xrefs for 1435D3678 FrameBase:
    XREF Signature #1  @ 142A86D95: 4C 8B 35 ? ? ? ? BF
    XREF Signature #2  @ 140540216: 48 8B 3D ? ? ? ? 33 C9
    XREF Signature #3  @ 1405566F1: 48 8B 2D ? ? ? ? 80 BD
    XREF Signature #4  @ 14193F458: 48 8B 0D ? ? ? ? 80 F3
    XREF Signature #5  @ 142A85E70: 48 8B 0D ? ? ? ? 32 D2 E9
    Fixed Sigmaker for IDA Free 9.0:
    SigMaker64.zip

    [Source] C# Sig / Pattern Scanner
  2. Thanks Corthezz, Julio13090, nooberang, dreadcraft, aeo, kekaezVIP, Cooldude, m3ht_t (8 members gave Thanks to mazer for this useful post)
  3. #2
    nooberang's Avatar Member
    Reputation
    14
    Join Date
    Sep 2023
    Posts
    40
    Thanks G/R
    1/7
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    God's gift. This was huge help!

  4. Thanks kekaezVIP (1 members gave Thanks to nooberang for this useful post)
  5. #3
    baggiowo's Avatar Member
    Reputation
    1
    Join Date
    Jan 2025
    Posts
    2
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thank you!

  6. #4
    kekaezVIP's Avatar Member
    Reputation
    1
    Join Date
    Jan 2025
    Posts
    2
    Thanks G/R
    4/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I converted to C++ if anyone is interested..




    Code:
    #include  <iostream>
    #include  <vector>
    #include  <windows.h>
    #include  <string>
    #include  <sstream>
    #include  <iomanip>
    #include  <TlHelp32.h> // For process and module enumeration
    struct SignaturePattern {
        std::string Name;
        std::string IdaPattern;
    
        // Converts the IDA-style pattern into a byte pattern and mask
        std::pair<std::vector<BYTE>, std::string> ConvertIdaPattern() const {
            std::vector<BYTE> pattern;
            std::string mask;
            std::istringstream stream(IdaPattern);
            std::string part;
    
            while (stream >> part) {
                if (part == "?") {
                    pattern.push_back(0); // Wildcard byte
                    mask += "?";
                }
                else {
                    pattern.push_back(static_cast<BYTE>(std::stoi(part, nullptr, 16))); // Convert hex string to byte
                    mask += "x";
                }
            }
    
            return { pattern, mask };
        }
    };
    
    struct SignatureConfig {
        std::string WindowTitle; // Title of the window (not process name)
        std::vector<SignaturePattern> Patterns;
    };
    
    // Function to read memory of a process
    BOOL ReadProcessMemorySafe(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead) {
        return ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead);
    }
    
    // Function to scan memory for the given pattern
    std::pair<LPVOID, int> FindPattern(const std::vector<BYTE>& buffer, const std::vector<BYTE>& pattern, const std::string& mask, LPVOID baseAddress) {
        for (size_t i = 0; i < buffer.size() - pattern.size(); ++i) {
            bool found = true;
            for (size_t j = 0; j < pattern.size(); ++j) {
                if (mask[j] != '?' && pattern[j] != buffer[i + j]) {
                    found = false;
                    break;
                }
            }
    
            if (found) {
                // Here we need to get an integer value from the byte buffer
                int offset = *reinterpret_cast<const int*>(&buffer[i + 3]); // Using const_cast for safely casting away constness
                return { reinterpret_cast<LPVOID>(reinterpret_cast<ULONG_PTR>(baseAddress) + i), offset };
            }
        }
    
        return { nullptr, 0 };
    }
    
    // Function to scan process memory for a pattern
    std::pair<LPVOID, int> ScanProcessMemory(HANDLE hProcess, LPVOID baseAddress, DWORD moduleSize, const std::vector<BYTE>& pattern, const std::string& mask) {
        std::vector<BYTE> buffer(moduleSize);
        SIZE_T bytesRead = 0;
    
        // Read memory into buffer
        if (!ReadProcessMemorySafe(hProcess, baseAddress, buffer.data(), moduleSize, &bytesRead)) {
            std::cerr << "Failed to read process memory" << std::endl;
            return { nullptr, 0 };
        }
    
        return FindPattern(buffer, pattern, mask, baseAddress);
    }
    
    int main() {
        // Configuration for memory signatures
        SignatureConfig config = {
            "World of Warcraft", // Window title (not process name)
            {
                { "ObjectManager", "4C 8B 3D ? ? ? ? 45 33 F6" },
                { "PlayerGUID", "48 8D 0D ? ? ? ? E8 ? ? ? ? 48 83 BC 24 ? ? ? ? ? 7C ? 48 8B 4C 24" },
                { "PlayerTargetGUID", "0F 10 05 ? ? ? ? C7 05" },
                { "MouseOverGUID", "0F 11 05 ? ? ? ? 0F 10 07" },
                { "ZoneText", "4C 8B 0D ? ? ? ? 8B C0" },
                { "Camera", "48 8B 0D ? ? ? ? B3" },
                { "FrameBase", "4C 8B 35 ? ? ? ? BF" }
            }
        };
    
        // Find the window by title
        HWND hwnd = FindWindowA(NULL, config.WindowTitle.c_str());
        if (hwnd == NULL) {
            std::cout << "Window with title '" << config.WindowTitle << "' not found." << std::endl;
            return 1;
        }
    
        DWORD pid;
        GetWindowThreadProcessId(hwnd, &pid);
        HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid);
    
        if (hProcess == NULL) {
            std::cerr << "Failed to open process." << std::endl;
            return 1;
        }
    
        // Module snapshot and loading
        MODULEENTRY32 modEntry = { 0 };
        modEntry.dwSize = sizeof(MODULEENTRY32);
    
        // Create snapshot of modules and find the first module (usually the main module)
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
        if (hSnapshot == INVALID_HANDLE_VALUE) {
            std::cerr << "Failed to create snapshot of modules." << std::endl;
            CloseHandle(hProcess);
            return 1;
        }
    
        if (Module32First(hSnapshot, &modEntry) == FALSE) {
            std::cerr << "Failed to get module information." << std::endl;
            CloseHandle(hSnapshot);
            CloseHandle(hProcess);
            return 1;
        }
    
        // Scan for each pattern in the configuration
        for (const auto& sigPattern : config.Patterns) {
            auto patternData = sigPattern.ConvertIdaPattern();
            std::vector<BYTE> pattern = patternData.first;
            std::string mask = patternData.second;
    
            auto result = ScanProcessMemory(hProcess, modEntry.modBaseAddr, modEntry.modBaseSize, pattern, mask);
    
            if (result.first != nullptr) {
                // Calculate and output the final address
                ULONG_PTR finalAddress = reinterpret_cast<ULONG_PTR>(result.first) + result.second + 7 - reinterpret_cast<ULONG_PTR>(modEntry.modBaseAddr);
                std::cout << sigPattern.Name << ": 0x" << std::uppercase << std::hex << finalAddress << std::endl;
            }
            else {
                std::cout << sigPattern.Name << ": Not found" << std::endl;
            }
        }
    
        // Clean up
        CloseHandle(hSnapshot);
        CloseHandle(hProcess);
    
        return 0;
    }

  7. #5
    scizzydo's Avatar Established Member
    Reputation
    193
    Join Date
    Oct 2019
    Posts
    129
    Thanks G/R
    5/86
    Trade Feedback
    0 (0%)
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by kekaezVIP View Post
    I converted to C++ if anyone is interested..




    Code:
    #include  <iostream>
    #include  <vector>
    #include  <windows.h>
    #include  <string>
    #include  <sstream>
    #include  <iomanip>
    #include  <TlHelp32.h> // For process and module enumeration
    struct SignaturePattern {
        std::string Name;
        std::string IdaPattern;
    
        // Converts the IDA-style pattern into a byte pattern and mask
        std::pair<std::vector<BYTE>, std::string> ConvertIdaPattern() const {
            std::vector<BYTE> pattern;
            std::string mask;
            std::istringstream stream(IdaPattern);
            std::string part;
    
            while (stream >> part) {
                if (part == "?") {
                    pattern.push_back(0); // Wildcard byte
                    mask += "?";
                }
                else {
                    pattern.push_back(static_cast<BYTE>(std::stoi(part, nullptr, 16))); // Convert hex string to byte
                    mask += "x";
                }
            }
    
            return { pattern, mask };
        }
    };
    
    struct SignatureConfig {
        std::string WindowTitle; // Title of the window (not process name)
        std::vector<SignaturePattern> Patterns;
    };
    
    // Function to read memory of a process
    BOOL ReadProcessMemorySafe(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead) {
        return ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead);
    }
    
    // Function to scan memory for the given pattern
    std::pair<LPVOID, int> FindPattern(const std::vector<BYTE>& buffer, const std::vector<BYTE>& pattern, const std::string& mask, LPVOID baseAddress) {
        for (size_t i = 0; i < buffer.size() - pattern.size(); ++i) {
            bool found = true;
            for (size_t j = 0; j < pattern.size(); ++j) {
                if (mask[j] != '?' && pattern[j] != buffer[i + j]) {
                    found = false;
                    break;
                }
            }
    
            if (found) {
                // Here we need to get an integer value from the byte buffer
                int offset = *reinterpret_cast<const int*>(&buffer[i + 3]); // Using const_cast for safely casting away constness
                return { reinterpret_cast<LPVOID>(reinterpret_cast<ULONG_PTR>(baseAddress) + i), offset };
            }
        }
    
        return { nullptr, 0 };
    }
    
    // Function to scan process memory for a pattern
    std::pair<LPVOID, int> ScanProcessMemory(HANDLE hProcess, LPVOID baseAddress, DWORD moduleSize, const std::vector<BYTE>& pattern, const std::string& mask) {
        std::vector<BYTE> buffer(moduleSize);
        SIZE_T bytesRead = 0;
    
        // Read memory into buffer
        if (!ReadProcessMemorySafe(hProcess, baseAddress, buffer.data(), moduleSize, &bytesRead)) {
            std::cerr << "Failed to read process memory" << std::endl;
            return { nullptr, 0 };
        }
    
        return FindPattern(buffer, pattern, mask, baseAddress);
    }
    
    int main() {
        // Configuration for memory signatures
        SignatureConfig config = {
            "World of Warcraft", // Window title (not process name)
            {
                { "ObjectManager", "4C 8B 3D ? ? ? ? 45 33 F6" },
                { "PlayerGUID", "48 8D 0D ? ? ? ? E8 ? ? ? ? 48 83 BC 24 ? ? ? ? ? 7C ? 48 8B 4C 24" },
                { "PlayerTargetGUID", "0F 10 05 ? ? ? ? C7 05" },
                { "MouseOverGUID", "0F 11 05 ? ? ? ? 0F 10 07" },
                { "ZoneText", "4C 8B 0D ? ? ? ? 8B C0" },
                { "Camera", "48 8B 0D ? ? ? ? B3" },
                { "FrameBase", "4C 8B 35 ? ? ? ? BF" }
            }
        };
    
        // Find the window by title
        HWND hwnd = FindWindowA(NULL, config.WindowTitle.c_str());
        if (hwnd == NULL) {
            std::cout << "Window with title '" << config.WindowTitle << "' not found." << std::endl;
            return 1;
        }
    
        DWORD pid;
        GetWindowThreadProcessId(hwnd, &pid);
        HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid);
    
        if (hProcess == NULL) {
            std::cerr << "Failed to open process." << std::endl;
            return 1;
        }
    
        // Module snapshot and loading
        MODULEENTRY32 modEntry = { 0 };
        modEntry.dwSize = sizeof(MODULEENTRY32);
    
        // Create snapshot of modules and find the first module (usually the main module)
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
        if (hSnapshot == INVALID_HANDLE_VALUE) {
            std::cerr << "Failed to create snapshot of modules." << std::endl;
            CloseHandle(hProcess);
            return 1;
        }
    
        if (Module32First(hSnapshot, &modEntry) == FALSE) {
            std::cerr << "Failed to get module information." << std::endl;
            CloseHandle(hSnapshot);
            CloseHandle(hProcess);
            return 1;
        }
    
        // Scan for each pattern in the configuration
        for (const auto& sigPattern : config.Patterns) {
            auto patternData = sigPattern.ConvertIdaPattern();
            std::vector<BYTE> pattern = patternData.first;
            std::string mask = patternData.second;
    
            auto result = ScanProcessMemory(hProcess, modEntry.modBaseAddr, modEntry.modBaseSize, pattern, mask);
    
            if (result.first != nullptr) {
                // Calculate and output the final address
                ULONG_PTR finalAddress = reinterpret_cast<ULONG_PTR>(result.first) + result.second + 7 - reinterpret_cast<ULONG_PTR>(modEntry.modBaseAddr);
                std::cout << sigPattern.Name << ": 0x" << std::uppercase << std::hex << finalAddress << std::endl;
            }
            else {
                std::cout << sigPattern.Name << ": Not found" << std::endl;
            }
        }
    
        // Clean up
        CloseHandle(hSnapshot);
        CloseHandle(hProcess);
    
        return 0;
    }
    Just throwing this out here for my pattern scanner, if you're doing C++ and compiling the patterns in: https://github.com/scizzydo/PatternScanner

    It's very fast, and if using the CompileTimePattern it does all of the pattern conversion at compile time... obviously 😂

    It also allows for extra features built on top of just parsing the Ida style pattern

  8. Thanks kekaezVIP (1 members gave Thanks to scizzydo for this useful post)
  9. #6
    Razzue's Avatar Elite User Avid Ailurophile

    CoreCoins Purchaser Authenticator enabled
    Reputation
    398
    Join Date
    Jun 2017
    Posts
    608
    Thanks G/R
    193/283
    Trade Feedback
    2 (100%)
    Mentioned
    14 Post(s)
    Tagged
    0 Thread(s)
    Oh wait.. are we just linking our scanners now? XD
    GitHub - Razzue/Wow-Dumper: A simple wow offset dumper
    "May all your bacon burn"

  10. Thanks kekaezVIP (1 members gave Thanks to Razzue for this useful post)
  11. #7
    Archos's Avatar Member Authenticator enabled
    Reputation
    3
    Join Date
    Mar 2007
    Posts
    42
    Thanks G/R
    4/2
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I feel like we have come full circle. I rewrote GitHub - scizzydo/PatternScanner in C# for macOS!

  12. Thanks Razzue (1 members gave Thanks to Archos for this useful post)
  13. #8
    Cooldude's Avatar Member
    Reputation
    11
    Join Date
    Sep 2006
    Posts
    136
    Thanks G/R
    9/0
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Thank you! This is great to learn from. For a big noob to IDA, how do you find the object manager manually in case next patch the code around this function changes and the signature scanning breaks?

    I searched by text in IDA and found
    Code:
    ".rdata:0000000142D89FD8 aObjectManagerL db 'Object manager list status: (use gmvision to see server onlys)',0"
    When I try to jump to xrefs it says there are none. Any info or tutorial on this process to help my learning?

    Thanks again!

Similar Threads

  1. [Tool] EverScan - An Open Source Warden Scanner
    By DarkLinux in forum World of Warcraft Bots and Programs
    Replies: 20
    Last Post: 02-08-2017, 02:31 PM
  2. [source] C# Warden scanner
    By Wildbreath in forum WoW Memory Editing
    Replies: 7
    Last Post: 03-18-2014, 01:46 AM
  3. IDA Plugin - Pattern Maker - Source included
    By Tanaris4 in forum WoW Memory Editing
    Replies: 3
    Last Post: 05-05-2011, 08:51 PM
  4. Own pattern-scanner
    By TenshiSan in forum WoW Memory Editing
    Replies: 4
    Last Post: 04-09-2011, 07:33 AM
  5. Malu05's Pattern Scanner
    By UnknOwned in forum WoW Memory Editing
    Replies: 9
    Last Post: 03-01-2010, 04:06 PM
All times are GMT -5. The time now is 02:17 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search