Усовершенствованный метод сокрытия подгруженной dll в изложении на C для новых ОС семейства Windows (для начинающих)Usermode Hide dll metod in 'C' advanced for new family OS Windows RET; Sysenter © 2008 - 2020Я поместил весь код в один файл, что бы не париться и не оформлять потом в виде отдельной статьи, ибо время - деньги если у нас их нет, мы возьмем их у вас (шутка). Все что я здесь накодил - только для изучения стойкости систем защиты от вирусов и других вредных для нас программ и т.д. Как вы будете это применять мне абсолютно все равно, ибо cogitations poenam nemo patitur. К написанию данного примера, меня подтолкнула неспособность старых методов скрывать dll из списка загруженных модулей процесса в новых ОС семейства Windows, а именно фатальные ошибки, возникающие при попытках изменения циклических структур LIST_ENTRY.Blink, очевидно связанные с изменением производителями ядра самих этих структур. Поэтому используемые структуры максимально урезаны для данного применения. Наша цель - произвести изменения системной памяти родительского процесса, физически находящейся в его адресном пространстве между памятью выделенной под стек главного потока и начальным адресом проекции файла unicode.nls с целью уничтожения следов о загрузке нашей dll в память этого процесса, которые там оставил загрузчик ядра Windows. Привилегии отладчика нам для этого не нужны. Приступим к делу, пока ребята из Microsoft или чего нибудь не придумали нового. Код (C): #pragma once #define _WIN32_WINNT 0x501 #include <windows.h> //Укорачиваем машинный код, за счет секций и выкидываем по-возможности msvcrt //We abbreviate computer code, to account of sections and miscarry msvcrt //#pragma comment(linker, "/ENTRY:DllMain") //<-можно раскомментировать в последствии #pragma comment(linker, "/SECTION:.text,EWRX") #pragma comment(linker, "/MERGE:.rdata=.data") #pragma comment(linker, "/MERGE:.text=.data") /*Объявляем структуры (некоторые сильно урезанные для наших целей) We Declare structures (some powerfully pared for our whole) Назначение структур хорошо понятно из их названий и содержания*/ typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; typedef struct _PEB_LDR_DATA { ULONG Length; BOOLEAN Initialized; PVOID SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; //<-pared } PEB_LDR_DATA, *PPEB_LDR_DATA; typedef struct _LDR_MODULE { LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; LIST_ENTRY HashTableEntry; ULONG TimeDateStamp; } LDR_MODULE, *PLDR_MODULE; typedef struct _PEB { BOOLEAN InheritedAddressSpace; BOOLEAN ReadImageFileExecOptions; BOOLEAN BeingDebugged; BOOLEAN Spare; HANDLE Mutant; PVOID ImageBaseAddress; PPEB_LDR_DATA LoaderData; //<-pared }PEB,*PPEB; typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, *PCLIENT_ID; typedef struct _TEB { NT_TIB Tib; PVOID EnvironmentPointer; CLIENT_ID Cid; PVOID ActiveRpcInfo; PVOID ThreadLocalStoragePointer; PPEB Peb; //<-pared }PTEB; /*Прототип функции получения указателя на TEB из ntdll Function of reception of pointer on TEB from ntdll*/ typedef PTEB (NTAPI* GetCurrentNTTeb)(void); //Сама наша функция void DllHide(HANDLE hDLL) { PTEB TEB1; PEB* PEB1; LIST_ENTRY LIST_ENTRY1; PEB_LDR_DATA* PEB_LDR_DATA1; LDR_MODULE* LDR_MODULE1; /*Получаем указатель на PEB, это можно сделать 3-я методами Метод 1(самый простой) : __asm { mov eax, fs:[30h] mov PEB1, eax } Метод 2: __asm { mov eax, fs:[18h] mov TEB1, eax } PEB1=TEB1.Peb;*/ //Метод 3 (стандартными средствами натива=>,более-менее): GetCurrentNTTeb NtGetTEB = NULL; Или сразу NtGetPEB NtGetTEB = (GetCurrentNTTeb)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtCurrentTeb"); TEB1=NtGetTEB(); PEB1=TEB1.Peb; //Получаем указатель на структуру, оставленную загрузчиком ядра PEB_LDR_DATA1=PEB1->LoaderData; /*Получаем указатель на первый список загруженных модулей он всегда описывает ntdll.dll*/ LIST_ENTRY1=PEB_LDR_DATA1->InLoadOrderModuleList; /*Перечисляем списки, пока LDR_MODULE1->BaseAddress не совпадет с адресом загрузки нашей dll (здесь можно ускорить и так быстрый процесс, но это оставлю вам дебилам кто это читает)*/ do{ LIST_ENTRY1=*LIST_ENTRY1.Flink; LDR_MODULE1=(_LDR_MODULE *)LIST_ENTRY1.Flink; }while(LDR_MODULE1->BaseAddress!=hDLL); /*Подчищаем структуры, связанные с нашей dll здесь код немного растянут для понимаемости*/ MessageBox(NULL,"Вхождение найдено, после \n нажатия OK dll скроется","2008(c)RET",MB_OK); LIST_ENTRY* LIST_ENTRY2; LIST_ENTRY* LIST_ENTRY3; LIST_ENTRY3=LIST_ENTRY1.Flink; LIST_ENTRY2=LIST_ENTRY1.Blink; *LIST_ENTRY2->Flink=*LIST_ENTRY3; /*Дальше, начиная с XP SP2 не работает: LIST_ENTRY3=LIST_ENTRY1.Blink; LIST_ENTRY2=LIST_ENTRY1.Flink; *LIST_ENTRY2->Blink=*LIST_ENTRY3;*/ //Продолжаем LIST_ENTRY1=LDR_MODULE1->InMemoryOrderModuleList; LIST_ENTRY3=LIST_ENTRY1.Flink; LIST_ENTRY2=LIST_ENTRY1.Blink; *LIST_ENTRY2->Flink=*LIST_ENTRY3; /*Дальше, начиная с XP SP2 не работает: LIST_ENTRY3=LIST_ENTRY1.Blink; LIST_ENTRY2=LIST_ENTRY1.Flink; *LIST_ENTRY2->Blink=*LIST_ENTRY3;*/ /*Практически все, нас уже не видно в ProcessExplorer,Task Explorer, даже в Microsoft ListDlls, а вот в каком то-там Starter видно!!! А все это потому, что мы удалили вхождения, а вот дескриптор оставили*/ //Затираем дескриптор (для наглядности через ZeroMemory) RtlZeroMemory(&LDR_MODULE1->BaseAddress,sizeof(DWORD)); /*Практически все, нас нет, но мы работаем, и думая о будущем наших фаеров и антивирусов все же подчистим за собой мусор, а именно удалим от греха всю информацию о нашей dll из контекста*/ //Чистим путь к нашей dll RtlZeroMemory(&LDR_MODULE1->FullDllName,sizeof(UNICODE_STRING)); //Чистим имя нашей dll RtlZeroMemory(&LDR_MODULE1->BaseDllName,sizeof(UNICODE_STRING)); //Чистим дату создания нашей dll RtlZeroMemory(&LDR_MODULE1->TimeDateStamp,sizeof(DWORD)); //Чистим размер отображения нашей dll RtlZeroMemory(&LDR_MODULE1->SizeOfImage,sizeof(DWORD)); /*Если захотите можете замаскировать свою dll под какую-либо другую, заменив в LDR_MODULE вышеперечисленное чем-то своим*/ } //Только для примера//For examples DWORD WINAPI BEEPER(LPVOID hDll) { //пример вызова DllHide(hDll); while(true){Sleep(1000); Beep(8000,50);} return 0; } BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: /*Для примера таймер с бипером ч/з системный динамик правда отсюда создавать потоки не желательно Поток берется в качестве примера не случайно: Если посмотреть в списке потоков в том же Process Explorer, то мы увидим, что наш поток принадлежит якобы вовсе не нам а kernel32.dll т.к. указателя на дескриптор нашей dll в системной таблице контекста нет*/ CreateThread(NULL,0,BEEPER,(LPVOID)hModule,0,NULL); //For examples break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } if(hModule!=0) return true; else return false; } /*History source: -Tomasz Nowak (http://undocumented.ntinternals.net); -Sven B. Schreiber (sbs@orgon.com); -MS-Rem (http://wasm.ru/print.php?article=fwb P.S: подумал и решил в качестве статьи отослать.*/ P.S.: Вроде с тюрьмы писал Telegram: @DartSidys Tox: ADD1CD521F0F4E776D7C57BE367495731C8EDA1EA4B56CEB1A437275EAAB1E0811D0B21999AC E-mail: binokle@protonmail.com Jabber: CryptorX@404.city Jami: crypt
RETN, > метод сокрытия подгруженной dll От чего скрытие, сканер память прочитает. И авер вирта в своей среде прочитает.
Согласен, поэтому тут же выложу сорцы как это сделать)) Есть методология простая - сравнение: NtQuerySystemInformation NtQueryVirtualMemory RtlQueryProcessDebugInformation которая в моей приблуде к ProcessExplorer применялась в года, при которых еще мамонты водились))
RETN, Я ничего не понял. В чём суть техники ? Память можно скрыть лишь одним путём и системные вызовы там вообще не причем.
Демонстрационные функциональные улучшения для системного монитора Sysinternals Process Explorer1. Возможность выгрузки драйвера или динамических библиотек процесса двумя методами: 1.1. Мягкий метод: Контекстное меню панели отображения DLL (“Soft Unload Dll or Driver”) – попытка выгрузить модуль стандартными средствами Windows; 1.2. Жёсткий метод: Контекстное меню панели отображения DLL (“Hard Unload Dll”) – попытка выгрузить модуль стандартными средствами Windows и в случае неудачи – полное принудительное освобождение секции памяти, занимаемое модулем и последующее принудительное высвобождение виртуальной связанной памяти (помечается атрибутом Free); Примечание: A). При применении “Hard Unload Dll” возможен случай что информация о наличии DLL останется в PEB – структурах процесса, и она будет продолжать отображаться процесс-менеджерами, но в реальности модуль будет гарантированно выгружен из памяти, в чем можно убедиться программами мониторинга виртуальной памяти процессов (например VMMAP от того же Sysinternals, кстати встроил ее вызов в контекстное меню для удобства). B). Рекомендуется замораживать или удалять потоки, связанные с выгружаемым модулем,или процесс целиком стандартными средствами Process Explorer (лучше убедиться в принадлежности потока какому либо модулю, включив “View All Dll Mode”). C). Данная функциональность будет полезна при выгрузке троянских или рекламных Ad Ware –модулей. 2. Возможность анализа и отображения скрытых т.н. Stealth – модулей процесса, (Главное меню: “Options→View All Dll Mode”). При этом отображаются ВСЕ модули, загруженные в виртуальную память процесса (за исключением модулей, скрытых из режима ядра, но таких я не встречал). Эта опция будет полезна, например для поиска троянских и Ad ware модулей, вирусов и т.д. При включенной данной опции также возможна выгрузка с освобождением памяти не только DLL –модулей (в режиме “Hard Unload”). Опция “View All Dll Mode” включается автоматически при просмотре списка DLL процессов, чьи модули не доступны для отображения в обычной версии Process Explorer (процессы, доступ на чтение виртуальной памяти которых, полностью закрыт из режима ядра; например DrWeb5 и т.д.). При включении опции “View All Dll Mode” потоки скрытого модуля также будут отображаться на вкладке Threads как потоки именно этого модуля, а не как потоки kernel32 или ntdll как было раньше. Опция “View All Dll Mode” не работает полноценно на Windows XP и Windows2000 без установленных SP, на остальных переработано и протестировано в 2010 г. Примечание: вообще «перекрытие» доступа к VM процессов (обычно это антивирусы и сетевые экраны) – хороший повод внедрить туда троянский код или вирус, т.к. дыру найти всегда можно, если очень нужно…. 3. Внедрение любой динамической библиотеки в процесс (Контекстное меню процессов →”Inject DLL”) – без комментариев, причем внутри плагина осуществляется последовательно 2-мя методами. 4. Добавлена возможность загрузки и выгрузки драйверов (использовать осторожно, т.к. может привести к неработоспособности системы). 5. Добавлена возможность сканирования PE-образа файла на упаковщик/протектор или линкер сразу двумя методами (меню Dll→ “Scan PE”). 6. Добавлена возможность дампа любого модуля, спроецированного не только как Image, но и как проекция Data, на диск. Что бывает полезно при рипе данных, что в других утилитах я лично не встречал. (меню Dll→ “Dump …”, два вида дампа …). В комплект плагина входит библиотека TEST_HIDE.DLL, для тестирования режима инжекта и обнаружения срытых модулей. Сразу после инжекта в процесс она загружается (о чем выводится уведомление), скрывается (о чем выводится еще одно уведомление) и издает периодические сигналы. в системный динамик ПК. Её и потоки, принадлежащие её виртуальной памяти легко можно обнаружить и выгрузить только в режиме “View All Dll Mode”. В комплект входит тестовый драйвер, выводящий в верхней части экрана хаотично закрашенную цветную полосу. Все это разработано только в образовательных, ознакомительных, исследовательских и демонстрационных целях, по принципу «как есть». Проверялось на совместимость с Windows XP(все SP)и Windows Server 2003, Windows 7. Все пожелания, ошибки, предложения, информация по тестированию на совместимость с другими ОС, а так же заказы на разработку и «доработку» программного обеспечения и любых систем АСУТП принимаются на: Telegram: @DartSidys Tox: ADD1CD521F0F4E776D7C57BE367495731C8EDA1EA4B56CEB1A437275EAAB1E0811D0B21999AC Jabber: CryptorX@404.city © 2009 - 2010 HiEndSoft aka SYSENTER,Russia --- Сообщение объединено, 15 авг 2020 --- To Inde - да нет там сисколов, обычные ntdll - шные функи С сорцами сами разберетесь им 10 лет, чисто PoC пасс : hugtyoiygfolyihgvyBVHKHBytr51 https://www.sendspace.com/file/7xjzmi Сорцы не компилил и не редактил - чисто рабочая папка под Visual Studio 2010 Я тогда с этими "Улучшениями" впал в немилость на тогдашнем форуме Sysinternals у Руссиновича )