delphi 中的 Netcat 之类的监听程序不会发回命令

Netcat like listening program in delphi does not send back commands

我有一个 delphi 使用 winsock 监听端口 8080 的程序 这是到目前为止的代码:

program Project1;

{$APPTYPE CONSOLE}

uses
  Windows,
  SysUtils,
  WinSock;

var
  WSAData: TWSAData;
  ServerSocket,ClientSocket: TSocket;
  ServerAddr, ClientAddr: TSockAddr;
  ClientAddrSize,Status,ret: Integer;
  Buffer1,buffer2: array[0..1024] of Char;

begin
  writeln('started..');
  WSAStartup(01,WSAData);
  ServerSocket:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  ServerAddr.sin_family:=AF_INET;
  ServerAddr.sin_port:=htons(8080);
  ServerAddr.sin_addr.S_addr:=INADDR_ANY;
  bind(ServerSocket,ServerAddr,SizeOf(ServerAddr));
  listen(ServerSocket,10);
  ClientAddrSize:=SizeOf(ClientAddr);
  ClientSocket:=accept(ServerSocket,@ClientAddr,@ClientAddrSize);
  if ClientSocket <>  INVALID_SOCKET then
  begin
  while True do
   begin
    ret:=recv(ClientSocket,Buffer2,SizeOf(Buffer2),0);
    Writeln(Buffer2);
    Readln(Input, Buffer1);
    ret:=send(ClientSocket,Buffer1,SizeOf(Buffer1),0);
   end;
  end;

end.

正如您从此处的屏幕截图中所见:

我打开 netcat 并使用 "nc 127.0.0.1 8080 -e cmd.exe" 连接到我的程序 打开远程命令 shell.

我的程序得到了你通常在打开命令提示符时看到的第一行,但后来我无法执行像 "dir" 这样的命令,即使我在

之后发送命令
Readln(Input, Buffer1);

有什么想法吗?

编辑:如您所见,"dir" 命令写在 "C:\>" 下面 我需要像 netcat 那样做,也许我需要为命令创建一个管道。

到目前为止这还不是绝对正确的,因为出于某种原因它会回显第一个命令,而其余的则需要两次输入才能执行。

program Project1;

{$APPTYPE CONSOLE}

uses
  Windows,
  SysUtils,
  WinSock,
  uSockFunc in 'uSockFunc.pas';

var
  WSAData: TWSAData;
  ServerSocket,ClientSocket: TSocket;
  ServerAddr, ClientAddr: TSockAddr;
  ClientAddrSize: Integer;
  Buffer1, buffer2 : string;

begin
  writeln('started..');
  WSAStartup(1,WSAData);
  ServerSocket:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  ServerAddr.sin_family:=AF_INET;
  ServerAddr.sin_port:=htons(8080);
  ServerAddr.sin_addr.S_addr:=INADDR_ANY;
  bind(ServerSocket,ServerAddr,SizeOf(ServerAddr));
  listen(ServerSocket,10);
  ClientAddrSize:=SizeOf(ClientAddr);
  ClientSocket:=accept(ServerSocket,@ClientAddr,@ClientAddrSize);
  if ClientSocket <>  INVALID_SOCKET then
  begin
  while True do
   begin

    Buffer2 := RecvLn(ClientSocket, #$A);
    Writeln(Buffer2);
    Buffer2 := '';

    Readln(Input, Buffer1);
    SendString(ClientSocket, Buffer1 + #13#10);
    Buffer1 := '';

   end;
  end;

end.

我还使用了这个不是我的单位的 "SendString" 和 "RecvLn" 功能:

unit uSockFunc;

interface
uses windows, winsock;
const
EOL = #13#10;
function Connect(address : String;  port : Integer) : Integer;
procedure Disconnect(sinsock : TSocket);
function SendBuf(s : TSocket; var Buffer; Len : Integer) : Integer;
function SendString(s : TSocket; str : String) : Integer;
function RecvLn(s : TSocket; Delim: String = EOL): String;
function RecvLen(s : TSocket) : Integer;
function RecvBuf(s : TSocket; var Buffer; Len : Integer) : Integer;
implementation

function Connect(address : String;  port : Integer) : Integer;
var
  sinsock           : TSocket;
  SockAddrIn        : TSockAddrIn;
  hostent           : PHostEnt;
begin
  sinsock := Winsock.socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  SockAddrIn.sin_family := AF_INET;
  SockAddrIn.sin_port := htons(Port);
  SockAddrIn.sin_addr.s_addr := inet_addr(pchar(address));
  if SockAddrIn.sin_addr.s_addr = INADDR_NONE then
  begin
    HostEnt := gethostbyname(pchar(Address));
    if HostEnt = nil then
    begin
      result := SOCKET_ERROR;
      Exit;
    end;
    SockAddrIn.sin_addr.s_addr := Longint(PLongint(HostEnt^.h_addr_list^)^);
  end;                           //CHANGE MADE
  if Winsock.Connect(sinSock, SockAddrIn, SizeOf(SockAddrIn)) = SOCKET_ERROR Then
    result := SOCKET_ERROR
  else
    result := sinsock;
end;

function SendBuf(s : TSocket; var Buffer; Len : Integer) : Integer;
begin
  Result := send(s, Buffer, Len, 0);
end;

function SendString(s : TSocket; str : String) : Integer;
begin
  result := SendBuf(s, str[1],Length(str));
end;

function RecvLn(s : TSocket; Delim: String = EOL): String;
const
  BUFFER_SIZE = 255;
var
  Buffer: String;
  I, L: Cardinal;
begin
  Result := '';
  I := 1;
  L := 1;
  SetLength(Buffer, BUFFER_SIZE);
  while (L <= Cardinal(Length(Delim))) do
  begin
    if recv(s, Buffer[I], 1, 0) < 1 then Exit;
      ///
    if Buffer[I] = Delim[L] then
      Inc(L)
    else
      L := 1;
    Inc(I);
    if I > BUFFER_SIZE then
    begin
      Result := Result + Buffer;
      I := 1;
    end;
  end;
    Result := Result + Copy(Buffer, 0, I - L);
end;

function RecvLen(s : TSocket) : Integer;
begin
  if ioctlsocket(s, FIONREAD, Longint(Result)) = SOCKET_ERROR then
  begin
    Result := SOCKET_ERROR;
  end;
end;

function RecvBuf(s : TSocket; var Buffer; Len : Integer) : Integer;
begin
  Result := recv(s, Buffer, Len, 0);
  if (Result = SOCKET_ERROR) and (WSAGetLastError = WSAEWOULDBLOCK) then
  begin
   Result := 0;
  end;
end;

procedure Disconnect(sinsock : TSocket);
begin
  closesocket(sinsock);
end;
end.