Приветствую всех, последние две недели я помогал в разработке чита для одной из популярных игр на Unity. Но админы использовали «античит» программы для получения всех dll игры, и конечно отображалась и наша dll с читом которая была заинжекчена. Одна из моих задач была обойти античит и скрыть заинжектированную dll. Я хоть и сталкивался в работе с низкоуровневым программированием, но много вещей не понимал, и в результате столкнулся с множеством проблем.
По началу я решил выполнить поиск всех модулей в процессе вот таким образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public static void Search() { Console.WriteLine("Введите имя процесса, без .EXE"); string name = Console.ReadLine(); System.Diagnostics.Process[] local_procs = System.Diagnostics.Process.GetProcesses(); //получаем список всех процессов Process target_proc = local_procs.First(p => p.ProcessName == name);//Выбираем из этого списка нашу программу ProcessModuleCollection modules = target_proc.Modules; //Получаем коллекция модулей использующие нашу программу foreach (var dll in modules) //Производим перебор коллекции { ProcessModule prDll = (ProcessModule)dll; //Делаем upcast Console.WriteLine(prDll.ModuleName); } } |
Но он находил все dll за исключением инжектированных.
Перерыв множество статей в поиске решения проблемы, я решил использовать слепок процесса, как говорилось, этим методо можно получить весь список dll спомощью winapi. И я его испытал, готового решения не было, пришлось переписывать код с C++, в результате получилось:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
static void Main(string[] args) { Console.WriteLine("Введите имя процесса, без .EXE"); string name = Console.ReadLine(); Process proc = Process.GetProcessesByName(name)[0]; EnumProcessModules((uint)proc.Id); Console.ReadKey(); } static void EnumProcessModules(uint procID) { var snapshot = CreateToolhelp32Snapshot(SnapshotFlags.Module | SnapshotFlags.Module32, procID); MODULEENTRY32 mod = new MODULEENTRY32() { dwSize = (uint)Marshal.SizeOf(typeof(MODULEENTRY32)) }; if (!Module32First(snapshot, ref mod)) return; List<string> modules = new List<string>(); do { modules.Add(mod.szModule); } while (Module32Next(snapshot, ref mod)); foreach (var t in modules) { Console.WriteLine(t); } } [DllImport("kernel32.dll", SetLastError = true)] static public extern bool CloseHandle(IntPtr hHandle); [DllImport("kernel32.dll")] static public extern bool Module32First(IntPtr hSnapshot, ref MODULEENTRY32 lpme); [DllImport("kernel32.dll")] static public extern bool Module32Next(IntPtr hSnapshot, ref MODULEENTRY32 lpme); [DllImport("kernel32.dll", SetLastError = true)] static public extern IntPtr CreateToolhelp32Snapshot(SnapshotFlags dwFlags, uint th32ProcessID); public const short INVALID_HANDLE_VALUE = -1; [Flags] public enum SnapshotFlags : uint { HeapList = 0x00000001, Process = 0x00000002, Thread = 0x00000004, Module = 0x00000008, Module32 = 0x00000010, Inherit = 0x80000000, All = 0x0000001F } [StructLayoutAttribute(LayoutKind.Sequential)] public struct MODULEENTRY32 { public uint dwSize; public uint th32ModuleID; public uint th32ProcessID; public uint GlblcntUsage; public uint ProccntUsage; IntPtr modBaseAddr; public uint modBaseSize; IntPtr hModule; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szModule; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szExePath; }; |
К сожалению он вывел тот список что и первый вариант все стандартные dll, а мне все таких надо было найти dll которая была мною инжектирована.
Я приступил к тестированию античита, да бы понять его принцип работы. И обнаружил что он инжектил свою dll в процесс, и получал по всей видимости список модуле. Однако античит был на Delphi и разобраться с ним полностью мне не удалось. Я так же решил использовать инъекцию для получения всех сборок путем рефлексии. Для этого я написал код под Unity который выводит список всех, модулей, и к моему удивлению, я нашел и свою инжектированную dll. И так я приведу пример получения всех сборок под C# приложение, думаю вам без труда составит его перенести под Unity , я не стал его сюда приводить, слишком он большой.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public static void Search() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); string text=""; foreach (var w in assemblies) { foreach (var i in w.GetReferencedAssemblies()) { text += i.FullName+"\n"; Console.WriteLine(i.FullName); } } File.WriteAllText("D:\\test.txt", text); } |
Надеюсь мои начинания помогут вам, избежать тех ошибок с которыми столкнулся я, и с экономить ваше время.