C/C++知识点之ProcessInject(dll)
小标 2019-03-01 来源 : 阅读 619 评论 0

摘要:本文主要向大家介绍了 C/C++知识点之ProcessInject(dll),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了 C/C++知识点之ProcessInject(dll),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

C/C++知识点之ProcessInject(dll)

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


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

}

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程