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

alexmarch

Пользователи
  • Постов

    23
  • Зарегистрирован

  • Посещение

Репутация

6 Lamer

Информация о alexmarch

Посетители профиля

1 653 просмотра профиля
  1. Короче парни, если кто еще читает. Получилось то что хотел. Накопипастел со всего инета. Работает на 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(); }
  2. Почему данные храниться вне диапазона модуля? Да потому что я объясняю через Ж )))
  3. Короче. Я тут реально много флуда нафлудил Но вдруг кому то это тоже будет полезным разобраться. теперь я 100% могу сказать почему я не находил свои данные у меня 64 bit Win 8 bg оперативка, когда память не сильно загружена игра писала данные в область user-mode, а это как известно от от 0x0000000 до 0x7FFFFFFF как только память была "подзабита" игра писала "выше" и я уже не могу там нечего найти. Вот и весь ответ. Keng Очень хочу разобраться до конца, потому как твой способ мне видеться для этой задачи самый шустрый и компактнее. Еще раз 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; } }
  4. для этого нужно свою структуру вот тут подробно http://nmdsoft.blogspot.ru/2010/10/memorybasicinformation.html // если это кусок памяти доступен Так? да гораздо быстрее по PAGE_EXECUTE_READWRITE нечего не находит if (mem_basic_info.Protect == AllocationProtectEnum.PAGE_READWRITE && mem_basic_info.State == StateEnum.MEM_COMMIT);{}
  5. С Флагами поэксперементирую я пока не все доделал 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;}
  6. вот у меня как раз тот случай когда по имени модуля я не могу найти свои данные Если 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?
  7. спасибо поиск медленный не потому что C#, а потому что, во втором случаи, мы сканируем всю память User-Mode. Но тогда получается сканер сигнатур Кенга не работает корректно. меня в частности вот эти две строки интересуют. startAddress = (int)m.BaseAddress; // Берем базовый адресsizeToAllocate = m.ModuleMemorySize; // Размер модуляКенг просто берет имя модуля по названию игры, хотя данные могут хранится в другом месте, как в моем случаи
  8. Виртуальное адресное пространство процесса или как найти свою сигнатуру. 1. В 32-битных системах процессор может сгенерировать 32-битный адрес. Это означает, что каждому процессу выделяется диапазон виртуальных адресов от 0x00000000 до 0xFFFFFFFF. Эти 4 Гб адресов система делит примерно пополам, и для кода и данных пользовательского режима отводятся 2 Гб в нижней части памяти. Если быть более точным, то речь идет об виртуальных адресах, начиная с 0x00010000 и конечная 0x07FFEFFFF Источник тут >> 2. В большинстве современных операционных систем виртуальная память организуется с помощью страничной адресации. Оперативная память делится на страницы: области памяти фиксированной длины (например, 4096 байт), которые являются минимальной единицей выделяемой памяти (то есть даже запрос на 1 байт от приложения приведёт к выделению ему страницы памяти). Источник тут >> 3.Так же, как и в Win32, размер страницы на платформе x64 равен 4 Кб. Первые 64 Кб адресного пространства никогда не проецируются на физическую память, поэтому младший допустимый адрес - 0x10000. В отличие от Win32 системные DLL по умолчанию не загружаются по адресу в верхней части адресного пространства пользовательского режима. Вместо этого они загружаются после 4 Гб, обычно по адресам, близким к 0x7FF00000000. Источник тут >> Так как нам правильно сканировать память чужого процесса на C#? Windows запуская любой процесс, выделят память из кучи, стека и областей - однако Windows не будет выделять "весь блок" памяти целиком. Она пытается выделить любой свободной кусок памяти, доступной для так называемой User-Mode – таким образом выделенная память не будет непрерывной. Так же, Windows не скажет нам диапазон адресов, где мы можем найти данные программы. Таким образом, нам придется сканировать почти каждый возможный адрес ( с помощью GetSystemInfo ()) и проверять, принадлежит ли он к нашему процессу (с VirtualQueryEx ()): если это произойдет, будем читаем значения с помощью (ReadProcessMemory () ) код взял тут using System;using System.Diagnostics;using System.IO;using System.Runtime.InteropServices;namespace MemoryScanner{ class Program { // REQUIRED CONSTS const int PROCESS_QUERY_INFORMATION = 0x0400; const int MEM_COMMIT = 0x00001000; const int PAGE_READWRITE = 0x04; const int PROCESS_WM_READ = 0x0010; // REQUIRED METHODS [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); [DllImport("kernel32.dll")] public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead); [DllImport("kernel32.dll")] static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo); [DllImport("kernel32.dll", SetLastError=true)] static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength); // REQUIRED STRUCTS public struct MEMORY_BASIC_INFORMATION { public int BaseAddress; public int AllocationBase; public int AllocationProtect; public int RegionSize; public int State; public int Protect; public int lType; } public struct SYSTEM_INFO { public ushort processorArchitecture; ushort reserved; public uint pageSize; public IntPtr minimumApplicationAddress; public IntPtr maximumApplicationAddress; public IntPtr activeProcessorMask; public uint numberOfProcessors; public uint processorType; public uint allocationGranularity; public ushort processorLevel; public ushort processorRevision; } // finally... public static void Main() { // getting minimum & maximum address SYSTEM_INFO sys_info = new SYSTEM_INFO(); GetSystemInfo(out sys_info); IntPtr proc_min_address = sys_info.minimumApplicationAddress; IntPtr proc_max_address = sys_info.maximumApplicationAddress; // saving the values as long ints so I won't have to do a lot of casts later long proc_min_address_l = (long)proc_min_address; long proc_max_address_l = (long)proc_max_address; // notepad better be runnin' Process process = Process.GetProcessesByName("notepad")[0]; // opening the process with desired access level IntPtr processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_WM_READ, false, process.Id); StreamWriter sw = new StreamWriter("dump.txt"); // this will store any information we get from VirtualQueryEx() MEMORY_BASIC_INFORMATION mem_basic_info = new MEMORY_BASIC_INFORMATION(); int bytesRead = 0; // number of bytes read with ReadProcessMemory while (proc_min_address_l < proc_max_address_l) { // 28 = sizeof(MEMORY_BASIC_INFORMATION) VirtualQueryEx(processHandle, proc_min_address, out mem_basic_info, 28); // if this memory chunk is accessible if (mem_basic_info.Protect == PAGE_READWRITE && mem_basic_info.State == MEM_COMMIT) { byte[] buffer = new byte[mem_basic_info.RegionSize]; // read everything in the buffer above ReadProcessMemory((int)processHandle, mem_basic_info.BaseAddress, buffer, mem_basic_info.RegionSize, ref bytesRead); // then output this in the file for (int i = 0; i < mem_basic_info.RegionSize; i++) sw.WriteLine("0x{0} : {1}", (mem_basic_info.BaseAddress+i).ToString("X"), (char)buffer[i]); } // move to the next memory chunk proc_min_address_l += mem_basic_info.RegionSize; proc_min_address = new IntPtr(proc_min_address_l); } sw.Close(); Console.ReadLine(); } }}
  9. я еще поработаю с этим, результаты сюда выложу... ВСЕМ, Большое спасибо за помощь
  10. Да нашел!!!! УРА действительно в конце пробел был. По модулям поиск не находит! Но поиск очень медленный В любом случаи спасибо, это хоть какое то решение. Но почему тогда в поиске по модулям в буфере оказывается не то! Зачем его тогда вообще использовать, если в нем нет нужных значений!
  11. 3C3F786D6C2076657273696F6E3D22312E302220656E636F64696E673D227574662D38223F3E0A3C646174613E3C696E76656E746F72793E Ругается благим матом, говорит непонятный символ
  12. может быть, я уже не знаю куда посмотреть все по 100 перепроверил. вот код как я ищу ща попробую Тип поиска массив байт? мне в int перевести надо? у меня HEX или стринг! 3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 22 31 2E 30 22 20 65 6E 63 6F 64 69 6E 67 3D 22 75 74 66 2D 38 22 3F 3E 0A 3C 64 61 74 61 3E 3C 69 6E 76 65 6E 74 6F 72 79 3E <?xml version="1.0" encoding="utf-8"?><data><inventory> public int GetProcessID(string nameProc) //Поиск Id процесса { foreach (Process proc in Process.GetProcessesByName(nameProc)) { pID = proc.Id; // запомним ID процесса return proc.Id; } return -1; } public int FindModulesAddress(string nameProc) // Поиск по модулям { if (pID !=0) // если ID процесса найден { foreach (var p in Process.GetProcesses()) { if (p.Id == pID ) // Ищем процеес с нашим ID { foreach (ProcessModule m in p.Modules) // Находим базовый модуль { if (m.ModuleName == nameProc + ".exe") // Имя модуля должно совпадать с именим exe-файла { string srtA = m.BaseAddress.ToString();//Удалить экперемент UInt32 Base = (UInt32)m.BaseAddress.ToInt32(); //Удалить экперемент startAddress = (int)m.BaseAddress; // Берем базовый адрес sizeToAllocate = m.ModuleMemorySize; // Размер модуля return 1; } } } } } return -1; }
  13. Отвечая на твой вопрос: в буфере ее нет. Я ищу в памяти набор байт определенной последовательности. Когда нахожу записываю и храню переменной Вот твой почти не переделанный код. public int FindSignature(string hexValues) { hexValues = hexValues.Replace(" ", string.Empty); //Удалим пробелы //Преобразуем из HEX в DEC16 int[] signature = Enumerable.Range(0, hexValues.Length / 2).Select(x => Convert.ToInt32(hexValues.Substring(x * 2, 2), 16)).ToArray(); //Посик сигнатуры File.WriteAllBytes(@"C:\buffer.txt", buffer); var counter = 0; // обьявляем переменную счетчик if (signature.Length <= buffer.Length) //Проверим что бы сигнатура была меньше буфера { for (var i = 0; i < buffer.Length; i++) //Цыкл гонит по всему массиву { if (buffer[i] == signature[0] | signature[0] == -1) //Если первый символ сигнатуры равен или равен -1, тогда ... { for (var j = 0; j < signature.Length; j++) //вхождение в сигнатуру { if (buffer[i + j] == signature[j] | signature[j] == -1) //Если свопадает с сигнатурой или равен -1, тогда ... { counter++; // Считаем совпадения if (counter == signature.Length) // Если сигнатура найдена { return xmlStart = i + startAddress; //Вернем найденый адрес } } else { counter = 0; } } } } } return -1; }
  14. В отладчике все классно нужная сигнатура есть. В буфере ее нет! в чем причина?
×
×
  • Создать...

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

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