防止运行过程中被注入Dll,可以挂钩Kernel32.LoadLibrary函数或更加底层的Ntdll.LdrLoadDll函数,因为注入Dll实际原理就是在目标进程中创建一个远程线程,线程函数调用LoadLibrary,LoadLibrary在内部又会调用LdrLoadDll,LdrLoadDll完成实质的加载Dll的操作。这种情况下,可以简单调用Advapi32.SetKernelObjectSecurity为自己的进程定义一个DACL(访问控制列表),拒绝所有用户对自身进程的访问。但是,此法可以通过调用Advapi32.AdjustTokenPrivileges函数破解,进程对象的DACL完全形同虚设,因为一旦有了Debug权限,总是可以以PROCESS_ALL_ACCESS(完全控制)权限来获取进程对象、线程对象的句柄。有了这个完全控制权限的句柄,想做什么就能做什么。所以,通过调用SetKernelObjectSecurity设置自身进程的安全权限,只针对于那些不能提升至Debug权限的恶意进程。
另一种情况。进程运行之初,我们自己定义的代码并不是最先执行的,因为Au3的解析器会在内部做一些初始化工作,然后才运行我们自己写的代码。如果恶意程序瞅准了时机,在我们挂钩LoadLibrary之前就已经注入了Dll,那通过挂钩法防止注入 就一点意义也没有。如果是这样,那么可以在一个循环中实时枚举自身进程中的Dll,如果找到了不符合预期的Dll,就调用FreeLibrary来释放。但是,你应该想到,恶意程序也可能在循环中实时监测Dll是否仍在我们的进程中,如果不在了,还可能会重新注入。或者,恶意程序注入dll到我们的进程中,很可能只是为了执行一小段代码,没等我们的进程循环完毕,恶意程序就从我们的进程中释放了此Dll。再者,如果我们进程中的某个线程正在执行Dll中的代码,此时调用FreeLibrary就会导致进程崩溃,这种可能性非常大。所以通过调用FreeLibrary来阻止注入也不是一种可行的方法。
修改Dll也不行,因为恶意程序可能调用了类似FileInstall的函数,将Dll内置进自己的程序中,每次注入的都是未经修改过的Dll。
要确保绝对不会被注入,最重要的是要取得系统的控制权。谁启动得更早,谁就更能控制整个操作系统,甚至控制杀软也不在话下。
以下这段代码,先设置自身进程的DACL,拒绝所有用户所有形式的访问。再创建一个受限令牌,随同此令牌,创建一个不受信任的恶意程序,由于恶意进程的令牌中没有Debug权限,所以就不能通过AdjustTokenPrivileges提权,以此就达到了保护自身进程的目的。运行代码,你会发现任务管理器不能结束自身进程了,更不必说远程注入和读写内存等其他恶意操作了。用这种方法成功保护自己的前提是,必须确保自身进程比恶意程序启动得早。另外,有一个非常非常强大的函数,Ntdll中的NtCreateToken,可以创建自定义令牌,这意味着不需要密码,就能创建任意用户下的进程,并且此进程还能够拥有比SYSTEM还高级的权限,以及还能够访问其他任何进程都访问不了的文件等对象。
#include <lsasecur.au3>
; 获取自身进程令牌,之后会用到
Local $hToken = _SeOpenProcessToken(-1)
; 获取Everyone账户SID
Local $pTrusteeSid = _SeLookupAccountName("Everyone")
; 创建访问控制列表,拒绝所有用户所有形式的访问
Local $pDacl = _SeSetEntriesInAcl1($pTrusteeSid, $SE_GENERIC_ALL, $SE_DENY_ACCESS, $SE_NO_INHERITANCE)
Local $pSecurityDescriptor = _SeInitSecurityDescriptor()
_SeSetSecurityDescriptorDacl($pSecurityDescriptor, $pDacl)
; 设置自身进程的安全属性
_SeSetKernelObjectSecurity(-1, $SE_INFO_DACL, $pSecurityDescriptor)
Local $aPrivilege[1] = [$SE_DEBUG_PRIV]
;Local $hToken = _SeOpenProcessToken(-1)
; 通过自身令牌创建受限令牌,不能通过此受限令牌提升至Debug权限
Local $hRestrictToken = _SeCreateRestrictedToken($hToken, 0, 0, $aPrivilege, 0)
; 恶意程序路径
Local $sUntrustApp = @SystemDir & "\taskmgr.exe"
; 创建进程,并赋予此进程一个受限制的令牌
Local $tProcessInfo = _SeCreateUserProcess($hRestrictToken, $sUntrustApp)
_SeCloseHandle(DllStructGetData($tProcessInfo, "Process"))
_SeCloseHandle(DllStructGetData($tProcessInfo, "Thread"))
_SeCloseHandle($hRestrictToken)
_SeCloseHandle($hToken)
_SeHeapFree($pSecurityDescriptor)
_SeHeapFree($pTrusteeSid)
_SeLocalFree($pDacl)
MsgBox(0, "OK", "Done~")
|