Using Pipes for bidirectional communication(Windows API)

huangapple go评论73阅读模式
英文:

Using Pipes for bidirectional communication(Windows API)

问题

我理解你的问题。你试图编写一个程序,通过使用管道向 cmd.exe 提供输入并通过管道获取输出,但在通过 PARENT_WRITE 提供输入后,无法通过另一个管道 PARENT_READ 获取输出。以下是你的代码的翻译:

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

#define BUFFER_LENGTH 1024
void handle_cleanup(STARTUPINFOW,  PROCESS_INFORMATION);
DWORD WINAPI ReadPipe(LPVOID);

HANDLE CMD_WRITE, PARENT_READ, CMD_READ, PARENT_WRITE;

int CreateProcessCMD(void){
   DWORD ThreadID;
   DWORD bytes_written;
   HANDLE hProcessCMD;
   
   STARTUPINFOW PSTARTUPINFO;
   PROCESS_INFORMATION PPROCESSINFO;
   SECURITY_ATTRIBUTES SECURITYATTR;

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

   if(!CreatePipe(&PARENT_READ,&CMD_WRITE, &SECURITYATTR,0)){
       printf("无法创建管道");
       return EXIT_FAILURE;
   }
   printf("CreatePipe(PARENT_READ, CMD_WRITE) -  成功!\n");
   
   if(!CreatePipe(&CMD_READ,&PARENT_WRITE, &SECURITYATTR,0)){
      printf("无法创建管道");
      return EXIT_FAILURE;
   }
   printf("CreatePipe(CMD_READ, PARENT_WRITE) - 成功!\n");

   ZeroMemory(&PSTARTUPINFO, sizeof(STARTUPINFO));
   printf("ZeroMemory(&PSTARTUPINFO, sizeof(STARTUPINFO) -  清零 STARTUPINFO 结构成功!\n");
   
   PSTARTUPINFO.cb = sizeof(STARTUPINFO);
   PSTARTUPINFO.hStdOutput = CMD_WRITE;
   printf("CMD_WRITE ---> %x\n", CMD_WRITE);
   printf("STARTINFO.hStdOutput ---> %x\n", PSTARTUPINFO.hStdOutput);
   PSTARTUPINFO.hStdInput = CMD_READ;
   printf("CMD_READ ---> %x\n", CMD_READ);
   printf("STARTINFO.hStdInput ---> %x\n", PSTARTUPINFO.hStdInput);
   PSTARTUPINFO.dwFlags |= STARTF_USESTDHANDLES;
   PSTARTUPINFO.dwFlags |= STARTF_USESHOWWINDOW;
   PSTARTUPINFO.wShowWindow = SW_SHOWNORMAL;
   BOOL success = CreateProcessW(L"C:\\Windows\\System32\\cmd.exe",
                      NULL,
                      NULL,
                      NULL,
                      TRUE,
                      NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
                      NULL,
                      NULL,
                      &PSTARTUPINFO,
                      &PPROCESSINFO);
   if(!success){
      printf("CreateProcessW() --> 无法创建进程!\n");
      printf("[-] 关闭程序");
      return EXIT_FAILURE;
   }
   
   printf("C:\\Windows\\System32\\cmd.exe 启动,PID ---> %i\n", PPROCESSINFO.dwProcessId);

   HANDLE hThread = CreateThread(NULL, 0, ReadPipe, NULL, 0, &ThreadID);
   if(hThread == NULL){
      printf("CreateThread() --> 失败,返回 %i\n", GetLastError());
      return EXIT_FAILURE;
   }
   printf("CreateThread() --> 创建新线程,TID --> %i\n", ThreadID);
   Sleep(2000);
      
   while(TRUE){   
      char cmd[256];
      printf("提示&gt; ");
      gets(cmd);
      WriteFile(PARENT_WRITE, cmd, strlen(cmd), &bytes_written, NULL);
      printf("WriteFile() --> 写入 %i 字节\n", bytes_written);
   }
   
   hProcessCMD = PPROCESSINFO.hProcess;
   switch (WaitForSingleObject(hProcessCMD, INFINITE))
   {
   case WAIT_ABANDONED :
      printf("WaitForSingleObject(hProcess, Timeout) ---> 返回 WAIT_ABANDONED\n");
      break;
   case WAIT_OBJECT_0:
      printf("WaitForSingleObject(hProcess, Timeout) ---> 指定对象的状态已标志 (进程已终止)\n");
      break;
   case WAIT_TIMEOUT:
      printf("WaitForSingleObject(hProcess, Timeout) ---> 返回 WAIT_TIMEOUT\n");
      break;
   case WAIT_FAILED:
      printf("WaitForSingleObject(hProcess, Timeout) ---> 失败,返回 %i\n", GetLastError());
      break;
   default:
      break;
   }
   
   handle_cleanup(PSTARTUPINFO, PPROCESSINFO);
   return EXIT_SUCCESS;
}

int main(void){

   printf("父进程 PID -------> %u\n", GetCurrentProcessId());
   if(CreateProcessCMD()){
      printf("CreateProcessCMD() - 函数返回 EXIT_FAILURE\n");
      return EXIT_FAILURE;
   }
   return EXIT_SUCCESS;
}

void handle_cleanup(STARTUPINFOW startupinfo,  PROCESS_INFORMATION  processinfo ){
    if(!CloseHandle(startupinfo.hStdInput)) printf("[-] 无法关闭标准输入句柄\n");
    if(!CloseHandle(startupinfo.hStdOutput)) printf("[-] 无法关闭标准输出句柄\n");
    if(!CloseHandle(startupinfo.hStdError)) printf("[-] 无法关闭标准错误句柄\n");
    if(!CloseHandle(processinfo.hProcess)) printf("[-] 无法关闭进程句柄\n");
    if(!CloseHandle(processinfo.hThread)) printf("[-] 无法关闭线程句柄\n");
}


DWORD  WINAPI ReadPipe(LPVOID lpThreadParameter){
     char buffer[BUFFER_LENGTH];
     
     DWORD bytes_read_from_pipe;
     while(TRUE) {
        int ret = ReadFile(PARENT_READ, buffer, BUFFER_LENGTH, &bytes_read_from_pipe, NULL);
        printf("ReadFile() --> 读取 %i\n", bytes_read_from_pipe);
        if(bytes_read_from_pipe>0){
           printf("%s\n", buffer);
           ZeroMemory(buffer, BUFFER_LENGTH);
           bytes_read_from_pipe = 0;
           continue;
        }
        break;
   }
}

至于你的输出问题,确保 cmd.exe 的输出通过 PARENT_READ 管道写入。你可以尝试添加更多的调试语句来查看问题所在。希望这有助于解决你的问题。如果你需要更多帮助,请随时提问。

英文:

I am trying to write a program that supplies input to cmd.exe and retrieve it's output through the use of pipes.(2 Sets of pipes). However after supplying input through PARENT_WRITE I get no output through the other pipe, PARENT_READ. Here's the code:

#include &lt;stdio.h&gt;
#include &lt;windows.h&gt;    
#define BUFFER_LENGTH 1024
void handle_cleanup(STARTUPINFOW,  PROCESS_INFORMATION);
DWORD WINAPI ReadPipe(LPVOID);
HANDLE CMD_WRITE, PARENT_READ, CMD_READ, PARENT_WRITE;
int CreateProcessCMD(void){
DWORD ThreadID;
DWORD bytes_written;
HANDLE hProcessCMD;
STARTUPINFOW PSTARTUPINFO;
PROCESS_INFORMATION PPROCESSINFO;
SECURITY_ATTRIBUTES SECURITYATTR;
SECURITYATTR.nLength = sizeof(SECURITY_ATTRIBUTES);
SECURITYATTR.bInheritHandle = TRUE;
SECURITYATTR.lpSecurityDescriptor = NULL;
if(!CreatePipe(&amp;PARENT_READ,&amp;CMD_WRITE, &amp;SECURITYATTR,0)){
printf(&quot;Could not create pipe&quot;);
return EXIT_FAILURE;
}
printf(&quot;CreatePipe(PARENT_READ, CMD_WRITE) -  Success!\n&quot;);
if(!CreatePipe(&amp;CMD_READ,&amp;PARENT_WRITE, &amp;SECURITYATTR,0)){
printf(&quot;Could not create pipe&quot;);
return EXIT_FAILURE;
}
printf(&quot;CreatePipe(CMD_READ, PARENT_WRITE) - Success!\n&quot;);
ZeroMemory(&amp;PSTARTUPINFO, sizeof(STARTUPINFO));
printf(&quot;ZeroMemory(&amp;PSTARTUPINFO, sizeof(STARTUPINFO) -  Zeroing STARTUPINFO structure success!\n&quot;);
PSTARTUPINFO.cb = sizeof(STARTUPINFO);
PSTARTUPINFO.hStdOutput = CMD_WRITE;
printf(&quot;CMD_WRITE ---&gt; %x\n&quot;, CMD_WRITE);
printf(&quot;STARTINFO.hStsOutput ---&gt; %x\n&quot;, PSTARTUPINFO.hStdOutput);
PSTARTUPINFO.hStdInput = CMD_READ;
printf(&quot;CMD_READ ---&gt; %x\n&quot;, CMD_READ);
printf(&quot;STARTINFO.hStdsInput ---&gt; %x\n&quot;, PSTARTUPINFO.hStdInput);
PSTARTUPINFO.dwFlags |= STARTF_USESTDHANDLES;
PSTARTUPINFO.dwFlags |= STARTF_USESHOWWINDOW;
PSTARTUPINFO.wShowWindow = SW_SHOWNORMAL;
BOOL success = CreateProcessW(L&quot;C:\\Windows\\System32\\cmd.exe&quot;,
NULL,
NULL,
NULL,
TRUE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
NULL,
NULL,
&amp;PSTARTUPINFO,
&amp;PPROCESSINFO);
if(!success){
printf(&quot;CreateProcessW() --&gt; Could not create process!\n&quot;);
printf(&quot;[-] Closing program&quot;);
return EXIT_FAILURE;
}
printf(&quot;C:\\Windows\\System32\\cmd.exe started with PID ---&gt; %i\n&quot;, PPROCESSINFO.dwProcessId);
HANDLE hThread = CreateThread(NULL, 0, ReadPipe, NULL, 0, &amp;ThreadID);
if(hThread == NULL){
printf(&quot;CreateThread() --&gt; Failed, Returned %i\n&quot;, GetLastError());
return EXIT_FAILURE;
}
printf(&quot;CreateThread() --&gt; New thread created with TID --&gt; %i\n&quot;, ThreadID);
Sleep(2000);
while(TRUE){   
char cmd[256];
printf(&quot;Prompt&gt; &quot;);
gets(cmd);
WriteFile(PARENT_WRITE, cmd, strlen(cmd), &amp;bytes_written, NULL);
printf(&quot;WriteFile() --&gt; Wrote %i bytes\n&quot;, bytes_written);
}
hProcessCMD = PPROCESSINFO.hProcess;
switch (WaitForSingleObject(hProcessCMD, INFINITE))
{
case WAIT_ABANDONED :
printf(&quot;WaitForSingleObject(hProcess, Timeout) ---&gt; Returned WAIT_ABANDONED\n&quot;);
break;
case WAIT_OBJECT_0:
printf(&quot;WaitForSingleObject(hProcess, Timeout) ---&gt; The state of the specified object is signaled (Process has terminated)\n&quot;);
break;
case WAIT_TIMEOUT:
printf(&quot;WaitForSingleObject(hProcess, Timeout) ---&gt; Returned WAIT_TIMEOUT\n&quot;);
break;
case WAIT_FAILED:
printf(&quot;WaitForSingleObject(hProcess, Timeout) ---&gt; Failed, Returned &amp;i\n&quot;, GetLastError());
break;
default:
break;
}
handle_cleanup(PSTARTUPINFO, PPROCESSINFO);
return EXIT_SUCCESS;
}
int main(void){
printf(&quot;Parent PID ------&gt; %u\n&quot;, GetCurrentProcessId());
if(CreateProcessCMD()){
printf(&quot;CreateProcessCMD() - Function returned EXIT_FAILURE\n&quot;);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
void handle_cleanup(STARTUPINFOW startupinfo,  PROCESS_INFORMATION  processinfo ){
if(!CloseHandle(startupinfo.hStdInput)) printf(&quot;[-] Could not close stdin handle\n&quot;);
if(!CloseHandle(startupinfo.hStdOutput)) printf(&quot;[-] Could not close stdout handle\n&quot;);
if(!CloseHandle(startupinfo.hStdError)) printf(&quot;[-] Could not close stderr handle\n&quot;);
if(!CloseHandle(processinfo.hProcess)) printf(&quot;[-] Could not close process handle\n&quot;);
if(!CloseHandle(processinfo.hThread)) printf(&quot;[-] Could not close thread handle\n&quot;);
}
DWORD  WINAPI ReadPipe(LPVOID lpThreadParameter){
char buffer[BUFFER_LENGTH];
DWORD bytes_read_from_pipe;
while(TRUE) {
int ret = ReadFile(PARENT_READ, buffer, BUFFER_LENGTH, &amp;bytes_read_from_pipe, NULL);
printf(&quot;ReadFile() --&gt; Read %i\n&quot;, bytes_read_from_pipe);
if(bytes_read_from_pipe&gt;0){
printf(&quot;%s\n&quot;, buffer);
ZeroMemory(buffer, BUFFER_LENGTH);
bytes_read_from_pipe = 0;
continue;
}
break;
}
}

And the output:

Parent PID ------&gt; 12064
CreatePipe(PARENT_READ, CMD_WRITE) -  Success!
CreatePipe(CMD_READ, PARENT_WRITE) - Success!
ZeroMemory(&amp;PSTARTUPINFO, sizeof(STARTUPINFO) -  Zeroing STARTUPINFO structure success!
CMD_WRITE ---&gt; 100
STARTINFO.hStsOutput ---&gt; 100
CMD_READ ---&gt; 104
STARTINFO.hStdsInput ---&gt; 104
C:\Windows\System32\cmd.exe started with PID ---&gt; 8700
CreateThread() --&gt; New thread created with TID --&gt; 16680
ReadFile() --&gt; Read 43
Microsoft Windows [Version ...]
ReadFile() --&gt; Read 89
(c) Microsoft Corporation. All rights reserved.
C:\Users\&lt;USER&gt;\Sandbox\&gt;
Prompt&gt; where calc.exe
WriteFile() --&gt; Wrote 14 bytes
Prompt&gt;
WriteFile() --&gt; Wrote 0 bytes

I seem to be able to write to it and cannot seem to be able to retrieve any output, ReadFile() Simple hangs

I am fairly new to the Windows API

答案1

得分: 1

如Hans Passant所说,你忘记了写回车键的按下。

在添加了这个之后:

Using Pipes for bidirectional communication(Windows API)

strcat_s(cmd, "\r\n");

它将正常工作。

Using Pipes for bidirectional communication(Windows API)

英文:

As Hans Passant said, you forgot to write the Enter key press.

After adding this:

Using Pipes for bidirectional communication(Windows API)

strcat_s(cmd, &quot;\r\n&quot;);

it will work fine.

Using Pipes for bidirectional communication(Windows API)

huangapple
  • 本文由 发表于 2023年5月17日 21:48:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76272852.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定