本帖最后由 清风私语 于 2025-02-23 20:01 编辑
C# .net逆向之内存修改和内存特征码搜索源码分享.net的内存特征码搜索 功能: 1、内存特征码搜索(支持跨进程,堆栈搜索,半码F?、全码??,编写自己的搜索工具) 2、程序集dll、C/C++模块的获取基址和映像大小 3、内存修改(可以带??,如:5F ?? 6E 7D ?? 8A)
部分实现代码: 获取程序集模块的基址 public static ulong Get_Assembly_Module_BaseAddress(string assemblyName) { try { if (string.IsNullOrEmpty(assemblyName)) return 0; return (ulong)Marshal.GetHINSTANCE( AppDomain.CurrentDomain.GetAssemblies() .SelectMany(m => m.GetModules() .Where(n => n.Name.Contains(assemblyName))) .FirstOrDefault()); } catch { return 0; } }
获取模块的映像大小,.net和C/C++的通用 public static ulong Get_Moule_SizeOfImage(ulong baseAddress) { try { IMAGE_DOS_HEADER dosHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure((IntPtr)baseAddress, typeof(IMAGE_DOS_HEADER)); IMAGE_NT_HEADERS ntHeader = (IMAGE_NT_HEADERS)Marshal.PtrToStructure((IntPtr)(baseAddress + (ulong)dosHeader.e_lfanew), typeof(IMAGE_NT_HEADERS)); return (ulong)ntHeader.OptionalHeader.SizeOfImage; } catch { return 0; } }
获取C/C++模块的基址 public static ulong Get_C_Module_BaseAddress(string cModuleName) { try { if (string.IsNullOrEmpty(cModuleName)) return 0; return (ulong)Process.GetCurrentProcess() .Modules.Cast<ProcessModule>() .Where(m => m.ModuleName.Contains(cModuleName)) .ToArray().FirstOrDefault().BaseAddress; } catch { return 0; } }
获取C/C++模块的映像大小 public static ulong Get_C_Module_SizeOfImage(string cModuleName) { try { if (string.IsNullOrEmpty(cModuleName)) return 0; return (ulong)Process.GetCurrentProcess() .Modules.Cast<ProcessModule>() .Where(m => m.ModuleName.Contains(cModuleName)) .ToArray().FirstOrDefault().ModuleMemorySize; } catch { return 0; } }
修改内存数据 public static bool WriteMemoryData(ulong baseAddress, string data) { try { if (string.IsNullOrEmpty(data)) return false; data = data.Replace(" ", ""); if ((data.Length & 1) != 0) return false; // 不能为单数 uint len = (uint)data.Length / 2; // 计算特征码长度 uint oldProtect; if (VirtualProtect((IntPtr)baseAddress, len, PAGE_EXECUTE_READWRITE, out oldProtect)) { for (uint i = 0; i < len; i++) { string tempStr = data.Substring((int)i * 2, 2); if (tempStr != "??") Marshal.WriteByte((IntPtr)(baseAddress + i), Convert.ToByte(tempStr, 16)); } VirtualProtect((IntPtr)baseAddress, len, oldProtect, out oldProtect); return true; } } catch { return false; } return false; }
Sunday算法搜索特征码 x86/x64 /// <summary> /// Sunday算法搜索特征码 x86/x64 /// </summary> /// <param name="hProcess">进程句柄</param> /// <param name="startAddress">搜索的起始地址</param> /// <param name="endAddress">搜索的结束地址</param> /// <param name="pattern">特征码支持半码?F、全码??</param> /// <param name="searchNum">搜索数量,0表示无限制</param> /// <returns>返回搜索到的特征码地址列表</returns> public static List<ulong> SundayPatternFind(IntPtr hProcess, ulong startAddress, ulong endAddress, string pattern, int searchNum) { ……略…… }
调用: private static void Main(string[] args) { // System.dll是.NET Framework的核心程序集,ntdll.dll是Windows系统的核心模块 var systemAssembly = PatchPattern.Get_Assembly_Module_BaseAddress("System.dll"); Console.WriteLine("System基址:0x" + systemAssembly.ToString("X")); Console.WriteLine("System大小:0x" + PatchPattern.Get_Moule_SizeOfImage(systemAssembly).ToString("X")); Console.WriteLine("ntdll基址:0x" + PatchPattern.Get_C_Module_BaseAddress("ntdll.dll").ToString("X")); Console.WriteLine("ntdll大小:0x" + PatchPattern.Get_C_Module_SizeOfImage("ntdll.dll").ToString("X")); // Hello World! 的特征码为 [url=tel:48 00 65 00]48 00 65 00[/url] 6C 00 6C 00 6F [url=tel:00 20 00 57 00]00 20 00 57 00[/url] 6F 00 72 00 6C [url=tel:00 64 00 21 00]00 64 00 21 00[/url] string testStr = "Hello World!"; string patternStr = "[url=tel:48 00 65 00]48 00 65 00[/url] 6C 00 6C ?? 6F 00 20 00 ?7 00 6F ?? 72 00 6C [url=tel:00 64 00 21 00]00 64 00 21 00[/url]"; IntPtr hProcess = Process.GetCurrentProcess().Handle; // 获取主模块基址和大小 ulong baseAddress = (ulong)Process.GetCurrentProcess().MainModule.BaseAddress; ulong size = (ulong)Process.GetCurrentProcess().MainModule.ModuleMemorySize; Console.WriteLine("模块基址:0x" + baseAddress.ToString("X") + "----模块大小:0x" + size.ToString("X")); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // 遍历内存,搜索特征码 // 注意:搜索前确保程序集或者dll已加载 List<ulong> result = PatchPattern.SundayPatternFind(hProcess, baseAddress, baseAddress + size, patternStr, 0); stopwatch.Stop(); Console.WriteLine("搜索用时: " + stopwatch.ElapsedMilliseconds + " 毫秒"); Console.WriteLine("搜索到特征码:" + result.Count + "个"); result.ForEach(x => Console.WriteLine("特征码地址:0x" + x.ToString("X"))); // 你好,世界!的unicode编码为 60 4F 7D 59 0C FF 16 4E 4C 75 01 FF Encoding.Unicode.GetBytes("你好,世界!").ToList().ForEach(x => Console.Write(x.ToString("X2") + " ")); Console.WriteLine(); // 修改搜索到的内存数据 if (result.Count > 0) // 将特征码替换为你好,世界!的unicode编码,并添加截断0000字节 if (PatchPattern.WriteMemoryData(result[0], "60 4F 7D 59 0C FF 16 4E 4C 75 01 FF" + "0000")) { Console.WriteLine("修改内存数据成功"); Console.WriteLine("修改为:" + Marshal.PtrToStringAuto((IntPtr)result[0])); } else Console.WriteLine("修改内存数据失败"); Console.ReadKey(); }
注:若转载请注明大神论坛来源(本贴地址)与作者信息。
|