2020年7月,微软公开发布了Windows DNS Server远程代码执行漏洞,漏洞编号为CVE-2020-1350,该漏洞影响 2003 到 2019 年发布的所有 Windows Server 版本,CVSS 评分为满分 10 分。微软在公告中指出,该漏洞可引发蠕虫式传播。Windows DNS Server 在处理特制的 SIG 响应包时,存在远程代码执行漏洞,未经身份验证的攻击者可通过维护一个域名并设置指向恶意服务器的 NS 记录,通过向目标 DNS 服务器查询该域名的 SIG 来利用此漏洞,成功利用此漏洞的远程攻击者可在目标系统上以 SYSTEM 账户权限执行任意代码。经研判,该漏洞无需交互、不需要身份认证且 Windows DNS Server 默认配置可触发。目前,互联网上已出现该漏洞相关细节、POC 以及漏洞利用视频。
此漏洞公开后,Check Point 发布了相关的分析文章,传送门:https://research.checkpoint.com/2020/resolving-your-way-into-domain-admin:-exploiting-a-17-year-old-bug-in-windows-dns-servers 。如果已了解漏洞原理可直接跳过本节。
以下为存在漏洞的函数 SigWireRead,SigWireRead 函数用来缓存 SIG 记录,当用户发起 SIG 查询时,DNS Server 首先查询有没有缓存记录,如果没有查询到或者该记录的 TTL 到期,则会向相应的 NS 服务器请求数据,这时候 DNS Server 会调用 SigWireRead 函数来存储这个记录。该漏洞是由整数溢出引发的堆溢出,漏洞位置位于倒数第 10 行和倒数第 3 行。
RR_AllocateEx 函数的第一个参数为 sigLength + nameSigner + 0x14,由于其大小为16 bits(仅使用 CX),可导致在计算参数时产生整数溢出,分配较小的缓冲区,后续使用 memcpy 函数向缓冲区复制大量数据导致堆溢出。
通过对比发现,关键变量 nameSigner 对应了数据包中 Signer's name 表示的域名长度,sigLength 则对应了 Signature 字段数据的长度。实际上 Signer's name 字段为 C0 0C,但解析成了 yyyyyyyyt.fun,这是因为使用了 DNS 名称压缩。 C0 表示启用名称压缩,后面的 0C 代表了数据相对于 DNS 报文的偏移,Name_PacketNameToCountNameEx 函数会处理这个,并将处理结果放在 &nameSigner 处。
正常 DNS 响应包大小不会超过 0xFFFF,基于 UDP 的 DNS 大小被限制到 512 字节,即使采用 TCP 连接,DNS 消息长度也被限制为 2 个字节,也就是 0xFFFF,如下图所示,这 0xFFFF 字节数据除了包含真实的 Signer's name 以及 Signature,还包括 DNS 头部和原始查询等信息,这些数据加起来已经明显超过0x14了,在这种情况下, sigLength + nameSigner + 0x14 小于 0x10000,因而不能直接产生溢出。
所以嘛,还需要观察一下 Name_PacketNameToCountNameEx 函数,以 "yyyyyyyyt.fun" 为例,经过该函数处理后 nameSigner 为 0xF,表示后面有 0xF 个字节,后面的 2 表示后面有两组数据,一组为 9 字节长度的 yyyyyyyyt,另一组为 3 字节长度的 fun。计算出的 nameSigner 会参与后续计算。
正常情况下,即使 DNS 响应包长度为 0xFFFF 也无法触发整数溢出,但由于攻击者可控制 DNS 响应数据,可通过设置 Signer's name 中的偏移,使其指向一个较大的数来增加 nameSigner。由于每一组的长度不能超过 0x40(Name_PacketNameToCountNameEx 函数中有判断),所以我选择查询 9.yyyyyyyyt.fun。当偏移由 0xC 变为 0xD,要处理的数据就由 "01 39 09 79 79 79 79 79 79 79 79 74 03 66 75 6e" 变成了 "39 09 79 79 79 79 79 79 79 79 74 03 66 75 6e"。Name_PacketNameToCountNameEx 函数执行完成后 nameSigner 为 0x3b(0x39+1+1)。
在这种情况下,sigLength + nameSigner + 0x14 的结果为 0x1000d,超过了 0xFFFF,成功整数溢出。虽然调用 RR_AllocateEx 函数时请求的大小为 0xd,但实际分配了 0x68 大小的缓冲区,因为分配的堆需要容纳 0x10 大小的自定义头部、0x38大小的 RR 头部以及重组的 DNS RR 数据(申请时的 0xd)。
SigWireRead 函数在后面会将 RR 数据重组(图2框里的数据),但由于 Signer's name 实际指向的数据的长度就超过了 0xd,所以在 Name_CopyCountName 处就会产生溢出,覆盖到邻接的堆块。
以下为后续调用 memcpy 函数向不可访问区域写数据时触发崩溃的场景:
RR_AllocateEx 函数被用来申请 RR 对象空间,在函数内部会将申请的长度加上 a2(例,SigWireRead 调用 RR_AllocateEx 时将 a2 设置为0),然后再加上 0x38(RR 对象头长度),然后调用 Mem_Alloc 函数。
如下所示,在 Mem_Alloc 函数中会将传入的 length 加 0x10(自定义堆头大小)。如果这个长度大于0xA0,会调用 allocMemory -> HeapAlloc 进行分配。而如果长度在 0xA0 以内,则从 StandardAllocLists 中分配合适大小的堆,如果当前 StandardAllocLists 中没有合适大小的堆,就会调用 allocMemory -> HeapAlloc 函数请求 v14[3] * v14[4] 大小的堆,并将它们分开并链接起来供 StandardAllocLists 查询。
StandardAllocLists 维护四个不同大小的堆链,包括 0x50、0x68、0x88 和 0xA0。例,如果 v8 在 0x89 到 0xA0 之间,则会分配到 0xA0 大小的 DNS 堆: index 0:0x50 0x33(个数)= 0xFF0(0x00〜0x50) index 1:0x68 0x27(个数)= 0xFD8(0x51〜0x68) index 2:0x88 0x1e(个数)= 0xFF0(0x69〜0x88) index 3:0xA0 0x19(个数)= 0xFA0(0x89〜0xA0)
由前面信息可知,RRSIG 对象包括 0x10 的自定义头部、0x38 字节的对象头部以及不确定长度的对象数据(包括 0x12 长度的数据、Signer's name 以及 Signature)。通过调整发送的响应包的 Signature 的长度可分配到目标大小的堆,如下,RRSIG 对象被分配到 0xA0 大小的块上。由于 RR 对象的结构已知,所以也很容易伪造。
当缓存信息超时后,将会自动释放该 RR 对象。可将目标 DNS 响应数据的 TTL 设置为 0,并在短时间内再次请求,从而释放原有的堆,同时也会重新申请一个新的堆来储存数据。以下为释放后的堆,其偏移 8 处指向下一个大小为 0xA0 的可用的堆。由于其大小在 0xA0 以内,因而会被 StandardAllocLists 记录(0xA0 大小,索引 3),也是遵循后进先出的原则。
为了避免漏洞触发时引发崩溃,可以多次请求服务器使其分配很多 RR 对象(保证这些对象在漏洞利用时不会被释放)。然后释放中间的一个对象,使得触发漏洞时,RRSIG 对象可以申请到之前释放的块。
1、分配大量 0x1000F 块(加上 0x10 字节的 _Heap_Entry 实际上是 0x10020),然后释放中间的一个 0x1000F 块 2、分配大小为 0xF05F 的块,从而分割出 0xFB0 大小的剩余可用空间 3、接下来再请求大量 0xA0 块就可以使目标 RR 缓冲区分配到这个 0xFB0 大小的块(_Heap_Entry 0x10 + 0xFA0)
这样可保证向重占位的 0xFB0 大小的块中的某个释放后的对象处复制超过 0xFFFF 大小的数据也不会触发崩溃。
某次测试时的布局如下,我们可以释放 sp_115 所在堆,然后利用漏洞申请相同大小的堆,并覆盖后面的数据。
通过设置 RR 对象中的 rr_size 可泄露后面对象的堆数据。当客户端发起 SIG 请求时,DNS Server 会从缓存中读取数据。如下,在 SigWireWrite 函数中,rr_size 可控制读取数据的长度,但要需要保证 rr_size - nameSigner - 0x14 的大小不超过 v4 - v9(Wire_TestForBytesRemaining 函数控制)。
将 sp_116 的 rr_size 设置为 0x1a0(本来是 0x57)然后请求其 SIG 可获取sp_117 和 sp_118 范围内的数据,如下:
当使用 RR_Free 函数释放超时的 RR 对象时,会判断 wtype 是否为 2(NS)或 6(SOA),如果是的话,就会调用 Timeout_FreeWithFunctionEx,在该函数中调用 Mem_Alloc 申请 0x38 大小的堆,用于存放对象指针(pItem)、释放函数指针(pFreeFunction)等等。对象释放时会在Timeout_CleanupDelayedFreeList 函数中调用 FreeFunction,且参数为 pItem,不过这通常需要一段时间。
如果可以将 DnsTimeoutObject(0x38大小)分配到可控的位置,再利用溢出覆盖 pItem 和 pFreeFunction,就可以在对象释放时控制执行流程(允许执行带一个参数的函数)。而且,原始的 pFreeFunction 指向 dns!RR_Free,可通过将其泄露从而进一步获取 DNS 基址(这需要收集不同版本的偏移)。
先前,研究人员已经找到了 CFG 允许执行的且只需要一个参数的 dns!NsecDNSRecordConvert 函数,它可以将第一个参数偏移0x20处的字符串复制到新开辟的区域,这允许我们进行任意地址读取。我们可以通过设置 v1 偏移 0x28 处的数据使 Rpc_AllocateRecord 函数申请到我们可控的区域,然后再使用数据泄露思路进行读取。
为了获得 msvcrt!system 函数(CFG允许)的地址,可通过上述思路进一步泄露 msvcrt!memcpy 函数地址,然后根据偏移计算出 system 函数地址。但这还需要一个可控的参数地址,可通过连续释放两个对象,然后泄露后一个对象空间来获得堆指针,将 dns!_imp_memcpy 地址布局到该地址偏移 0x20 处。成功获取 msvcrt!system 函数地址后,采用同样的思路调用 system 可获得任意命令执行。
Windows DNS Server 在处理特制的 SIG 响应包时,存在远程代码执行漏洞,未经身份验证的攻击者可通过向目标 DNS 服务器查询并响应 SIG 请求来利用此漏洞,成功利用此漏洞的远程攻击者可在目标系统上以 SYSTEM 账户权限执行任意代码。本文对此漏洞进行分析,并参考链接 [2-3] 中的漏洞利用思路,在实验环境下拿到了 SYSTEM SHELL,如下所示。PS:实验环境是指将 DNS 服务器转发器配置为攻击者控制的 NS 服务器。由于真实环境下的 DNS 服务器会处理大量请求,此思路可能无法很好地应用于实战。
[1] https://msrc.microsoft.com/update-guide/vulnerability/CVE-2020-1350
[2] http://blog.diffense.co.kr/2020/12/04/Sigred.html
[3] https://datafarm-cybersecurity.medium.com/exploiting-sigred-cve-2020-1350-on-windows-server-2012-2016-2019-80dd88594228
[4] https://research.checkpoint.com/2020/resolving-your-way-into-domain-admin:-exploiting-a-17-year-old-bug-in-windows-dns-servers
[5] https://msrc.microsoft.com/update-guide/vulnerability/CVE-2020-1350
[6] https://mp.weixin.qq.com/s/4HBVvDuq_HWXop14ENUSuA
_BYTE
*
__fastcall SigWireRead(__int64 a1, __int64 pMsg, __int64 pchData, unsigned __int16 a4)
{
__int64 v4;
/
/
rbx
unsigned __int64 pchEnd;
/
/
rdi
unsigned __int8
*
signameData;
/
/
r8
unsigned __int8
*
v7;
/
/
rax
unsigned __int8
*
v8;
/
/
rbp
size_t sigLength;
/
/
rdi
_BYTE
*
v10;
/
/
rax
_BYTE
*
v11;
/
/
rsi
unsigned __int8 nameSigner;
/
/
[rsp
+
30h
] [rbp
-
138h
]
v4
=
pchData;
pchEnd
=
pchData
+
a4;
signameData
=
(unsigned __int8
*
)(pchData
+
0x12
);
if
( (unsigned __int64)signameData >
=
pchEnd )
return
0i64
;
v7
=
Name_PacketNameToCountNameEx(&nameSigner, pMsg, signameData, pchEnd)
v8
=
v7;
if
( !v7 )
return
0i64
;
sigLength
=
pchEnd
-
(_QWORD)v7;
v10
=
RR_AllocateEx((unsigned __int16)sigLength
+
(unsigned __int16)nameSigner
+
0x14
,
0
,
0
);
/
/
整数溢出
v11
=
v10;
if
( !v10 )
return
0i64
;
*
(_OWORD
*
)(v10
+
0x38
)
=
*
(_OWORD
*
)v4;
*
((_WORD
*
)v10
+
0x24
)
=
*
(_WORD
*
)(v4
+
0x10
);
Name_CopyCountName(v10
+
0x4A
, &nameSigner);
memcpy(&v11[(unsigned __int8)v11[
0x4A
]
+
0x4C
], v8, sigLength);
/
/
堆溢出
return
v11;
}
_BYTE
*
__fastcall SigWireRead(__int64 a1, __int64 pMsg, __int64 pchData, unsigned __int16 a4)
{
__int64 v4;
/
/
rbx
unsigned __int64 pchEnd;
/
/
rdi
unsigned __int8
*
signameData;
/
/
r8
unsigned __int8
*
v7;
/
/
rax
unsigned __int8
*
v8;
/
/
rbp
size_t sigLength;
/
/
rdi
_BYTE
*
v10;
/
/
rax
_BYTE
*
v11;
/
/
rsi
unsigned __int8 nameSigner;
/
/
[rsp
+
30h
] [rbp
-
138h
]
v4
=
pchData;
pchEnd
=
pchData
+
a4;
signameData
=
(unsigned __int8
*
)(pchData
+
0x12
);
if
( (unsigned __int64)signameData >
=
pchEnd )
return
0i64
;
v7
=
Name_PacketNameToCountNameEx(&nameSigner, pMsg, signameData, pchEnd)
v8
=
v7;
if
( !v7 )
return
0i64
;
sigLength
=
pchEnd
-
(_QWORD)v7;
v10
=
RR_AllocateEx((unsigned __int16)sigLength
+
(unsigned __int16)nameSigner
+
0x14
,
0
,
0
);
/
/
整数溢出
v11
=
v10;
if
( !v10 )
return
0i64
;
*
(_OWORD
*
)(v10
+
0x38
)
=
*
(_OWORD
*
)v4;
*
((_WORD
*
)v10
+
0x24
)
=
*
(_WORD
*
)(v4
+
0x10
);
Name_CopyCountName(v10
+
0x4A
, &nameSigner);
memcpy(&v11[(unsigned __int8)v11[
0x4A
]
+
0x4C
], v8, sigLength);
/
/
堆溢出
return
v11;
}
0
:
001
>
dns!SigWireRead
+
0x3c
:
00007ff7
`a9daf90c e86755fcff call dns!Name_PacketNameToCountNameEx (
00007ff7
`a9d74e78)
0
:
001
> db r8
000002ea
`
760b445d
c0
0c
00
00
00
00
00
00
-
00
00
00
00
00
00
00
00
................
0
:
001
> r rcx
rcx
=
000000f775b7f1f0
0
:
001
> p
dns!SigWireRead
+
0x41
:
00007ff7
`a9daf911
488be8
mov rbp,rax
0
:
001
> db rcx
/
/
&nameSigner
000000f7
`
75b7f1f0
0f
02
09
79
79
79
79
79
-
79
79
79
74
03
66
75
6e
...yyyyyyyyt.fun
000000f7
`
75b7f200
00
be
6c
75
ea
02
00
00
-
00
00
00
00
00
00
00
00
..lu............
0
:
001
> u rip l6
dns!SigWireRead
+
0x4e
:
00007ff7
`a9daf91e
482bf8
sub rdi,rax
00007ff7
`a9daf921
6683c114
add cx,
14h
00007ff7
`a9daf925
33d2
xor edx,edx
00007ff7
`a9daf927
6603cf
add cx,di
00007ff7
`a9daf92a
4533c0
xor r8d,r8d
00007ff7
`a9daf92d e8263c0800 call dns!RR_AllocateEx (
00007ff7
`a9e33558)
0
:
001
> r cx
cx
=
f
0
:
001
> ? rdi
-
rax
Evaluate expression:
65472
=
00000000
`
0000ffc0
0
:
001
> ? cx
+
ffc0
+
14
/
/
无法整数溢出
Evaluate expression:
65507
=
00000000
`
0000ffe3
0
:
001
>
dns!SigWireRead
+
0x3c
:
00007ff7
`a9daf90c e86755fcff call dns!Name_PacketNameToCountNameEx (
00007ff7
`a9d74e78)
0
:
001
> db r8
000002ea
`
760b445d
c0
0c
00
00
00
00
00
00
-
00
00
00
00
00
00
00
00
................
0
:
001
> r rcx
rcx
=
000000f775b7f1f0
0
:
001
> p
dns!SigWireRead
+
0x41
:
00007ff7
`a9daf911
488be8
mov rbp,rax
0
:
001
> db rcx
/
/
&nameSigner
000000f7
`
75b7f1f0
0f
02
09
79
79
79
79
79
-
79
79
79
74
03
66
75
6e
...yyyyyyyyt.fun
000000f7
`
75b7f200
00
be
6c
75
ea
02
00
00
-
00
00
00
00
00
00
00
00
..lu............
0
:
001
> u rip l6
dns!SigWireRead
+
0x4e
:
00007ff7
`a9daf91e
482bf8
sub rdi,rax
00007ff7
`a9daf921
6683c114
add cx,
14h
00007ff7
`a9daf925
33d2
xor edx,edx
00007ff7
`a9daf927
6603cf
add cx,di
00007ff7
`a9daf92a
4533c0
xor r8d,r8d
00007ff7
`a9daf92d e8263c0800 call dns!RR_AllocateEx (
00007ff7
`a9e33558)
0
:
001
> r cx
cx
=
f
0
:
001
> ? rdi
-
rax
Evaluate expression:
65472
=
00000000
`
0000ffc0
0
:
001
> ? cx
+
ffc0
+
14
/
/
无法整数溢出
Evaluate expression:
65507
=
00000000
`
0000ffe3
0
:
001
>
dns!Name_PacketNameToCountNameEx
+
0xdd
:
00007ff7
`a9d74f55
493bf6
cmp
rsi,r14
0
:
001
> ub rip
dns!Name_PacketNameToCountNameEx
+
0xbb
:
00007ff7
`a9d74f33
4c8d46ff
lea r8,[rsi
-
1
]
00007ff7
`a9d74f37
0fb606
movzx eax,byte ptr [rsi]
00007ff7
`a9d74f3a
488db530190000
lea rsi,[rbp
+
1930h
]
00007ff7
`a9d74f41
440fb6ca
movzx r9d,dl
00007ff7
`a9d74f45
6641c1e108
shl r9w,
8
00007ff7
`a9d74f4a
66440bc8
or
r9w,ax
00007ff7
`a9d74f4e
410fb7c1
movzx eax,r9w
00007ff7
`a9d74f52
4803f0
add rsi,rax
/
/
rax
=
0xd
0
:
001
> db rsi l40
000002ea
`
760b442d
39
09
79
79
79
79
79
79
-
79
79
74
03
66
75
6e
00
9.yyyyyyyyt
.fun.
000002ea
`
760b443d
00
18
00
01
c0
0c
00
18
-
00
01
00
00
00
00
ff d2 ................
000002ea
`
760b444d
00
01
05
00
00
00
00
00
-
00
00
00
00
00
00
00
00
................
000002ea
`
760b445d
00
00
c0
0d
00
00
00
00
-
00
00
00
00
00
00
00
00
................
0
:
001
> gu
/
/
函数返回
dns!SigWireRead
+
0x41
:
00007ff7
`a9daf911
488be8
mov rbp,rax
0
:
001
> db rcx l40
/
/
&nameSigner
000000f7
`
75b7f1f0
3b
01
39
09
79
79
79
79
-
79
79
79
79
74
03
66
75
;.
9.yyyyyyyyt
.fu
000000f7
`
75b7f200
6e
00
00
18
00
01
c0
0c
-
00
18
00
01
00
00
00
00
n...............
000000f7
`
75b7f210
ff d2
00
01
05
00
00
00
-
00
00
00
00
00
00
00
00
................
000000f7
`
75b7f220
00
00
00
00
c0
0d
00
00
-
00
00
00
00
00
7f
00
00
................
0
:
001
>
dns!Name_PacketNameToCountNameEx
+
0xdd
:
00007ff7
`a9d74f55
493bf6
cmp
rsi,r14
0
:
001
> ub rip
dns!Name_PacketNameToCountNameEx
+
0xbb
:
00007ff7
`a9d74f33
4c8d46ff
lea r8,[rsi
-
1
]
00007ff7
`a9d74f37
0fb606
movzx eax,byte ptr [rsi]
00007ff7
`a9d74f3a
488db530190000
lea rsi,[rbp
+
1930h
]
00007ff7
`a9d74f41
440fb6ca
movzx r9d,dl
00007ff7
`a9d74f45
6641c1e108
shl r9w,
8
00007ff7
`a9d74f4a
66440bc8
or
r9w,ax
00007ff7
`a9d74f4e
410fb7c1
movzx eax,r9w
00007ff7
`a9d74f52
4803f0
add rsi,rax
/
/
rax
=
0xd
0
:
001
> db rsi l40
000002ea
`
760b442d
39
09
79
79
79
79
79
79
-
79
79
74
03
66
75
6e
00
9.yyyyyyyyt
.fun.
000002ea
`
760b443d
00
18
00
01
c0
0c
00
18
-
00
01
00
00
00
00
ff d2 ................
000002ea
`
760b444d
00
01
05
00
00
00
00
00
-
00
00
00
00
00
00
00
00
................
000002ea
`
760b445d
00
00
c0
0d
00
00
00
00
-
00
00
00
00
00
00
00
00
................
0
:
001
> gu
/
/
函数返回
dns!SigWireRead
+
0x41
:
00007ff7
`a9daf911
488be8
mov rbp,rax
0
:
001
> db rcx l40
/
/
&nameSigner
000000f7
`
75b7f1f0
3b
01
39
09
79
79
79
79
-
79
79
79
79
74
03
66
75
;.
9.yyyyyyyyt
.fu
000000f7
`
75b7f200
6e
00
00
18
00
01
c0
0c
-
00
18
00
01
00
00
00
00
n...............
000000f7
`
75b7f210
ff d2
00
01
05
00
00
00
-
00
00
00
00
00
00
00
00
................
000000f7
`
75b7f220
00
00
00
00
c0
0d
00
00
-
00
00
00
00
00
7f
00
00
................
0
:
001
> u rip l6
dns!SigWireRead
+
0x4e
:
00007ff7
`a9daf91e
482bf8
sub rdi,rax
00007ff7
`a9daf921
6683c114
add cx,
14h
00007ff7
`a9daf925
33d2
xor edx,edx
00007ff7
`a9daf927
6603cf
add cx,di
00007ff7
`a9daf92a
4533c0
xor r8d,r8d
00007ff7
`a9daf92d e8263c0800 call dns!RR_AllocateEx (
00007ff7
`a9e33558)
0
:
001
> r cx
cx
=
3b
0
:
001
> ? cx
+
rdi
-
rax
+
14
/
/
整数溢出
Evaluate expression:
65549
=
00000000
`
0001000d
……
0
:
001
>
dns!SigWireRead
+
0x5d
:
00007ff7
`a9daf92d e8263c0800 call dns!RR_AllocateEx (
00007ff7
`a9e33558)
0
:
001
> r rcx
rcx
=
000000000000000d
/
/
dns!Mem_Alloc
00007ff7
`a9e32f3a
3b3dfc850a00
cmp
edi,dword ptr [dns!StandardAllocLists
+
0xc
(
00007ff7
`a9edb53c)]
00007ff7
`a9e32f40
488d1de9850a00
lea rbx,[dns!StandardAllocLists (
00007ff7
`a9edb530)]
00007ff7
`a9e32f47
760c
jbe dns!Mem_Alloc
+
0xe9
(
00007ff7
`a9e32f55)
00007ff7
`a9e32f49
488bc3
mov rax,rbx
00007ff7
`a9e32f4c
4883c358
add rbx,
58h
00007ff7
`a9e32f50
3b7864
cmp
edi,dword ptr [rax
+
64h
] ds:
00007ff7
`a9edb594
=
00000068
0
:
001
> dq dns!StandardAllocLists
+
58
00007ff7
`a9edb588
000002ea
`
758c5b18
00000068
`
00000001
/
/
0x68
大小的 AllocLists
00007ff7
`a9edb598
0000000b
`
00000027
0000009c
`
00000004
00007ff7
`a9edb5a8
0000004e
`
000000df
00000000
`
00003f60
00007ff7
`a9edb5b8 ffffffff`ffffffff
00000000
`ffffffff
00007ff7
`a9edb5c8
00000000
`
00000000
00000000
`
00000000
00007ff7
`a9edb5d8
00000000
`
00001388
000002ea
`
752c5098
/
/
0x88
大小的 AllocLists
00007ff7
`a9edb5e8
00000088
`
00000002
00000004
`
0000001e
00007ff7
`a9edb5f8
000000d2
`
00000007
00000021
`
000000ef
0
:
001
> gu
dns!SigWireRead
+
0x62
:
00007ff7
`a9daf932
488bf0
mov rsi,rax
0
:
001
> db rax
-
10
/
/
分配到
0x2ea758c5b18
,长度为
0x68
000002ea
`
758c5b18
1c
00
00
00
bb
1a
69
00
-
ef
0c
0c
0c
0c
0c
0c
fe ......i.........
000002ea
`
758c5b28
00
00
00
00
00
00
00
00
-
00
80
00
00
00
00
0d
00
................
000002ea
`
758c5b38
00
00
00
00
00
00
00
00
-
00
00
00
00
00
00
00
00
................
000002ea
`
758c5b48
00
00
00
00
00
00
00
00
-
00
00
00
00
00
00
00
00
................
000002ea
`
758c5b58
00
00
00
00
00
00
00
00
-
18
04
02
62
30
03
6f
72
...........b0.
or
000002ea
`
758c5b68
67
0b
61
66
69
6c
69
61
-
73
2d
6e
73
74
03
6f
72
g.afilias
-
nst.
or
000002ea
`
758c5b78
67
00
00
00
00
00
00
00
-
00
00
00
00
ee
22
69
00
g............"i.
000002ea
`
758c5b88
e8
5b
8c
75
ea
02
00
00
-
ef
0b
0b
fe ef
0b
0b
fe .[.u............
0
:
001
> u rip l6
dns!SigWireRead
+
0x4e
:
00007ff7
`a9daf91e
482bf8
sub rdi,rax
00007ff7
`a9daf921
6683c114
add cx,
14h
00007ff7
`a9daf925
33d2
xor edx,edx
00007ff7
`a9daf927
6603cf
add cx,di
00007ff7
`a9daf92a
4533c0
xor r8d,r8d
00007ff7
`a9daf92d e8263c0800 call dns!RR_AllocateEx (
00007ff7
`a9e33558)
0
:
001
> r cx
cx
=
3b
0
:
001
> ? cx
+
rdi
-
rax
+
14
/
/
整数溢出
Evaluate expression:
65549
=
00000000
`
0001000d
……
0
:
001
>
dns!SigWireRead
+
0x5d
:
00007ff7
`a9daf92d e8263c0800 call dns!RR_AllocateEx (
00007ff7
`a9e33558)
0
:
001
> r rcx
rcx
=
000000000000000d
/
/
dns!Mem_Alloc
00007ff7
`a9e32f3a
3b3dfc850a00
cmp
edi,dword ptr [dns!StandardAllocLists
+
0xc
(
00007ff7
`a9edb53c)]
00007ff7
`a9e32f40
488d1de9850a00
lea rbx,[dns!StandardAllocLists (
00007ff7
`a9edb530)]
00007ff7
`a9e32f47
760c
jbe dns!Mem_Alloc
+
0xe9
(
00007ff7
`a9e32f55)
00007ff7
`a9e32f49
488bc3
mov rax,rbx
00007ff7
`a9e32f4c
4883c358
add rbx,
58h
00007ff7
`a9e32f50
3b7864
cmp
edi,dword ptr [rax
+
64h
] ds:
00007ff7
`a9edb594
=
00000068
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!