在远控类程序中,远程执行CMD命令的功能非常实用,可以实现大量远控本身没有提供 的功能。一般远控程序提供类似于资源管理器的文件目录浏览功能,文件上传、下载功能, 远程运行程序、键盘记录和屏幕等基本功能,但受限于体积和开发等问题,很难面面俱到, 比如文件搜索、进程查看、端口查看等。如果提供一个远程的CMD功能,那就可以像在本机 使用命令行一样操作远程主机了。在远控中这个功能常用管道的方式实现。近日在黑防编辑 的指导下,利用传送控制台缓冲区的方式实现了一个远程同步CMD SHELL的程序,该程序利 用 UDP协议传输CMD SHELL窗口的缓冲区数据,可使在本地主机CMD窗口中输入的命令在远 程主机上的CMD窗口中同步显示和执行,返回结果也同样同步显示。测试效果如图1所示 ![]() 程序分为本地控制端和远程被控端两部分,通过UDP协议进行数据传输。运行时先打开 本地控制端程序,就会出现一个CMD 窗口,程序绑定了 UDP 的 8123 端口等待接收数据。同 时程序安装一个事件钩子,也就是建立了一个回调函数,当检测到输入为 Crtl+C 或 Crtl+Break 后就退出程序。紧接着程序会创建并激活一个控制台屏幕缓冲区作为当前显示 的控制台的屏幕缓冲区。之后程序进入循环,等待接收绑定的UDP8123端口上的数据。一旦 接收到数据就会存入到当前的控制台屏幕缓冲区当中并显示出来。当我们在此CMD窗口中输 入数据时,程序就会将屏幕缓冲区中的数据通过UDP包传回到远程被控端。从而实现了本地 CMD窗口的数据和远程被控端的窗口数据的一致。本地控制端程序如图二所示:其中dir命 令显示的是远程主机的C盘数据。 ![]()
本地控制端的程序代码部分注释如下: HANDLE MutexClient = CreateMutex( NULL,FALSE,"RemoteCMD" ); ...... hsocket = socket( AF_INET, SOCK_DGRAM , 0); //创建一个 UDP 协议套接字 ...... if( ioctlsocket( hsocket , FIONBIO , &argit ) ) //设置 socket 为非阻塞模式 { ...... return; } UdpPort = htons(8123); //接收数据的 UDP 端口 //设置绑定的套接字地址结构 bindSockaddr.sin_family = AF_INET; bindSockaddr.sin_port = UdpPort; bindSockaddr.sin_addr.s_addr = INADDR_ANY; if( SOCKET_ERROR==bind( hsocket ,(const struct sockaddr *)&bindSockaddr , sizeof(bindSockaddr) ) ) //绑定套接字 { MessageBox( 0,"Bind RemoteCMD port fail...",NULL,MB_OK ); CloseHandle( MutexClient ); closesocket( hsocket ); WSACleanup(); return; } SetConsoleCtrlHandler( HandlerRoutine,TRUE );//安装一个事件钩子,用以响应退 出按键 SetConsoleTitle("RemoteCMD"); //给控制台窗口设置标题 safe_attrib.nLength = sizeof(SECURITY_ATTRIBUTES); safe_attrib.lpSecurityDescriptor = NULL; safe attrib.bInheritHandle = TRUE; //创建一个新的屏幕缓冲区并返回其句柄。控制台程序通过句柄访问控制台的输入缓冲区及屏幕缓冲区,该句柄 //可以用在任意需要控制台输入的函数中。 //新的屏幕缓冲区不会激活,除非调用了 SetConsoleActiveScreenBuffer 函数 hConsoleOutput = CreateConsoleScreenBuffer ( GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &safe_attrib, CONSOLE_TEXTMODE_BUFFER, NULL); ...... dwSize.X = 80; //控制台屏幕缓冲区的大小 dwSize.Y = 100; SetConsoleScreenBufferSize( hConsoleOutput , dwSize ); SetConsoleActiveScreenBuffer( hConsoleOutput ); //激活该缓冲区 while( RecvSreen() ) //接收屏幕数据 { if (!KeyboardEvent( 100 ) ) //发送键盘数据 { break; } } SetConsoleCtrlHandler( HandlerRoutine , FALSE ); //卸载事件钩子 CloseHandle( MutexClient ); //关闭互斥体 closesocket( hsocket ); //关闭套接字 |