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;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值