alexmarch Опубликовано 28 апреля, 2015 Поделиться Опубликовано 28 апреля, 2015 (изменено) Всем привет. читаю из памяти все прекрасно работает. lpBuffer пополняться от 0 до 255Хочу все это сохранить в файл на диск сохраняю так: Теперь в чем вопрос когда смотрю в память процесса через Cheat Engine я нахожу свою сигнатуру "3C 2F 69 74 65 6D 3E 3C 2F 63 6F 6D 6D 6F 64 69 74 69 65 73 3E 3C 2F 64 61 74 61 3E"но когда просматриваю в сохранённом файле на диске ее там нет.В чем может быть причина?как сделать дамп памяти запущенного процесса правильно?static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,[Out] byte[]lpBuffer,int dwSize, out int lpNumberOfBytesRead); protected bool SaveData(byte[] Data) { BinaryWriter Writer = null; string Name = @"C:\buffer.txt"; try { // Create a new stream to write to the file Writer = new BinaryWriter(File.OpenWrite(Name)); // Writer raw data Writer.Write(Data); Writer.Flush(); Writer.Close(); } catch { //... return false; } return true; } Изменено 28 апреля, 2015 пользователем alexmarch Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 28 апреля, 2015 Поделиться Опубликовано 28 апреля, 2015 Попробуй сделать по аналогии. Тут запись текста в файло. Пара пирмеров using System;using System.IO;using System.Text;class Test { public static void Main() { string path = @"c:\temp\MyTest.txt"; // Open the stream and write to it. using (FileStream fs = File.OpenWrite(path)) { Byte[] info = new UTF8Encoding(true).GetBytes("This is to test the OpenWrite method."); // Add some information to the file. fs.Write(info, 0, info.Length); } // Open the stream and read it back. using (FileStream fs = File.OpenRead(path)) { byte[] b = new byte[1024]; UTF8Encoding temp = new UTF8Encoding(true); while (fs.Read(b,0,b.Length) > 0) { Console.WriteLine(temp.GetString(); } } }}using System;using System.Windows.Forms;using System.IO;using System.Text;namespace WindowsApplication1{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { FileStream writeStream ; try { writeStream = new FileStream("c:\\csharp.net-informations.dat", FileMode.Create); BinaryWriter writeBinay = new BinaryWriter(writeStream); writeBinay.Write("CSharp.net-informations.com binary writer test"); writeBinay.Close(); } catch (Exception ex) { MessageBox.Show (ex.ToString()); } } }} Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 28 апреля, 2015 Поделиться Опубликовано 28 апреля, 2015 Привет! Нельзя просто так взять и записать массив байт туда, куда нужно записывать тип string. Нужно сначала смотреть в документацию. Можно сделать, например, вот так: В данном случае я использовал класс BitConverter, чтобы привести тип byte[] к типу string. Есть и другие способы. Подробнее - в поисковике по запросу "C# byte array to string". using System;using System.IO; namespace fileio_bytearray_test{ class Program { static void Main(string[] args) { var data = new byte[] { 11, 22, 33 }; try { using (var bw = new BinaryWriter(File.OpenWrite(@"test.txt"))) { bw.Write(BitConverter.ToString(data)); bw.Flush(); } } catch (Exception e) { Console.Out.WriteLine(e.InnerException.ToString()); } } }} Ссылка на комментарий Поделиться на другие сайты Поделиться
alexmarch Опубликовано 28 апреля, 2015 Автор Поделиться Опубликовано 28 апреля, 2015 Keng твой вариант приводит к такому результату4D-5A-90-00-03-00-00-00-04-00-00-00-FF-FFа должно быть приблизительно так:MZ !This program cannot be run in DOS mode.Я прекрасно отдаю себе отчет разницу между string и byteЭтот наверно подходит File.WriteAllBytes(@"C:\buffer.txt", buffer);Если честно я уже все перепробовал и не понимаю на какой стадии ошибкаЭто все твой же код я мучаю по поиску сигнатурвот пример ReadProcessMemory(handle, (IntPtr)startAddress, buffer, sizeToAllocate, out bytesread); //Читаем, с начала адресса, в буфер, весь файл, и заглушкатут переменные int startAddress = 0; // Начало файлаint sizeToAllocate = 0; // Размер файлаbyte[] buffer; // Буфер для записи всей игры из памятии вот когда я ищу свою сигнатуру я не могу ее там найти вот я и решил ее слить на диск и посмотреть в Cheat Engine, вдруг думаю я что то упустилтак вот в сохраненном buffer тоже нет моей сигнатуры. Если быть точнее есть ее куски но не целиком.Я непониманию где БАГ помогите Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 28 апреля, 2015 Поделиться Опубликовано 28 апреля, 2015 Если ты прекрасно понимаешь разницу, то тогда почему ты пытаешься скормить массив байт методу, который ждет string? Сканер сигнатур возвращает адрес памяти, причем первый найденный. Если он тебе возвращает что-то не то, а код ты подсмотрел у меня, то проблема не в моем коде, а в сигнатуре - попробуй сделать другую в этой же игре. Ссылка на комментарий Поделиться на другие сайты Поделиться
alexmarch Опубликовано 28 апреля, 2015 Автор Поделиться Опубликовано 28 апреля, 2015 ты пытаешься скормить массив байт методу, который ждет string?Покажи где я пытаюсь это сделать? то проблема не в моем кодеСпасибо за твой код все чудесноЕдинственно я его сделал несколько удобнее string hexValues = "3C 63 6F 6D 6D 6F 64 69 74 69 65 73 3E 3C 69 74 65 6D 3E 3C 69 64 3E"; 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(); //Посик сигнатуры Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 28 апреля, 2015 Поделиться Опубликовано 28 апреля, 2015 Гм, шапка темы, 2-й спойлер, 16-я строка: Writer.Write(Data); То, что ты сохранишь N байт на диск вряд ли даст что-то полезное. Я еще раз повторю, что сканер сигнатур возвращает адрес памяти, по которому было найдено первое вхождение сигнатуры, или же код ошибки на выбор разработчика. Адрес можно посмотреть в твоей программе, а что по адресу находится - в отладчике. Если же что-то работает не так, что, прежде всего, надо попробовать другую сигнатуру. Ссылка на комментарий Поделиться на другие сайты Поделиться
alexmarch Опубликовано 28 апреля, 2015 Автор Поделиться Опубликовано 28 апреля, 2015 У меня не стоит задача записи на диск всей памяти. Делал я это от безысходности так как хотел увидеть что хранит в себе buffer.buffer если я все правильно вижу хранить массив байт, с который можно проводить int сравнение в пределах 0 до 255Я думал что я неправильно конверчу свою сигнатуру все проверил там все ОК. потом я понял что что то не так с buffer-ом и поэтому начал его сохранять на диск что бы посмотреть Cheat Engine-омсейчас я так данные сохраняюFile.WriteAllBytes(@"C:\buffer.txt", buffer);Но это не решило проблемымогу видео записать Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 28 апреля, 2015 Поделиться Опубликовано 28 апреля, 2015 Как я уже писал выше, способов перевода из массива байт в текстовую строку существует довольно много. Подробнее можно почитать об этом, например, [тут]. Я все еще не совсем понимаю, как это может помочь в отладке работы сканера сигнатур, если всю необходимую информацию можно посмотреть в отладчике. Ссылка на комментарий Поделиться на другие сайты Поделиться
alexmarch Опубликовано 28 апреля, 2015 Автор Поделиться Опубликовано 28 апреля, 2015 В отладчике все классно нужная сигнатура есть. В буфере ее нет! в чем причина? Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 28 апреля, 2015 Поделиться Опубликовано 28 апреля, 2015 Нет, погоди-ка. Что значит "в буфере нет сигнатуры"? Вот пример: 0x0000001: A+B0x0000002: C+E0x0000003: F+Z Представим, что буквы - это опкоды ассемблерных инструкций, а 16-ричные цифры - адреса памяти, по которым находится этот псевдокод. Пишем такую сигнатуру: "ABCEFZ" Что делает сканер? Он берет адрес исполняемого модуля, его размер в байтах, а затем бежит по этому массиву байт и ищет в нем первое вхождение сигнатуры, то есть совпадения с ней. И возвращает адрес, по которому это совпадение нашел, то есть адрес модуля + смещение. Типа вот так: 0x0000011: A+B0x0000022: C+E0x0000033: F+Z В первом случае сканер вернет адрес 0x0000001, а во втором - 0x0000011. Если не найдет ничего - то и вернет 0 или -1. Что дальше с этим адресом делать? Например, инъекцию кода, или просто записать на его место нужное количество команд NOP. В свете вышенаписанного, что означает "в буфере нет сигнатуры"? Ссылка на комментарий Поделиться на другие сайты Поделиться
alexmarch Опубликовано 28 апреля, 2015 Автор Поделиться Опубликовано 28 апреля, 2015 Отвечая на твой вопрос: в буфере ее нет.Я ищу в памяти набор байт определенной последовательности. Когда нахожу записываю и храню переменнойВот твой почти не переделанный код.Я все понимаю о чем ты говоришь, что он ищет начало сигнатуры меня это все устраивает, я никак не могу обьяснить что по какой то блин ФАНТАСТИЧЕСКОЙ, ЗАГАДОЧНОЙ, причине в Буффере НЕТ этой сигнатуре, когда как я ее явно, отчетливо, в упор вижу через отладчик! ЧУДО, которое я не могу никак объяснить.Поэтому и прошу Вас многоуважаемые подсказать, ткнуть носом где ошибка. 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; } Ссылка на комментарий Поделиться на другие сайты Поделиться
Laziz Опубликовано 29 апреля, 2015 Поделиться Опубликовано 29 апреля, 2015 (изменено) Вы хотите сказат что на ЧитЭнжине находит последвательност байтов(сигнатуру), код каторый на С# не находит так?.Просто суть вопроса не могу понять. П.С. Вы Изменено 29 апреля, 2015 пользователем Laziz 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
alexmarch Опубликовано 29 апреля, 2015 Автор Поделиться Опубликовано 29 апреля, 2015 Ты хочеш сказат что на ЧитЭнжине находит последвательност байтов(сигнатуру), код каторый на С# не находит так?. Просто суть вопроса не могу понять. Абсолютно точно. Именно это я и говорю. Ссылка на комментарий Поделиться на другие сайты Поделиться
CuBiC Опубликовано 29 апреля, 2015 Поделиться Опубликовано 29 апреля, 2015 Может просто CE ищет сигнатуру в модуле, а ты в исполняемом файле или наоборот? 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Laziz Опубликовано 29 апреля, 2015 Поделиться Опубликовано 29 апреля, 2015 попробуйте этим поискать, потом скажете. находит ли вообше.http://forum.gamehacklab.ru/topic/3567-videourok-kenga-poisk-signatury-signaturu/?p=26679 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
alexmarch Опубликовано 29 апреля, 2015 Автор Поделиться Опубликовано 29 апреля, 2015 (изменено) Может просто CE ищет сигнатуру в модуле, а ты в исполняемом файле или наоборот? может быть, я уже не знаю куда посмотреть все по 100 перепроверил.вот код как я ищу попробуйте этим поискать, потом скажете. находит ли вообше.http://forum.gamehacklab.ru/topic/3567-videourok-kenga-poisk-signatury-signaturu/?p=26679ща попробуюТип поиска массив байт? мне в 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; } Изменено 29 апреля, 2015 пользователем alexmarch Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 29 апреля, 2015 Поделиться Опубликовано 29 апреля, 2015 Тип поиска массив байт? мне в 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 Тип: массив байтПо поводу сигнатуры: пробелы просто убери, и вставь в программу. Ссылка на комментарий Поделиться на другие сайты Поделиться
alexmarch Опубликовано 29 апреля, 2015 Автор Поделиться Опубликовано 29 апреля, 2015 (изменено) Тип: массив байтПо поводу сигнатуры: пробелы просто убери, и вставь в программу.3C3F786D6C2076657273696F6E3D22312E302220656E636F64696E673D227574662D38223F3E0A3C646174613E3C696E76656E746F72793E Ругается благим матом, говорит непонятный символ Изменено 29 апреля, 2015 пользователем alexmarch Ссылка на комментарий Поделиться на другие сайты Поделиться
Laziz Опубликовано 29 апреля, 2015 Поделиться Опубликовано 29 апреля, 2015 3C3F786D6C2076657273696F6E3D22312E302220656E636F64696E673D227574662D38223F3E0A3C646174613E3C696E76656E746F72793E Ругается благим матом, говорит непонятный символ В конце пробел стоит наверно, у меня не ругается. Ссылка на комментарий Поделиться на другие сайты Поделиться
alexmarch Опубликовано 29 апреля, 2015 Автор Поделиться Опубликовано 29 апреля, 2015 (изменено) Да нашел!!!!УРА действительно в конце пробел был. По модулям поиск не находит!Но поиск очень медленныйВ любом случаи спасибо, это хоть какое то решение.Но почему тогда в поиске по модулям в буфере оказывается не то!Зачем его тогда вообще использовать, если в нем нет нужных значений! Изменено 29 апреля, 2015 пользователем alexmarch Ссылка на комментарий Поделиться на другие сайты Поделиться
Laziz Опубликовано 29 апреля, 2015 Поделиться Опубликовано 29 апреля, 2015 Да нашел!!!!УРА действительно в конце пробел был. По модулям поиск не находит!Но поиск очень медленныйВ любом случаи спасибо, это хоть какое то решение.Но почему тогда в поиске по модулям в буфере оказывается не то!Зачем его тогда вообще использовать, если в нем нет нужных значений!На все эти вопросы ответ придет со временем, если усердно потрудитесь, и тогда скажете БИНГО! А пока скажу так.Модуль - по сути, те ж файлы на диске, а современнный игры, да и старые использует еще дополнительный памят. Поиск по модулям там не ищет. Как то так. Но почему тогда в поиске по модулям в буфере оказывается не то!не знаю, или вы так думаете или вам кажется так. во всяком случае там ничего не оказываеться. поиск медленный - потому что не С++. Ссылка на комментарий Поделиться на другие сайты Поделиться
alexmarch Опубликовано 29 апреля, 2015 Автор Поделиться Опубликовано 29 апреля, 2015 я еще поработаю с этим, результаты сюда выложу...ВСЕМ, Большое спасибо за помощь Ссылка на комментарий Поделиться на другие сайты Поделиться
alexmarch Опубликовано 30 апреля, 2015 Автор Поделиться Опубликовано 30 апреля, 2015 Виртуальное адресное пространство процесса или как найти свою сигнатуру.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(); } }} Ссылка на комментарий Поделиться на другие сайты Поделиться
Laziz Опубликовано 30 апреля, 2015 Поделиться Опубликовано 30 апреля, 2015 Виртуальное адресное пространство процесса или как найти свою сигнатуру....Прогресс на лицо. Норм. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения