я так понял ты относительно своей процедуры выгрузки длл из памяти? это я уже научился делать правда несколько иным способом ))))) сейчас надо снять установленные хуки, чтобы небыло бсодов при выгрузке этой дллки из винлогона... з.ы. токо сча заметил твой пост относительно FreeLibraryAndExitThread. прийду домой - попробую. спасибо!!!
SiruS Как-то ты очень интересно выгружаешь длл-ки. Если длл-ка посторонняя - удаленный поток - еще более менее приемлимое решение. Но для своей дллки - это глупость. Используй средства межпроцессной синхронизации. В самом простом случае достаточно события (Event-а) Отдельным потоком мониторишь в дллке эвент. И в случае если кто-то выполнил SetEvent() - тотально выгружаешься. В более сложном: эвент + разделяемая память (куда можно передавать имя процесса или ПИД, из которого нужно выгрузиться) О приемах межпроцессной синхронизации читай статьи на васме
писал для себя побыстрому, поэтому имя Dll и PId процесса подставляется до компиляции, можно было сделать GUI Код (Text): format PE GUI 4.0 entry start include '%fasminc%\win32a.inc' PID = 0000009A8h DLLNAME equ 'uxtheme.dll' INFINITE = 0FFFFFFFFh ; Infinite timeout section '.code' code readable executable align 4 start: mov eax, [FreeLibrary] mov [ddFreeLibrary], eax mov eax, [GetModuleHandle] mov [ddGetModuleHandle], eax invoke OpenProcess, PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_WRITE or SYNCHRONIZE, FALSE, PID test eax, eax jz @exit mov [hProcess], eax invoke VirtualAllocEx, eax, NULL, inject_code_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE test eax, eax jz @close mov [DllNameAddress], eax invoke WriteProcessMemory, [hProcess], eax, inject_code_start, inject_code_size, NULL test eax, eax jz @free mov eax, [DllNameAddress] add eax, sizeofDllName invoke CreateRemoteThread, [hProcess], NULL, 0, eax, 0, 0, NULL test eax, eax jz @free push eax invoke WaitForSingleObject, eax, INFINITE call [CloseHandle] invoke VirtualFreeEx, [hProcess], [DllNameAddress], 0, MEM_RELEASE invoke CloseHandle, [hProcess] invoke MessageBox, NULL, szDone, NULL, MB_OK or MB_ICONINFORMATION jmp @exit @free: invoke VirtualFreeEx, [hProcess], [DllNameAddress], 0, MEM_RELEASE @close: invoke CloseHandle, [hProcess] @exit: invoke ExitProcess, 0 section '.data' data readable writeable inject_code_start = $ DllName db DLLNAME,0 sizeofDllName = $ - DllName db 68h ; push DllNameAddress dd 0 db 0B8h ; mov eax, ddGetModuleHandle dd 0 call eax push eax db 0B8h ; mov eax, ddFreeLibrary dd 0 call eax retn 4 inject_code_size = $ - inject_code_start szDone db 'Done!',0 hProcess dd ? section '.idata' import data readable library kernel32,'KERNEL32.DLL',\ user32,'USER32.DLL' include '%fasminc%\APIA\KERNEL32.INC' include '%fasminc%\APIA\USER32.INC'
А Если попробовать вот так: 1) получить TEB процесса, перебрать все LDR модули, и найти нужный 2) суспендить либо полностью процесс, либо все потоки 3) открыть процесс, и вызвать invoke ZwUnmapViewOfSection,ProcessHendl,LDR_DATA_TABLE_ENTRY.DllBase 4) ресуспенд Должно сработать.., и некакие записы в процесс и удаленные потоки не понадобятся..
Magnum говорю же, эт не моя дллка. была бы моя - было бы проще ))) Asterix делаю так же как и ты, ток без VirtualAllocEx и WriteProcessMemory Flasher спасибо, мне пока и создание удаленного потока подходит ) slow по прежнему неудаеться снять хуки. поиск по форуму на предмет "снятие хуков" ничего не дал (
SiruS "Хуки" - это на самом деле скорее всего сплайсинг. Вам нужно искать в отладчике, где dll ставит свои перехваты и просто заменить подменённые инструкции оригинальными.
Добавить к коду Asterix цикл - это при возможном ref count не 1. + хорошо бы сделать поиск апишек (в случае ASLR).
нашел вот такой код: Код (Text): VOID UnhookMod( LPSTR lpModName ) { HANDLE hFile, hMapping; HMODULE hMod; LPVOID hMap; CHAR lpSystemDir[MAX_PATH*2]; ULONG b; GetSystemDirectory( lpSystemDir, MAX_PATH-1 ); lstrcat( lpSystemDir, "\\" ); lstrcat( lpSystemDir, lpModName ); hFile = CreateFile( lpSystemDir, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0 ); if (hFile != INVALID_HANDLE_VALUE) { hMapping = CreateFileMapping( hFile, 0, PAGE_READONLY|SEC_IMAGE, 0, 0, 0 ); if (hMapping != INVALID_HANDLE_VALUE) { hMap = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 ); if (hMap) { IMAGE_DOS_HEADER *dh = (IMAGE_DOS_HEADER*)hMap; IMAGE_NT_HEADERS *nh = (IMAGE_NT_HEADERS*)((ULONG)hMap+dh->e_lfanew); IMAGE_FILE_HEADER *fh = (IMAGE_FILE_HEADER*)&nh->FileHeader; IMAGE_OPTIONAL_HEADER *oh = (IMAGE_OPTIONAL_HEADER*)&nh->OptionalHeader; IMAGE_EXPORT_DIRECTORY *ed = (IMAGE_EXPORT_DIRECTORY*)((ULONG)hMap+oh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); ULONG *functionEntryPoints = (ULONG*)((ULONG)hMap+ed->AddressOfFunctions); BYTE entryPointBytes[10], originalBytes[10]; for (int i = 0; i < ed->NumberOfFunctions; i++) { ULONG entryVA = oh->ImageBase+functionEntryPoints[i], entryMA = ((ULONG)hMap+functionEntryPoints[i]); memcpy( originalBytes, (PVOID)entryMA, 10 ); ReadProcessMemory( (HANDLE)-1, (LPVOID)entryVA, (LPVOID)entryPointBytes, 10, &b ); if (memcmp( entryPointBytes, originalBytes, 10 )) WriteProcessMemory( (HANDLE)-1, (LPVOID)entryVA, (LPVOID)originalBytes, 10, &b ); } } } } UnmapViewOfFile( hMap ); CloseHandle( hMapping ); CloseHandle( hFile ); } VOID UnloadWLHook( VOID ) { MODULEENTRY32 me; HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, GetCurrentProcessId() ); if (hSnapshot != INVALID_HANDLE_VALUE && Module32First( hSnapshot, &me )) { do { if (lstrcmp( me.szModule, "wl_hook.dll" )) UnhookMod( me.szModule ); } while (Module32Next( hSnapshot, &me )); } CloseHandle( hSnapshot ); FreeLibrary( GetModuleHandle( "wl_hook.dll" ) ); } помогите перевести вот этот кусок: Код (Text): IMAGE_DOS_HEADER *dh = (IMAGE_DOS_HEADER*)hMap; IMAGE_NT_HEADERS *nh = (IMAGE_NT_HEADERS*)((ULONG)hMap+dh->e_lfanew); IMAGE_FILE_HEADER *fh = (IMAGE_FILE_HEADER*)&nh->FileHeader; IMAGE_OPTIONAL_HEADER *oh = (IMAGE_OPTIONAL_HEADER*)&nh->OptionalHeader; IMAGE_EXPORT_DIRECTORY *ed = (IMAGE_EXPORT_DIRECTORY*)((ULONG)hMap+oh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); ULONG *functionEntryPoints = (ULONG*)((ULONG)hMap+ed->AddressOfFunctions); BYTE entryPointBytes[10], originalBytes[10]; for (int i = 0; i < ed->NumberOfFunctions; i++) { ULONG entryVA = oh->ImageBase+functionEntryPoints[i], entryMA = ((ULONG)hMap+functionEntryPoints[i]); заранее спасибо!
SiruS //обычное переприсвоение dh = hMap IMAGE_DOS_HEADER *dh = (IMAGE_DOS_HEADER*)hMap; //по смещению e_lfanew (поле структуры IMAGE_DOS_HEADER) относительно адреса структуры dh берём двойное слово, которое является смещением NT-заголовка, прибавляем к нему базу (hMap) и запоминаем в nh IMAGE_NT_HEADERS *nh = (IMAGE_NT_HEADERS*)((ULONG)hMap+dh->e_lfanew); //адрес смещения FileHeader (поле структуры IMAGE_NT_HEADERS) относительно адреса nh запоминаем в fh IMAGE_FILE_HEADER *fh = (IMAGE_FILE_HEADER*)&nh->FileHeader; //адрес смещения OptionalHeader (поле структуры IMAGE_NT_HEADERS) относительно nh запоминаем в oh IMAGE_OPTIONAL_HEADER *oh = (IMAGE_OPTIONAL_HEADER*)&nh->OptionalHeader; //по смещению DataDirectory (поле структуры IMAGE_OPTIONAL_HEADER, а так же массив структур IMAGE_DATA_DIRECTORY) относительно oh находим поле VirtualAddress нулевой структуры (т.к. IMAGE_DIRECTORY_ENTRY_EXPORT = 0), которое содержит смещение таблицы экспорта, прибавляем к нему базу (hMap) и запоминаем в ed. IMAGE_EXPORT_DIRECTORY *ed = (IMAGE_EXPORT_DIRECTORY*)((ULONG)hMap+oh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); //по смещению AddressOfFunctions относительно ed (начало таблицы экспорта) берём двойное слово, которое является смещением массива смещений экспортируемых функций, прибавляем к нему базу и запоминаем в functionEntryPoints ULONG *functionEntryPoints = (ULONG*)((ULONG)hMap+ed->AddressOfFunctions); BYTE entryPointBytes[10], originalBytes[10]; //Этим циклом проходимся по массиву смещений экспортируемых функций и копируем оригинальные байты из библиотеки, загруженной по адресу hMap в библиотеку, загруженную по адресу ImageBase. И это, кстати, грубая ошибка, т.к. библиотека во многих случаях не будет загружена по адресу ImageBase. Поэтому вместо значения oh->ImageBase нужно подставлять значение GetModuleHandle(lpModName). for (int i = 0; i < ed->NumberOfFunctions; i++) { ULONG entryVA = oh->ImageBase+functionEntryPoints, entryMA = ((ULONG)hMap+functionEntryPoints); Везде, где упоминается слово "смещение", его можно заменить на слово "RVA". Подробнее читайте этот цикл. А ещё подробнее эту статью.
SiruS Так я ж перевёл... на русский. Если нужно на ассемблер, показывайте, что получается, и задавайте конкретные вопросы по тому, что не получается.