首页
社区
课程
招聘
[求助]将其他文件加载到自己的进程失败
发表于: 2020-6-9 14:48 2333

[求助]将其他文件加载到自己的进程失败

2020-6-9 14:48
2333

想实现一个将其他文件加载到自己的进程并执行。思路是将自己文件的IMAGEBASE设置到较高的地址,然后将文件按照运行时的格式贴到自己的进程空间的低地址,最后跳转到低地址的入口点开始执行,但是不知道最后一步要怎么跳转到入口点执行。我的方法是定义一个函数指针,用函数指针指向一个地址,但是最后报错,希望大佬进来帮忙看看,万分感谢!!!

#include <Windows.h>
#include <iostream>
#include <fstream>
using namespace std;

void (*Entry)(void);

#pragma pack(push, 1)
typedef struct _THUNK {
    DWORD data : 31;
    DWORD flag : 1;
}THUNK, *PTHUNK;
#pragma pack(pop)

DWORD r2f(LPBYTE buffer, DWORD rva);

int main()
{
    //读取文件
    ifstream infile("c:/a.exe", ios::in | ios::binary);
    if (!infile.is_open()) {
        cout << "文件打开失败" << endl;
        return 0;
    }
    infile.seekg(0, ios::end);
    int fileSize = infile.tellg();
    infile.seekg(0, ios::beg);
    char* buffer = new char[fileSize];
    ZeroMemory(buffer, fileSize);
    infile.read(buffer, fileSize);
    infile.close();


    //缓冲区拉伸拷贝到指定空间
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)buffer;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(buffer + pDosHeader->e_lfanew);
    PIMAGE_SECTION_HEADER pSecHeader = (PIMAGE_SECTION_HEADER)((PBYTE)&pNtHeader->OptionalHeader + pNtHeader->FileHeader.SizeOfOptionalHeader);
    //需要的简写
    DWORD sizeOfImage = pNtHeader->OptionalHeader.SizeOfImage;
    DWORD sizeOfHeader = pNtHeader->OptionalHeader.SizeOfHeaders;
    DWORD numOfSec = pNtHeader->FileHeader.NumberOfSections;

    DWORD ipAddr = 0x00400000;
    DWORD entryPoint = ipAddr + pNtHeader->OptionalHeader.AddressOfEntryPoint;
    LPVOID newAddress = VirtualAlloc((LPVOID)ipAddr, sizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (newAddress == NULL) {
        cout << "内存空间申请失败" << endl;
        delete[] buffer;
        return 0;
    }
    ZeroMemory((LPVOID)ipAddr, sizeOfImage);
    memcpy((LPVOID)ipAddr, buffer, sizeOfHeader);
    //循环拷贝节
    for (UINT i = 0; i < numOfSec; i++) {
        memcpy((LPVOID)(ipAddr + pSecHeader[i].VirtualAddress),
            buffer + pSecHeader[i].PointerToRawData, 
                pSecHeader[i].SizeOfRawData);
    }

    //修复IAT表
    //先找到导入表
    PIMAGE_DATA_DIRECTORY pdd;
    pdd = &pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
    PIMAGE_IMPORT_DESCRIPTOR pid = (PIMAGE_IMPORT_DESCRIPTOR)(buffer + r2f((LPBYTE)buffer, pdd->VirtualAddress));
    //遍历导入表
    while (!(pid->OriginalFirstThunk == 0 && pid->FirstThunk == 0)) {
        //判断INT表中的值是名字还是编号
        //找到INT表首地址
        PDWORD pINT = (PDWORD)(buffer + r2f((LPBYTE)buffer, pid->OriginalFirstThunk));
        //找到IAT表首地址
        PDWORD pIAT = (PDWORD)(buffer + r2f((LPBYTE)buffer, pid->FirstThunk));
        for (int i = 0; *(pINT + i) != 0; i++) {
            if (((PTHUNK)(pINT + i))->flag == 0) {
                //是名字,创建BYNAME结构获取地址
                PIMAGE_IMPORT_BY_NAME pByName = (PIMAGE_IMPORT_BY_NAME)(buffer + r2f((LPBYTE)buffer, ((PTHUNK)(pINT + i))->data));
                /*DWORD tmp = (DWORD)(buffer + r2f((LPBYTE)buffer, pid->Name));
                cout << hex << tmp << endl;*/
                HANDLE hProcHandle = GetProcAddress(LoadLibraryA((buffer + r2f((LPBYTE)buffer, pid->Name))), pByName->Name);
                //给IAT赋值
                *(pIAT + i) = (DWORD)hProcHandle;
            }
            else {
                HANDLE hProcHandle = GetProcAddress(LoadLibraryA((buffer + r2f((LPBYTE)buffer, pid->Name))), (LPCSTR)((PTHUNK)(pINT + i))->data);
                *(pIAT + i) = (DWORD)hProcHandle;
            }
        }
        pid++;
    }

    //跳转到入口点开始执行
    Entry = (void (*)())(entryPoint);
    Entry();

    //释放内存
    delete[] buffer;
    return 0;
}

DWORD r2f(LPBYTE buffer, DWORD rva) {
    //从缓冲区获取节的信息
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)buffer;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(buffer + pDosHeader->e_lfanew);
    PIMAGE_SECTION_HEADER pSecHeader = (PIMAGE_SECTION_HEADER)((PBYTE)&pNtHeader->OptionalHeader + pNtHeader->FileHeader.SizeOfOptionalHeader);

    //判断越界
    if (rva > pSecHeader[pNtHeader->FileHeader.NumberOfSections - 1].VirtualAddress +
        max(pSecHeader[pNtHeader->FileHeader.NumberOfSections - 1].Misc.VirtualSize,
            pSecHeader[pNtHeader->FileHeader.NumberOfSections - 1].SizeOfRawData))
        return 0xFFFFFFFF;
    if (rva < pNtHeader->OptionalHeader.SizeOfHeaders) return rva;
    //判断文件在第几个节
    UINT i = 0;
    for (; i < pNtHeader->FileHeader.NumberOfSections; i++) {
        if (rva >= pSecHeader[i].VirtualAddress &&
            rva < pSecHeader[i].VirtualAddress + max(pSecHeader[i].SizeOfRawData, pSecHeader[i].Misc.VirtualSize)) {
            break;
        }
    }
    return pSecHeader[i].PointerToRawData + rva - pSecHeader[i].VirtualAddress;
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (9)
雪    币: 259
活跃值: (283)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
这不就是傀儡进程?
2020-6-9 17:37
0
雪    币: 248
活跃值: (49)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
ZwCopyAll 这不就是傀儡进程?
思路差不多,可以帮忙看看问题吗大佬
2020-6-9 18:26
0
雪    币: 30050
活跃值: (2457)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
https://bbs.pediy.com/thread-259969-1.htm
其实这个不算傀儡进程,你应该找一个内存Dll加载的开源代码来修改,区别在于最后一步的入口函数定义:WinMain,就是你上面那个
 //跳转到入口点开始执行
    Entry = (void (*)())(entryPoint);
    Entry();
2020-6-9 22:51
0
雪    币: 248
活跃值: (49)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
bestbird https://bbs.pediy.com/thread-259969-1.htm 其实这个不算傀儡进程,你应该找一个内存Dll加载的开源代码来修改,区别在于最后一步的入口函数定义:WinMain, ...
大佬又来啦,感谢回复,其实WinMain这个我没有太明白。我调试的时候就是转到入口点这一步不行。我是在某视频中学到的,他没有用开源的代码,就是读取了一个exe程序,和我这个一样,但是我就是不知道最后一步转到入口点执行要怎么弄。大佬可以详细说一下嘛,万分感谢!!!
2020-6-9 23:06
0
雪    币: 15
活跃值: (3576)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
// HighRun.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include "DEFINE.h"
#include "GgetPE_Info.h"
#define szFileName "C:/Src.exe"

int _tmain(int argc, _TCHAR* argv[])
{

        //当前进程在高地址运行
        //读取目标文件到内存 拉伸 贴入0x400000   读取他的IAT表  需要的DLL  LOAD进来 修复IAT表 JMP过去运行 
        

       //读取文件到内存
          PVOID pImage=0;
        if(!ReadFileToImage(szFileName,&pImage))
        {
                Sleep(5000);
                return -1;
        }
        PVOID pNewBuffer=0;

        //拉伸为运行时的状态
        ImageBufferToNewBuffer(pImage,&pNewBuffer);
        //释放读取时的内存
        free(pImage);        

        //获取ImageBase和OEP
        PVOID pOptionHeader=0;
        GetPEOptionHeader(pNewBuffer,&pOptionHeader);
        
        DWORD dwSizeOfImage=((PIMAGE_OPTIONAL_HEADER)pOptionHeader)->SizeOfImage;
        DWORD dwEntryOfPoint=((PIMAGE_OPTIONAL_HEADER)pOptionHeader)->AddressOfEntryPoint;
        DWORD dwOldImageBase=((PIMAGE_OPTIONAL_HEADER)pOptionHeader)->ImageBase;
        PVOID  pAllocAddr=(PVOID)0x400000;

        //在0x400000处申请内存
        PVOID pAllocBuffer= VirtualAlloc(pAllocAddr,dwSizeOfImage,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
        PVOID pRelocTable=0;
        if (!pAllocBuffer)
        {
                //如果申请失败就在任意位置申请内存
                pAllocBuffer=VirtualAlloc(0,dwSizeOfImage,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
                
        }
        //把拉伸后的数据贴入申请到的位置
        memcpy_s(pAllocBuffer,dwSizeOfImage,pNewBuffer,dwSizeOfImage);

        //如果没有申请到原来的ImageBase   进行重定位 已经拉伸为内存状态
        if((DWORD)pAllocBuffer!=dwOldImageBase)
        {
        RelocImageBuffer(pAllocBuffer,(DWORD)pAllocBuffer);
     }
        

       if(!RepairImportTable(pAllocBuffer))
       {
               MessageBox(0,TEXT("修复导入表失败"),TEXT("警告"),0);
               
               return false;
       }
       
        //修改县城上下文
       HANDLE hThread=GetCurrentThread();
        CONTEXT ct;
       ct.ContextFlags=CONTEXT_FULL;
       GetThreadContext(hThread,&ct);
       ct.Eax=dwEntryOfPoint;
       
       memcpy_s((PVOID)(ct.Ebx+8),4,&pAllocBuffer,4);//这句注释掉也能运行
    
       SetThreadContext(hThread,&ct);
       DWORD dwJmpAddr=dwEntryOfPoint+(DWORD)pAllocBuffer;
       _asm
       {
               jmp dwJmpAddr
       }
       
    getchar();
       return 0;
}

2020-6-10 01:50
0
雪    币: 248
活跃值: (49)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
麻木的时间 // HighRun.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "DEFINE.h" ...
我检查了代码,修复IAT没有问题呀,不知道为啥就是运行不了呀。。。
2020-6-10 16:18
0
雪    币: 15
活跃值: (3576)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
你代码肯定出问题了呀,我当时写这个的时候是可以运行的。
2020-6-10 16:45
0
雪    币: 248
活跃值: (49)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
麻木的时间 你代码肯定出问题了呀,我当时写这个的时候是可以运行的。
检查了好几遍。。。。大佬可不可以帮忙看一下代码
2020-6-10 18:59
0
雪    币: 15
活跃值: (3576)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
球球 加  
 857305819 我把全部代码还给你。你自己查。
2020-6-10 21:29
0
游客
登录 | 注册 方可回帖
返回
//