给定指令在 运行 进程中的地址,在可执行文件中查找指令?
Find an instruction in an executable file, given its address in a running process?
我正在修改一个旧的废弃软件游戏以获得无限生命。
包含指令dec ecx
的地址与其在被调试的.exe中的位置不一致
记得有一次老朋友告诉我,有一个公式可以通过.exe里面的指令得到"true"地址。作弊引擎给了我内存地址。我记得在数学公式中,我需要得到模块,在 OllyDbg 中我得到了它。但是我不记得公式了。有人知道那个数学公式是怎么来的吗?公式非常简单!
还有另一种获取文件位置永久修改.exe的方法吗?
当然有公式
我们只需要反转 PE 加载器所做的事情:
- 找到文件中 PE 部分开始的位置。
这些数字称为文件偏移量。
- 相对于基地址,定位 PE 部分必须加载到内存中的位置。
这些地址称为 RVA(相对虚拟地址)
- 选择1一个可用的基地址并将其添加到 RVA。
这些地址被称为VAs(Virtual Addresses),是文件偏移量的最终地址。
为了帮助理解以下步骤,请记住每个 PE 部分都具有以下属性:
- 起始文件偏移量,节在文件中开始的位置。
- 文件中的长度。
- 一个起始内存地址,该节应该加载到内存中的位置(相对于基地址)
- 一旦加载到内存中的长度(这可能与文件长度不同)。
因此对于给定的内存地址 X,您必须:
- 减去基地址,对于遗留 Windows 程序,这通常是 40 0000h。
- 你现在有一个 RVA,找到第一个 PE 部分,它的起始内存地址低于 RVA,结束内存地址在它之后2。
- 减去节起始内存地址,您现在有一个节偏移量。
- 添加节起始文件偏移量,您现在有一个文件偏移量。
有一个名为 PEEditor 1.7 的工具可以为您执行此操作。
由于某种原因,现在很难找到它,但它应该仍然存在于 Internet 上。请记住:它是免费的。
找到PE编辑器:Here,使用密码tuts4you解压RAR包
加载文件(通过拖入 window 或使用浏览按钮)然后点击 FLC(文件位置计算器)。在新的window中输入地址。
1 多半这实际上意味着使用PE中设置的基地址header,多亏了分页。
2计算为内存起始地址+内存长度-1
有一个 "formula" 但您实际上需要查看可执行文件的内部(尽管可以根据一些假设简化此公式)。
- 获取你感兴趣的指令/数据的内存地址(虚拟地址)[VA]
- 获取指令/数据所在模块的基址。 [MODBASE]
- VA减去MODBASE,得到所谓的相对虚拟地址[RVA]:
- VA - MODBASE = RVA
- 用 PE 文件解析器/编辑器打开二进制文件(例如 *.exe 或 *.dll)并查看 headers.
部分
- 找到您的 RVA 所在的部分。
- 找到 RVA 所在的部分后,获取“相对虚拟地址”部分。 [SECRVA].
- 从 RVA 中减去 SECRVA,然后得到 [OFFSET]。
- RVA - SECRVA = OFFSET
- 获取您在 5.
找到的部分的 RawAddress [SECRAWADDR]
- 在[SECRAWADDR]中加上[OFFSET],结果就是你要查找的指令/数据在二进制文件。
- OFFSET + SECRAWADDR = INSDATAOFFSET(指令或数据在磁盘文件中的偏移)。
假设
通常(我坚持通常,有时情况并非如此),第一部分的[SECRVA]将是0x1000——恰好是代码部分——并且它的 [SECRAWADDR] 将是 0x400.
因此,如果您根据指令在内存中的地址搜索指令的偏移量,通常可以假设:
SECRVA = 0x1000
SECRAWADDR = 0x400
例子
示例基于 cmd.exe。
假设我在 0x1C34B0
处搜索此代码,当程序加载到内存中时:
CPU Disasm
Address Hex dump Command Comments
001C34B0 /$ E8 B3040000 CALL 001C3968
001C34B5 \.^ E9 2EFEFFFF JMP 001C32E8
注意指令操作码(字节)为:0xE8B3040000
VA = 0x1C34B0
- 正在内存中搜索模块库(使用调试器或 ProcessExplorer;此处有趣的列在进程资源管理器中简称为 "Base"。):
MODBASE = 0x1B0000
VA - MODBASE = RVA ; 0x1C34B0 - 0x1B0000 = 0x134B0
; RVA = 0x134B0
用PE编辑器打开二进制文件(我用的是CFF explorer):
- 让我们看看0x134B0在哪个部分:
第一部分是 .text,它的虚拟地址是 0x1000,它的虚拟大小是 0x23E4C(所以该部分的结尾是 0x1000 + 0x23E4C = 0x24E4C
)。
0x134B0 在 0x1000 和 0x24E4C 之间吗?
0x1000 >= 0x134B0 < 0x24E4C
-> 正确:所以地址位于 .text 部分。
注意:对每个部分重复相同的过程,直到找到正确的部分。
SECRVA = 0x1000
(部分虚拟地址)
RVA - SECRVA = OFFSET ; 0x134B0 - 0x1000 = 0x124B0
SECRAWADDR = 0x400
(部分原始地址)
OFFSET + SECRAWADDR = INSDATAOFFSET ; 0x124B0 + 0x400 = 0x128B0
如果我们查看文件中的 0x128B0
,我们有:
所以我们在文件 (0xE8B3040000
) 中发现了与内存中完全相同的字节。
我正在修改一个旧的废弃软件游戏以获得无限生命。
包含指令dec ecx
的地址与其在被调试的.exe中的位置不一致
记得有一次老朋友告诉我,有一个公式可以通过.exe里面的指令得到"true"地址。作弊引擎给了我内存地址。我记得在数学公式中,我需要得到模块,在 OllyDbg 中我得到了它。但是我不记得公式了。有人知道那个数学公式是怎么来的吗?公式非常简单! 还有另一种获取文件位置永久修改.exe的方法吗?
当然有公式
我们只需要反转 PE 加载器所做的事情:
- 找到文件中 PE 部分开始的位置。
这些数字称为文件偏移量。 - 相对于基地址,定位 PE 部分必须加载到内存中的位置。
这些地址称为 RVA(相对虚拟地址) - 选择1一个可用的基地址并将其添加到 RVA。
这些地址被称为VAs(Virtual Addresses),是文件偏移量的最终地址。
为了帮助理解以下步骤,请记住每个 PE 部分都具有以下属性:
- 起始文件偏移量,节在文件中开始的位置。
- 文件中的长度。
- 一个起始内存地址,该节应该加载到内存中的位置(相对于基地址)
- 一旦加载到内存中的长度(这可能与文件长度不同)。
因此对于给定的内存地址 X,您必须:
- 减去基地址,对于遗留 Windows 程序,这通常是 40 0000h。
- 你现在有一个 RVA,找到第一个 PE 部分,它的起始内存地址低于 RVA,结束内存地址在它之后2。
- 减去节起始内存地址,您现在有一个节偏移量。
- 添加节起始文件偏移量,您现在有一个文件偏移量。
有一个名为 PEEditor 1.7 的工具可以为您执行此操作。
由于某种原因,现在很难找到它,但它应该仍然存在于 Internet 上。请记住:它是免费的。
找到PE编辑器:Here,使用密码tuts4you解压RAR包
加载文件(通过拖入 window 或使用浏览按钮)然后点击 FLC(文件位置计算器)。在新的window中输入地址。
1 多半这实际上意味着使用PE中设置的基地址header,多亏了分页。
2计算为内存起始地址+内存长度-1
有一个 "formula" 但您实际上需要查看可执行文件的内部(尽管可以根据一些假设简化此公式)。
- 获取你感兴趣的指令/数据的内存地址(虚拟地址)[VA]
- 获取指令/数据所在模块的基址。 [MODBASE]
- VA减去MODBASE,得到所谓的相对虚拟地址[RVA]:
- VA - MODBASE = RVA
- 用 PE 文件解析器/编辑器打开二进制文件(例如 *.exe 或 *.dll)并查看 headers. 部分
- 找到您的 RVA 所在的部分。
- 找到 RVA 所在的部分后,获取“相对虚拟地址”部分。 [SECRVA].
- 从 RVA 中减去 SECRVA,然后得到 [OFFSET]。
- RVA - SECRVA = OFFSET
- 获取您在 5. 找到的部分的 RawAddress [SECRAWADDR]
- 在[SECRAWADDR]中加上[OFFSET],结果就是你要查找的指令/数据在二进制文件。
- OFFSET + SECRAWADDR = INSDATAOFFSET(指令或数据在磁盘文件中的偏移)。
假设
通常(我坚持通常,有时情况并非如此),第一部分的[SECRVA]将是0x1000——恰好是代码部分——并且它的 [SECRAWADDR] 将是 0x400.
因此,如果您根据指令在内存中的地址搜索指令的偏移量,通常可以假设:
SECRVA = 0x1000
SECRAWADDR = 0x400
例子
示例基于 cmd.exe。
假设我在 0x1C34B0
处搜索此代码,当程序加载到内存中时:
CPU Disasm
Address Hex dump Command Comments
001C34B0 /$ E8 B3040000 CALL 001C3968
001C34B5 \.^ E9 2EFEFFFF JMP 001C32E8
注意指令操作码(字节)为:0xE8B3040000
VA = 0x1C34B0
- 正在内存中搜索模块库(使用调试器或 ProcessExplorer;此处有趣的列在进程资源管理器中简称为 "Base"。):
MODBASE = 0x1B0000
VA - MODBASE = RVA ;
0x1C34B0 - 0x1B0000 = 0x134B0
;RVA = 0x134B0
用PE编辑器打开二进制文件(我用的是CFF explorer):
- 让我们看看0x134B0在哪个部分:
第一部分是 .text,它的虚拟地址是 0x1000,它的虚拟大小是 0x23E4C(所以该部分的结尾是 0x1000 + 0x23E4C = 0x24E4C
)。
0x134B0 在 0x1000 和 0x24E4C 之间吗?
0x1000 >= 0x134B0 < 0x24E4C
-> 正确:所以地址位于 .text 部分。
注意:对每个部分重复相同的过程,直到找到正确的部分。
SECRVA = 0x1000
(部分虚拟地址)RVA - SECRVA = OFFSET ;
0x134B0 - 0x1000 = 0x124B0
SECRAWADDR = 0x400
(部分原始地址)OFFSET + SECRAWADDR = INSDATAOFFSET ;
0x124B0 + 0x400 = 0x128B0
如果我们查看文件中的 0x128B0
,我们有:
所以我们在文件 (0xE8B3040000
) 中发现了与内存中完全相同的字节。