当前位置: 首页 > 工具软件 > unload_dll > 使用案例 >

UnLoadDll

羊禄
2023-12-01
// 程序功能:结束进程中的一个模块。
// 程序日期: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)
int KillModule(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) };
   
    char szMsg[MAX_PATH] = {0};


    // 遍历所有进程
    fOk = Process32First(hthSnapshot, &pe);
    for (; fOk; fOk = Process32Next(hthSnapshot, &pe))
    {
        // 找到远程进程
        //if (stricmp(pe.szExeFile, strPName) == 0)
        if (1)
        {
            //wsprintf(szMsg, "process name = %s /n", pe.szExeFile);
            //printf("process name = %s /n", pe.szExeFile);
            //OutputDebugString(szMsg);
           
            // 遍历模块
            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)
                {
                    //printf("dll name = %s /n", strDllName);
                    //OutputDebugString(szMsg);
                   
                    __try
                    {
                        // 1.遍历模块中的线程,如果有结束
                        dwDllSize = GetFileSize(me.szExePath);
                        HANDLE hthSnapshotT = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, me.th32ProcessID);
                        if (hthSnapshot == NULL) __leave;
                        THREADENTRY32 te = { sizeof(te) };
                        fOK1 = Thread32First(hthSnapshotT, &te);
                       
                        // 遍历线程
                        for (; fOK1; fOK1 = Thread32Next(hthSnapshotT, &te))
                        {
                            if (te.th32OwnerProcessID == pe.th32ProcessID)
                            {
                                //printf("te.th32OwnerProcessID = %d /n", te.th32OwnerProcessID);

                                __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);
                                           
                                            //printf("TerminateThread successed! /n");
                                        }
                                    }
                                }
                               
                                // 释放资源
                                __except(EXCEPTION_EXECUTE_HANDLER)
                                {
                                    printf("exception~~~/n");
                                    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");
                        printf(" in process : %s /n", pe.szExeFile);
                        nKilled = 1;
                    }
                    __finally
                    {
                        //printf("exception emun process~~~/n");
                        //if (hthSnapshot != NULL)
                        //    CloseHandle(hthSnapshot);
                    }
                }// if
            } // for
        }//end if
    }// for
 
    if (hthSnapshot != NULL)
        CloseHandle(hthSnapshot);

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

int main(int argc, char **argv)
{
    printf("Force Free Library!/n");
   
    if (argc < 2)
    {
        printf("Parameter error./n");
        printf("arg1: DLL filename/n");
        printf("Example: command myDll.dll/n/n");
        return 0;
    }
   
    // 看版本号
    if (!GetVersionInfo())
    {
        printf("Don't run at this OS./n");
        return 0;
    }
   
    // 获得权限
    SetPrivilege_Debug();
   
    // 结束模块
    KillModule(argv[1]);
    //KillModule("Win32Hook.dll");
   
    //getchar();
    return 0;
}
 
 类似资料:

相关阅读

相关文章

相关问答