代码之家  ›  专栏  ›  技术社区  ›  Ira

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

  •  3
  • Ira  · 技术社区  · 9 年前

    我有一个用winsock监听8080端口的delphi程序 以下是迄今为止的代码:

    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($0101,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.
    

    从这里的截图可以看到: enter image description here

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

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

    Readln(Input, Buffer1);
    

    有什么想法吗?

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

    1 回复  |  直到 9 年前
        1
  •  0
  •   Ira    9 年前

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

    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($101,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.