coocky Нельзя ли сформулировать первоначальную задачу? К какому процессу нужно прилипнуть? На каком этапе? Что нужно подгрузить? Что выполнить? Какие условия выгрузки? и прочее... если, конечно, нужна помощь. ps/ Чем точнее постановка задачи, тем проще находится решение. pps/ можно в РМ....
DMD Да без проблем. Работаю только из User mode 1.Нужно внедрят длл во все процессы,для перехвата функций для работы с файлами.Это для криворукой безопасности на моей фирме для бухгалтеров.Для перехвата испоьлзую либу Detours. 2.Я умею внедрять через CreateRemoteThread (запуском LoadLibrary()) в уже открытые процессы. Проблем нет. 3.Для внедрения во вновь создаваемые процессы я пользовался ключиком AppInit_Dlls.Но оказалось он не всегда справлялся..Решил пойти путем перехвата CreateProccess ( ведь при старте программы своей я всегда внедрюсь во все запущеные процессы,которые в свою очередь могут создать другие процессы) и внедрение во вновь создаваемый процесс своей длл функцией из либы Detours DetourCreateProcessWithDll. Она все делает красиво,никаких глюков. 4.Однако,мои длл НЕ ВЫГРУЖАЮТСЯ через CreateRemoteThread (FreeLibrary) из ТЕХ приложений,куда я внедрился путем функции DetourCreateProcessWithDll ,а выгружаются только из процессов,куда внедрился через CreateRemoteThread (запуском LoadLibrary()).Хотя все функции отрабатывают окейно..Но длл находится в процессе.. 5.Мне нужно позарез выгружать либы,т.к. вторичный старт исключен,т.к. загрузчик не внедряет мою длл в те процессы,где есть уже не выгуженая длл.Сами понимаете почему. Вот вообщем и все. Жаль ,что это моя работа.. Если б баловство-я б плюнул давно..
На вся кий случай исходник Код (Text): BOOL WINAPI DetourCreateProcessWithDllA(LPCSTR lpApplicationName, __in_z LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation, LPCSTR lpDetouredDllFullName, LPCSTR lpDllName, PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA) { DWORD dwMyCreationFlags = (dwCreationFlags | CREATE_SUSPENDED); PROCESS_INFORMATION pi; if (pfCreateProcessA == NULL) { pfCreateProcessA = CreateProcessA; } if (!pfCreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwMyCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, &pi)) { return FALSE; } LPCSTR rlpDlls[2]; DWORD nDlls = 0; if (lpDetouredDllFullName != NULL) { rlpDlls[nDlls++] = lpDetouredDllFullName; } if (lpDllName != NULL) { rlpDlls[nDlls++] = lpDllName; } if (!UpdateImports(pi.hProcess, rlpDlls, nDlls)) { return FALSE; } if (lpProcessInformation) { CopyMemory(lpProcessInformation, &pi, sizeof(pi)); } if (!(dwCreationFlags & CREATE_SUSPENDED)) { ResumeThread(pi.hThread); } return TRUE; } Все не сложно,особый интерес здесь может представить функция UpdateImports Код (Text): static BOOL UpdateImports(HANDLE hProcess, LPCSTR *plpDlls, DWORD nDlls) { BOOL fSucceeded = FALSE; BYTE * pbNew = NULL; DETOUR_EXE_RESTORE der; DWORD i; ZeroMemory(&der, sizeof(der)); der.cb = sizeof(der); PBYTE pbModule = (PBYTE)FindExe(hProcess); IMAGE_DOS_HEADER idh; ZeroMemory(&idh, sizeof(idh)); if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { DETOUR_TRACE(("ReadProcessMemory(idh) failed: %d\n", GetLastError())); finish: if (pbNew != NULL) { delete[] pbNew; pbNew = NULL; } return fSucceeded; } CopyMemory(&der.idh, &idh, sizeof(idh)); der.pidh = (PIMAGE_DOS_HEADER)pbModule; if (idh.e_magic != IMAGE_DOS_SIGNATURE) { goto finish; } IMAGE_NT_HEADERS inh; ZeroMemory(&inh, sizeof(inh)); if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) { DETOUR_TRACE(("ReadProcessMemory(inh) failed: %d\n", GetLastError())); goto finish; } CopyMemory(&der.inh, &inh, sizeof(inh)); der.pinh = (PIMAGE_NT_HEADERS)(pbModule + idh.e_lfanew); if (inh.Signature != IMAGE_NT_SIGNATURE) { goto finish; } if (inh.IMPORT_DIRECTORY.VirtualAddress == 0) { DETOUR_TRACE(("No IMAGE_DIRECTORY_ENTRY_IMPORT\n")); goto finish; } // Zero out the bound table so loader doesn't use it instead of our new table. inh.BOUND_DIRECTORY.VirtualAddress = 0; inh.BOUND_DIRECTORY.Size = 0; // Find the size of the mapped file. DWORD dwFileSize = 0; DWORD dwSec = idh.e_lfanew + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + inh.FileHeader.SizeOfOptionalHeader; for (i = 0; i < inh.FileHeader.NumberOfSections; i++) { IMAGE_SECTION_HEADER ish; ZeroMemory(&ish, sizeof(ish)); if (!ReadProcessMemory(hProcess, pbModule + dwSec + sizeof(ish) * i, &ish, sizeof(ish), NULL)) { DETOUR_TRACE(("ReadProcessMemory(inh) failed: %d\n", GetLastError())); goto finish; } DETOUR_TRACE(("ish[%d] : va=%p sr=%d\n", i, ish.VirtualAddress, ish.SizeOfRawData)); // If the file didn't have an IAT_DIRECTORY, we create one... if (inh.IAT_DIRECTORY.VirtualAddress == 0 && inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress && inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) { inh.IAT_DIRECTORY.VirtualAddress = ish.VirtualAddress; inh.IAT_DIRECTORY.Size = ish.SizeOfRawData; } // Find the end of the file... if (dwFileSize < ish.PointerToRawData + ish.SizeOfRawData) { dwFileSize = ish.PointerToRawData + ish.SizeOfRawData; } } DETOUR_TRACE(("dwFileSize = %08x\n", dwFileSize)); // Find the current checksum. WORD wBefore = ComputeChkSum(hProcess, pbModule, &inh); DETOUR_TRACE(("ChkSum: %04x + %08x => %08x\n", wBefore, dwFileSize, wBefore + dwFileSize)); DETOUR_TRACE((" Imports: %8p..%8p\n", (DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, (DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size)); DWORD obRem = sizeof(IMAGE_IMPORT_DESCRIPTOR) * nDlls; DWORD obTab = PadToDwordPtr(obRem + inh.IMPORT_DIRECTORY.Size); DWORD obDll = obTab + sizeof(DWORD_PTR) * 4 * nDlls; DWORD obStr = obDll; DWORD cbNew = obStr; DWORD n; for (n = 0; n < nDlls; n++) { cbNew += PadToDword((DWORD)strlen(plpDlls[n]) + 1); } pbNew = new BYTE [cbNew]; if (pbNew == NULL) { DETOUR_TRACE(("new BYTE [cbNew] failed.\n")); goto finish; } ZeroMemory(pbNew, cbNew); PBYTE pbBase = pbModule; PBYTE pbNext = pbBase + inh.OptionalHeader.BaseOfCode + inh.OptionalHeader.SizeOfCode + inh.OptionalHeader.SizeOfInitializedData + inh.OptionalHeader.SizeOfUninitializedData; if (pbBase < pbNext) { pbBase = pbNext; } DETOUR_TRACE(("pbBase = %p\n", pbBase)); PBYTE pbNewIid = FindAndAllocateNearBase(hProcess, pbBase, cbNew); if (pbNewIid == NULL) { DETOUR_TRACE(("FindAndAllocateNearBase failed.\n")); goto finish; } DWORD dwProtect = 0; der.impDirProt = 0; if (!VirtualProtectEx(hProcess, pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, inh.IMPORT_DIRECTORY.Size, PAGE_EXECUTE_READWRITE, &dwProtect)) { DETOUR_TRACE(("VirtualProtextEx(import) write failed: %d\n", GetLastError())); goto finish; } DETOUR_TRACE(("IMPORT_DIRECTORY perms=%x\n", dwProtect)); der.impDirProt = dwProtect; DWORD obBase = (DWORD)(pbNewIid - pbModule); if (!ReadProcessMemory(hProcess, pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, pbNew + obRem, inh.IMPORT_DIRECTORY.Size, NULL)) { DETOUR_TRACE(("ReadProcessMemory(imports) failed: %d\n", GetLastError())); goto finish; } PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew; DWORD_PTR *pt; for (n = 0; n < nDlls; n++) { HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]); if (FAILED(hrRet)) { DETOUR_TRACE(("StringCchCopyA failed: %d\n", GetLastError())); goto finish; } DWORD nOffset = obTab + (sizeof(DWORD_PTR) * (4 * n)); piid[n].OriginalFirstThunk = obBase + nOffset; pt = ((DWORD_PTR*)(pbNew + nOffset)); pt[0] = IMAGE_ORDINAL_FLAG + 1; pt[1] = 0; nOffset = obTab + (sizeof(DWORD_PTR) * ((4 * n) + 2)); piid[n].FirstThunk = obBase + nOffset; pt = ((DWORD_PTR*)(pbNew + nOffset)); pt[0] = IMAGE_ORDINAL_FLAG + 1; pt[1] = 0; piid[n].TimeDateStamp = 0; piid[n].ForwarderChain = 0; piid[n].Name = obBase + obStr; obStr += PadToDword((DWORD)strlen(plpDlls[n]) + 1); } for (i = 0; i < nDlls + (inh.IMPORT_DIRECTORY.Size / sizeof(*piid)); i++) { DETOUR_TRACE(("%8d. Look=%08x Time=%08x Fore=%08x Name=%08x Addr=%08x\n", i, piid[i].OriginalFirstThunk, piid[i].TimeDateStamp, piid[i].ForwarderChain, piid[i].Name, piid[i].FirstThunk)); if (piid[i].OriginalFirstThunk == 0 && piid[i].FirstThunk == 0) { break; } } if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) { DETOUR_TRACE(("WriteProcessMemory(iid) failed: %d\n", GetLastError())); goto finish; } DETOUR_TRACE(("obBase = %p..%p\n", inh.IMPORT_DIRECTORY.VirtualAddress, inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size)); DETOUR_TRACE(("obBase = %p..%p\n", obBase, obBase + obStr)); inh.IMPORT_DIRECTORY.VirtualAddress = obBase; inh.IMPORT_DIRECTORY.Size = cbNew; /////////////////////////////////////////////////// Update the CLR header. // if (inh.CLR_DIRECTORY.VirtualAddress != 0 && inh.CLR_DIRECTORY.Size != 0) { DETOUR_CLR_HEADER clr; PBYTE pbClr = pbModule + inh.CLR_DIRECTORY.VirtualAddress; if (!ReadProcessMemory(hProcess, pbClr, &clr, sizeof(clr), NULL)) { DETOUR_TRACE(("ReadProcessMemory(clr) failed: %d\n", GetLastError())); goto finish; } der.pclrFlags = (PULONG)(pbClr + offsetof(DETOUR_CLR_HEADER, Flags)); der.clrFlags = clr.Flags; clr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag. if (!VirtualProtectEx(hProcess, pbClr, sizeof(clr), PAGE_READWRITE, &dwProtect)) { DETOUR_TRACE(("VirtualProtextEx(clr) write failed: %d\n", GetLastError())); goto finish; } if (!WriteProcessMemory(hProcess, pbClr, &clr, sizeof(clr), NULL)) { DETOUR_TRACE(("WriteProcessMemory(clr) failed: %d\n", GetLastError())); goto finish; } if (!VirtualProtectEx(hProcess, pbClr, sizeof(clr), dwProtect, &dwProtect)) { DETOUR_TRACE(("VirtualProtextEx(clr) restore failed: %d\n", GetLastError())); goto finish; } } /////////////////////// Update the NT header for the import new directory. /////////////////////////////// Update the DOS header to fix the checksum. // if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders, PAGE_EXECUTE_READWRITE, &dwProtect)) { DETOUR_TRACE(("VirtualProtextEx(inh) write failed: %d\n", GetLastError())); goto finish; } idh.e_res[0] = 0; if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError())); goto finish; } if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) { DETOUR_TRACE(("WriteProcessMemory(inh) failed: %d\n", GetLastError())); goto finish; } WORD wDuring = ComputeChkSum(hProcess, pbModule, &inh); DETOUR_TRACE(("ChkSum: %04x + %08x => %08x\n", wDuring, dwFileSize, wDuring + dwFileSize)); idh.e_res[0] = detour_sum_minus(idh.e_res[0], detour_sum_minus(wDuring, wBefore)); if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError())); goto finish; } if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders, dwProtect, &dwProtect)) { DETOUR_TRACE(("VirtualProtextEx(idh) restore failed: %d\n", GetLastError())); goto finish; } WORD wAfter = ComputeChkSum(hProcess, pbModule, &inh); DETOUR_TRACE(("ChkSum: %04x + %08x => %08x\n", wAfter, dwFileSize, wAfter + dwFileSize)); DETOUR_TRACE(("Before: %08x, After: %08x\n", wBefore + dwFileSize, wAfter + dwFileSize)); if (wBefore != wAfter) { DETOUR_TRACE(("Restore of checksum failed %04x != %04x.\n", wBefore, wAfter)); goto finish; } if (!DetourCopyPayloadToProcess(hProcess, DETOUR_EXE_RESTORE_GUID, &der, sizeof(der))) { DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError())); goto finish; } fSucceeded = TRUE; goto finish; } и последняя Код (Text): BOOL WINAPI DetourCopyPayloadToProcess(HANDLE hProcess, REFGUID rguid, PVOID pData, DWORD cbData) { DWORD cbTotal = (sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) + sizeof(DETOUR_SECTION_HEADER) + sizeof(DETOUR_SECTION_RECORD) + cbData); PBYTE pbBase = (PBYTE)VirtualAllocEx(hProcess, NULL, cbTotal, MEM_COMMIT, PAGE_READWRITE); if (pbBase == NULL) { DETOUR_TRACE(("VirtualAllocEx(%d) failed: %d\n", cbTotal, GetLastError())); return FALSE; } PBYTE pbTarget = pbBase; IMAGE_DOS_HEADER idh; IMAGE_NT_HEADERS inh; IMAGE_SECTION_HEADER ish; DETOUR_SECTION_HEADER dsh; DETOUR_SECTION_RECORD dsr; SIZE_T cbWrote = 0; ZeroMemory(&idh, sizeof(idh)); idh.e_magic = IMAGE_DOS_SIGNATURE; idh.e_lfanew = sizeof(idh); if (!WriteProcessMemory(hProcess, pbTarget, &idh, sizeof(idh), &cbWrote) || cbWrote != sizeof(idh)) { DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError())); return FALSE; } pbTarget += sizeof(idh); ZeroMemory(&inh, sizeof(inh)); inh.Signature = IMAGE_NT_SIGNATURE; inh.FileHeader.SizeOfOptionalHeader = sizeof(inh.OptionalHeader); inh.FileHeader.Characteristics = IMAGE_FILE_DLL; inh.FileHeader.NumberOfSections = 1; if (!WriteProcessMemory(hProcess, pbTarget, &inh, sizeof(inh), &cbWrote) || cbWrote != sizeof(inh)) { return FALSE; } pbTarget += sizeof(inh); ZeroMemory(&ish, sizeof(ish)); memcpy(ish.Name, ".detour", sizeof(ish.Name)); ish.VirtualAddress = (DWORD)((pbTarget + sizeof(ish)) - pbBase); ish.SizeOfRawData = (sizeof(DETOUR_SECTION_HEADER) + sizeof(DETOUR_SECTION_RECORD) + cbData); if (!WriteProcessMemory(hProcess, pbTarget, &ish, sizeof(ish), &cbWrote) || cbWrote != sizeof(ish)) { return FALSE; } pbTarget += sizeof(ish); ZeroMemory(&dsh, sizeof(dsh)); dsh.cbHeaderSize = sizeof(dsh); dsh.nSignature = DETOUR_SECTION_HEADER_SIGNATURE; dsh.nDataOffset = sizeof(DETOUR_SECTION_HEADER); dsh.cbDataSize = (sizeof(DETOUR_SECTION_HEADER) + sizeof(DETOUR_SECTION_RECORD) + cbData); if (!WriteProcessMemory(hProcess, pbTarget, &dsh, sizeof(dsh), &cbWrote) || cbWrote != sizeof(dsh)) { return FALSE; } pbTarget += sizeof(dsh); ZeroMemory(&dsr, sizeof(dsr)); dsr.cbBytes = cbData + sizeof(DETOUR_SECTION_RECORD); dsr.nReserved = 0; dsr.guid = rguid; if (!WriteProcessMemory(hProcess, pbTarget, &dsr, sizeof(dsr), &cbWrote) || cbWrote != sizeof(dsr)) { return FALSE; } pbTarget += sizeof(dsr); if (!WriteProcessMemory(hProcess, pbTarget, pData, cbData, &cbWrote) || cbWrote != cbData) { return FALSE; } pbTarget += cbData; DETOUR_TRACE(("Copied %d bytes into target process at %p\n", cbTotal, pbTarget - cbTotal)); return TRUE; } Понимаю, что код,мало кто будет смотреть,но все же.. Вообщем ничего нового они не делают.. Вот что они пишут в мануале
У всех своя работа, бывает и не такое.. Если я все правильно понял, имеет место такая цепочка: потом по неким определенным условиям - выгрузка длл из процесса с возвратом в процесс или завершение оного {этого я не понял, но это не очень принципиально}.. Ок, может быть такой путь будет проще в реализации: 1) начало: {в этом случае нет гарантии, что процесс не работал с security-файлами до старта программы} 2) внедряясь в запущенные процессы оставляем в каждом сторожа, который перехватывает две составляющие (лучше через некую добавочную Mini-длл): а) CreateProccess б) апи работы с файлами (на собственное усмотрение) и отрабатывает загрузку/выгрузку базовой длл если выловили а) -> п.2 если выловили б) -> собственные действия Если условия для выгрузки определяется по неким внешним факторам - предусматриваем в базовой длл возврат в код сторожа и выполнение выгрузки базовой длл. При попытке вторичного "прохода" после выгрузки базовой длл или ищем наличие сторожа (дальше все прозрачно) или клеем его и дальше тоже все ясно.. сторож для каждого процесса размещаем в AllocMemory. в "его" длл две функции: hook api + loadlibrary/freelibrary. такой сценарий подойдет? ps/ мне не понятно вот что: как из user mode ты мониторишь создание всех процессов в системе, отсеивая системные процессы? к системникам же клеиться не нужно?