Windows下的进程隐藏

9X环境中Windows提供了想光的API函数用于隐藏系统进程。但是到了2000以上系统,已经无法真正的做到对于进程的隐藏,除非编写底层驱动。但是我们可以通过一些变通的办法来达到隐藏进程的目的,其中一个就是远程注入。简单的说就是先编写一个API的DLL,然后将这个DLL库注入到一个系统进程中,作为它的一个线程去执行。
要实现DLL注入,首先需要打开目标进程。
hRemoteProcess = OpenProcess( PROCESS_CREATE_THREAD | //允许远程创建线程
    PROCESS_VM_OPERATION | //允许远程VM操作
    PROCESS_VM_WRITE, //允许远程VM写
    FALSE, dwRemoteProcessId )
由于我们后面需要写入远程进程的内存地址空间并建立远程线程,所以需要申请足够的权限(PROCESS_CREATE_THREAD、VM_OPERATION、VM_WRITE)。
如果进程打不开,以后的操作就别想了。进程打开后,就可以建立远线程了,不过别急,先想想这个远线程的线程函数是什么?我们的目的是注入一个DLL。而且我们知道用LoadLibrary可以加载一个DLL到本进程的地址空间。于是,自然会想到如果可以在目标进程中调用LoadLibrary,不就可以把DLL加载到目标进程的地址空间了吗?对!就是这样。远线程就在这儿用了一次,建立的远线程的线程函数就是LoadLibrary,而参数就是要注入的DLL的文件名。(这里需要自己想一想,注意到了吗,线程函数ThreadProc和LoadLibrary函数非常相似,返回值,参数个数都一样) 还有一个问题,LoadLibrary这个函数的地址在哪儿?也许你会说,这个简单,GetProcAddress就可以得出。于是代码就出来了。
char *pszLibFileRemote="my.dll";
PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA");
CreateRemoteThread( hRemoteProcess, NULL, 0, pfnStartAddr, pszLibFileRemote, 0, NULL);
    但是不对!不要忘了,这是远线程,不是在你的进程里,而pszLibFileRemote指向的是你的进程里的数据,到了目标进程,这个指针都不知道指向哪儿去了,同样pfnStartAddr这个地址上的代码到了目标进程里也不知道是什么了,不知道是不是你想要的LoadLibraryA了。但是,问题总是可以解决的,Windows有些很强大的API函数,他们可以在目标进程里分配内存,可以将你的进程中的数据拷贝到目标进程中。因此pszLibFileRemote的问题可以解决了。
char *pszLibFileName="my.dll";//注意,这个一定要是全路径文件名,除非它在系统目录里;原因大家自己想想。
//计算DLL路径名需要的内存空间
int cb = (1 + lstrlenA(pszLibFileName)) * sizeof(char);
//使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名缓冲区
pszLibFileRemote = (char *) VirtualAllocEx( hRemoteProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
//使用WriteProcessMemory函数将DLL的路径名复制到远程进程的内存空间
iReturnCode = WriteProcessMemory(hRemoteProcess, pszLibFileRemote, (PVOID) pszLibFileName, cb, NULL);
    OK,现在目标进程也认识pszLibFileRemote了,但是pfnStartAddr好像不好办,我怎么可能知道LoadLibraryA在目标进程中的地址呢?其实Windows为我们解决了这个问题,LoadLibraryA这个函数是在Kernel32.dll这个核心DLL里的,而这个DLL很特殊,不管对于哪个进程,Windows总是把它加载到相同的地址上去。因此你的进程中LoadLibraryA的地址和目标进程中LoadLibraryA的地址是相同的(其实,这个DLL里的所有函数都是如此)。至此,DLL注入结束了。
 
但是目前还有一个问题,上面的方法是无法将DLL注入到系统进程中去的,原因是进程级别不够。那么我们就要提升注入程序的进程级别。使用下面的函数:
void EnableDebugPriv( void )
{
 HANDLE hToken;
 LUID sedebugnameValue;
 TOKEN_PRIVILEGES tkp;
 if ( ! OpenProcessToken( GetCurrentProcess(),
  TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
  return;
 if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) ){
  CloseHandle( hToken );
  return;
 }
 tkp.PrivilegeCount = 1;
 tkp.Privileges[0].Luid = sedebugnameValue;
 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
  CloseHandle( hToken );
}
 
 
 
最后我们来做一个简单的例子:
首先编写注入程序的代码
// DLLAdd.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "winnt.h"
void EnableDebugPriv();
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 EnableDebugPriv();
  // TODO: Place code here.
 HANDLE hRemoteProcess;
 HANDLE hRemoteThread;
 //PWSTR pszLibFileRemote;
 //LPCWSTR pszLibFileName;
 BOOL iReturnCode;
 char *pszLibFileRemote="RemoteDLL.dll";
 char *pszLibFileName="C://RemoteDLL.dll";//注意,这个一定要是全路径文件名,除非它在系统目录里
 hRemoteProcess = OpenProcess(PROCESS_CREATE_THREAD
        |PROCESS_VM_OPERATION
        |PROCESS_VM_WRITE,
        FALSE,0x3E0);//0x3E0是进程的id,测试时是explorer的进程id,可以用spy++去查找。
 //计算DLL路径名需要的内存空间
 int cb = (1 + lstrlenA(pszLibFileName)) * sizeof(char);
 //使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名缓冲区
 pszLibFileRemote = (char *) VirtualAllocEx(hRemoteProcess, NULL, cb,
            MEM_COMMIT, PAGE_READWRITE);
 //使用WriteProcessMemory函数将DLL的路径名复制到远程进程的内存空间
 iReturnCode = WriteProcessMemory(hRemoteProcess,
    pszLibFileRemote, (PVOID) pszLibFileName, cb, NULL);
 //计算LoadLibraryW的入口地址
 PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)
          GetProcAddress(GetModuleHandle(TEXT("Kernel32")),
          "LoadLibraryA");
 //启动远程线程LoadLibraryW,通过远程线程调用用户的DLL文件
 hRemoteThread = CreateRemoteThread( hRemoteProcess, NULL, 0,
          pfnStartAddr, pszLibFileRemote, 0, NULL);

 return 0;
}
 
//提升权限
void EnableDebugPriv( void )
{
 HANDLE hToken;
 LUID sedebugnameValue;
 TOKEN_PRIVILEGES tkp;
 if ( ! OpenProcessToken( GetCurrentProcess(),
  TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
  return;
 if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) ){
  CloseHandle( hToken );
  return;
 }
 tkp.PrivilegeCount = 1;
 tkp.Privileges[0].Luid = sedebugnameValue;
 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
  CloseHandle( hToken );
}
 
 

然后编写需要注入的DLL的代码

#include "stdafx.h"
#include "winnt.h"
#include <stdlib.h>
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
 char szProcessId[64];
 int i=1;
 switch(ul_reason_for_call)
 {
 case DLL_PROCESS_ATTACH:
  {
   _itoa(GetCurrentProcessId(),szProcessId,10);
   MessageBox(NULL,szProcessId,"RemoteDLL",MB_OK);
  }
 default:
  return TRUE;
 }
}
 
将编译好的dll放到C盘根目录下面运行注入程序。我们可以发现弹出了一个标示了被注入进程id的对话框。
 
如上,只要我们再dll中编写我们需要的代码,就可以隐秘的在电脑里执行我们需要的事情。
 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值