吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4034|回复: 21
收起左侧

[C&C++ 原创] c/c++实现内存注入

[复制链接]
yoyoRev 发表于 2022-11-18 16:46
本帖最后由 yoyoRev 于 2022-11-18 23:45 编辑

看了相关视频,是易语言实现的内存注入,用c/c++来实现一下

内存注入的基本步骤:
1.将要注入的dll文件读取到缓冲区然后拉伸
2.对拉伸后的dll文件进行重定位表的修复
3.起远程线程修复iat表
4.抹除pe指纹,跳转到oep

以下是dll文件代码,只有一个MessageBox函数

#include "pch.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        MessageBox(0, TEXT("测试dll"), 0, 0);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}



以下是注入器代码

#include <stdio.h>
#include <windows.h>
typedef struct _InjcetPara {
        DWORD NewImageBase;
        DWORD AddressOfEntryPoint;
        LPVOID LoadLibraryAdd;
        LPVOID GetProcAdd;
        DWORD RvaIdt;
        DWORD SizeOfHeaders;
}InjcetPara,*PInjcetPara;
InjcetPara inp;

BYTE ReIat[] = "\x8B\xFF\x55\x8B\xEC\x83\xEC\x40\x8B\x45\x08\x36\x8B\
\x18\x89\x5D\xFC\x36\x8B\x58\x08\x89\x5D\xF8\x36\x8B\x58\x0C\x89\x5D\xF4\
\x8B\x50\x10\x03\x55\xFC\x89\x55\xEC\x8B\x55\xEC\x83\x7A\x0C\x00\x74\x68\x8B\
\x42\x0C\x03\x45\xFC\x50\xFF\x55\xF8\x89\x45\xE8\xC7\x45\xF0\x00\x00\x00\x00\
\x8B\x55\xEC\x8B\x42\x10\x03\x45\xFC\x89\x45\xE4\x8B\x45\xE4\x8B\xD8\x8B\x7D\xF0\
\xC1\xE7\x02\x83\x3C\x1F\x00\x74\x31\x8B\x04\x1F\xA9\x00\x00\x00\x80\x74\x09\x25\
\xFF\xFF\xFF\x7F\x8B\xD0\xEB\x06\x03\x45\xFC\x8D\x50\x02\x52\xFF\x75\xE8\xFF\x55\xF4\
\x8B\x5D\xE4\x8B\x75\xF0\xC1\xE6\x02\x89\x04\x1E\xFF\x45\xF0\xEB\xBE\x83\x45\xEC\x14\
\xEB\x8F\xFC\x8B\x7D\xFC\x33\xC0\x8B\x5D\x08\x36\x8B\x4B\x14\xC1\xE9\x02\xF3\xAB\x6A\x00\
\x6A\x00\x6A\x01\xFF\x75\xFC\x36\x8B\x43\x04\x03\x45\xFC\xFF\xD0\xC9\xC3";
BOOL FileToImage(PDWORD pFile,PDWORD pImage,PDWORD pImageSize) {
        DWORD ImageBufferSize = 0;
        PIMAGE_DOS_HEADER pNt = (PIMAGE_DOS_HEADER)pFile;
        PIMAGE_FILE_HEADER pFileHead = PIMAGE_FILE_HEADER((DWORD)pFile + pNt->e_lfanew + 4);
        PIMAGE_OPTIONAL_HEADER pOption = PIMAGE_OPTIONAL_HEADER(pFileHead + 1);
        PIMAGE_SECTION_HEADER pSection = PIMAGE_SECTION_HEADER((DWORD)pFileHead +0x14 + pFileHead->SizeOfOptionalHeader);
        inp.AddressOfEntryPoint = pOption->AddressOfEntryPoint;
        inp.SizeOfHeaders = pOption->SizeOfHeaders;
        ImageBufferSize = pOption->SizeOfImage;
        *pImageSize = pOption->SizeOfImage;
        PBYTE pImageFile = (PBYTE)malloc(ImageBufferSize);
        if (!pImageFile) {
                return 0;
        }
        *pImage = (DWORD)pImageFile;
        memset(pImageFile,0, ImageBufferSize);
        memcpy((PBYTE)pImageFile, (PBYTE)pFile, pOption->SizeOfHeaders);
        //printf("%s\n", pSection->Name);
        for (int i = 0; i < pFileHead->NumberOfSections; i++) {
                memcpy(PBYTE((DWORD)pImageFile+ pSection->VirtualAddress), PBYTE((DWORD)pFile+ pSection->PointerToRawData), pSection->SizeOfRawData);
                pSection++;
        }
        return 0;
}

BOOL Reloc(PDWORD pImage,DWORD NewImageBase) {
        PIMAGE_DOS_HEADER pNt = (PIMAGE_DOS_HEADER)pImage;
        PIMAGE_FILE_HEADER pFileHead = PIMAGE_FILE_HEADER((DWORD)pImage + pNt->e_lfanew + 4);
        PIMAGE_OPTIONAL_HEADER pOption = PIMAGE_OPTIONAL_HEADER(pFileHead + 1);
        PIMAGE_DATA_DIRECTORY pDataDire = PIMAGE_DATA_DIRECTORY((DWORD)(pFileHead + 1) + 0x60);
        if (!(pDataDire + 5)->VirtualAddress) {
                printf("没有重定位表\n");
                return 0;
        }
        inp.RvaIdt = (pDataDire + 1)->VirtualAddress;
        PIMAGE_BASE_RELOCATION pbreloc = PIMAGE_BASE_RELOCATION((DWORD)pImage + (pDataDire + 5)->VirtualAddress);
        PWORD PReFlag = 0;
        while (pbreloc->VirtualAddress) {
                PReFlag = PWORD(pbreloc + 1);
                for (int i = 0; i < (pbreloc->SizeOfBlock - 8) / 2; i++) {
                        if ((*PReFlag & 0xf000) == 0x3000) {
                                PDWORD ptemp = PDWORD(pbreloc->VirtualAddress + (*PReFlag & 0xfff) + (DWORD)pImage);
                                *ptemp = *ptemp - pOption->ImageBase + NewImageBase;
                        }
                        PReFlag++;
                }
                pbreloc = PIMAGE_BASE_RELOCATION((DWORD)pbreloc + pbreloc->SizeOfBlock);
        }
        return 1;
}
DWORD CreateMapFile(LPCSTR lpFileName, PDWORD pFileSize) {
        HANDLE hFile = INVALID_HANDLE_VALUE;
        HANDLE hMapFile = INVALID_HANDLE_VALUE;
        DWORD FileSize = NULL;
        LPVOID lpMemory = NULL;
        //读取文件
        hFile = CreateFileA(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (!hFile) {
                MessageBox(0, TEXT("读取文件失败"), 0, 0);
                return 0;
        }
        //获取文件大小
        FileSize = GetFileSize(hFile, NULL);
        if (!FileSize) {
                MessageBox(0, TEXT("获取文件大小失败"), 0, 0);
                return 0;
        }
        *pFileSize = FileSize;
        //创建文件映像
        hMapFile = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, 0, FileSize, NULL);
        if (!hMapFile) {
                MessageBox(0, TEXT("创建文件映像失败"), 0, 0);
                return 0;
        }
        lpMemory = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
        if (!lpMemory) {
                MessageBox(0, TEXT("调用文件映射失败"), 0, 0);
                return 0;
        }
        CloseHandle(hFile);
        CloseHandle(hMapFile);
        return (DWORD)lpMemory;
}
HANDLE GetProcessHandle(DWORD dwProcessId) {
        HANDLE hProcess = NULL;
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
        if (!hProcess) {
                printf("打开进程句柄失败,错误码:%d\n",GetLastError());
        }
        return hProcess;
}
int main(int argc, char* argv[]) {

        DWORD ImageAddress = 0;
        DWORD ImageSize = 0;
        DWORD FileSize = 0;
        DWORD ThreadReIat = 0;
        if (argc < 3) {
                printf("参数不够,注入失败\n");
                return 0;
        }
        DWORD dwProcessId = atoi(argv[1]);
        HANDLE hProcess = GetProcessHandle(dwProcessId);
        if (!hProcess) {
                return 0;
        }
        DWORD MeMoryAddress = CreateMapFile(argv[2], &FileSize);
        if (!MeMoryAddress) {
                return 0;
        }
        FileToImage((PDWORD)MeMoryAddress,&ImageAddress,&ImageSize);
        UnmapViewOfFile((LPVOID)MeMoryAddress);
        DWORD NewImageBase = (DWORD)VirtualAllocEx(hProcess,NULL, ImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!NewImageBase) {
                printf("申请空间失败\n");
                return 0;
        }
        inp.NewImageBase = NewImageBase;
        if (!Reloc((PDWORD)ImageAddress, NewImageBase)) {
                printf("模块没有重定位表,注入失败\n");
                VirtualFreeEx(hProcess, (LPVOID)NewImageBase, 0, MEM_RELEASE);
                return 0;
        }
        HMODULE hKernel = LoadLibraryA("kernel32.dll");
        if (!hKernel) {
                printf("获取kernel32句柄失败\n");
                VirtualFreeEx(hProcess, (LPVOID)NewImageBase, 0, MEM_RELEASE);
                return 0;
        }
        inp.LoadLibraryAdd = GetProcAddress(hKernel,"LoadLibraryA");
        inp.GetProcAdd = GetProcAddress(hKernel, "GetProcAddress");
        if (!inp.LoadLibraryAdd || !inp.GetProcAdd) {
                printf("获取函数地址失败\n");
                VirtualFreeEx(hProcess, (LPVOID)NewImageBase, 0, MEM_RELEASE);
                return 0;
        }
        WriteProcessMemory(hProcess, (LPVOID)NewImageBase, (LPCVOID)ImageAddress,ImageSize, NULL);
        ThreadReIat = (DWORD)VirtualAllocEx(hProcess, NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!ThreadReIat) {
                printf("申请线程空间失败\n");
                return 0;
        }
        WriteProcessMemory(hProcess, (LPVOID)ThreadReIat,&inp,sizeof(inp),NULL);
        WriteProcessMemory(hProcess, (LPVOID)(ThreadReIat +0x30), &ReIat, sizeof(ReIat), NULL);
        //远程线程修复iat表
        HANDLE hReIat = CreateRemoteThread(hProcess,NULL,NULL, LPTHREAD_START_ROUTINE(ThreadReIat + 0x30),(LPVOID)ThreadReIat,0,NULL);
        if (!hReIat) {
                printf("创建远程线程失败,修复IAT表失败\n");
                return 0;
        }
        WaitForSingleObject(hReIat,INFINITE);

        VirtualFreeEx(hProcess, (LPVOID)NewImageBase, 0, MEM_RELEASE);
        VirtualFreeEx(hProcess, (LPVOID)ThreadReIat, 0, MEM_RELEASE);

        return 0;
}


构造了一个结构体,用于远程线程修复iat表,BYTE ReIat[]是进行修复IAT表的shellcode

具体汇编代码如下

;参数说明
        ;ebp-4:dll文件基址
        ;ebp-8:LoadLibrary函数地址
        ;ebp-c:GetProcAddress函数地址
        ;ebp-10:IAT数组标号
        ;ebp-14:导入表地址
        ;ebp-18:导入表NAME指向dll的基址
        ;ebp-1c:iat数组基址
        .386
    .model flat,stdcall
    option casemap:none

        .code
                start:
                        mov edi,edi
                        push ebp
                        mov ebp,esp
                        sub esp,40h
                        mov eax,dword ptr ss:[ebp+8]        
                        mov ebx,dword ptr ss:[eax]        
                        mov dword ptr ss:[ebp-4],ebx
                        mov ebx,dword ptr ss:[eax+8]
                        mov dword ptr ss:[ebp-8],ebx
                        mov ebx,dword ptr ss:[eax+0ch]
                        mov dword ptr ss:[ebp-0ch],ebx
                        mov edx,dword ptr ds:[eax+10h]
                        add edx,dword ptr ss:[ebp-4]
                        mov dword ptr ss:[ebp-14h],edx
                r2:
                        mov edx,dword ptr ss:[ebp-14h]
                        cmp dword ptr ds:[edx+0ch],0
                        jz clPe
                        mov eax,dword ptr ds:[edx+0ch]
                        add eax,dword ptr ss:[ebp-4h]
                        push eax
                        call dword ptr ss:[ebp-8]
                        mov dword ptr ss:[ebp-18h],eax
                        mov dword ptr ss:[ebp-10h],0
                        mov edx,dword ptr ss:[ebp-14h]
                        mov eax,dword ptr ds:[edx+10h]        ;获取iat数组偏移
                        add eax,dword ptr ss:[ebp-4]        ;指向iat数组
                        mov dword ptr ss:[ebp-01ch],eax
                IsNull:
                        mov eax,dword ptr ss:[ebp-01ch]
                        mov ebx,eax
                        mov edi,dword ptr ss:[ebp-10h]
                        shl edi,2
                        cmp dword ptr ds:[ebx+edi],0
                        jz r1
                        mov eax,dword ptr ds:[ebx+edi]
                        test eax,80000000h                        ;判断最高位是否为1
                        jz IsRva
                        and eax,7fffffffh
                        mov edx,eax
                        jmp GetProc
                IsRva:
                        add eax,dword ptr ss:[ebp-4]
                        lea edx,dword ptr ds:[eax+2]
                GetProc:
                        push edx
                        push dword ptr ss:[ebp-18h]
                        call dword ptr ss:[ebp-0ch]
                        mov ebx,dword ptr ss:[ebp-01ch]
                        mov esi,dword ptr ss:[ebp-10h]
                        shl esi,2
                        mov dword ptr ds:[ebx+esi],eax
                        inc dword ptr ss:[ebp-10h]
                        jmp IsNull
                r1:
                        add dword ptr ss:[ebp-14h],14h
                        jmp r2
                clPe:                                                                ;抹除PE指纹
                        cld 
                        mov edi,dword ptr ss:[ebp-4]
                        xor eax,eax
                        mov ebx,dword ptr ss:[ebp+8]
                        mov ecx,dword ptr ss:[ebx+14h]
                        shr ecx,2
                        rep stosd
                        push 0
                        push 1
                        push dword ptr ss:[ebp-4]
                        mov eax,dword ptr ss:[ebx+4]
                        add eax,dword ptr ss:[ebp-4]
                        call eax
                        leave
                        ret
                end start


运行效果

调试器里看不到dll的痕迹

调试器里看不到dll的痕迹

用法及效果

用法及效果

免费评分

参与人数 2吾爱币 +8 热心值 +1 收起 理由
Circulation2020 + 1 用心讨论,共获提升!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

unpy 发表于 2023-10-27 22:18
牛逼

请教一下:
1) BYTE ReIat[] =  这段魔数代码是啥意思?怎么构造呢?
2) DLL Main中只能直接增加立即执行的逻辑,怎么去比如修改界面(比如增加菜单/按钮)当用户操作对应界面的时候才触发代码?
丶MaGuoGuo 发表于 2022-11-23 10:54
cnv587 发表于 2022-11-27 16:16
你猫临死前 发表于 2022-12-8 00:35
有无文件试试
紈絝 发表于 2022-12-9 21:27
有无成品啊
fuyunxiao01 发表于 2022-12-10 11:48
牛逼,我看源码还好,看非源码的代码头疼
 楼主| yoyoRev 发表于 2023-1-6 19:16

什么文件
摩托哈哈哥 发表于 2023-1-7 18:44
我一个c++菜鸟是看不太懂
ssjjtt 发表于 2023-4-24 15:52
太难了吧…………
CSGO001 发表于 2023-7-31 11:09
请问这种注入算哪一种,比如反射式,无痕什么的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-15 02:21

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表