首页
社区
课程
招聘
未解决 [求助]将其他文件加载到自己的进程失败
2020-6-9 14:46 1951

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

2020-6-9 14:46
1951

想实现一个将其他文件加载到自己的进程并执行。思路是将自己文件的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;
}

[培训]科锐软件逆向50期预科班报名即将截止,速来!!! 50期正式班报名火爆招生中!!!

收藏
免费 1
打赏
分享
最新回复 (6)
雪    币: 219
活跃值: (221)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
礁石的爱 2020-6-9 19:32
2
0
EXE入口点不是直接void*就调用的, 你看看他的声明, 按照声明去调用就好了
雪    币: 248
活跃值: (49)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
LimitLess 2020-6-9 20:49
3
0
礁石的爱 EXE入口点不是直接void*就调用的, 你看看他的声明, 按照声明去调用就好了
声明是哪个声明啊。。。大佬,我有点愚钝
雪    币: 219
活跃值: (221)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
礁石的爱 2020-6-9 20:57
4
0
像DLL就是这样的BOOL APIENTRY DllMain (HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
EXE的话控制台跟窗口程序也不一样 你VS新建个项目就看见了
雪    币: 219
活跃值: (221)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
礁石的爱 2020-6-9 21:03
5
0
github上搜MemoryLoadDll,照着那个写就好了
雪    币: 248
活跃值: (49)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
LimitLess 2020-6-9 21:09
6
0
礁石的爱 github上搜MemoryLoadDll,照着那个写就好了
这个入口函数我明白了,我是想要跳转到我申请的入口点的地址然后继续执行程序,这样也需要这个入口API吗?
雪    币: 219
活跃值: (221)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
礁石的爱 2020-6-9 21:20
7
0
如果你加载的PE是编译器默认生成的入口点,那就是固定的那几种定义.
你自己新建个那个WIN32窗口项目就知道了, 系统入口点都是固定那几种
游客
登录 | 注册 方可回帖
返回