如果一个exe使用LoadLibrary函数加载了自己
众所周知,exe文件可以使用LoadLibrary函数可以加载一个dll并和GetProcAddress函数连用即可获取到dll中导出函数的地址如果我们将dll换成exe呢?
我写了一个程序,它有一个导出函数add,并且在main函数中加载了自己并获取导出函数add的地址,如下:
header.h:
#include <iostream>
#include <windows.h>
extern "C" __declspec(dllexport) int add(int a, int b);
header.cpp:
#include "header.h"
int add(int a, int b)
{
return a + b;
}
main.cpp:
#include "header.h"
using namespace std;
typedef int(*pAdd)(int, int);
int main() {
HMODULE hDll = LoadLibrary(L"整活.exe");
pAdd add = (pAdd)GetProcAddress(hDll, "add");
int result = add(1, 2);
cout << "1 + 2 = " << result << endl;
FreeLibrary(hDll);
return 0;
}
编译,会发现编译器竟然为我们生成了.lib文件,这个文件在后面测试静态调用时会用到
可以看到,exe文件确实导出了函数add
接下来,我们在x32dbg中看
LoadLibrary函数执行完成后,观察到eax寄存器的值不是0,表示加载成功
0x00180000?这个地址怎么这么不对劲?
对了,这正是我们exe的基址,也就是使用LoadLibrary函数加载自己时返回的是自己的基址
接下来我们继续单步,执行完GetProcAddress后,eax寄存器也不为0,代表这个函数也成功了
嗯?这个地址怎么也这么眼熟?跳过去看看
什么?这个地址就在我们程序的OEP上面?(这里使用了VS的debug模式,实际上会直接跳到add的函数体中)
那,如果我们不载入本身,add函数还存在吗?
重新载入程序,可以发现,OEP上方仍然是jmp到add函数
这是不是跟我们下面的代码很像:
typedef int(*pAdd)(int,int);
int add(int a,int b){
return a+b;
}
pAdd Add = add;
接下来,我们再来试试不导出函数add,执行与上面相同的操作,可以发现LoadLibrary函数仍然执行成功,但是执行到GetProcAddress函数时,eax寄存器(返回值)的值为0,也就是函数失败了
总结:无论是否有导出函数,LoadLibrary函数加载自己时都会成功,且返回自己的基址,这与GetModuleHandle(0)是等效的
如果自己导出了函数add,则调用GetProcAddress函数获取add返回的是add函数的指针,即使不加载自己add函数也可以通过函数指针获取到
如果自己没有导出函数add,则无论自己是否定义了add,GetProcAddress函数都会失败
其他程序可不可以加载exe呢,答案是可以,当其他程序使用LoadLibrary加载了一个exe时,效果跟加载dll类似
还记得前面的lib文件吗?我们编译以下代码:
#include <iostream>
#pragma comment(lib,"整活.lib")
using namespace std;
extern "C" __declspec(dllimport) int add(int, int);
int main() {
cout << add(10, 20) <<endl;
return 0;
}
编译通过,如果整活.exe可以被加载,则程序正常运行。如果整活.exe没有被家长,则会弹出以下错误:
是的,这个弹窗提示的不再是缺少某个dll了,而是提示你缺少某个exe,是不是很好玩呢? 倒数第二行 没有被家长
应该是 没有被加载 之前就玩过,修改自身的加载地址再编译。LoadLibrary可执行文件,再把这个可执行文件跑起来。 真心提问一下,想要达到楼主您的水平 得学什么专业,怎么规划? zhendebuyiban 发表于 2024-6-18 16:49
真心提问一下,想要达到楼主您的水平 得学什么专业,怎么规划?
我也就会一点c++基础和一点逆向基础,甚至入门都谈不上
页:
[1]