17.1 隐藏执行CMD命令
本章内容涉及使用Socket API和CMD命令行工具实现本地CMD命令执行、无管道正向CMD和无管道反向CMD三种功能。执行本地CMD实现使用CreateProcess函数创建一个新的CMD进程,并将标准输入、输出和错误输出重定向到当前进程的标准输入、输出和错误输出。无管道正向CMD和无管道反向CMD使用WSASocket函数创建TCP套接字,并将CMD进程的标准输入、输出和错误输出重定向到套接字的句柄上,通过网络连接实现远程命令执行功能。
首先来实现一个CMD命令行运行功能,通过使用CreatePipe创建匿名管道,并使用CreateProcess函数创建一个新的CMD进程,然后将标准输入、输出和错误输出重定向到当前进程的标准输入、输出和错误输出。这样就可以通过当前进程的输入输出来执行CMD命令并获取命令输出结果。
CreatePipe 函数,用于创建一个匿名管道。匿名管道是一种用于进程间通信的机制,允许一个进程将输出数据传输给另一个进程。CreatePipe函数的原型如下:
BOOL CreatePipe(
PHANDLE hReadPipe,
PHANDLE hWritePipe,
LPSECURITY_ATTRIBUTES lpPipeAttributes,
DWORD nSize
);
参数hReadPipe和hWritePipe是指向HANDLE类型的指针,用于接收创建的管道的读端和写端的句柄。参数lpPipeAttributes是一个指向SECURITY_ATTRIBUTES结构体的指针,用于设置管道的安全性。参数nSize是一个DWORD类型的值,用于指定管道的缓冲区大小,通常可以设置为0表示使用系统默认值。
创建匿名管道后,可以使用ReadFile函数从管道的读端读取数据,使用WriteFile函数将数据写入管道的写端。在使用完管道后,应使用CloseHandle函数关闭管道的句柄,以释放资源。
CreateProcess 函数可以创建一个新的进程,并为该进程分配内存空间、初始化环境变量、创建主线程等。其中,参数lpApplicationName用于指定需要执行的可执行文件名,参数lpCommandLine用于指定命令行参数。如果lpApplicationName参数为NULL,则系统会自动使用lpCommandLine参数指定的命令行来创建进程。
该函数原型如下:
BOOL CreateProcess(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
该函数可以创建包括控制台窗口的进程。如果需要使用CreateProcess()函数创建不带控制台窗口的进程,则需要在dwCreationFlags参数中指定CREATE_NO_WINDOW标志位。
在创建进程时,可以通过STARTUPINFO结构体设置进程的一些属性,例如标准输入、标准输出和标准错误输出的重定向,启动窗口的显示方式等。同时,CreateProcess()函数会返回一个PROCESS_INFORMATION结构体,其中包含新进程的句柄和ID等信息。
如下RunCommand函数所示,该函数传入一个字符串类型的命令参数,并返回一个字符串执行结果,在函数内部,使用 CreatePipe() 函数创建了一个匿名管道,并使用 CreateProcess() 函数启动了一个新的 CMD 进程并将其标准输出和错误输出重定向到管道的写入端。接着使用 ReadFile() 函数从管道的读取端读取输出数据,并将读取到的数据存储到一个缓冲区中。最后,它将缓冲区的内容拼接成一个完整的输出结果返回给调用者。
// 以隐藏方式执行CMD命令
BOOL RunCommand(char* cmdStr, char* message)
{
DWORD readByte = 0;
// 执行命令行
char command[1024] = { 0 };
// 缓冲区
char buf[8192] = { 0 };
HANDLE hRead, hWrite;
// 启动配置信息
STARTUPINFO si;
// 进程信息
PROCESS_INFORMATION pi;
// 管道安全属性
SECURITY_ATTRIBUTES sa;
// 拼接CMD命令
sprintf(command, "cmd.exe /c %s", cmdStr);
// printf("-- CMD 命令: [%s]n", command);
// 配置管道安全属性
sa.nLength = sizeof(sa);
// 管道句柄可被继承
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
// 创建匿名管道,管道句柄是可被继承的
if (!CreatePipe(&hRead, &hWrite, &sa, 1024))
{
// printf("管道创建失败 %xn", (unsigned int)GetLastError());
return FALSE;
}
// 配置 cmd 启动信息
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si); // 获取兼容大小
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; // 标准输出等使用额外的
si.wShowWindow = SW_HIDE; // 隐藏窗口启动
si.hStdOutput = si.hStdError = hWrite; // 输出流和错误流指向管道写的一头
// 创建子进程,运行命令,子进程是可继承的
if (!CreateProcess(
NULL, // 不传程序路径, 使用命令行
command, // 命令行命令
NULL, // 不继承进程句柄(默认)
NULL, // 不继承线程句柄(默认)
TRUE, // 继承句柄
0, // 没有创建标志(默认)
NULL, // 使用默认环境变量
NULL, // 使用父进程的目录
&si, // STARTUPINFO 结构存储启动信息
&pi)) // PROCESS_INFORMATION 保存启动后的进程相关信息
{
// printf("创建进程失败 %x \n", (unsigned int)GetLastError());
CloseHandle(hRead);
CloseHandle(hWrite);
return FALSE;
}
CloseHandle(hWrite);
/*
管道的 write 端句柄已被 cmd 的输出流和错误流继承,即 cmd 输出时会把数据写入管道。
我们通过读取管道的 read 端,就可以获得 cmd 的输出
*/
while (ReadFile(hRead, buf, 8192, &readByte, NULL))
{
strcat(message, buf);
ZeroMemory(buf, 8192);
}
//printf("-- [CMD] Message: [%s] Length:%d n", message, strlen(message) + 1);
CloseHandle(hRead);
return TRUE;
}
上述函数的调用非常容易,我们以执行ipconfig函数为例,调用案例为RunCommand((char*)"ipconfig", szBuffer),函数执行命令ipconfig参数,并将返回值存储值szBuffer变量内,输出效果图如下所示;

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/4fefd4fc.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
17.1 隐藏执行CMD命令的更多相关文章
- [转]Delphi执行CMD命令
今天看到有人在问用代码执行CMD命令的问题,就总结一下用法,也算做个备忘. Delphi中,执行命令或者运行一个程序有2个函数,一个是winexec,一个是shellexecute.这两个大家应该都见 ...
- 如何使用Java执行cmd命令
用JAVA代码实现执行CMD命令的方法! Runtime rt = Runtime.getRuntime(); Process p = rt.exec(String[] cmdarray); ...
- Java 调用并执行cmd命令
cmd java 调用 执行 概要: Java 调用并执行cmd命令 Java | 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 2 ...
- JAVA之执行cmd命令
感言在前:时隔好久没有更新博客园了,忙东忙西也没忙出个什么之所以然来.回首过去一两个月,只能用“疲倦”两个字来形容,而且是身心疲惫.每天11.12个小时的工作我都没觉得烦,但是总是想克服却又很难克服的 ...
- C# 执行CMD 命令
/// <summary> /// 执行CMD 命令 /// </summary> /// <param name="strCommand">命 ...
- C# 执行CMD命令的方法
/// <summary> /// 执行CMD命令 /// </summary> /// <param name="str"></para ...
- java执行cmd命令并获取输出结果
1.java执行cmd命令并获取输出结果 import java.io.BufferedReader; import java.io.InputStreamReader; import org.apa ...
- Atitit.执行cmd 命令行 php
Atitit.执行cmd 命令行 php 1. 执行cmd 命令行,调用系统命令的基础 1 1.1. 实际执行模式 1 1.2. 空格的问题 1 1.3. 中文路径的问题,程序文件读取编码设置 1 1 ...
- node执行cmd命令方法
var cmd='tasklist';//获取 子进程模块的exec方法,用于执行cmd命令var exec = require('child_process').exec; //运行 定义的cmd命 ...
- java中执行cmd命令
一.java执行cmd命令的三种方式:http://www.jb51.net/article/80829.htm 参考:https://www.cnblogs.com/zhufu9426/p/7928 ...
随机推荐
- ERP查询Q报表开发代码
一,按照一般ERP开发流程可参考ERP开发流程,直到下载程序. 当我们的查询页签存在栏位需要判断或者特殊处理时,在global中的自定义模组变数下添加,例如: 1 #add-point:自定義模組變數 ...
- 【WebSocket】多节点下WebSocket消息收发解决案例
单体Webscoket springboot版本: 2.1.1.RELEASE jdk: 1.8 示例代码 WebsocketServer @ServerEndpoint("/client/ ...
- freeswitch的mod_cdr_csv模块
概述 freeswitch是一款简单好用的VOIP开源软交换平台. 在语音呼叫的过程中,话单是重要的计价和结算依据,话单的产生需要稳定可靠,可回溯. fs中基本的话单模块mod_cdr_csv,可以满 ...
- hexo博客生成报错YAMLException: can not read a block mapping entry
报错信息: YAMLException: can not read a block mapping entry; a multiline key may not b --- title: [转]--I ...
- typedef和define有什么区别
typedef 和define 都是替一个对象取一个别名,以此增强程序的可读性,区别如下: 使用不用 define 定义后面不用加分号,并且它的别名在对象的前面 typedef需要加分号,并且它的别名 ...
- 2021-7-12 VUE的生命周期
挂载: beforeCreate created beforeMount mounted:el挂载到实例上时运行 更新: beforeUpdate updated 销毁: beforeDestory ...
- Django: Token分发
Django后台token分发 在settings.py中引入 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'd ...
- CSSRelated
CSS 几种常用的清除浮动方法 ️️️ 父级 div 定义伪类:after 和 zoom; /* 这个class名指的是需要清除浮动的父级 */ .clearfloat:after { display ...
- SpringSecurity1: spring boot web 样例快速体验
本文只讲操作实践,不讲原理,这样对于想快速搭建起一个基于SpringSecurity的Web项目的朋友们而言,比较友好.文章主要由两部分构成: 快速演示样例 所有账户和授权数据均基于内存,能在极短的时 ...
- Spring HandlerInterceptor工作机制
本文以一个通过正常注册拦截器流程注册拦截器失败的实际场景,来带领大家阅读源码,体会Spring的HandlerInterceptor拦截器整个工作流程 简单认识 org.springframework ...