阻止惡意遠程線程_第1頁
阻止惡意遠程線程_第2頁
阻止惡意遠程線程_第3頁
阻止惡意遠程線程_第4頁
阻止惡意遠程線程_第5頁
已閱讀5頁,還剩13頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

阻止惡意遠程線程在WIN2000/XP/2003里,遠程線程只有在建立新進程時,系統(tǒng)會用遠程線程調(diào)用新進程的入口函數(shù),除此之外,建立遠程線程的一般是惡意程序,如何發(fā)現(xiàn)這些惡意程序并找到建立惡意程序的執(zhí)行文件呢?下面本人提供一個最近完工的小程序。先說原理:在WIN2000/XP/2003里,建立本地線程和遠程線程都是調(diào)用ntdll.dll里的NtCreateThread函數(shù),只不過是如果建立本地線程,則進程句柄是-1,反之則是目標進程的句柄(一個大于0且小于0xffffffff的具體數(shù)字)。而本程序先駐留ntdll+800h處的空隙,之后攔截NtCreateThread,如果是建立本地線程則跳過,如果是建立遠程線程,就跟蹤到目標進程,在目標進程分配4K內(nèi)存,把自身復(fù)制到目標進程,并且把遠程線程的入口改為跟蹤代碼,經(jīng)過跟蹤代碼的判斷,而決定是否讓遠程線程執(zhí)行。判斷規(guī)則是:如果遠程線程所處的模塊沒有MZ頭和PE頭,則拒絕;如果遠程線程的入口是LoadLibrary函數(shù)的地址,也拒絕;其他的就放行。由于要搶先攔截NtCreateThread函數(shù),所以采用驅(qū)動的形式。編譯方法:@ml/c/coff/Cp%1.asm@link/subsystem:native/driver:wdm/release/align:16/base:0x10000/section:.text,RWE/out:%1.sys%1.obj@del%1.obj安裝驅(qū)動的方法:copy/yartwdm.sys%systemroot%/system32/driverssccreateartwdmbinpath=%systemroot%/system32/drivers/artwdm.systype=kernelerror=ignorestart=systemscstartartwdm下面是源代碼:.586p.modelflat,stdcalloptioncasemap:noneassumefs:nothingassumegs:nothingincludelibntoskrnl.lib;必須從WIN2000DDK復(fù)制到MASM的INCLUDE目錄NtQuerySystemInformationproto:dword,:dword,:dword,:dword.constalign4szdlldb'ntdll.dll',0align4szNtQueryVirtualMemorydb'NtQueryVirtualMemory',0align4szNtAllocateVirtualMemorydb'NtAllocateVirtualMemory',0align4szNtWriteVirtualMemorydb'NtWriteVirtualMemory',0align4szNtCreateThreaddb'NtCreateThread',0align4szMyLdrLoadDlldb'LdrLoadDll',0.data?dwTempVardd?szTempBufferdb10000hdup(?).codestart:;int3nopnopnopnoppushadcall_GetNtdllHandle;獲取ntdll.dll的地址movebx,eaxmovhntdll,eax.if!eaxjmp_exit.endifpushoffsetszMyLdrLoadDll;獲取ntdll.LdrLoadDll函數(shù)的地址pushebxcall_GetProcAddressmovlpLdrLoadDll,eax.if!eaxjmp_exit.endifpushoffsetszNtQueryVirtualMemory;獲取ntdll.NtQueryVirtualMemory函數(shù)的地址pushebxcall_GetProcAddressmovlpNtQueryVirtualMemory,eax.if!eaxjmp_exit.endifpushoffsetszNtAllocateVirtualMemory;獲取ntdll.NtAllocateVirtualMemory函數(shù)的地址pushebxcall_GetProcAddressmovlpNtAllocateVirtualMemory,eax.if!eaxjmp_exit.endifpushoffsetszNtWriteVirtualMemory;獲取ntdll.NtWriteVirtualMemory函數(shù)的地址pushebxcall_GetProcAddressmovlpNtWriteVirtualMemory,eax.if!eaxjmp_exit.endifpushoffsetszNtCreateThread;獲取ntdll.NtCreateThread函數(shù)的地址pushebxcall_GetProcAddressmovesi,eax.if!esijmp_exit.endifmovecx,cr0btcecx,16movcr0,ecxmovdwordptr[ebx+32h],'fgm'.ifbyteptr[esi+5]!=0bah;判斷ntdll.NtCreateThread函數(shù)的第二條指令是不是movedx,xxxxxxxx(指令長度5字節(jié),以0bah開頭,剛好替換成一條call指令)jmp_exit.endifaddesi,10;ESI指向被替換指令movedx,xxxxxxxx的尾部moveax,[esi-4];保存原來指令的操作數(shù)xxxxxxxxmovdwordptr_HookNtCreateThread+1,eaxleaedi,[ebx+800h];EDI指向駐留地址(ntdll.dll+800h)處moveax,edisubeax,esi;計算兩條指令的相對地址movdwordptr[esi-4],eax;修改NtCreateThread函數(shù)的第二條指令為call指令movbyteptr[esi-5],0e8h;修改NtCreateThread函數(shù)的第二條指令為call指令movesi,offset_HookNtCreateThreadmovecx,offset_AssertRemoteThreadEnd-offset_HookNtCreateThreadrepmovsb;攔截代碼駐留ntdll.dll+800hmovecx,cr0btsecx,16movcr0,ecx_exit:popadxoreax,eaxret8;以上代碼在驅(qū)動入口執(zhí)行,權(quán)限為RING0_GetNtdllHandleproc;獲取ntdll.dll的地址之函數(shù)xoreax,eaxpushadinvokeNtQuerySystemInformation,11,offsetszTempBuffer,10000h,offsetdwTempVar.if!eaxmovedi,dwTempVaraddedi,offsetszTempBuffermovesi,offsetszdll.whiledwordptrszTempBufferpushfdpushesipushedicldxoreax,eaxsubedi,100hmovecx,30hrepnzscasbsubedi,10push10pushedicall_Mytolowermovecx,9repzcmpsbsetzalpopedipopesipopfd.ifalsubedi,11chmoveax,[edi+8]mov[esp+1ch],eax.break.endifsubedi,11chdecdwordptrszTempBuffer.endw.endifpopadret_GetNtdllHandleendp_MytolowerproclpName,dwSize;大寫轉(zhuǎn)小寫函數(shù)pushadmovesi,lpNamemovedi,esimovecx,dwSize.repeatlodsb.ifal>='A'&&al<='Z'addal,20h.endifstosb.untilcxzpopadret_Mytolowerendp;以下代碼在ntdll+800h處運行,RING3_HookNtCreateThread:;攔截ntdll.NtCreateThread函數(shù)的代碼movedx,0enter400h,0pushfdpushad.ifdwordptr[ebp+0ch+0ch]==-1;如果在本地進程建立線程就返回jmp_HookNtCreateThreadExit.endif;程序執(zhí)行到這里,表明有線程要在別的進程建立遠程線程,以下的代碼將跟蹤到目標進程并在目標進程做判斷db0e8h,2,0,0,0,'M','$'popedxsubedx,$-3movebx,edx;代碼重定位leaesi,_AssertRemoteThread[ebx]leaedi,[ebp-400h]movecx,offset_AssertRemoteThreadEnd-offset_AssertRemoteThreadrepmovsb;復(fù)制跟蹤代碼到局部緩沖區(qū),原因是當前代碼處于ntdll+800h地址處,是只讀的,而后面的變量必須賦值,因此只有;把從標簽_AssertRemoteThread開始的代碼復(fù)制到可寫的局部堆棧里的緩沖區(qū)leaedx,[ebp-8]leaecx,szwkernel32[ebx]movdwordptr[edx],001a0018hmovdwordptr[edx+4],ecx;構(gòu)造UNICODE_STRING的kernel32.dll字符串moveax,offsethKernel32-offset_AssertRemoteThread;計算hKernel32變量距離駐留代碼開頭_AssertRemoteThread標簽的偏移leaesi,[ebp-400h+eax]pushesipushedxleaeax,[ebp-0ch]pusheaxleaeax,szwEnvStr[ebx]pusheaxcalllpLdrLoadDll[ebx];裝載KERNEL32.DLL,如果失敗就返回,如果成功則kernel32的模塊地址存入hKernel32變量.ifeaxjmp_HookNtCreateThreadExit.endifleaedx,szGetProcAddress[ebx]pushedxpush[esi]call_GetProcAddress;獲取KERNEL32.GetProcAddress()的地址movecx,offsetlpGetProcAddress-offset_AssertRemoteThreadmov[ebp-400h+ecx],eax;放入局部緩沖區(qū)里的代碼中的lpGetProcAddress變量里movedi,eaxleaedx,szGetModuleFileName[ebx]pushedxpush[esi]calledi;獲取KERNEL32.GetModuleFileName()的地址movecx,offsetlpGetModuleFileName-offset_AssertRemoteThreadmov[ebp-400h+ecx],eax;放入局部緩沖區(qū)里的代碼中的lpGetModuleFileName變量里leaedx,szGetCurrentProcessId[ebx]pushedxpush[esi]calledi;獲取KERNEL32.GetCurrentProcessId()的地址calleax;獲取當前進程的PIDmovecx,offsetdwProcessId-offset_AssertRemoteThreadmov[ebp-400h+ecx],eax;PID放入局部緩沖區(qū)里的代碼中的dwProcessId變量里leaedx,szGetCurrentThreadId[ebx]pushedxpush[esi]calledi;獲取KERNEL32.GetCurrentThreadId()的地址calleax;獲取當前線程的TIDmovecx,offsetdwThreadId-offset_AssertRemoteThreadmov[ebp-400h+ecx],eax;TID放入局部緩沖區(qū)里的代碼中的dwThreadId變量里movesi,[ebp+8];定位調(diào)用NtCreateThread()的代碼地址,放在ESI.ifesi>70000000hmovesi,[ebp]movesi,[esi+4];定位調(diào)用NtCreateThread()的代碼地址,放在ESI.endifleaedi,[ebp-20h]pushedipush20hpushedipush0pushesipush-1calllpNtQueryVirtualMemory[ebx];定位調(diào)用NtCreateThread()的代碼地址所處的模塊地址.if!eaxmoveax,[edi+4]subesi,eaxmovecx,offsetdwModuleRva-offset_AssertRemoteThreadmov[ebp-400h+ecx],esi;把調(diào)用NtCreateThread()的代碼地址所處的模塊RVA值放入dwModuleRva變量里movecx,offsetszModuleName-offset_AssertRemoteThreadleaedi,[ebp-400h+ecx]push78hpushedi;EDI指向局部緩沖區(qū)里的代碼當中的szModuleName緩沖區(qū)pusheaxmovecx,offsetlpGetModuleFileName-offset_AssertRemoteThreadcalldwordptr[ebp-400h+ecx];把調(diào)用NtCreateThread()的代碼地址所處的模塊的模塊名放入szModuleName緩沖區(qū)里.endifleaesi,[ebp+0ch]moveax,[esi+14h]moveax,[eax+0b0h]movecx,offset_AssertRemoteThreadJmp-offset_AssertRemoteThread-5movdwordptr[ebp-400h+ecx],eax;替換遠程線程的開始地址,使其指向我的跟蹤代碼的地址leaecx,[ebp-4]leaedx,[ebp-8]movdwordptr[ecx],1000hmovdwordptr[edx],0push4push1000hpushecxpush0pushedxpushdwordptr[esi+0ch]calllpNtAllocateVirtualMemory[ebx];在目標進程分配4K內(nèi)存,把跟蹤代碼復(fù)制過去,目標進程就會先執(zhí)行跟蹤代碼,進行判斷后再執(zhí)行遠程線程.ifeaxjmp_HookNtCreateThreadExit.endifmovecx,offset_AssertRemoteThreadEnd-offset_AssertRemoteThreadleaedx,[ebp-400h]push0pushecxpushedxpushdwordptr[ebp-8]pushdwordptr[esi+0ch]calllpNtWriteVirtualMemory[ebx];復(fù)制跟蹤代碼.if!eaxmovedx,[ebp-8]moveax,[esi+14h]movdwordptr[eax+0b0h],edx;如果在目標進程分配內(nèi)存失敗就恢復(fù)原來的遠程線程的開始地址.endif_HookNtCreateThreadExit:popadpopfdleaveretlpNtAllocateVirtualMemorydd0lpNtWriteVirtualMemorydd0lpLdrLoadDlldd0_HookNtCreateThreadend:align4szwkernel32dw'k','e','r','n','e','l','3','2','.','d','l','l',0align4szwEnvStrdw'c',':','/','w','i','n','d','o','w','s',';','c',':','/','w','i','n','d','o','w','s','/','s','y','s','t','e','m','3','2',0_GetModuleAddress:@@:andax,0f000hsubeax,1000hcmpwordptr[eax],'ZM'jnz@bmovecx,eaxaddecx,[ecx+3ch]cmpdwordptr[ecx],'EP'jnz@bret_GetProcAddressprocusesecxesiedi,_hModule,_lpszProcNamelocal@dwSizemovedx,_hModuleaddedx,[edx+3ch]movedx,[edx+78h]addedx,_hModulemovecx,[edx+18h]movesi,[edx+20h]movedi,_lpszProcNamepushedipushecxxoreax,eaxmovecx,0ffffffffhrepnzscasbnotecxdececxmov@dwSize,ecxpopecxpopediaddesi,_hModule@@:pushedipushecxmovecx,@dwSizelodsdaddeax,_hModulexchgeax,esirepzcmpsbxchgeax,esipopecxpopediloopnz@b.if!ZERO?xoreax,eaxret.endifsubesi,_hModulesubesi,4subesi,[edx+20h]shresi,1addesi,[edx+24h]addesi,_hModulelodsdmovzxeax,axshleax,2addeax,[edx+1ch]addeax,_hModulemovedx,[eax]addedx,_hModulexchgedx,eaxret_GetProcAddressendpalign4_AssertRemoteThread:;本函數(shù)現(xiàn)在已經(jīng)處于遠程線程所在的目標進程pushaddb0e8h,2,0,0,0,'M','$'popedxsubedx,$-3movebx,edxleaedi,_AssertRemoteThreadEnd[ebx]pushedipush20hpushedipush0push_AssertRemoteThreadJmp[ebx-5]push-1calllpNtQueryVirtualMemory[ebx];獲取原來遠程線程分配的模塊地址.ifeaxpushebpleaeax,_AssertRemoteThreadSafe[ebx]pusheaxleaeax,_AssertRemoteThreadJmp[ebx]pusheaxpushfs:[0]movfs:[0],esp;設(shè)置SEHmoveax,_AssertRemoteThreadJmp[ebx-5]andeax,0fffff000h.repeatsubeax,1000h.untilwordptr[eax]=='ZM';循環(huán)查找遠程線程代碼所處的模塊的MZ頭_AssertRemoteThreadSafe:popfs:[0]popecxpopecxpopecxmovedi,eax.elsemovedi,[edi+4].endif.ifwordptr[edi]!='ZM';如果沒有找到MZ頭,說明遠程線程是純代碼,絕大部分是含有惡意的,拒絕執(zhí)行jmp_AssertRemoteThreadDeny.endifaddedi,[edi+3ch].ifdwordptr[edi]!='EP';如果找的MZ頭,再找PE頭,如果找不到PE頭,,絕大部分是含有惡意的,拒絕執(zhí)行jmp_AssertRemoteThreadDeny.endifleaedx,szLoadLibraryA[ebx]pushedxpushhKernel32[ebx]calllpGetProcAddress[ebx].ifeax==_AssertRemoteThreadJmp[ebx-5];如果遠程線程的開始地址是LoadLibraryA函數(shù)的地址,也拒絕執(zhí)行jmp_AssertRemoteThreadDeny.endifleaedx,szLoadLibraryW[ebx]pushedxpushhKernel32[ebx]calllpGetProcAddress[ebx].ifeax!=_AssertRemoteThreadJmp[ebx-5];如果遠程線程的開始地址是LoadLibraryW函數(shù)的地址,也拒絕執(zhí)行jmp_AssertRemoteThreadExit.endif_AssertRemoteThreadDeny:;執(zhí)行到這里時,遠程線程已經(jīng)被拒絕執(zhí)行,這里負責顯示一個提醒對話框leaedx,szLoadLibraryA[ebx]pushedxpushhKernel32[ebx]calllpGetProcAddress[ebx];獲取LoadLibraryA的地址leaecx,szUser32[ebx]pushecxcalleax;裝載USER32.DLLmovhUser32[ebx],eaxleaedx,szMessageBox[ebx]pushedxpushhUser32[ebx]calllpGetProcAddress[ebx];獲取MessageBox函數(shù)的地址movesi,eaxleaedx,szwsprintf[ebx]pushedxpushhUser32[ebx]calllpGetProcAddress[ebx];獲取wsprintf函數(shù)的地址movedi,eaxleaedx,szGetCurrentProcessId[ebx]pushedxpushhKernel32[ebx]calllpGetProcAddress[ebx];獲取GetCurrentProcessId函數(shù)的地址calleax;GetCurrentProcessId()pusheaxmoveax,dwModuleRva[ebx]pusheaxmoveax,dwThreadId[ebx]pusheaxmoveax,dwProcessId[ebx]pusheaxleaeax,szModuleName[ebx]pusheaxleaeax,szformat[ebx]pusheaxleaeax,_AssertRemoteThreadEnd[ebx]pusheaxcalledi;格式化字符串a(chǎn)ddesp,4*7leaedx,sztitle[ebx]leaedi,_AssertRemoteThreadEnd[ebx]push34hpushedxpushedipush0callesi;顯示MESSAGEBOX.ifeax==6;如果用戶按了"確定"鍵,就終止建立遠程線程的代碼所處在的線程leaedx,szNtOpenThread[ebx]pushedxpushhntdll[ebx]calllpGetProcAddress[ebx];獲取NtOpenThread函數(shù)的地址leaedx,dwProcessId[ebx]pushedxleaedx,stForOpenThread[ebx]pushedxpush1pushedicalleax;OPEN建立遠程線程的線程.if!eaxleaedx,szNtTerminateThread[ebx]pushedxpushhntdll[ebx]calllpGetProcAddress[ebx];獲取NtTerminateThread函數(shù)的地址push0p

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論