鱼C论坛

 找回密码
 立即注册
查看: 2261|回复: 2

[技术交流] 管道学习(一)

[复制链接]
发表于 2015-7-5 12:54:55 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
0x00
环境:win7 & VC++6.0
管道是一种特殊的进程,通常我们使用它进行线程之间的通信。管道是单向的,也就说管道中的数据传递方向只能是一个方向。
1.下面给出创建管道的函数原型:
  1. BOOL WINAPI CreatePipe(
  2.   _Out_    PHANDLE               hReadPipe,
  3.   _Out_    PHANDLE               hWritePipe,
  4.   _In_opt_ LPSECURITY_ATTRIBUTES lpPipeAttributes,
  5.   _In_     DWORD                 nSize
  6. );
复制代码

hReadPipe :管道读句柄
hWritePipe :管道写句柄
lpPipeAttributes:确定返回的句柄是否可以被子进程继承
nSize:管道缓冲区大小,如果设置为0,则使用系统默认值

2.管道的读写可以使用ReadFile和WriteFile两个函数:
  1. BOOL WINAPI ReadFile(
  2.   _In_        HANDLE       hFile,
  3.   _Out_       LPVOID       lpBuffer,
  4.   _In_        DWORD        nNumberOfBytesToRead,
  5.   _Out_opt_   LPDWORD      lpNumberOfBytesRead,
  6.   _Inout_opt_ LPOVERLAPPED lpOverlapped
  7. );

  8. BOOL WINAPI WriteFile(
  9.   _In_        HANDLE       hFile,
  10.   _In_        LPCVOID      lpBuffer,
  11.   _In_        DWORD        nNumberOfBytesToWrite,
  12.   _Out_opt_   LPDWORD      lpNumberOfBytesWritten,
  13.   _Inout_opt_ LPOVERLAPPED lpOverlapped
  14. );
复制代码

将文件句柄改成管道句柄就可以实现管道读写。

0x01
双管道实现读写。我们建立两个管道,一个管道循环读,一个管道循环写。
RTX截图未命名.png

我们本地端通过socket连接到远程端的一个Win32 Console Application程序,该远程端程序中实现一个Winsock和一对读写管道链接到cmd。
首先来建立两个线程函数,分别实现管道读写。
  1. DWORD WINAPI ThreadWrite(LPVOID lpParam){
  2.         SECURITY_ATTRIBUTES sa;
  3.         sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  4.         sa.lpSecurityDescriptor = NULL;
  5.         sa.bInheritHandle = TRUE;

  6.         DWORD nByteToWrite, nByteWritten;
  7.         char recv_buff[1024];

  8.         //create a pipe
  9.         CreatePipe(&hReadPipe, &hWriteFile, &sa, 0);
  10.         while(true){
  11.                 Sleep(250);
  12.                
  13.                 //recv client host's command
  14.                 nByteToWrite = recv(sClient, recv_buff, 1024, 0);

  15.                 //Write the pipe
  16.                 WriteFile(hWriteFile, recv_buff, nByteToWrite, &nByteWritten, NULL);
  17.         }
  18.         return 0;
  19. }

  20. DWORD WINAPI ThreadRead(LPVOID lpParam){

  21.         SECURITY_ATTRIBUTES sa;
  22.         sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  23.         sa.lpSecurityDescriptor = NULL;
  24.         sa.bInheritHandle = TRUE;

  25.         DWORD len;
  26.         char send_buff[2048];

  27.         CreatePipe(&hReadFile, &hWritePipe, &sa, 0);
  28.         while(true){
  29.                 // read data from the pipe
  30.                 ReadFile(hReadFile, send_buff, 2048, &len, NULL);
  31.                
  32.                 //send data to client host
  33.                 send(sClient, send_buff, len, 0);
  34.         }

  35.         return 0;
  36. }
复制代码

0x02
接下来我们启动一个cmd进程,可以使用函数:
  1. BOOL WINAPI CreateProcess(
  2.   _In_opt_    LPCTSTR               lpApplicationName,
  3.   _Inout_opt_ LPTSTR                lpCommandLine,
  4.   _In_opt_    LPSECURITY_ATTRIBUTES lpProcessAttributes,
  5.   _In_opt_    LPSECURITY_ATTRIBUTES lpThreadAttributes,
  6.   _In_        BOOL                  bInheritHandles,
  7.   _In_        DWORD                 dwCreationFlags,
  8.   _In_opt_    LPVOID                lpEnvironment,
  9.   _In_opt_    LPCTSTR               lpCurrentDirectory,
  10.   _In_        LPSTARTUPINFO         lpStartupInfo,
  11.   _Out_       LPPROCESS_INFORMATION lpProcessInformation
  12. );
复制代码

但我们得将该cmd进程与我们的管道相关联,这样管道和cmd之间才能传输数据。实现它们的管理,可以在CreateProcess函数的倒数第二个参数LPSTARTUPINFO中设置,这个结构体如下:
  1. typedef struct _STARTUPINFO {
  2.   DWORD  cb;
  3.   LPTSTR lpReserved;
  4.   LPTSTR lpDesktop;
  5.   LPTSTR lpTitle;
  6.   DWORD  dwX;
  7.   DWORD  dwY;
  8.   DWORD  dwXSize;
  9.   DWORD  dwYSize;
  10.   DWORD  dwXCountChars;
  11.   DWORD  dwYCountChars;
  12.   DWORD  dwFillAttribute;
  13.   DWORD  dwFlags;
  14.   WORD   wShowWindow;
  15.   WORD   cbReserved2;
  16.   LPBYTE lpReserved2;
  17.   HANDLE hStdInput;
  18.   HANDLE hStdOutput;
  19.   HANDLE hStdError;
  20. } STARTUPINFO, *LPSTARTUPINFO;
复制代码

成员很多,一个一个地去填写,很麻烦,我们可以使用一个函数返回本进程的STARTUPINFO信息,然后我们再修改一些参数以实现它与管道相关联。
  1. VOID WINAPI GetStartupInfo(
  2.   _Out_ LPSTARTUPINFO lpStartupInfo
  3. );
复制代码
STARTUPINFO中需要修改的参数:
  1. dwFlags=STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // enable
  2. hStdInput = hReadPipe; //read data from ThreadWrite pipe
  3. hStdError = hWritePipe; //write data to ThreadRead pipe
  4. hStdOutput = hWritePipe;
  5. wShowWindow = SW_HIDE; //hide cmd window
复制代码


0x03
下面给出全部的code:

这里应该是有代码的,,但鉴于上面的排版全乱了,那么给出一个word版的附件,排版稍微好点。
管道学习(一).zip (11.17 KB, 下载次数: 2)

0x04
将它在远程机上运行,作者测试使用自己的虚拟机(192.168.0.8),然后在本地启用一个telnet:
telnet 192.168.0.8 4500
这样在本地机上会得到一个shell,直接可以操控远程机。

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-7-5 12:55:49 | 显示全部楼层
我还以为排版乱了,,结果没乱,,下次直接code了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-7-5 14:06:30 | 显示全部楼层
管道有什么作用呢     
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-20 08:28

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表