天天看點

windows系統下遠端shell實作 C++

 1.實作一代碼

#include<Windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<string>
#include<string.h>

std::string ExeCmd(std::string pszCmd)
{
	// 建立匿名管道
	SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
	HANDLE hRead, hWrite;
	if (!CreatePipe(&hRead, &hWrite, &sa, 0))
	{
		return " \n";
	}

	// 設定指令行程序啟動資訊(以隐藏方式啟動指令并定位其輸出到hWrite
	STARTUPINFO si = { sizeof(STARTUPINFO) };
	GetStartupInfo(&si);
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	si.wShowWindow = SW_HIDE;
	si.hStdError = hWrite;
	si.hStdOutput = hWrite;

	// 啟動指令行
	PROCESS_INFORMATION pi;
	if (!CreateProcess(NULL, (LPSTR)pszCmd.c_str(), NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))
	{
		return "Cannot create process.\n";
	}

	// 立即關閉hWrite
	CloseHandle(hWrite);

	// 讀取指令行傳回值
	std::string strRetTmp;
	char buff[1024] = { 0 };
	DWORD dwRead = 0;

	strRetTmp.clear();
	while (ReadFile(hRead, buff, 1024, &dwRead, NULL)){	
		strRetTmp.append(buff);
		memset(buff, 0, sizeof(buff));
	}
	CloseHandle(hRead);

	return strRetTmp;
}


int main(int argc, char *argv[])
{

	while (1) 
	{
		char cmd_Str[1024];
		memset(cmd_Str, 0, sizeof(cmd_Str));

		printf("shell---->");
		gets_s(cmd_Str, sizeof(cmd_Str) - 1);

		std::string retStr = ExeCmd(cmd_Str);
		printf("%s\n", retStr.c_str());

	}

    return 0;
}
           

2.實作二代碼 

//RemoteShell.h

#pragma once
#include <iostream>
#include <windows.h>
#include<thread>

using namespace std;

class CPipe
{
private:
	HANDLE hpiperead = NULL;
	HANDLE hpipewrite = NULL; 
	HANDLE hpiperead2 = NULL;
	HANDLE hpipewrite2 = NULL;
	HANDLE hProHandle = NULL;
	HANDLE hThrLoop = NULL;
	HANDLE hThrisLoop = NULL;
	SECURITY_ATTRIBUTES ai;
	PROCESS_INFORMATION pi;
	STARTUPINFOA si;
	BOOL pipe = false;
	INT status = 1;  // 0 = 異常 1 = 正常 -1 = 錯誤 、
	string errorString;
public:
	void loop();
	void isloop(); 
	const BOOL isPipeOff() const;
	const INT getStatus() const;
	const string & getError() const;
	const BOOL sendCommand(const char *); 
	void setPipeOn(const BOOL);
	void setStatus(const INT, const char*);
	void setStatus(const INT);
	CPipe(char * str);
	~CPipe();
};

//RemoteShell.cpp

#include"RemoteShell.h"



DWORD __stdcall ThrPipeThreadRead(void *www)
{
	CPipe * pipe = (CPipe *)www;
	pipe->loop();
	return 0;
	//建立核心對象使用完之後一定記得關閉,有可能會産生記憶體洩露
}
DWORD __stdcall WaitPipe(void *www)
{
	CPipe * pipe = (CPipe *)www;
	pipe->isloop();
	return 0;
}


CPipe::CPipe(char * com)
{
	ai.nLength = sizeof(SECURITY_ATTRIBUTES);
	ai.bInheritHandle = true;
	ai.lpSecurityDescriptor = NULL;
	if (!CreatePipe(&hpiperead, &hpipewrite, &ai, 0))  //建立讀入管道
	{

		this->setStatus(-1, "[0x01]Read 流建立失效");
		return;
	}

	if (!CreatePipe(&hpiperead2, &hpipewrite2, &ai, 0))  //建立讀入管道
	{

		this->setStatus(-1, "[0x02]Write 流建立失效");
		return;
	}
	GetStartupInfoA(&si);    //擷取目前程序的STARTUPINFO
	si.cb = sizeof(STARTUPINFO);
	si.hStdError = hpipewrite;
	si.hStdOutput = hpipewrite;
	si.hStdInput = hpiperead2;
	si.wShowWindow = SW_SHOW;
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

	if (!(CreateProcessA(NULL, com, NULL, NULL, true, NULL, NULL, NULL, &si, &pi)))      //建立隐藏的CMD程序
	{
		this->setStatus(-1, "[0x03] CreateProcess函數執行出錯");
		return;
	}


	DWORD dwThread = FALSE;
	hThrLoop = CreateThread(NULL, 0, ThrPipeThreadRead, this, 0, &dwThread);//chuangjian
	if (hThrLoop == false) {
		this->setStatus(-1, "[0x11] 線程建立失敗 CreateThread LOOP 失敗");
		return;
	}
	hThrLoop = CreateThread(NULL, 0, WaitPipe, this, 0, &dwThread);//chuangjian
	if (hThrLoop == false) {
		this->setStatus(-1, "[0x12] 線程建立失敗 CreateThread ISLOOP失敗");
		return;
	}
}




CPipe::~CPipe()
{
	//建立核心對象使用完之後一定記得關閉,有可能會産生記憶體洩露
	this->setPipeOn(false);
	this->setStatus(-1);
	CloseHandle(hThrisLoop);
	CloseHandle(hThrLoop);
	CloseHandle(hpipewrite);
	CloseHandle(hpiperead);
	CloseHandle(hpiperead2);
	CloseHandle(hpipewrite2);
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

}
const INT CPipe::getStatus() const
{
	return this->status;
}

const string & CPipe::getError() const
{
	return this->errorString;
}

const BOOL CPipe::isPipeOff() const
{
	return pipe;
}

void CPipe::setPipeOn(const BOOL bools)
{
	this->pipe = bools;
}

void CPipe::setStatus(const INT status, const char * info)
{
	this->errorString = info;    //你說會不會有更好的指派方法?
	this->status = status;
}

void CPipe::setStatus(const INT status = 1)
{
	this->status = status;
}

const BOOL CPipe::sendCommand(const char * com)     //執行指令
{
	DWORD dwWrite = 0;
	char www[1024];
	memset(www, 0, sizeof(www));
	strcpy_s(www, com);
	strcat_s(www, "\r\n");
	return WriteFile(hpipewrite2, www, strlen(www), &dwWrite, NULL);
	//0x001C7796 處有未經處理的異常(在 ConsoleApplication2.exe 中):  0xC0000005:  讀取位置 0x0000000C 時發生通路沖突。
}

void CPipe::loop() {
	char outbuff[4096];        //輸出緩沖
	DWORD byteread;
	this->setPipeOn(true);
	while (true)
	{
		memset(outbuff, '\0', 4096);
		if (ReadFile(this->hpiperead, outbuff, 4095, &byteread, NULL) == NULL)
		{
			this->setPipeOn(false);
			break;
		}
		printf("%s", outbuff);
		memset(outbuff, '\0', 4096);
	}
	this->setPipeOn(false);
	std::cout << "Pipe Stoped!" << endl;
}

void CPipe::isloop()
{
	DWORD dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
	while (dwRet == WAIT_TIMEOUT)
	{
		dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
	}

	if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_ABANDONED)
	{
		this->setPipeOn(false);
		std::cout << "[END] Pipe Stoped!" << endl;
	}
}

//main.cpp

#include"RemoteShell.h"

using namespace std;

void read();
void Loop();

CPipe * pipe;


int Luncher()
{
	thread t1(read);
	thread t2(Loop);

	pipe = new CPipe((char *)"cmd.exe");
	t1.join();
	t2.join();
	return 0;
}
void read() {

	while (true) {
		char str[200];
		memset(str, 0, sizeof(str));
		gets_s(str);
		pipe->sendCommand(str);
	}
}

void Loop() {
	while (true)
	{
		Sleep(1000);
		if (pipe->getStatus() == -11)
		{
			cout << " ERROR " << endl;
			return;
		}
	}
}

int main(int argc, char *argv[])
{

	Luncher();

	return 0;
}