分享

怎么用exe调用另一个exe里函数,像调用dll那样

 quasiceo 2013-12-13

怎么用exe调用另一个exe里函数,像调用dll那样 [问题点数:40分,结帖人handongfeng]

handongfeng
handongfeng
handongfeng
等级:Blank
结帖率:100%
楼主 发表于: 2010-07-06 22:56:56
如题,现在有需要像调用dll里的函数那样调用一个exe里面的函数,不知道该怎么做,有些人说可以像DLL那样调用,有些人说不可以,我也调试了 LoadLibaryEx("a.exe",null,**AS_FILEDATA)也照网上那样写了,好像这一步好了,但下面获取函数地址的时候又是空地址。
所以请各位大侠指教下。
最好有个详细的例子,多谢
分享到: 更多 0
回复次数:36
yunyun1886358
yunyun1886358
yunyun1886358
等级:Blank
#1 得分:5 回复于: 2010-07-06 23:12:07
以下代码来自看雪论坛
[code] 
前两天想搞出一个游戏的封包解密函数,又懒怕还原成高级语言 想直接调用他EXE内部的解密函数,
本来记得PEDIY的有篇文章是增加节来导出内部函数的,但是找不到那篇文章了;所以就开始自己尝试一下,现在以自己写的一个EXE为类型

先写一个EXE程序

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}
procedure DoPub;//内部函数 等待导出
begin
MessageBox(0, 'Test', 'Test', MB_OK);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MessageBox(0, 'Test', 'Test', MB_OK);
end;

end.

上面编译成成 hook32.exe 名字为Hook没什么意思 只是个人习惯 跟钩子没关联 呵呵

然后用OD载入我们的程序 下段BP MessageBoxA 按 按钮运行 断下 执行到返回
00456498 >/$ 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
0045649A |. 68 AC644500 PUSH hook32.004564AC ; |Title = "Test"
0045649F |. 68 AC644500 PUSH hook32.004564AC ; |Text = "Test"
004564A4 |. 6A 00 PUSH 0 ; |hOwner = NULL
004564A6 |. E8 A509FBFF CALL ; \MessageBoxA
004564AB \. C3 RETN

得知我们的内部函数地址为 00456498 这里我就偷懒啦 用LORDPE的文件计算器 
计算 RVA=00056498
Offset=00055898
好了现在来修改导出表,再次偷懒 不加新节啦,WinHex打开文件 直接找个程序空白的地方
我在偏移64B90找到大片0字节区域 好就在这里开刀啦
这里我们先来熟悉一下导出表结构
Characteristics 4字节
TimeDateStamp 4字节
MajorVersion 2字节
MinorVersion 2字节
Name 4字节
Base 4字节 
NumberOfFunctions 4字节 你要导出函数的个数
NumberOfNames 4字节 你要导出函数名称的个数
AddressOfFunctions 4字节 //函数地址
AddressOfNames 4字节 //函数名地址
AddressOfNameOrdinals 4字节 //函数名顺序地址
注意上面都是保存RVA的值哦 千万别搞错了
好了 让我们来根据上面结构来在偏移64B90 处构造导出表
我们的模块名字是 hook32.exe 到出名字就随便起个吧 我这里叫 _W
构建如下

Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F

00064B90 00 00 00 00 00 00 00 00 00 00 00 00 C2 E7 06 00 ............络..
00064BA0 01 00 00 00 01 00 00 00 01 00 00 00 B8 E7 06 00 ............哥..
00064BB0 BC E7 06 00 C0 E7 06 00 98 64 05 00 CD E7 06 00 肩..犁..榙..顽..
00064BC0 00 00 68 6F 6F 6B 33 32 2E 65 78 65 00 5F 57 00 ..hook32.exe._W.

也就是
->Export Table
Characteristics: 0x00000000
TimeDateStamp: 0x00000000 (GMT: Thu Jan 01 00:00:00 1970)
MajorVersion: 0x0000
MinorVersion: 0x0000 -> 0.00
Name: 0x0006E7C2 ("hook32.exe")
Base: 0x00000001
NumberOfFunctions: 0x00000001
NumberOfNames: 0x00000001
AddressOfFunctions: 0x0006E7B8
AddressOfNames: 0x0006E7BC
AddressOfNameOrdinals: 0x0006E7C0

Ordinal RVA Symbol Name
------- ---------- ----------------------------------
0x0001 0x00056498 "_W"




bujin888
2008-06-22, 02:52
导出表做好后 就让我们把导出表更新到PE结构里面去吧
用OD载入程序 ALT+M打开内存 选择 hook32 PE文件头那行 进入PE文件头数据窗口
看到
0040003C 00010000 DD 00000100 ; Offset to PE signature
这句话的意思说 PE文件头在偏移100处
我们来到偏移100处
00400100 50 45 00 00>ASCII "PE" ; PE signature (PE)
00400104 4C01 DW 014C ; Machine = IMAGE_FILE_MACHINE_I386
00400106 0900 DW 0009 ; NumberOfSections = 9
00400108 4E255D48 DD 485D254E ; TimeDateStamp = 485D254E
0040010C 00000000 DD 00000000 ; PointerToSymbolTable = 0
00400110 00000000 DD 00000000 ; NumberOfSymbols = 0
00400114 E000 DW 00E0 ; SizeOfOptionalHeader = E0 (224.)
00400116 8E81 DW 818E ; Characteristics = EXECUTABLE_IMAGE|32BIT_MACHINE|LINE_NUMS_STRIPPED|LOCAL_SYMS_STRIPPED|BYTES_REVERSED_LO|BYTES_REVERSED_HI
00400118 0B01 DW 010B ; MagicNumber = PE32
0040011A 02 DB 02 ; MajorLinkerVersion = 2
0040011B 19 DB 19 ; MinorLinkerVersion = 19 (25.)
0040011C 00600500 DD 00056000 ; SizeOfCode = 56000 (352256.)
00400120 00E80000 DD 0000E800 ; SizeOfInitializedData = E800 (59392.)
00400124 00000000 DD 00000000 ; SizeOfUninitializedData = 0
00400128 1C770500 DD 0005771C ; AddressOfEntryPoint = 5771C
0040012C 00100000 DD 00001000 ; BaseOfCode = 1000
00400130 00800500 DD 00058000 ; BaseOfData = 58000
00400134 00004000 DD 00400000 ; ImageBase = 400000
00400138 00100000 DD 00001000 ; SectionAlignment = 1000
0040013C 00020000 DD 00000200 ; FileAlignment = 200
00400140 0400 DW 0004 ; MajorOSVersion = 4
00400142 0000 DW 0000 ; MinorOSVersion = 0
00400144 0000 DW 0000 ; MajorImageVersion = 0
00400146 0000 DW 0000 ; MinorImageVersion = 0
00400148 0400 DW 0004 ; MajorSubsystemVersion = 4
0040014A 0000 DW 0000 ; MinorSubsystemVersion = 0
0040014C 00000000 DD 00000000 ; Reserved
00400150 00F00600 DD 0006F000 ; SizeOfImage = 6F000 (454656.)
00400154 00040000 DD 00000400 ; SizeOfHeaders = 400 (1024.)
00400158 00000000 DD 00000000 ; CheckSum = 0
0040015C 0200 DW 0002 ; Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
0040015E 0000 DW 0000 ; DLLCharacteristics = 0
00400160 00001000 DD 00100000 ; SizeOfStackReserve = 100000 (1048576.)
00400164 00400000 DD 00004000 ; SizeOfStackCommit = 4000 (16384.)
00400168 00001000 DD 00100000 ; SizeOfHeapReserve = 100000 (1048576.)
0040016C 00100000 DD 00001000 ; SizeOfHeapCommit = 1000 (4096.)
00400170 00000000 DD 00000000 ; LoaderFlags = 0
00400174 10000000 DD 00000010 ; NumberOfRvaAndSizes = 10 (16.)
00400178 00000000 DD 00000000 ; Export Table address = 0
0040017C 00000000 DD 00000000 ; Export Table size = 0
00400180 00F00500 DD 0005F000 ; Import Table address = 5F000
00400184 94240000 DD 00002494 ; Import Table size = 2494 (9364.)
00400188 00A00600 DD 0006A000 ; Resource Table address = 6A000
0040018C 00480000 DD 00004800 ; Resource Table size = 4800 (18432.)
00400190 00000000 DD 00000000 ; Exception Table address = 0
00400194 00000000 DD 00000000 ; Exception Table size = 0
00400198 00000000 DD 00000000 ; Certificate File pointer = 0
0040019C 00000000 DD 00000000 ; Certificate Table size = 0
004001A0 00400600 DD 00064000 ; Relocation Table address = 64000
004001A4 345B0000 DD 00005B34 ; Relocation Table size = 5B34 (23348.)
004001A8 00000000 DD 00000000 ; Debug Data address = 0
004001AC 00000000 DD 00000000 ; Debug Data size = 0
004001B0 00000000 DD 00000000 ; Architecture Data address = 0
004001B4 00000000 DD 00000000 ; Architecture Data size = 0

文件头结构有很多 我们只要 关心 这两行就可以
00400178 00000000 DD 00000000 ; Export Table address = 0
0040017C 00000000 DD 00000000 ; Export Table size = 0
这里是保存 导出表的地址和大小的地方
用OD相对偏移计算如下
$+178 00000000 DD 00000000 ; Export Table address = 0
$+17C 00000000 DD 00000000 ; Export Table size = 0
也就是说 导出表地址和长度保存在文件偏移 178 和17C处
用winhex打开文件 ALT+G 来到偏移178处 将原来我们构造导出表的地址00064B90 转换为RVA为6E790 

偏移178处4个字节改成 90 E7 06 00 数了一下我们的导出表共有64个字节16进制为0x40 
与是偏移178处4个字节改成40 00 00 00 到这里就一切OK了 保存好修改好的PE结构 然后我们写个程序来调用一下这个到处函数看看

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

doSth:procedure;
pfun:DWORD;
implementation

{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
DLLModule:DWORD;
begin
DLLModule := LoadLibrary('hook32.exe');
doSth:= GetProcAddress(DLLModule,'_W'); //取得API地址
doSth;
end;

end.

试验结果 HOOK32.EXE的内部函数被成功调用了!
[/code]
yunyun1886358
yunyun1886358
yunyun1886358
等级:Blank
#2 得分:5 回复于: 2010-07-06 23:14:24
[code] 
前两天想搞出一个游戏的封包解密函数,又懒怕还原成高级语言 想直接调用他EXE内部的解密函数,
本来记得PEDIY的有篇文章是增加节来导出内部函数的,但是找不到那篇文章了;所以就开始自己尝试一下,现在以自己写的一个EXE为类型

先写一个EXE程序

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}
procedure DoPub;//内部函数 等待导出
begin
MessageBox(0, 'Test', 'Test', MB_OK);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MessageBox(0, 'Test', 'Test', MB_OK);
end;

end.

上面编译成成 hook32.exe 名字为Hook没什么意思 只是个人习惯 跟钩子没关联 呵呵

然后用OD载入我们的程序 下段BP MessageBoxA 按 按钮运行 断下 执行到返回
00456498 >/$ 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
0045649A |. 68 AC644500 PUSH hook32.004564AC ; |Title = "Test"
0045649F |. 68 AC644500 PUSH hook32.004564AC ; |Text = "Test"
004564A4 |. 6A 00 PUSH 0 ; |hOwner = NULL
004564A6 |. E8 A509FBFF CALL ; \MessageBoxA
004564AB \. C3 RETN

得知我们的内部函数地址为 00456498 这里我就偷懒啦 用LORDPE的文件计算器 
计算 RVA=00056498
Offset=00055898
好了现在来修改导出表,再次偷懒 不加新节啦,WinHex打开文件 直接找个程序空白的地方
我在偏移64B90找到大片0字节区域 好就在这里开刀啦
这里我们先来熟悉一下导出表结构
Characteristics 4字节
TimeDateStamp 4字节
MajorVersion 2字节
MinorVersion 2字节
Name 4字节
Base 4字节 
NumberOfFunctions 4字节 你要导出函数的个数
NumberOfNames 4字节 你要导出函数名称的个数
AddressOfFunctions 4字节 //函数地址
AddressOfNames 4字节 //函数名地址
AddressOfNameOrdinals 4字节 //函数名顺序地址
注意上面都是保存RVA的值哦 千万别搞错了
好了 让我们来根据上面结构来在偏移64B90 处构造导出表
我们的模块名字是 hook32.exe 到出名字就随便起个吧 我这里叫 _W
构建如下

Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F

00064B90 00 00 00 00 00 00 00 00 00 00 00 00 C2 E7 06 00 ............络..
00064BA0 01 00 00 00 01 00 00 00 01 00 00 00 B8 E7 06 00 ............哥..
00064BB0 BC E7 06 00 C0 E7 06 00 98 64 05 00 CD E7 06 00 肩..犁..榙..顽..
00064BC0 00 00 68 6F 6F 6B 33 32 2E 65 78 65 00 5F 57 00 ..hook32.exe._W.

也就是
->Export Table
Characteristics: 0x00000000
TimeDateStamp: 0x00000000 (GMT: Thu Jan 01 00:00:00 1970)
MajorVersion: 0x0000
MinorVersion: 0x0000 -> 0.00
Name: 0x0006E7C2 ("hook32.exe")
Base: 0x00000001
NumberOfFunctions: 0x00000001
NumberOfNames: 0x00000001
AddressOfFunctions: 0x0006E7B8
AddressOfNames: 0x0006E7BC
AddressOfNameOrdinals: 0x0006E7C0

Ordinal RVA Symbol Name
------- ---------- ----------------------------------
0x0001 0x00056498 "_W"




bujin888
2008-06-22, 02:52
导出表做好后 就让我们把导出表更新到PE结构里面去吧
用OD载入程序 ALT+M打开内存 选择 hook32 PE文件头那行 进入PE文件头数据窗口
看到
0040003C 00010000 DD 00000100 ; Offset to PE signature
这句话的意思说 PE文件头在偏移100处
我们来到偏移100处
00400100 50 45 00 00>ASCII "PE" ; PE signature (PE)
00400104 4C01 DW 014C ; Machine = IMAGE_FILE_MACHINE_I386
00400106 0900 DW 0009 ; NumberOfSections = 9
00400108 4E255D48 DD 485D254E ; TimeDateStamp = 485D254E
0040010C 00000000 DD 00000000 ; PointerToSymbolTable = 0
00400110 00000000 DD 00000000 ; NumberOfSymbols = 0
00400114 E000 DW 00E0 ; SizeOfOptionalHeader = E0 (224.)
00400116 8E81 DW 818E ; Characteristics = EXECUTABLE_IMAGE|32BIT_MACHINE|LINE_NUMS_STRIPPED|LOCAL_SYMS_STRIPPED|BYTES_REVERSED_LO|BYTES_REVERSED_HI
00400118 0B01 DW 010B ; MagicNumber = PE32
0040011A 02 DB 02 ; MajorLinkerVersion = 2
0040011B 19 DB 19 ; MinorLinkerVersion = 19 (25.)
0040011C 00600500 DD 00056000 ; SizeOfCode = 56000 (352256.)
00400120 00E80000 DD 0000E800 ; SizeOfInitializedData = E800 (59392.)
00400124 00000000 DD 00000000 ; SizeOfUninitializedData = 0
00400128 1C770500 DD 0005771C ; AddressOfEntryPoint = 5771C
0040012C 00100000 DD 00001000 ; BaseOfCode = 1000
00400130 00800500 DD 00058000 ; BaseOfData = 58000
00400134 00004000 DD 00400000 ; ImageBase = 400000
00400138 00100000 DD 00001000 ; SectionAlignment = 1000
0040013C 00020000 DD 00000200 ; FileAlignment = 200
00400140 0400 DW 0004 ; MajorOSVersion = 4
00400142 0000 DW 0000 ; MinorOSVersion = 0
00400144 0000 DW 0000 ; MajorImageVersion = 0
00400146 0000 DW 0000 ; MinorImageVersion = 0
00400148 0400 DW 0004 ; MajorSubsystemVersion = 4
0040014A 0000 DW 0000 ; MinorSubsystemVersion = 0
0040014C 00000000 DD 00000000 ; Reserved
00400150 00F00600 DD 0006F000 ; SizeOfImage = 6F000 (454656.)
00400154 00040000 DD 00000400 ; SizeOfHeaders = 400 (1024.)
00400158 00000000 DD 00000000 ; CheckSum = 0
0040015C 0200 DW 0002 ; Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
0040015E 0000 DW 0000 ; DLLCharacteristics = 0
00400160 00001000 DD 00100000 ; SizeOfStackReserve = 100000 (1048576.)
00400164 00400000 DD 00004000 ; SizeOfStackCommit = 4000 (16384.)
00400168 00001000 DD 00100000 ; SizeOfHeapReserve = 100000 (1048576.)
0040016C 00100000 DD 00001000 ; SizeOfHeapCommit = 1000 (4096.)
00400170 00000000 DD 00000000 ; LoaderFlags = 0
00400174 10000000 DD 00000010 ; NumberOfRvaAndSizes = 10 (16.)
00400178 00000000 DD 00000000 ; Export Table address = 0
0040017C 00000000 DD 00000000 ; Export Table size = 0
00400180 00F00500 DD 0005F000 ; Import Table address = 5F000
00400184 94240000 DD 00002494 ; Import Table size = 2494 (9364.)
00400188 00A00600 DD 0006A000 ; Resource Table address = 6A000
0040018C 00480000 DD 00004800 ; Resource Table size = 4800 (18432.)
00400190 00000000 DD 00000000 ; Exception Table address = 0
00400194 00000000 DD 00000000 ; Exception Table size = 0
00400198 00000000 DD 00000000 ; Certificate File pointer = 0
0040019C 00000000 DD 00000000 ; Certificate Table size = 0
004001A0 00400600 DD 00064000 ; Relocation Table address = 64000
004001A4 345B0000 DD 00005B34 ; Relocation Table size = 5B34 (23348.)
004001A8 00000000 DD 00000000 ; Debug Data address = 0
004001AC 00000000 DD 00000000 ; Debug Data size = 0
004001B0 00000000 DD 00000000 ; Architecture Data address = 0
004001B4 00000000 DD 00000000 ; Architecture Data size = 0

文件头结构有很多 我们只要 关心 这两行就可以
00400178 00000000 DD 00000000 ; Export Table address = 0
0040017C 00000000 DD 00000000 ; Export Table size = 0
这里是保存 导出表的地址和大小的地方
用OD相对偏移计算如下
$+178 00000000 DD 00000000 ; Export Table address = 0
$+17C 00000000 DD 00000000 ; Export Table size = 0
也就是说 导出表地址和长度保存在文件偏移 178 和17C处
用winhex打开文件 ALT+G 来到偏移178处 将原来我们构造导出表的地址00064B90 转换为RVA为6E790 

偏移178处4个字节改成 90 E7 06 00 数了一下我们的导出表共有64个字节16进制为0x40 
与是偏移178处4个字节改成40 00 00 00 到这里就一切OK了 保存好修改好的PE结构 然后我们写个程序来调用一下这个到处函数看看

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

doSth:procedure;
pfun:DWORD;
implementation

{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
DLLModule:DWORD;
begin
DLLModule := LoadLibrary('hook32.exe');
doSth:= GetProcAddress(DLLModule,'_W'); //取得API地址
doSth;
end;

end.

试验结果 HOOK32.EXE的内部函数被成功调用了!
[/code]
hengshan
hengshan
hengshan
等级:Blank
#3 得分:5 回复于: 2010-07-06 23:15:55
应该是不可以的
handongfeng
handongfeng
handongfeng
等级:Blank
#4 得分:0 回复于: 2010-07-07 08:18:31
以下代码来自看雪论坛

我怎么什么也看不到呀,请贴一个例子,谢谢
liuwei2500
liuwei2500
liuwei2500
等级:Blank
#5 得分:5 回复于: 2010-07-07 08:36:21
有的exe就像dll一样,可以提供供外部调用的函数方法,但是有的没有
wl173235844
wl173235844
wl173235844
等级:Blank
#6 得分:5 回复于: 2010-07-07 08:58:55
没听说过这种调用方法。
xianglitian
xianglitian 版主
向立天
等级:Blank
4
9
更多勋章
#7 得分:5 回复于: 2010-07-07 10:00:22
exe和dll是不同的
要想实现调用好像是需要反汇编
liuwei2500
liuwei2500
liuwei2500
等级:Blank
#8 得分:5 回复于: 2010-07-07 11:03:39
http://topic.csdn.net/t/20050909/17/4260400.html
这个你到可以看一下

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多