Как получить список всех модулей? C#

Приветствую всех, последние две недели я помогал в  разработке чита для одной из популярных игр на Unity. Но админы использовали «античит» программы для получения всех dll игры, и конечно отображалась и наша dll с читом которая была заинжекчена. Одна из моих задач была обойти античит и скрыть заинжектированную dll. Я хоть и сталкивался в работе с низкоуровневым программированием, но много вещей не понимал, и в результате столкнулся с множеством проблем.

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

    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++, в результате получилось:

 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 , я не стал его сюда приводить, слишком он большой.

   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);
        }

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

 

 

Обновлено: 26.10.2018 — 13:19

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.