博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线程注入ThreadInject(dll)
阅读量:7226 次
发布时间:2019-06-29

本文共 5838 字,大约阅读时间需要 19 分钟。

原理通过挂起线程(SuspendThread),设置线程(SetThreadContext)上下文中的eip(rip)方式注入。

//ThreadInject.h

#pragma once// ThreadInject 对话框class ThreadInject : public CDialogEx{    DECLARE_DYNAMIC(ThreadInject)public:    ThreadInject(CWnd* pParent = NULL);   // 标准构造函数    virtual ~ThreadInject();// 对话框数据    enum { IDD = IDD_DIALOG2 };protected:    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持    DECLARE_MESSAGE_MAP()public:    // 进程ID    DWORD m_dwPid;    CString m_strDllPath;    afx_msg void OnBnClickedButton2();    afx_msg void OnBnClickedButton3();    afx_msg void OnBnClickedButton4();};

//ThreadInject.cpp

// ThreadInject.cpp : 实现文件//#include "stdafx.h"#include "MyInjectTool.h"#include "ThreadInject.h"#include "afxdialogex.h"//777A01D5    68 78563412     push    12345678//777A01DA    9C              pushfd//777A01DB    60              pushad//777A01EB    61              popad//777A01EC    9D              popfd//777A01ED    C3              retn//结构必须字节对齐1#pragma pack(1)  typedef struct _INJECT_CODE{    BYTE  byPUSH;    DWORD dwPUSH_VALUE;    BYTE  byPUSHFD;    BYTE  byPUSHAD;    BYTE  byMOV_EAX;          //mov eax, addr szDllpath    DWORD dwMOV_EAX_VALUE;    BYTE  byPUSH_EAX;         //push eax    BYTE  byMOV_ECX;          //mov ecx, LoadLibrary    DWORD dwMOV_ECX_VALUE;    WORD  wCALL_ECX;          //call ecx    BYTE  byPOPAD;    BYTE  byPOPFD;    BYTE  byRETN;    CHAR  szDllPath[MAX_PATH];}INJECT_CODE, *PINJECT_CODE;#pragma pack()  // ThreadInject 对话框IMPLEMENT_DYNAMIC(ThreadInject, CDialogEx)ThreadInject::ThreadInject(CWnd* pParent /*=NULL*/)    : CDialogEx(ThreadInject::IDD, pParent)    , m_dwPid(0)    , m_strDllPath(_T("")){}ThreadInject::~ThreadInject(){}void ThreadInject::DoDataExchange(CDataExchange* pDX){    CDialogEx::DoDataExchange(pDX);    DDX_Text(pDX, IDC_EDIT1, m_dwPid);    DDX_Text(pDX, IDC_EDIT4, m_strDllPath);}BEGIN_MESSAGE_MAP(ThreadInject, CDialogEx)    ON_BN_CLICKED(IDC_BUTTON2, &ThreadInject::OnBnClickedButton2)    ON_BN_CLICKED(IDC_BUTTON3, &ThreadInject::OnBnClickedButton3)    ON_BN_CLICKED(IDC_BUTTON4, &ThreadInject::OnBnClickedButton4)END_MESSAGE_MAP()// ThreadInject 消息处理程序void ThreadInject::OnBnClickedButton2(){    // TODO:  在此添加控件通知处理程序代码    char szFilter[] = "动态链接库|*.dll";    CFileDialog fileDlg(TRUE, "dll", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);    UpdateData(TRUE);    if (fileDlg.DoModal() == IDOK)    {        m_strDllPath = fileDlg.GetPathName();    }    UpdateData(FALSE);}HANDLE g_hProcess = 0;LPVOID g_lpBuffer = NULL;void ThreadInject::OnBnClickedButton3(){    // TODO:  在此添加控件通知处理程序代码    //打开目标进程    BOOL   bRet = 0;    INJECT_CODE ic = { 0 };    THREADENTRY32 te32 = { 0 };    HANDLE hThreadSnap = NULL;    DWORD dwThreadId = 0;    HANDLE hThread = NULL;    CONTEXT oldContext = { 0 };    CONTEXT newContext = { 0 };    DWORD dwOldEip = 0;    //打开进程    g_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwPid);    if (!g_hProcess)    {        MessageBox("OpenProcess 失败");        return;    }    g_lpBuffer = VirtualAllocEx(g_hProcess, NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);    if (!g_lpBuffer)    {        MessageBox("VirtualAllocEx 失败");        return;    }    //给ShellCode结构体赋值    ic.byPUSH           = 0x68;    ic.dwPUSH_VALUE     = 0x12345678;   //用于保存原来的返回地址    ic.byPUSHFD         = 0x9C;    ic.byPUSHAD         = 0x60;    ic.byMOV_EAX        = 0xB8;    ic.dwMOV_EAX_VALUE = (DWORD)g_lpBuffer + offsetof(INJECT_CODE, szDllPath);    ic.byPUSH_EAX       = 0x50;    ic.byMOV_ECX        = 0xB9;    ic.dwMOV_ECX_VALUE  = (DWORD)&LoadLibrary;    ic.wCALL_ECX        = 0xD1FF;    ic.byPOPAD          = 0x61;    ic.byPOPFD          = 0x9D;    ic.byRETN           = 0xC3;    memcpy(ic.szDllPath, m_strDllPath.GetBuffer(0), m_strDllPath.GetLength());    //写入ShellCode    bRet = WriteProcessMemory(g_hProcess, g_lpBuffer, &ic, sizeof(ic), NULL);    if (!bRet)    {        MessageBox("写入内存失败");        return;    }    //创建线程快照查找目标程序主线程    te32.dwSize = sizeof(te32);    hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);    if (hThreadSnap == INVALID_HANDLE_VALUE)    {        MessageBox("CreateToolhelp32Snapshot 失败");        return;    }    //遍历查询目标程序主线程ID    if (Thread32First(hThreadSnap, &te32))    {        do        {            if (m_dwPid == te32.th32OwnerProcessID)            {                dwThreadId = te32.th32ThreadID;                break;            }        } while (Thread32Next(hThreadSnap, &te32));    }    //打开目标主线程    hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId);    if (!OpenThread)    {        MessageBox("OpenThread 失败");        return;    }    //挂起目标主线程    bRet = SuspendThread(hThread);    if (bRet == -1)    {        MessageBox("SuspendThread 失败");        return;    }    oldContext.ContextFlags = CONTEXT_FULL;    bRet = GetThreadContext(hThread, &oldContext);    if (!bRet)    {        MessageBox("GetThreadContext 失败");        return;    }    newContext = oldContext;#ifdef _WIN64    newContext.Rip = (DWORD)g_lpBuffer;    dwOldEip = oldContext.Rip;#else     newContext.Eip = (DWORD)g_lpBuffer;    dwOldEip = oldContext.Eip;#endif    //;将指针指向ShellCode第一句push 12345678h中的地址,写入返回地址    bRet = WriteProcessMemory(g_hProcess, ((char*)g_lpBuffer) + 1, &dwOldEip, sizeof(DWORD), NULL);    if (!bRet)    {        MessageBox("写入内存失败");        return;    }    bRet = SetThreadContext(hThread, &newContext);    if (!bRet)    {        MessageBox("SetThreadContext 失败");        return;    }    //然后把主线程跑起来    bRet = ResumeThread(hThread);    if (bRet == -1)    {        MessageBox("ResumeThread 失败");        return;    }}void ThreadInject::OnBnClickedButton4(){    // TODO:  在此添加控件通知处理程序代码    if (!VirtualFreeEx(g_hProcess, g_lpBuffer, 0, MEM_RELEASE))    {        MessageBox("VirtualFreeEx 失败");        return;    }    MessageBox("释放对方空间成功");}

转载于:https://blog.51cto.com/haidragon/2306817

你可能感兴趣的文章
linux基础:10、基础命令(4)
查看>>
linux中强大的screen命令
查看>>
放开那个程序员
查看>>
构建高性能数据库缓存之Redis(一)
查看>>
测试驱动开发
查看>>
解决MySQL不允许从远程访问
查看>>
puppet介绍及基于httpd实例部署
查看>>
UML常用工具之三--RSA
查看>>
iis7 appcmd的基础命令及简单用法
查看>>
用脚本实现移动某目录下文件名符合指定规则的文件到另一个目录的功能
查看>>
关于SQL镜像配置报错
查看>>
终于找到解决方案了,Qt的Model/View Framework解析
查看>>
线程信息的获取和设置
查看>>
Databricks Scala 编程风格指南
查看>>
Tkinter,label内容随多选框变化
查看>>
PHP开发中的数据类型 ( 第3篇 ) :Heaps
查看>>
网络七层协议
查看>>
4种删除Word空白页的小技巧,都是你需要用到的!
查看>>
单服务器MySQL主从复制实践
查看>>
CentOS 7 root口令恢复
查看>>