DLL注入

原创 2016年06月01日 19:11:16

前两篇文章介绍了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;

}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Windows下使用二进制插装工具Pin

Pin是Intel公司提供的一个程序插装工具,支持IA-32,Intel(R) 64和IA64架构上的Linux和Windows可执行程序。 Pin允许一个工具在可执行程序的任何地方插入任意代码...
  • nbabn
  • nbabn
  • 2013-05-21 14:19
  • 6132

软件测试-二进制插桩

关键词:插桩,软件测试     二进制插桩作用 1.        程序运行时拦截,在运行时向程序注入我们自己的代码。 2.     ...

结构体的强制类型转换

结构体赋值遇到的一点问题

获取进程列表和模块信息

获取本地进程列表与进程模块信息

通过WINNT.H定义的结构体,获取进程IAT表

利用已定义的PE文件结构体获取本进程的IAT表

Inline Hook

Inline Hooking的实现

DLL的两种加载方式

DLL有两种调用方式 一,隐式加载(需要.lib和.dll) 二,显式加载(需要.dll)

IAT HOOK

IAT Hook的实现

内存注入之IAT Hook和Inline Hook综合程序

内存注入综合程序 1) 进程列表获取 2) IAT表项获取 3) IAT Hook 4) Inline Hook
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)