DLL注入

毕设做了一个相关的东西,一个关于注册表和文件监控的东西,主要的思路是hook 文件和注册表相关的api,然后改变api执行流程,加入自己的处理代码。时间过去了快一年了,在研究生课上有个作业要用到这些,于是就写回忆了一下,发现还不能写出来,所以,写个博客,复习一下吧。
其中借鉴了一下网上其他人的代码,具体是谁的,也忘了,如果谁能认出来,可以告诉我,我在标识出来。而且具体的方法和讲解在《Windows核心编程》里面有具体的讲解。

以前觉得dll注入是个很高大上的东西,自己研究过后,发现也是一件很简单的事情,但是理解起来,则会需要非常全面的知识。大概流程是这样的:

  1. 使得进程获取权限,不然在注入的时候会有不成功的时候
  2. 使用OpenProcess获取要注入的进程的句柄
  3. 在要注入的进程空间内申请一段内存
  4. 在申请的内存中写入要注入的dll的绝对路径
  5. 获取loadLibrary的地址
  6. CreateRemoteThread创建远程线程,函数为loadLibrary,参数为dll的路径
  7. 等待线程创建完毕,然后释放内存,关闭线程句柄

卸载dll的逻辑也是十分简单:

  1. 获取注入的dll模块的句柄,发现了有两种方法
    1.1 通过创建进程快照的方式,遍历获取
    1.2 通过创建远程线程,直接在进程空间里面获取
  2. 打开被注入的进程,获取句柄,然后把dll的path写入到该进程空间中,然后饭后创建远程线程,并且执行函数FreeLibrary

下面是注入的代码

inject(DWORD dwRemoteProcessId)
{
    //如果输入“”表示向自身进程注入
    if (dwRemoteProcessId == 0)
       dwRemoteProcessId = GetCurrentProcessId();

    //获得调试权限
    if (EnableDebugPriv(SE_DEBUG_NAME))
    {
       printf("Add Privilege error\n");
       return -1;
    }
    //调用OpenProcess()获得句柄
    HANDLE hRemoteProcess;
    if ((hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwRemoteProcessId)) == NULL)
    {
       printf("OpenProcess error\n");
       printf("Error Code:%d\n",GetLastError());
       system("pause");
       return -2;
    }

    //在远程进程中分配内存,准备拷入DLL路径字符串
    //取得当前DLL路径
    char DllPath[260]; //Windows路径最大为
    GetCurrentDirectoryA(260, DllPath);  //获取当前进程执行目录
    printf("Proces***e Directory is %s\n", DllPath); 
    strcat(DllPath, "xxx.dll"); //链接到DLL路径
    LPVOID pRemoteDllPath = VirtualAllocEx(hRemoteProcess, NULL, strlen(DllPath) + 1, MEM_COMMIT, PAGE_READWRITE);
    if (pRemoteDllPath == NULL)
    {
       printf("VirtualAllocEx error\n");
       return -3;
    }

    //向远程进程空间中写入DLL路径字符串
    printf("DllPath is %s\n", DllPath);
    DWORD Size;
    if (WriteProcessMemory(hRemoteProcess, pRemoteDllPath, DllPath, strlen(DllPath) +1, &Size) == NULL)
    {
       printf("WriteProcessMemory error\n");
       return -4;
    }
    printf("WriteRrmoyrProcess Size is %d\n\n", Size);

    //获得远程进程中LoadLibrary()的地址
    LPTHREAD_START_ROUTINE pLoadLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");
    if (pLoadLibrary == NULL)
    {
       printf("GetProcAddress error\n");
       return -5;
    }
    else
    {
       printf("LoadLibrary's Address is 0x%x\n\n", pLoadLibrary);
    }

    //启动远程线程
    DWORD dwThreadId;
    HANDLE hThread;
    if ((hThread = CreateRemoteThread(hRemoteProcess, NULL, 0, pLoadLibrary, pRemoteDllPath, 0, &dwThreadId)) == NULL)
    {
       printf("CreateRemoteThread error\n");
       return -6;
    }
    else
    {
    WaitForSingleObject(hThread, INFINITE);
    printf("dwThreadId is %d\n\n", dwThreadId);
    printf("Inject is done\n");
    }

    //释放分配内存
    if (VirtualFreeEx(hRemoteProcess, pRemoteDllPath, 0, MEM_RELEASE) == 0)
    {
       printf("VitualFreeEx error\n");
       return -8;
    }

    //释放句柄
    if (hThread != NULL) CloseHandle(hThread);
    if (hRemoteProcess != NULL) CloseHandle(hRemoteProcess);
}

int EnableDebugPriv(char *name)
{
    HANDLE hToken;   //进程令牌句柄
    TOKEN_PRIVILEGES tp;  //TOKEN_PRIVILEGES结构体,其中包含一个【类型+操作】的权限数组
    LUID luid;       //上述结构体中的类型值

    //打开进程令牌环
    //GetCurrentProcess()获取当前进程的伪句柄,只会指向当前进程或者线程句柄,随时变化
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken))
    {
       printf("OpenProcessToken error\n");
       return -8;
    }

    //获得本地进程name所代表的权限类型的局部唯一ID
    if (!LookupPrivilegeValue(NULL, name, &luid))
    {
       printf("LookupPrivilegeValue error\n");
    }

    tp.PrivilegeCount = 1;    //权限数组中只有一个“元素”
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;  //权限操作
    tp.Privileges[0].Luid = luid;   //权限类型

    //调整进程权限
    if (!AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
    {
       printf("AdjustTokenPrivileges error!\n");
       return -9;
    }

    return 0;
}

卸载代码其一,这是通过创建远程线程获取的dll的句柄:

int uninject(DWORD dwRemoteProcessId, char *DllPath)
{
    DWORD   ProcessPID=dwRemoteProcessId;  

    //打开进程  
    HANDLE hProcess;  
    hProcess=OpenProcess(  
                                PROCESS_CREATE_THREAD   |  
                                PROCESS_VM_OPERATION    |  
                                PROCESS_VM_WRITE        ,  
                                FALSE,ProcessPID);  
    if(!hProcess)  
    {  
        printf("打开目标进程失败\n");  
        CloseHandle(hProcess);  
        return 3;  
    }  

    int allocSize=(strlen(DllPath)+1)*sizeof(char);   
    //申请内存存放以DLL文件路径名  
    char *pLibFileName=(char*)VirtualAllocEx(hProcess,NULL,allocSize,MEM_COMMIT,PAGE_READWRITE);   
    //写DLL文件路径名到远程进程  
    if(!pLibFileName)  
    {  
        printf("申请目标进程内存失败");  
        CloseHandle(hProcess);  
        return 4;  
    }  
    if(!WriteProcessMemory(hProcess,pLibFileName,(PVOID)DllPath, allocSize, NULL))  
    {  
        printf("写目标进程内存失败");  
        VirtualFreeEx(hProcess,pLibFileName,allocSize,MEM_RELEASE);  
        CloseHandle(hProcess);  
        return 5;  
    }  

    while(1)  
    {  
        //创建远程线程,GetModuleHandle获取刚刚注入的DLL的句柄  
        HANDLE  hThread=CreateRemoteThread(hProcess,NULL,0,(PTHREAD_START_ROUTINE)GetModuleHandle,pLibFileName,0,NULL);  
        if(!hThread)  
        {  
            printf("创建目标线程运行GetModuleHandle失败");  
            VirtualFreeEx(hProcess,pLibFileName,allocSize,MEM_RELEASE);  
            CloseHandle(hThread);  
            CloseHandle(hProcess);  
            return 6;  
        }  

        WaitForSingleObject(hThread,INFINITE);  
        DWORD hDll;  
        GetExitCodeThread(hThread,&hDll);  
        if(!hDll)  
        {  
            printf("卸载DLL成功");//卸载结束!!  
            VirtualFreeEx(hProcess,pLibFileName,allocSize,MEM_RELEASE);  
            CloseHandle(hThread);  
            CloseHandle(hProcess);  
            return 7;  
        }  
        CloseHandle(hThread);  
        hThread=NULL;  


        //创建远程线程,卸载远程DLL  
        hThread=CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)FreeLibrary,(LPVOID)hDll,0,NULL);  
        if(!hThread)  
        {  
            printf("创建远程线程运行FreeLibrary失败");  
            VirtualFreeEx(hProcess,pLibFileName,allocSize,MEM_RELEASE);  
            CloseHandle(hThread);  
            CloseHandle(hProcess);  
            return 8;  
        }  
        WaitForSingleObject(hThread,INFINITE);  

        DWORD FreeLibInfo;  
        GetExitCodeThread(hThread,&FreeLibInfo);  
        if(!FreeLibInfo)  
        {  
            printf("FreeLibrary失败");  
            VirtualFreeEx(hProcess,pLibFileName,allocSize,MEM_RELEASE);  
            CloseHandle(hThread);  
            CloseHandle(hProcess);  
            return 9;  
        }  
    }  

    return 0;
}

卸载代码其二,这是通过进程快照获取的:

void UnInjectDll(char *szDllName, DWORD dwPid)  
{  
    if(dwPid==0 || strlen(szDllName)==0)  
    {  
        AfxMessageBox("输入信息不全");  
        return;  
    }  
    //创建进程快照  
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,dwPid);  
    MODULEENTRY32 ME32 = {0};  
    ME32.dwSize = sizeof(MODULEENTRY32);  
    BOOL isNext = Module32First(hSnap,&ME32);  
    BOOL flag = FALSE;  
    while(isNext)  
    {  
        if(strcmp(ME32.szModule,szDllName)==0)  
        {  
            flag = TRUE;  
            break;  
        }  
        isNext = Module32Next(hSnap,&ME32);  
    }  
    if(flag == FALSE)  
    {  
        AfxMessageBox("找不到目标模块");  
        return;  
    }  
    CloseHandle(hSnap);  
    HANDLE hPro = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPid);  
    FARPROC pFun = GetProcAddress(GetModuleHandle("kernel32.dll"),"FreeLibrary");  
    HANDLE hThread = CreateRemoteThread(hPro,NULL,0,(LPTHREAD_START_ROUTINE)pFun,ME32.szModule,0,NULL);  
    if(!hThread)  
    {  
        AfxMessageBox("创建远程线程失败");  
        return ;  
    }  
    AfxMessageBox("卸载成功");  
    WaitForSingleObject(hThread,INFINITE);  
    CloseHandle(hThread);  
    CloseHandle(hPro);  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值