强行卸载DLL模块(转载)

卸载dll模块可以用于杀毒程序中


// 程序功能:结束进程中的一个模块。
// 程序日期:2006.10.8
// 程序说明:这个程序写于2003年,主要针对一些木马注入程序。以往结束远程注入木马(dll)时需要
// 结束进程,这个程序不用结束进程而直接结束单个DLL。结束后会出现一些问题,某些情况
//           下会导致整个进程异常,这是很正常的,例如结束了一个进程需要调用的DLL;或者结束后DLL
//           又被主进程加载,例如mfc42.dll。
// 程序原理:根据DLL地址范围找到进程用的DLL线程,结束这个线程即DLL。
// 调试参数:explorer.exe secur32.dll

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

#pragma warning(disable:4996)

#define OS_SDK 0

#define BUFSIZE 80

typedef enum _THREAD_INFORMATION_CLASS {

 ThreadBasicInformation,
 ThreadTimes,
 ThreadPriority,
 ThreadBasePriority,
 ThreadAffinityMask,
 ThreadImpersonationToken,
 ThreadDescriptorTableEntry,
 ThreadEnableAlignmentFaultFixup,
 ThreadEventPair,
 ThreadQuerySetWin32StartAddress,
 ThreadZeroTlsCell,
 ThreadPerformanceCount,
 ThreadAmILastThread,
 ThreadIdealProcessor,
 ThreadPriorityBoost,
 ThreadSetTlsArrayAddress,
 ThreadIsIoPending,
 ThreadHideFromDebugger

} THREAD_INFORMATION_CLASS, *PTHREAD_INFORMATION_CLASS;
typedef DWORD (CALLBACK* NTQUERYINFORMATIONTHREAD)(HANDLE,DWORD,PVOID,DWORD,PDWORD);

int GetVersionInfo()
{
 OSVERSIONINFOEX osvi;
 BOOL bOsVersionInfoEx;

 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
 // If that fails, try using the OSVERSIONINFO structure.

 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

 if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
 {
  osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
   return FALSE;
 }

 switch (osvi.dwPlatformId)
 {
  // Test for the Windows NT product family.
 case VER_PLATFORM_WIN32_NT:

  // Test for the specific product family.
  if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
   printf ("Microsoft Windows&nbsp;.NET Server&nbsp;2003 family, ");

  if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
   printf ("Microsoft Windows XP ");

  if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
   printf ("Microsoft Windows 2000 ");

  if ( osvi.dwMajorVersion <= 4 )
   printf("Microsoft Windows NT ");

  // Test for specific product on Windows NT 4.0 SP6 and later.
  if( bOsVersionInfoEx )
  {
#if OS_SDK
   // Test for the workstation type.
   if ( osvi.wProductType == VER_NT_WORKSTATION )
   {
    if( osvi.dwMajorVersion == 4 )
     printf ( "Workstation 4.0 " );
    else if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
     printf ( "Home Edition " );
    else
     printf ( "Professional " );
   }

   // Test for the server type.
   else if ( osvi.wProductType == VER_NT_SERVER )
   {
    if( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
    {
     if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
      printf ( "Datacenter Edition " );
     else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
      printf ( "Enterprise Edition " );
     else if ( osvi.wSuiteMask == VER_SUITE_BLADE )
      printf ( "Web Edition " );
     else
      printf ( "Standard Edition " );
    }

    else if( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
    {
     if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
      printf ( "Datacenter Server " );
     else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
      printf ( "Advanced Server " );
     else
      printf ( "Server " );
    }

    else  // Windows NT 4.0
    {
     if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
      printf ("Server 4.0, Enterprise Edition " );
     else
      printf ( "Server 4.0 " );
    }
   }
#endif
  }
  else  // Test for specific product on Windows NT 4.0 SP5 and earlier
  {
   HKEY hKey;
   char szProductType[BUFSIZE];
   DWORD dwBufLen=BUFSIZE;
   LONG lRet;

   lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
    "SYSTEM//CurrentControlSet//Control//ProductOptions",
    0, KEY_QUERY_VALUE, &hKey );
   if( lRet != ERROR_SUCCESS )
    return FALSE;

   lRet = RegQueryValueEx( hKey, "ProductType", NULL, NULL,
    (LPBYTE) szProductType, &dwBufLen);
   if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE) )
    return FALSE;

   RegCloseKey( hKey );

   if ( lstrcmpi( "WINNT", szProductType) == 0 )
    printf( "Workstation " );
   if ( lstrcmpi( "LANMANNT", szProductType) == 0 )
    printf( "Server " );
   if ( lstrcmpi( "SERVERNT", szProductType) == 0 )
    printf( "Advanced Server " );

   printf( "%d.%d ", osvi.dwMajorVersion, osvi.dwMinorVersion );
  }

  // Display service pack (if any) and build number.

  if( osvi.dwMajorVersion == 4 &&
   lstrcmpi( osvi.szCSDVersion, "Service Pack 6" ) == 0 )
  {
   HKEY hKey;
   LONG lRet;

   // Test for SP6 versus SP6a.
   lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
    "SOFTWARE//Microsoft//Windows NT//CurrentVersion//Hotfix//Q246009",
    0, KEY_QUERY_VALUE, &hKey );
   if( lRet == ERROR_SUCCESS )
    printf( "Service Pack 6a (Build %d)/n", osvi.dwBuildNumber & 0xFFFF );        
   else // Windows NT 4.0 prior to SP6a
   {
    printf( "%s (Build %d)/n",
     osvi.szCSDVersion,
     osvi.dwBuildNumber & 0xFFFF);
   }

   RegCloseKey( hKey );
  }
  else // Windows NT 3.51 and earlier or Windows 2000 and later
  {
   printf( "%s (Build %d)/n",
    osvi.szCSDVersion,
    osvi.dwBuildNumber & 0xFFFF);
  }


  break;

  // Test for the Windows 95 product family.
 case VER_PLATFORM_WIN32_WINDOWS:

  if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
  {
   printf ("Microsoft Windows 95 ");
   if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
    printf("OSR2 " );
   return 0;
  }

  if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
  {
   printf ("Microsoft Windows 98 ");
   if ( osvi.szCSDVersion[1] == 'A' )
    printf("SE " );
   return 0;
  }

  if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
  {
   printf ("Microsoft Windows Millennium Edition/n");
   return 0;
  }
  break;

 case VER_PLATFORM_WIN32s:

  printf ("Microsoft Win32s/n");
  return 0;
  break;
 }
 return TRUE;
}

// 函数功能:设置权限
BOOL SetPrivilege(LPCTSTR Privilege, BOOL bEnablePrivilege)
{
 HANDLE hToken, h;
 TOKEN_PRIVILEGES tkp;

 // 获得令牌
 typedef VOID (WINAPI *MYPROC1)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
 MYPROC1 ProcAdd1 = (MYPROC1)GetProcAddress(GetModuleHandle(TEXT("Advapi32")), "OpenProcessToken");
 if (ProcAdd1 == NULL)
  return FALSE;
 h = GetCurrentProcess();
 if (h == NULL)
  return FALSE;
 ProcAdd1(h, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);

 // 开机关机权限
 typedef VOID (WINAPI *MYPROC2)( LPCTSTR lpSystemName, LPCTSTR lpName,  PLUID lpLuid);
 MYPROC2 ProcAdd2 = (MYPROC2)GetProcAddress(GetModuleHandle(TEXT("Advapi32")), "LookupPrivilegeValueA");
 if (ProcAdd2 == NULL)
  return FALSE;
 (ProcAdd2)(NULL, Privilege, &tkp.Privileges[0].Luid);

 // 第一次
 tkp.PrivilegeCount = 1;  // one privilege to set   
 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

 typedef VOID (WINAPI *MYPROC3)( HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,  PDWORD ReturnLength);
 MYPROC3 ProcAdd3 = (MYPROC3)GetProcAddress(GetModuleHandle(TEXT("Advapi32")), "AdjustTokenPrivileges");
 if (ProcAdd3 == NULL)
  return FALSE;
 (ProcAdd3)(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);

 // 第二次
 tkp.PrivilegeCount = 1;  // one privilege to set   
 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

 if(bEnablePrivilege)
  tkp.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
 else
  tkp.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tkp.Privileges[0].Attributes);
 (ProcAdd3)(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);


 return TRUE;
}

// 函数功能:获取关机/重启权限
BOOL SetPrivilege_ShutDown()
{
 return SetPrivilege(SE_SHUTDOWN_NAME,true);
}

// 函数功能:获取关闭其它进程权限
int SetPrivilege_Debug()      
{
 return SetPrivilege(SE_DEBUG_NAME,true);
}

// 函数功能:获取文件的大小
// 函数返回:文件大小
DWORD GetFileSize(char *pFileName)
{
 FILE *pFile;
 DWORD dwPos;
 DWORD dwFileSize;

 if( (pFile  = fopen(pFileName, "rb" )) == NULL )
 {
  printf( "The file 'data' was not opened/n" );
  return 0;
 }

 dwPos = ftell(pFile);
 fseek(pFile, 0, SEEK_END);
 dwFileSize = ftell(pFile);
 fseek(pFile, dwPos, SEEK_SET);
 fclose(pFile);

 return dwFileSize;
}

// 函数功能:杀进程中的模块
typedef HANDLE (WINAPI *MYPROC1)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
int KillModule(char *strPName, char *strMName)
{
 char strDllName[MAX_PATH];
 HANDLE hProcess, hThread;
 DWORD dwStartAddr = 0;
 DWORD dwRetLen = 0;
 DWORD dwDllSize = 0;
 PWSTR pszLibFileRemote = NULL;
 int  nKilled = 0;
 BOOL fOk, fOK1;
 HANDLE hmeSnapshot;
 BOOL fME;
 char *pdest;
 HMODULE hNtdll;
 int  cch;
 int  cb;
 int  nDllKillNum;

 MYPROC1 ProcAdd1;

 PTHREAD_START_ROUTINE  pfnThreadRtn;
 NTQUERYINFORMATIONTHREAD NtQueryInformationThread;
 
 HANDLE hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 PROCESSENTRY32 pe = { sizeof(pe) };
 MODULEENTRY32 me = { sizeof(me) };

 // 遍历所有进程
 fOk = Process32First(hthSnapshot, &pe);
 for (; fOk; fOk = Process32Next(hthSnapshot, &pe))
 {
  // 找到远程进程
  if (stricmp(pe.szExeFile, strPName) == 0)
  {
   // 遍历模块
   hmeSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe.th32ProcessID);
   fME = Module32First(hmeSnapshot, &me);
   for (; fME; fME = Module32Next(hmeSnapshot, &me))
   {
    strcpy(strDllName, me.szExePath);
    pdest = strrchr(strDllName, '//');
    strcpy(strDllName, ++pdest);

    // 找到远程进程中的模块, 杀之,3个步骤
    if (stricmp(strDllName, strMName) == 0)
    {
     __try
     {
      // 1.遍历模块中的线程,如果有结束
      dwDllSize = GetFileSize(me.szExePath);
      hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, me.th32ProcessID);
      if (hthSnapshot == NULL) __leave;
      THREADENTRY32 te = { sizeof(te) };
      fOK1 = Thread32First(hthSnapshot, &te);

      // 遍历线程
      for (; fOK1; fOK1 = Thread32Next(hthSnapshot, &te))
      {
       if (te.th32OwnerProcessID == pe.th32ProcessID)
       {
        __try
        {
         // 得到线程句柄
         ProcAdd1 = (MYPROC1)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "OpenThread");
         if (ProcAdd1 == NULL)
          return FALSE;
         hThread = (ProcAdd1(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID));
         if (hThread == NULL) __leave;

         // 找到ntdll.dll中函数NtQueryInformationThread地址
         hNtdll = LoadLibrary( "ntdll.dll" );
         if (!hNtdll) return 0;
         NtQueryInformationThread = (NTQUERYINFORMATIONTHREAD)GetProcAddress(hNtdll, "NtQueryInformationThread");

         // 获取线程入口地址
         NtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, &dwStartAddr, 0x4, &dwRetLen);
         if (dwStartAddr != NULL)
         {
          // 判断线程入口地址是否在模块中
          if ((dwStartAddr - (DWORD)me.hModule) <=  dwDllSize)
          {
           // 结束线程
           TerminateThread(hThread, 0);
           CloseHandle(hThread);
          }
         }
        }

        // 释放资源
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
         return 0;
        }
       }
      } // for

      // 2.释放DLL
      // 获取远程进程中的DLL句柄
      hProcess = OpenProcess(
       PROCESS_QUERY_INFORMATION |   // Required by Alpha
       PROCESS_CREATE_THREAD     |   // For CreateRemoteThread
       PROCESS_VM_OPERATION      |   // For VirtualAllocEx/VirtualFreeEx
       PROCESS_VM_WRITE,             // For WriteProcessMemory
       FALSE, me.th32ProcessID);
      if (hProcess == NULL) __leave;

      // 计算DLL名称需要的字节数
      cch = 1 + strlen(me.szExePath);
      cb  = cch * sizeof(CHAR);

      // 分配远程进程路径名空间
      pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
      if (pszLibFileRemote == NULL) __leave;

      // 考贝DLL路径名到远程进程空间
      if (!WriteProcessMemory(hProcess, pszLibFileRemote, (PVOID)me.szExePath, cb, NULL)) __leave;

      // 得到GetModuleHandle在Kernel32.dll中的地址
      pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
      if (pfnThreadRtn == NULL) __leave;

      // 创建远程进程,调用GetModuleHandle(DLLPathname)
      nDllKillNum = (me.GlblcntUsage > me.ProccntUsage) ? me.GlblcntUsage : me.ProccntUsage;
      if (nDllKillNum == 65535)
       nDllKillNum = 3;
      for (int i = 0; i < nDllKillNum; i++)
      {
       hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, me.hModule, 0, NULL);
       if (hThread == NULL) __leave;
      }

      // 3.删除DLL
      //DeleteFile(me.szExePath);
      CloseHandle(hProcess);
      CloseHandle(hThread);
      printf("Killed !!!/n");
      nKilled = 1;
     }
     __finally
     {
      if (hthSnapshot != NULL)
       CloseHandle(hthSnapshot);
     }
    }// if
   } // for
  }
 }// for

 if (nKilled == 0)
  printf("Sorry, No found!/n");
  
 return 0;
}

int main(int argc, char **argv)
{
 printf("KillModule V1.0(2006). Welcome to myblog: www.blog.163.com/lanhai96");

 if (argc < 3)
 {
  printf("Parameter error./n");
  return 0;
 }

 // 看版本号
 if (!GetVersionInfo())
 {
  printf("Don't run at this OS./n");
  return 0;
 }

 // 获得权限
 SetPrivilege_Debug();

 // 结束模块
 KillModule(argv[1], argv[2]);

 return 0;
}

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lanhai96

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值