为了账号安全,请及时绑定邮箱和手机立即绑定

ProcessInject(dll)

标签:
C++


原理:

通过以挂起的方式创建进程对其注入。

#include <stdio.h>

#include <stdlib.h>

#include <windows.h>

#include<tchar.h>

typedef struct Param

{

    DWORD year;

    DWORD Month;

    DWORD Day;

    FARPROC pFun[2];

}Param,*pParam;

void _declspec(naked) AddTimelimit(pParam param)

{

    _asm

    {

        pushfd

        push eax

        push ecx

        push edx

        push ebx

        sub esp, 0x18

        lea eax, ss:[esp + 0x6]

        push eax

        mov ebx,[esp+0x34]                  //保存param结构体指针

        call ds:[ebx+0xc]

        lea eax, ss : [esp + 0x6]

        mov cx, word ptr ss : [esp + 0x6]

        mov word ptr ss : [esp], cx

        mov cx, word ptr ss : [esp + 0x8]

        mov word ptr ss : [esp + 2], cx

        mov cx, word ptr ss : [esp + 0xc]

        mov word ptr ss : [esp + 4], cx

        mov eax, ss : [ebx]

        mov ecx, ss : [ebx + 0x4]

        mov edx, ss : [ebx + 0x8]

        cmp word ptr ss : [esp], ax

        ja _Label_exit

        cmp word ptr ss : [esp + 2], cx

        ja _Label_exit

        cmp word ptr ss : [esp + 4], dx

        ja _Label_exit

        add esp, 0x18

        pop ebx

        pop edx

        pop ecx

        pop eax

        popfd

        retn

        _Label_exit :

            push 0

            call ds : [ebx + 0x10]

            retn

    }

}       //code的原型

BYTE code[] = { 0x9C,0x68,0x00,0x00,0x00,0x00,0x50,0x51,0x52,0x53,0x83,0xEC,0x18,0x36,0x8D,

                0x44,0x24,0x06,0x50,0x8B,0x5C,0x24,0x2C,0x3E,0xFF,0x53,0x0C,0x36,0x8D,0x44,0x24,0x06,0x36,0x66,0x8B,

                0x4C,0x24,0x06,0x36,0x66,0x89,0x0C,0x24,0x36,0x66,0x8B,0x4C,0x24,0x08,0x36,

                0x66,0x89,0x4C,0x24,0x02,0x36,0x66,0x8B,0x4C,0x24,0x0C,0x36,0x66,0x89,0x4C,

                0x24,0x04,0x36,0x8B,0x03,0x36,0x8B,0x4B,0x04,0x36,0x8B,0x53,0x08,0x36,0x66,

                0x39,0x04,0x24,0x77,0x1E,0x36,0x66,0x39,0x4C,0x24,0x02,0x77,0x16,0x36,0x66,

                0x39,0x54,0x24,0x04,0x77,0x0E,0x83,0xC4,0x18,0x5B,0x5A,0x59,0x58,0x9D,0x9D,

                0x55,0x8B,0xEC,0xE9,0x00,0x00,0x00,0x00,0x6A,0x00,0x3E,0xFF,0x53,0x10,0xC2,0x04,0x00};

BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)     //提升程序权限

{

    TOKEN_PRIVILEGES tp;

    HANDLE hToken;

    LUID luid;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))     //获取令牌句柄

    {

        _tprintf(TEXT("OpenProcessToken error : %u\n"), GetLastError());

        return FALSE;

    }

    LookupPrivilegeValue(NULL, lpszPrivilege, &luid);                                                   //获取指定权限的LUID

    tp.PrivilegeCount = 1;

    tp.Privileges[0].Luid = luid;

    if (bEnablePrivilege)

        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    else

        tp.Privileges[0].Attributes = 0;

    if (!AdjustTokenPrivileges(hToken,          //令牌句柄

        FALSE,          //FALSE则修改权限

        &tp,            //令牌权限的结构(包括LUID和tp中的数组个数吗)

        sizeof(TOKEN_PRIVILEGES),

        (PTOKEN_PRIVILEGES)NULL,

        (PDWORD)NULL))

    {

        _tprintf(TEXT("AdjustTokenPrivileges error : %u\n"), GetLastError());

        return FALSE;

    }                                                                                           //调整进程的权限

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)

    {

        _tprintf(TEXT("The Token does not have the specified privilege. \n"));

        return FALSE;

    }

    return TRUE;

}

void main()

{

    STARTUPINFO si = { sizeof(si) };

    PROCESS_INFORMATION pi;

    LPVOID pRemoteParam,pRemoteFun, pBuf_user32;

    Param param = {0};

    DWORD dwBufSize,dwTemp;

    BYTE mbxBuffer[5] = { 0 }, Buf_user32[] = "user32.dll", jmpcode[5] = { 0xE9,0,0,0,0 }, 

        shellcode[100] = {  0x50,0x9C,0x68,0x00,0x00,0x1C,0x00,0xE8,0xC4,0xD8,0xDC,0x75,0xE8,

                            0x0F,0x1A,0x79,0x75,0x50,0xE8,0xE9,0xEC,0xDC,0x75,0x9D,0x58,0xE9,

                            0xD3,0xAE,0xAD,0x77 };

    FARPROC Address_mbx = GetProcAddress(LoadLibraryA("user32.dll") , "CreateWindowExA");

    DWORD OldProtect = 0;

    BYTE *pShellcode;

    param.year = 2018;

    param.Month = 2;

    param.Day = 1;

    param.pFun[0] = GetProcAddress(GetModuleHandle("kernel32.dll"),"GetLocalTime");

    param.pFun[1] = GetProcAddress(GetModuleHandle("kernel32.dll"), "ExitProcess");

    SetPrivilege(SE_DEBUG_NAME, TRUE);

    CreateProcessA("需要挂起的程序路径",

        NULL, NULL,NULL,NULL,CREATE_SUSPENDED,NULL,NULL,&si,&pi);

    //写入参数到目标进程

    dwBufSize = sizeof(param);

    pRemoteParam = VirtualAllocEx(pi.hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);

    WriteProcessMemory(pi.hProcess,pRemoteParam,(LPVOID)¶m,dwBufSize,NULL);

    //写入shellcode到目标进程

    dwBufSize = 127;

    pRemoteFun = VirtualAllocEx(pi.hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    memcpy(&code[2], &pRemoteParam, 4);

    dwTemp = (DWORD)Address_mbx + 5 - (DWORD)pRemoteFun - 113 - 5;

    memcpy(&code[114], &dwTemp, 4);

    WriteProcessMemory(pi.hProcess, pRemoteFun, (LPVOID)code, dwBufSize, NULL);

    //不sleep就会出现读取不到的297错误

    Sleep(50);              

    //获取线程上下文

    CONTEXT ct = { 0 };

    ct.ContextFlags = CONTEXT_CONTROL;

    GetThreadContext(pi.hThread, &ct);

    printf("ct.eip = %X", ct.Eip);

    //读取挂起位置,供写入shellcode使用

    dwBufSize = sizeof(Buf_user32);

    pBuf_user32 = VirtualAllocEx(pi.hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    WriteProcessMemory(pi.hProcess, pBuf_user32, (LPVOID)Buf_user32, dwBufSize, NULL);

    //为shellcode分配100字节空间并写入

    pShellcode = (BYTE *)VirtualAllocEx(pi.hProcess, NULL, 100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    dwTemp = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA") - (DWORD)pShellcode - 5 -7;             //push eax                                                                                                                              

    memcpy(&shellcode[3],&pBuf_user32,4);                                                                                   //call LoadlibraryA                 

    memcpy(&shellcode[8], &dwTemp, 4);                                                                                      //pushfd

    dwTemp = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetCurrentThread") - (DWORD)pShellcode - 5 - 12;           //push add_of_user32.dll

    memcpy(&shellcode[13], &dwTemp, 4);

    dwTemp = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"), "SuspendThread") - (DWORD)pShellcode - 5 - 18;

    memcpy(&shellcode[19], &dwTemp, 4);

    dwTemp = ct.Eip - 5 - (DWORD)pShellcode - 25;

    memcpy(&shellcode[26],&dwTemp,4);

    WriteProcessMemory(pi.hProcess,pShellcode,shellcode,100,NULL);

    ct.Eip = (DWORD)pShellcode;

    SetThreadContext(pi.hThread,&ct);

    ResumeThread(pi.hThread);

    Sleep(50);

    VirtualProtectEx(pi.hProcess,(LPVOID)Address_mbx,10,PAGE_EXECUTE_READWRITE,&OldProtect);

    //printf("err = %d", GetLastError());

    ReadProcessMemory(pi.hProcess, (LPVOID)Address_mbx,(LPVOID)mbxBuffer,10,NULL);

    //printf("err = %d", GetLastError());

    DWORD offset = (DWORD)pRemoteFun - (DWORD)Address_mbx - 5;

    memcpy(&jmpcode[1], &offset, 4);

    WriteProcessMemory(pi.hProcess,(LPVOID)Address_mbx,jmpcode,5,NULL);

    ResumeThread(pi.hThread);               //恢复shellcode里挂起的线程

}

// ProcessInject.h

#pragma once

// ProcessInject 对话框

class ProcessInject : public CDialogEx

{

    DECLARE_DYNAMIC(ProcessInject)

public:

    ProcessInject(CWnd* pParent = NULL);   // 标准构造函数

    virtual ~ProcessInject();

// 对话框数据

    enum { IDD = IDD_DIALOG3 };

protected:

    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

    DECLARE_MESSAGE_MAP()

public:

    CString m_strExePath;

    CString m_strDllPath;

    afx_msg void OnBnClickedInject();

    afx_msg void OnBnClickedFreemem();

    afx_msg void OnBnClickedButton3();

    afx_msg void OnBnClickedButton4();

};

// ProcessInject.cpp

// ProcessInject.cpp : 实现文件

//

#include "stdafx.h"

#include "MyInjectTool.h"

#include "ProcessInject.h"

#include "afxdialogex.h"

//ShellCode结构体

//结构必须字节对齐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()  

// ProcessInject 对话框

IMPLEMENT_DYNAMIC(ProcessInject, CDialogEx)

ProcessInject::ProcessInject(CWnd* pParent /*=NULL*/)

    : CDialogEx(ProcessInject::IDD, pParent)

    , m_strExePath(_T(""))

    , m_strDllPath(_T(""))

{

}

ProcessInject::~ProcessInject()

{

}

void ProcessInject::DoDataExchange(CDataExchange* pDX)

{

    CDialogEx::DoDataExchange(pDX);

    DDX_Text(pDX, IDC_EDIT1, m_strExePath);

    DDX_Text(pDX, IDC_EDIT2, m_strDllPath);

}

BEGIN_MESSAGE_MAP(ProcessInject, CDialogEx)

    ON_BN_CLICKED(IDC_INJECT, &ProcessInject::OnBnClickedInject)

    ON_BN_CLICKED(IDC_FREEMEM, &ProcessInject::OnBnClickedFreemem)

    ON_BN_CLICKED(IDC_BUTTON3, &ProcessInject::OnBnClickedButton3)

    ON_BN_CLICKED(IDC_BUTTON4, &ProcessInject::OnBnClickedButton4)

END_MESSAGE_MAP()

// ProcessInject 消息处理程序

HANDLE g_hProcess1 = NULL;

LPVOID g_lpBuffer1 = NULL;

void ProcessInject::OnBnClickedInject()

{

    // TODO:  在此添加控件通知处理程序代码

    // TODO:  在此添加控件通知处理程序代码

    BOOL bRet = FALSE;

    STARTUPINFO si = { 0 };

    PROCESS_INFORMATION pi = { 0 };

    CONTEXT oldContext = { 0 };

    CONTEXT newContext = { 0 };

    INJECT_CODE ic = { 0 };

    DWORD dwOldEip = 0;

    si.wShowWindow = SW_SHOWDEFAULT;

    si.cb = sizeof(PROCESS_INFORMATION);

    HANDLE hThread = NULL;

    //以挂起的方式创建进程

    bRet = CreateProcess(m_strExePath.GetBuffer(0), NULL, NULL, NULL, FALSE, CREATE_SUSPENDED,

        NULL, NULL, &si, &pi);

    if (!bRet)

    {

        MessageBox("CreateProcess 失败");

        return;

    }

    g_hProcess1 = pi.hProcess;

    hThread = pi.hThread;

    //申请内存

    g_lpBuffer1 = VirtualAllocEx(g_hProcess1, NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    if (g_lpBuffer1 == NULL)

    {

        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_lpBuffer1 + 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_hProcess1, g_lpBuffer1, &ic, sizeof(ic), NULL);

    if (!bRet)

    {

        MessageBox("写入内存失败");

        return;

    }

    //获取线程上下文

    oldContext.ContextFlags = CONTEXT_FULL;

    bRet = GetThreadContext(hThread, &oldContext);

    if (!bRet)

    {

        MessageBox("GetThreadContext 失败");

        return;

    }

    newContext = oldContext;

#ifdef _WIN64

    newContext.Rip = (DWORD)g_lpBuffer1;

    dwOldEip = newContext.Rip;

#else 

    newContext.Eip = (DWORD)g_lpBuffer1;

    dwOldEip = newContext.Eip;

#endif

    //;将指针指向ShellCode第一句push 12345678h中的地址,写入返回地址

    bRet = WriteProcessMemory(g_hProcess1, ((char*)g_lpBuffer1) + 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 ProcessInject::OnBnClickedFreemem()

{

    // TODO:  在此添加控件通知处理程序代码

    if (!VirtualFreeEx(g_hProcess1, g_lpBuffer1, 0, MEM_RELEASE))

    {

        MessageBox("VirtualFreeEx 失败");

        return;

    }

    MessageBox("释放对方空间成功");

}

void ProcessInject::OnBnClickedButton3()

{

    // TODO:  在此添加控件通知处理程序代码

    char szFilter[] = "可执行程序|*.exe";

    CFileDialog fileDlg(TRUE, "exe", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);

    UpdateData(TRUE);

    if (fileDlg.DoModal() == IDOK)

    {

        m_strExePath = fileDlg.GetPathName();

    }

    UpdateData(FALSE);

}

void ProcessInject::OnBnClickedButton4()

{

    // 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);

}

©著作权归作者所有:来自51CTO博客作者土匪猿的原创作品,如需转载,请注明出处,否则将追究法律责任


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消