360 compression 3.2.0.2030 stack buffer overflow + Null Pointer Reference
360 improper data connection during ZIP file compression causes stack buffer overflow PoC1.
0: 000> k
ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
001289e8 7c98d144 360zip + 0x70000e
00128a50 00410041 ntdll! RtlDebugAllocateHeap + 0x281
00128a60 00410041 360zip + 0x10041
00128a64 0041005c 360zip + 0x10041
00128a68 00410041 360zip + 0x1005c
00128a6c 00410041 360zip + 0x10041
00128a70 00410041 360zip + 0x10041
00128a74 00410041 360zip + 0x10041
00128a78 00410041 360zip + 0x10041
00128a7c 00410041 360zip + 0x10041
00128a80 00410041 360zip + 0x10041
00128a84 00410041 360zip + 0x10041
00128a88 00410041 360zip + 0x10041
00128a8c 00410041 360zip + 0x10041
Although the maximum path length of a layer is MAX_PATH, it is not necessarily the number because the names of the upper and lower layers of folders are added up, therefore, the two string copy functions at 360zip + 0x7124b rushed to the street, and stack buffer overflow occurred after the copy was completed. Fortunately, Security Cookies are covered.
The problem is:
0:000> gBreakpoint 2 hiteax=03190748 ebx=00000002 ecx=00120000 edx=03190562 esi=00000060 edi=00a64670eip=0047108b esp=001289d4 ebp=03190560 iopl=0 nv up ei pl zr na pe nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246360zip+0x7108b:0047108b 2bc2 sub eax,edx
Sort out the problematic functions as follows (for pseudo code ):
Inline BOOL IsWordValid (WORD wd) {return! (Wd <0x30 | wd> 0x39);} inline ULONG Min (ULONG a, ULONG B) {return a> B? B: a;} ULONG ListItemValueProc (WCHAR * strFileName, WCHAR * strFullPath) {if (strFileName & strFullPath) // strFileName directory name, contents of the upper-level directory name of strFullPath and the file name of the current layer are combined {ULONG nLenFileName = wcslen (strFileName); ULONG nLenFullPath = wcslen (strFullPath); if (nLenFileName> 0) {ULONG nPos1 = 0; ULONG nPos2 = 0; ULONG nPosTemp = 0; WCHAR wTemp = 0; while (1) {if (nPos2> nLenFileName) goto some mark // break; if (! IsWordValid (pszStrFileName [pos]) |! IsWordValid (pszStrFullPath [pos2]) break; nPosTemp = nPos1; pos2 ++; if (nPos1 + 1 <nLenFullPath) {while (nPosTemp ++ <nLenFullPath & IsWordValid (pszStrFileName [nPosTemp]);} // where's ifwhile (nPos2 ++ <nLenFullPath & IsWordValid (pszStrFullPath [nPos2]); ULONG nCounter1 = 0; ULONG nCounter2 = 0; // WCHAR * szString1 = 0; WCHAR szSomeBuffer [MAX_PATH] = {0}; swscanf (pszStrFileName [nPos1], L "% d % s", & nCounter1, sz SomeBuffer); // szString1); swscanf (pszStrFullPath [nPos1], L "% d % s", & nCounter2, szSomeBuffer); // szString1 ); // szString1 should be buffer. If (nCounter1> nCounter2) return 1; if (nCounter1 <nCounter2) return-1; nPos1 = nPosTemp; SOMELABELUNKNOWN: if (nPos> = nLenFullPath) goto endOfScanning ;} // end of while (1) ULONG nPosA = nPos1 + 1; ULONG nPosB = nPos2 + 1; if (pos + 1 <nLenFileName) {while (nPosA ++ <nLenFullPath & IsWordValid (pszStrFileName [nPosA]); // locate the last valid character} // same as above, same operation while (nPosB ++ <nLenFullPath & IsWordValid (pszStrFul LPath [nPosB]); ULONG nDiff = nPosA-nPos1; ULONG nDiff2 = nPosB-nPos2; ULONG nDiff3 = nLenFileName-nPos1; ULONG nDiff4 = nLenFullPath-nPos2; if (nDiff <nDiff2) {nDiff4 = Min (nDiff2, nDiff3);} else {if (nDiff4> nDiff) nDiff4 = nDiff;} WCHAR szSomeBufferA [MAX_PATH] = {0 }; WCHAR szSomeBufferB [MAX_PATH] = {0}; wcsncpy (szSomeBufferA, pszStrFileName [nPos1], nDiff4 );//!!! WARNING !!! Wcsncpy (szSomeBufferB, pszStrFullPath [nPos2], nDiff4 );//!!! WARNING !!! ULONG cursor = CompareStringW (LOCALE_USER_DEFAULT, NORM_IGNORECASE, szSomeBufferA,-1, delimiter,-1); //-1: The string is Null Terminatedif (Signature) {if (nCompareResult = 2) {LABEL_42: pos + = nDiff4; pos2 + = nDiff4; goto SOMELABELUNKNOWN;} if (nCompareResult = 1) result =-1; elseresult = 1; // 2 * (nCompareResult! = 1)-1;} else {result = _ wcsicmp (szSomeBufferA, szSomeBufferB);} if (result) return result; elsegoto LABEL_42;} endOfScanning: result = 0; if (nLenFileName! = NLenFullPath) {if (nLenFileName> nLenFullPath) result = 1; elseresult =-1 ;}} else // if (strFileName & strFullPath) else part {result = 0 ;} return result ;}
0:000> pcteax=001289f0 ebx=00000000 ecx=00000000 edx=00128bf8 esi=00000128 edi=00000000eip=0047127e esp=001289b4 ebp=0222029e iopl=0 nv up ei pl nz na pe nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206360zip+0x7127e:0047127e ff1590a14e00 call dword ptr [360zip+0xea190 (004ea190)] ds:0023:004ea190={kernel32!CompareStringW (7c80a3ee)}0:000> kChildEBP RetAddr WARNING: Stack unwind information not available. Following frames may be wrong.001289e8 7c98d144 360zip+0x7127e00128a50 00410041 ntdll!RtlDebugAllocateHeap+0x28100128a60 00410041 360zip+0x1004100128a64 0041005c 360zip+0x1004100128a68 00410041 360zip+0x1005c00128a6c 00410041 360zip+0x1004100128a70 00410041 360zip+0x1004100128a74 00410041 360zip+0x1004100128a78 00410041 360zip+0x1004100128a7c 00410041 360zip+0x1004100128a80 00410041 360zip+0x1004100128a84 00410041 360zip+0x1004100128a88 00410041 360zip+0x1004100128a8c 00410041 360zip+0x1004100128a90 00410041 360zip+0x1004100128a94 00410041 360zip+0x10041
0:000> dd esp L200001289b4 00000400 00000001 001289f0 ffffffff001289c4 00128bf8 ffffffff 00a75a70 00000002001289d4 00a64708 00128e34 0000018a 0222004c001289e4 00000128 ffffffff 7c98d144 00580045001289f4 00520054 004c0041 004e004f 0041004700128a04 00410041 00410041 00410041 0041004100128a14 00410041 00410041 00410041 0041004100128a24 00410041 00410041 00410041 0041004100128a34 00410041 00410041 00410041 0041004100128a44 00410041 00410041 00410041 0041004100128a54 00410041 00410041 00410041 0041004100128a64 00410041 0041005c 00410041 0041004100128a74 00410041 00410041 00410041 0041004100128a84 00410041 00410041 00410041 0041004100128a94 00410041 00410041 00410041 0041004100128aa4 00410041 00410041 00410041 0041004100128ab4 00410041 00410041 00410041 0041004100128ac4 00410041 00410041 00410041 0041004100128ad4 00410041 00410041 00410041 0041004100128ae4 00410041 00410041 00410041 0041004100128af4 00410041 00410041 00410041 0041004100128b04 00410041 00410041 00410041 0041004100128b14 00410041 00410041 00410041 0041004100128b24 00410041 00410041 00410041 0041004100128b34 00410041 00410041 00410041 0041004100128b44 00410041 00410041 00410041 0041004100128b54 00410041 00410041 00410041 0041004100128b64 00410041 00410041 00410041 0041004100128b74 00410041 00410041 00410041 0041004100128b84 00410041 00410041 00410041 00410041
and。。poc2:
(59c. 3a4): Access violation-code c0000005 (!!! Second chance !!!)
eax=00000000 ebx=02267cf4 ecx=00000002 edx=028d0016 esi=00000005 edi=015a3ee8eip=01517ca5 esp=02417ba4 ebp=015a3ee4 iopl=0 nv up ei pl nz na po nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\360\360zip\360zipc.dll - 360zipc!DeleteExtractObject+0x1f4a5:01517ca5 394858 cmp dword ptr [eax+58h],ecx ds:0023:00000058=????????
Solution:
Use the _ s copy Function
Or check the data to be written into the buffer.