Перейти к содержанию

C# ReadProcessMemory и сохранение на диск


Рекомендуемые сообщения

Прогресс на лицо. Норм.

спасибо

поиск медленный - потому что не С++.

поиск медленный не потому что C#, а потому что, во втором случаи, мы сканируем всю память User-Mode. Но тогда получается сканер сигнатур Кенга не работает корректно.

меня в частности вот эти две строки интересуют.

startAddress = (int)m.BaseAddress; // Берем базовый адрес
sizeToAllocate = m.ModuleMemorySize; // Размер модуля

Кенг просто берет имя модуля по названию игры, хотя данные могут хранится в другом месте, как в моем случаи

Изменено пользователем alexmarch
Ссылка на комментарий
Поделиться на другие сайты

К посту 24.

 

Сначала приведу описания

 

 

Можно значительно ускорить поиск даже на C#, если

 

1) Указывать флаг  не PAGE_READWRITE, а например PAGE_EXECUTE_READWRITE. Во всяком случае флаги нужно подбирать в соответствии с тем что и где ищем. Если это код, то ищем в памяти где права на код. Если это данные перезаписываемые, то и ищем по флагам соответствующим. Подробно флаги расписаны в MSDN

 

2) Указывать модуль  в адресном пространстве которого ищем сигну (*.exe или *.dll).

 

Пункты 1 и 2 должны значительно ускорить поиск. 

//http://www.pinvoke.net/default.aspx/kernel32/VirtualQueryEx.html//MEMORY_BASIC_INFORMATION     [StructLayout(LayoutKind.Sequential)]     public struct MEMORY_BASIC_INFORMATION     {     public IntPtr BaseAddress;     public IntPtr AllocationBase;     public uint AllocationProtect;     public IntPtr RegionSize;     public uint State;     public uint Protect;     public uint Type;     }//Flags     public enum AllocationProtect : uint     {     PAGE_EXECUTE = 0x00000010,     PAGE_EXECUTE_READ = 0x00000020,     PAGE_EXECUTE_READWRITE = 0x00000040,     PAGE_EXECUTE_WRITECOPY = 0x00000080,     PAGE_NOACCESS = 0x00000001,     PAGE_READONLY = 0x00000002,     PAGE_READWRITE = 0x00000004,     PAGE_WRITECOPY = 0x00000008,     PAGE_GUARD = 0x00000100,     PAGE_NOCACHE = 0x00000200,     PAGE_WRITECOMBINE = 0x00000400     }
Ссылка на комментарий
Поделиться на другие сайты

Кстати говоря, я слабо себе представляю, как оно будет работать без флага EXECUTE. Мы же исполняемый код ищем, а не данные. И да, я беру имя модуля, нужное для конкретного случая. Все модули сканировать смысла нет- слишком долго будет, а в том же CE всегда можно посмотреть, в каком модуле нужный код лежит - его и следует сканировать.
Ссылка на комментарий
Поделиться на другие сайты

вот у меня как раз тот случай когда по имени модуля я не могу найти свои данные

Если

VirtualQueryEx(processHandle, proc_min_address, out mem_basic_info, 28);
то мы получаем в результате всю память игры. И статическую и динамическую. 

 

всем понятно что статическая память нужна для переменных выделяемых заранее, для хранения и (.text  и т.д.), в отличие от динамической она выделяется после того  был запущен модуль, в которой переменные  будут выделены в кучу (динамическое пространство-адрес. прим. Кенг об этом говорил). Стек динамически выделяется и будет находиться за пределами сегментов памяти модуля. 

короче можно сделать проверку и дело пойдет быстрее

VirtualQueryEx(processHandle, proc_min_address, out mem_basic_info, 28);if (mem_basic_info.Type == MEM_IMAGE) {}
работает ли это с адресами x64? Изменено пользователем alexmarch
Ссылка на комментарий
Поделиться на другие сайты

if (mem_basic_info.Type == MEM_IMAGE) {}

а что за переменный "MEM_IMAGE"?

 

Медленный - имелся введу в широком смысле. Я конечно знаю разницу между двумя способами. Кенг показал один способ поиска и тоже корректный, но для узкого круга поиска.

Изменено пользователем Laziz
Ссылка на комментарий
Поделиться на другие сайты

С Флагами поэксперементирую

а что за переменный "MEM_IMAGE"?

 

 

я пока не все доделал

 

public enum TypeEnum : uint{MEM_IMAGE = 0x1000000,MEM_MAPPED = 0x40000,MEM_PRIVATE = 0x20000}public struct MEMORY_BASIC_INFORMATION{public uint BaseAddress;public IntPtr AllocationBase;public AllocationProtectEnum AllocationProtect;public uint RegionSize;public StateEnum State;public AllocationProtectEnum Protect;public TypeEnum lType;}
Ссылка на комментарий
Поделиться на другие сайты

Ты можешь это сам проверить  ;)

для этого нужно свою структуру

 

  

protected struct MEMORY_BASIC_INFORMATION_x64

 

Да я на шарпе 2 неделе...

Мда хакеры уже пошли нет те :-P  

 

а что за переменный "MEM_IMAGE"?

 

Медленный - имелся введу в широком смысле. Я конечно знаю разницу между двумя способами. Кенг показал один способ поиска и тоже корректный, но для узкого круга поиска.

вот тут подробно http://nmdsoft.blogspot.ru/2010/10/memorybasicinformation.html

 

1) Указывать флаг  не PAGE_READWRITE, а например PAGE_EXECUTE_READWRITE. Во всяком случае флаги нужно подбирать в соответствии с тем что и где ищем. Если это код, то ищем в памяти где права на код. Если это данные перезаписываемые, то и ищем по флагам соответствующим. Подробно флаги расписаны в MSDN

                // если это кусок памяти доступен

 

Так? да гораздо быстрее

1) Указывать флаг  не PAGE_READWRITE, а например PAGE_EXECUTE_READWRITE.

по PAGE_EXECUTE_READWRITE нечего не находит

                if (mem_basic_info.Protect == AllocationProtectEnum.PAGE_READWRITE && mem_basic_info.State == StateEnum.MEM_COMMIT);{}
Изменено пользователем alexmarch
Ссылка на комментарий
Поделиться на другие сайты

по PAGE_EXECUTE_READWRITE нечего не находит

мне кажется для начало надо посмотрет на СЕ тот регион, где байты, в каком состаянии

post-8512-0-15369200-1430415257_thumb.jp

исходя из этого надо писат  PAGE_EXECUTE_READWRITE или READWRITE или READ

Изменено пользователем Laziz
Ссылка на комментарий
Поделиться на другие сайты

Короче. Я тут реально много флуда нафлудил :)

Но вдруг кому то это тоже будет полезным разобраться.

теперь я 100% могу сказать почему я не находил свои данные

у меня 64 bit Win 8 bg оперативка, когда память не сильно загружена игра писала данные в область user-mode, а это как известно от  от 0x0000000  до 0x7FFFFFFF

как только память была "подзабита" игра писала "выше" и я уже не могу там нечего найти.

Вот и весь ответ.

Keng

Очень хочу разобраться до конца, потому как твой способ мне видеться для этой задачи самый шустрый и компактнее.

Еще раз

почему в диапазон адресов   между (int)m.BaseAddress и m.ModuleMemorySize не попадают те данные которые хранит игра?

почему данные моего модуля храниться вне этого диапазона?

foreach (ProcessModule m in p.Modules) // Получаем модули связанные с процесом                        {                            if (m.ModuleName == nameProc + ".exe") // Имя модуля должно совпадать с именим exe-файла                            {                                startAddress = (int)m.BaseAddress; // Возвращает адрес в памяти, куда был загружен модуль.                                sizeToAllocate = m.ModuleMemorySize; // Возвращает размер модуля                                lblProgress.Text = string.Format("{0}/{1}", startAddress, sizeToAllocate);                                return 1;                                                            }                        }
Изменено пользователем alexmarch
  • Плюс 3
Ссылка на комментарий
Поделиться на другие сайты

33ef052868ed6e9cb29902c2d64d98c3.png

Почему данные храниться вне диапазона модуля?

Здорово, сам нашел причину и никто даже не догадывался в теме.

Да потому что я объясняю через Ж :)))) Изменено пользователем alexmarch
Ссылка на комментарий
Поделиться на другие сайты

Почему данные храниться вне диапазона модуля?

 

Они там хранятся, потому что они там нужны, а не в другом месте. Нужна временная память разного размера под временные данные. Поэтому вне модуля. 

Ссылка на комментарий
Поделиться на другие сайты

Короче парни, если кто еще читает.
Получилось то что хотел. Накопипастел со всего инета.
Работает на x64 сканирует 32х приложения и находит мои данные в пределах выше 4 гб.
И что самое приятное, он пожалуй самый быстрый.(хотя по модулю может чуть быстрее)
И очень простой и маленький код
Спасибо кенгу за его видо уроки и Laziz за вектор поиска
вот готовый код

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using TradingAssisetent;using System.Diagnostics;using System.Runtime.InteropServices;namespace TradingAssisetent{    public class sigScan    {        [DllImport("kernel32.dll")]        public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, int lpNumberOfBytesRead);        [DllImport("kernel32.dll")]        protected static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);        [StructLayout(LayoutKind.Sequential)]        protected struct MEMORY_BASIC_INFORMATION        {            public IntPtr BaseAddress;     // Указатель на базовый адрес региона страниц.            public IntPtr AllocationBase;  // Указатель на базовый адрес диапазона страниц, выделенных VirtualAlloc функции. Страница, на которую указывает BaseAddress элемента, содержащаяся в данном диапазоне распределения.            public uint AllocationProtect; // Опция Защита памяти, когда область была первоначально выделено. Этот элемент может быть одним из постоянных защиты памяти или 0, если абонент не имеет доступа.            public uint RegionSize;        // Размер области, начиная с базового адреса, в которой все страницы имеют идентичные атрибуты, в байтах.            public uint State;            public uint Protect;            public uint Type;        }        List<MEMORY_BASIC_INFORMATION> MemReg { get; set; }                                          // Структура карты памяти MemReg        public void MemInfo(IntPtr pHandle)                                                          // В место того что бы каждый раз читать ReadProcessMemory, создадим свою карту памяти.                                                                                                     // Свалим все, в одну кучу(MemReg) и будем в нем искать свою сигнатуру         {                                                                                            // Функция VirtualQueryEx возвращает информацию о диапазоне страниц, виртуального адресного пространства указанного процесса.            IntPtr Addy = new IntPtr();                                                              // hProcess: THandle;                      //дескриптор процесса            while (true)                                                                             // lpAddress: Pointer;                     //адрес начала региона памяти             {                                                                                        // var lpBuffer: TMemoryBasicInformation;  //буфер для получения информации                MEMORY_BASIC_INFORMATION MemInfo = new MEMORY_BASIC_INFORMATION();                   // dwLength: DWORD                         //размер буфера                int MemDump = VirtualQueryEx(pHandle, Addy, out  MemInfo, Marshal.SizeOf(MemInfo));  // Вызовим VirtualQueryEx, получим базовый адрес процесса и размер региона в структуру MEMORY_BASIC_INFORMATION                if (MemDump == 0) break;                                                             // Выход из цыкла                 if ((MemInfo.State & 0x1000) != 0 && (MemInfo.Protect & 0x100) == 0)                 // Если флаг региона  0x1000, 0x100 известные флаги (MEM_COMMIT, MEM_RESERVE, MEM_FREE, MEM_PRIVATE, MEM_MAPPED, or MEM_IMAGE).                    MemReg.Add(MemInfo);                                                             // Добавим в MemReg                                 Addy = new IntPtr(MemInfo.BaseAddress.ToInt32() + (int)MemInfo.RegionSize);                            }        }               public IntPtr _Scan(byte[] sIn, byte[] sFor)        {            int[] sBytes = new int[256]; int Pool = 0;            int End = sFor.Length - 1;            for (int i = 0; i < 256; i++)                sBytes[i] = sFor.Length;            for (int i = 0; i < End; i++)                sBytes[sFor[i]] = End - i;            while (Pool <= sIn.Length - sFor.Length)            {                for (int i = End; sIn[Pool + i] == sFor[i]; i--)                    if (i == 0) return new IntPtr(Pool);                Pool += sBytes[sIn[Pool + End]];            }            return IntPtr.Zero;        }        public IntPtr AobScan(string ProcessName, byte[] Pattern)        {            Process[] P = Process.GetProcessesByName(ProcessName);  // Получим в p процес;            if (P.Length == 0) return IntPtr.Zero;                  // Если процесс не найден, вернем 0;            MemReg = new List<MEMORY_BASIC_INFORMATION>();          // Создадим маcсив структуры -> MEMORY_BASIC_INFORMATION;            MemInfo(P[0].Handle);                                   // Получим  хендл;            for (int i = 0; i < MemReg.Count; i++)                  // Перечисляем пока есть страницы            {                byte[] buff = new byte[MemReg[i].RegionSize ];       // Буфер                ReadProcessMemory(P[0].Handle, MemReg[i].BaseAddress, buff, MemReg[i].RegionSize, 0);                IntPtr Result = _Scan(buff, Pattern);                if (Result != IntPtr.Zero)                    return new IntPtr(MemReg[i].BaseAddress.ToInt32() + Result.ToInt32());            }            return IntPtr.Zero;        }    } } 
 private void button3_Click(object sender, EventArgs e)        {            sigScan sigScan = new sigScan();                       textBox1.Text = "";            string hexValues = textBox2.Text;   //берем значение с поисковой строки            byte[] toFind = System.Text.Encoding.UTF8.GetBytes(hexValues);   //перводим стринг в байт            IntPtr MyAddress = sigScan.AobScan("EliteDangerous32", toFind);            textBox1.Text = textBox1.Text + MyAddress.ToString();        } 
Изменено пользователем alexmarch
  • Плюс 2
Ссылка на комментарий
Поделиться на другие сайты

Еще, по правилам этикета не плохо бы определить к классу IDisposable. https://msdn.microsoft.com/en-us/library/system.idisposable.aspx

http://metanit.com/sharp/tutorial/8.1.php

Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.