[C#] Сканирование Памяти! Срыф Покроф

Тема в разделе "Создания ПО", создана пользователем iDReeM!, 21 мар 2016.

  1. iDReeM!

    iDReeM! Active Member Команда форума

    Репутация:
    0
    Регистрация:
    5 дек 2013
    Сообщения:
    3.168
    Симпатии:
    3
    [hr]
    Решил что давно не публиковался и собрал прикольную фитчу, сканирование памяти по набору байт (как поиск адресов в СЕ).[hr]Как выяснилось, СЕ и его нынешние аналоги в том же варфейсе устарели и палятся по лютому, по этому руководствуясь методами что будут описаны ниже, вы сможете сделать свой маленький аналог Cheat Engine. [hr]При копипасте на другие сайты указывайте Для просмотра внешних ссылок необходимо зарегистрироваться либо авторизоваться !!!![hr]​
    Без лишних слов код.[hr]Зависимости:
    Код:
    using System;
    
    using System.Collections;
    
    using System.Collections.Generic;
    
    using System.ComponentModel;
    
    using System.Runtime.InteropServices;
    [hr]Импорты:
    Код:
    [DllImport("kernel32.dll",SetLastError = true)]
    
    static extern bool 
    
    ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint dwSize, uint lpNumberOfBytesRead);
    
    [DllImport("kernel32.dll")]
    
    static extern bool
    
    VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, uint flNewProtect, out uint lpflOldProtect);
    [hr]Обработка:
    Код:
    bool 
    
    zReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint dwSize, uint lpNumberOfBytesRead)
    
    {
    
        try
    
        {
    
            return ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, dwSize, lpNumberOfBytesRead);
    
        }
    
         catch (Win32Exception Ex)
    
        {
    
            throw new Win32Exception("[Error] ReadProcessMemory: {0}", Ex);
    
        }
    
    }
    
    bool 
    
    zVirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, uint flNewProtect, out uint lpflOldProtect)
    
    {
    
        try
    
        {
    
            return VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect, out lpflOldProtect);
    
        }
    
        catch (Win32Exception Ex)
    
        {
    
            throw new Win32Exception("[Error] VirtualProtectEx: {0}", Ex);
    
        }
    
    }
    [hr]Функция сравнения двух моссивов байт:
    Код:
    bool Check(byte[] Bytes1, byte[] Bytes2)
    
    {
    
        IStructuralEquatable Checker = Bytes1;
    
        return Checker.Equals(Bytes2, StructuralComparisons.StructuralEqualityComparer);
    
    }
    [hr]Иии сама функция:
    Код:
    int[] MemoryScan(IntPtr HandleProcess, int StartAdress, int Size, byte[] ToSearch)
    
    {
    
        int[] Result = null;
    
        List<int> REV = new List<int>();
    
    
    
        for (int i = StartAdress; i < StartAdress + Size; i++)
    
        {
    
            byte[] dwRead = new byte[ToSearch.Length];
    
    
    
            uint FlNEWProtect = 0u;
    
            zVirtualProtectEx(HandleProcess, (IntPtr)i, ToSearch.Length, 0x40, out FlNEWProtect);
    
            zReadProcessMemory(HandleProcess, (IntPtr)i, dwRead, (uint)ToSearch.Length, 0);
    
            zVirtualProtectEx(HandleProcess, (IntPtr)i, ToSearch.Length, FlNEWProtect, out FlNEWProtect);
    
    
    
            if (Check(dwRead, ToSearch))
    
            {
    
                REV.Add(i);
    
            }
    
        }
    
    
    
        Result = new int[REV.Count];
    
    
    
        for (int a = 0; a < REV.Count; a++)
    
        {
    
            Result[a] = REV[a];
    
        }
    
    
    
        return Result;
    
    }
    [hr]Метод можно кучей способов модернизировать, по крайней мере работает)[hr]Распишу потенциал использования: (для узкоголовых)[hr]На практике многие знают, а многие и нет, что чуток модернизировав метод, можно многого достичь в сканировании памяти, можно как в СЕ искать и отсеивать адреса не только в Array of Bytes как в этом методе, но и int, float и других типах данных. (Задаёте размер нужный, на пример bool 1 байт, int и float 4 байт) читаете байты, конвертируете в значение и сравниваете, там ещё проще. Т.е можно реализовать все нужные методы поиска адресов по значениям. [hr]Как применял я:[hr]Добыл статический адресс некой функции, было необходимо найти адреса, которые на него указывают, дабы найти проверку которая проверяет эту функцию. Сравнивая добытый мною адрес с int значениями которые читал метод отсеял адреса которые указывали на нужный мне. Профит на лицо. Прелесть в том что можно читать как со всего процесса, так и с отдельных его модулей, указывая базовый адресс нужного модуля или нужный размер. т.е можно сделать тулзу лучше чем СЕ, причем самому и без лишних функций которые вы не используете.[hr]Пруф работоспособности опубликованного метода для сопляшек:
    [​IMG]
    [hr]Всем пасибо.





     
  2. SilverDeaD

    SilverDeaD New Member

    Репутация:
    0
    Регистрация:
    7 окт 2013
    Сообщения:
    124
    Симпатии:
    0
    красава)
     
  3. iDReeM!

    iDReeM! Active Member Команда форума

    Репутация:
    0
    Регистрация:
    5 дек 2013
    Сообщения:
    3.168
    Симпатии:
    3
    И так, первый пример модернизации метода.

    Можно отсеять то, что нам сканить не нужно, например проверка флагов страниц памяти.

    Структура:

    Код:
    [StructLayout(LayoutKind.Sequential)]
    
    public struct MEMORY_BASIC_INFORMATION
    
    {
    
        public IntPtr BaseAddress;
    
        public IntPtr AllocationBase;
    
        public uint AllocationProtect;
    
        public uint RegionSize;
    
        public uint State;
    
        public uint Protect;
    
        public uint Type;
    
    }
    Иморт и обработка:

    Код:
    [DllImport("kernel32.dll")]
    
    static extern int 
    
    VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);
    
    
    
    int zVirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength)
    
    {
    
        try
    
        {
    
            return VirtualQueryEx(hProcess, lpAddress, out lpBuffer, dwLength);
    
        }
    
        catch (Win32Exception Ex)
    
        {
    
            throw new Win32Exception("[Error] VirtualQueryEx: {0}", Ex);
    
        }
    
    }
    Пример модернизации метода:
    Код:
    int[] MemoryScan(IntPtr HandleProcess, int StartAdress, int Size, byte[] ToSearch)
    
    {
    
        int[] Result = null;
    
        List<int> REV = new List<int>();
    
    
    
        for (int i = StartAdress; i < StartAdress + Size; i++)
    
        {
    
            byte[] dwRead = new byte[ToSearch.Length];
    
    
    
            uint FlNEWProtect = 0u;
    
    
    
            MEMORY_BASIC_INFORMATION MemInfo = new MEMORY_BASIC_INFORMATION();
    
    
    
            int reg = zVirtualQueryEx(HandleProcess, (IntPtr)i, out MemInfo, Marshal.SizeOf(MemInfo));
    
    
    
            if ((MemInfo.State & 0x1000) != 0 && (MemInfo.Protect & 0x100) == 0)
    
            {
    
                zVirtualProtectEx(HandleProcess, (IntPtr)i, ToSearch.Length, 0x40, out FlNEWProtect);
    
                zReadProcessMemory(HandleProcess, (IntPtr)i, dwRead, (uint)ToSearch.Length, 0);
    
                zVirtualProtectEx(HandleProcess, (IntPtr)i, ToSearch.Length, FlNEWProtect, out FlNEWProtect);
    
    
    
                if (Check(dwRead, ToSearch))
    
                {
    
                    REV.Add(i);
    
                }
    
            }
    
        }
    
    
    
        Result = new int[REV.Count];
    
    
    
        for (int a = 0; a < REV.Count; a++)
    
        {
    
            Result[a] = REV[a];
    
        }
    
    
    
        return Result;
    
    }
     
    Rango-hack нравится это.
  4. AnVIRUS

    AnVIRUS Member

    Репутация:
    0
    Регистрация:
    14 ноя 2011
    Сообщения:
    979
    Симпатии:
    1
    Красава, конечно же) Но я в этом не понимаю нихера)
     
  5. iDReeM!

    iDReeM! Active Member Команда форума

    Репутация:
    0
    Регистрация:
    5 дек 2013
    Сообщения:
    3.168
    Симпатии:
    3
    У друга возник вопрос, по этому отвечу для всех, вопрос звучал так: "Сканирование памяти происходит медленей чем в СЕ и его аналогах, почему так?".

    Почему же? разберёмся как работает СЕ.

    Ему задают начало поиска и конец. Конец это начало + размер.

    Он разбивает память по регионам, как это сделать я показал выше, и считывает ВСЕ РЕГИОНЫ в себя, т.е он копирует память сканируемого процесса внутрь себя и дальше проверяет че ему надо, что обеспечивает большее быстродействие поиска за счет меньшего количества вызовов ReadProcessMemory и VirtualProtectEx. Т.е они лишь раз так сказать, дампят память, а потом уже заносят в лист все результаты перебирая и анализируя эту скопированную память внутри себя, что обеспечивает большее быстродействие + ко всему, не забывайте про многопоточность. Даркбайтс не один год работал над своим творением (Cheat Engine) , а мой пример я сделал за 20 минут.
     
  6. iDReeM!

    iDReeM! Active Member Команда форума

    Репутация:
    0
    Регистрация:
    5 дек 2013
    Сообщения:
    3.168
    Симпатии:
    3
    iDReeM!,
     

Поделиться этой страницей