探索黑客技术攻防,实战研究与安全创新

导航菜单

OSVDB-94390注册表溢出漏洞分析

本文要介绍的漏洞相当特别,是通过导入注册表文件来触发溢出漏洞的。按OSVDB的描述,为“containsanoverflowconditionthatistriggeredasuser-suppliedinputisnotproperlyvalidatedwhenpassedviathe'RegistrationCode'field”。

相信在很多人的印象中,注册表一般是保存配置信息、验证是否注册的地方,谁能想到在这里居然成了一个溢出点!可是请别忘了,注册表也是一串数据,读取注册表也需要用到缓冲区,凭什么就不能溢出呢?先让我们看看相关注册表的结构,入图1所示。

B1.png

右边共有5个注册表项,其中“Serial”即为“序列号”,这也是触发漏洞的关键——溢出数据的来源——但我们要先寻找的是执行流中的溢出之处。思路是:既然是注册表漏洞,那就先找到相应的API。注册表操作相关的API通常以“Reg”开头,如创建注册表项的RegCreateKeyExA/W、读取注册表项值的RegQueryValueExA/W、写入注册表项值的RegSetValueExA/W,以及关闭注册表操作句柄的RegCloseKey(文中A/W的意思分别指ASCII和宽字符所对应的API)。

OD载入漏洞程序EasyLanFolderShare.exe,想知道程序调用了哪些API,我们可以通过Ctrl+N,找到注册表相关的操作,如图2所示。

B2.png

从中可以看到,程序调用了几项与注册表相关的API,这里我们只关心读取注册表项值

的RegQueryValueExA,跟进调用该API的地方。


0041A8B2
|.
50
push
eax
;
|ValueName
0041A8B3
0041A8B6
0041A8B7
|.
|.
|.
8B4304
50
mov
eax,dwordptr[ebx+4]
;|
push
call
eax
;|hKey
E868440900
004AED24
;
\RegQueryValueExA


运行程序,在到达溢出点前,程序会两次调用RegQueryValueExA,等到第二次,也就是函数参数ValueName为“Serial”时,单步执行API调用,然后对缓冲区,也即函数参数Buffer指向的内存地址下内存访问断点,本例为0x1483288,如图3所示,之后将断在如图4所示的位置。

B3.png

接着需要跳过旁枝末节,两次Ctrl+F9,让OD自动执行到函数并返回。


00406819
0040681C
0040681F
00406824
00406827
0040682A
0040682F
00406834
00406837
.
.
.
.
.
.
.
.
.
8D55B4
lea
lea
edx,dwordptr[ebp-4C]
eax,dwordptr[ebp-4]
0049B5DC
8D45FC
E8B84D0900
FF4D84
call
dec
lea
;
0049B5DC
0049B5AC
dwordptr[ebp-7C]
eax,dwordptr[ebp-4C]
edx,2
8D45B4
BA02000000
E8784D0900
FF4D84
mov
call
dec
lea
0049B5AC
;
dwordptr[ebp-7C]
eax,dwordptr[ebp-48]
8D45B8
0040683A
0040683F
00406844
00406847
.
BA02000000
E8684D0900
8B45FC
mov
call
edx,2
.
0049B5AC
;
0049B5AC
Here
.
.
mov
call
eax,dwordptr[ebp-4]
00406B64
E818030000
;
00406DB7
00406DBA
00406DBC
00406DC1
00406DC3
|.
8B55EC
EB05
mov
jmp
edx,dwordptr[ebp-14]
short00406DC1
edx,4B377D
eax,eax
|.
;00406DC1
|>
|>
|.
BA7D374B00
33C0
mov
xor
8BFA
mov
edi,edx
00406DC5
00406DC8
00406DCE
00406DD0
00406DD2
00406DD4
00406DD6
00406DD8
|.
|.
|.
|.
|.
|.
|.
|.
83C9FF
or
ecx,FFFFFFFF
esi,dwordptr[ebp-248]
scasbyteptres:[edi]
ecx
8DB5B8FDFFFFlea
F2:AE
F7D1
repne
not
sub
2BF9
edi,ecx
8BD1
87F7
mov
xchg
shr
edx,ecx
edi,esi
C1E902
ecx,2
00406DDB
00406DDD
|.
|.
8BC7
mov
rep
eax,edi
F3:A5
movsdwordptres:[edi],dwordptr[esi]


为什么上文一再提醒需要留意计数单位呢?因为这个特别的漏洞,成因正是读写所用的计数单位不同所致,具体是指字符串长度计算单位不同,一个为scasb,以byte为单位,一个为movsd,以dword,因此实际复制的长度为实际长度的4倍,覆盖了正常的堆栈。也许当时程序员打了个盹,或者手稍微抖了一下,将b写d,但就是这么一个不仔细看都看不出来的疏忽,造成了这个特别的溢出。