C++ , Cheat Engine / OllyDBG 查找基础“静态”多级指针的地址
我又回来了,沮丧并拼命寻求帮助:D。
我正在尝试为一个简单的程序创建一个作弊程序,它基本上是一个 .dll 文件,当使用其基地址注入主程序时,它将更改主程序中的整数值。问题是,我无法使用作弊引擎找到它,主要是因为有多个带有负数的级别指针?偏移量。例如:
//Starting pointer address
0x0033FCF0 -> 200
//Finding second level pointer using "Find out what's accessing this address" in Cheat Engine
**(mov eax,[ebp+08])** // **EAX=0x00000007** , **EPB=0x0033FCE8 => mov 00000007,[0033FCE8+08]**
2nd Level Pointer:
**(0033FCE8+18) -> 200**
所以我继续使用“找出什么是......”来查找下一个指针,但是在使用 T-SEARCH 和第二级指针地址时,我得到了 7 - 8 个新的静态地址。
问题是,我无法判断哪一个是正确的,因为作弊引擎拒绝让我使用负数添加指针?抵消。
示例:
Base Pointer:
**mov eax,[epb-18] !!!** // Notice the **MINUS**
最重要的是,作弊引擎拒绝接受具有负偏移量的指针!
那么,是否有另一种方法可以从多个级别查找基地址指点? 欢迎 OlyDBG / Idapro 解决方案。非常感谢大家!
这是我试图破解的简单程序的源代码:
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <stdlib.h>
int main(){
int hp = 100;
while(1){
std::cout << hp << std::endl;
Sleep(3000);
hp += 10;
system("cls");
}
return 0;
}
我想做的是用这个 .dll 编辑 hp 整数
#include <windows.h>
#define BASE 0xBASE_POINTERS_ADDRESS_WHICH_I_NEED_TO_FIND
#define OFFSET 0xTHE_OFFSET
#define VALUE 90
void MainFunction()
{
while(1)
{
if (GetAsyncKeyState(VK_MENU)&0x8000 && GetAsyncKeyState('C')&0x8000)
MessageBox(0,L"Alt + C was pressed!",L"MessageBox! ",0);
*(int*)((*(int*)BASE) + OFFSET) = VALUE;
Sleep(100); //Let the program rest, otherwise it hogs cpu resources.
}
}
BOOL WINAPI DllMain(HINSTANCE MyInstance,DWORD reason_for_call,LPVOID PointerToVoid)
{
if (reason_for_call == DLL_PROCESS_ATTACH) CreateThread(0,0,(LPTHREAD_START_ROUTINE)&MainFunction,0,0,0);
return true;
}
顺便说一句,我试图破解马力! 〜哦,等等,我已经说过了,哦,好吧,无论如何;)
谢谢你们,上帝保佑你们!
I'm back again, frustrated and desperately searching for help :D.
I am trying to create a cheat for a simple program, it's basically going to be a .dll file which will change an integer's value from the main program when it's injected to it using its base address. The thing is, I can't find it using cheat engine mainly because there are multiple level pointers with NEGATIVE? offsets. for example:
//Starting pointer address
0x0033FCF0 -> 200
//Finding second level pointer using "Find out what's accessing this address" in Cheat Engine
**(mov eax,[ebp+08])** // **EAX=0x00000007** , **EPB=0x0033FCE8 => mov 00000007,[0033FCE8+08]**
2nd Level Pointer:
**(0033FCE8+18) -> 200**
So I proceed to find the next pointer using "Find out what's .... " but while using T-SEARCH with the second-level pointers address and i get like 7 - 8 new static addresses.
The thing is, I cannot tell which one is correct because cheat engine REFUSES to let me add a pointer using a NEGATIVE? offset.
Example:
Base Pointer:
**mov eax,[epb-18] !!!** // Notice the **MINUS**
And on top of everything Cheat Engine refuses to accept a pointer with a negative offset!
So , is there another way of finding the base address from multiple level pointers?
OlyDBG / Idapro solutions are welcome. Thanks alot guys!
Here's the source code of the simple program I'm trying to hack:
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <stdlib.h>
int main(){
int hp = 100;
while(1){
std::cout << hp << std::endl;
Sleep(3000);
hp += 10;
system("cls");
}
return 0;
}
What i am trying to do is edit the hp integer with this .dll
#include <windows.h>
#define BASE 0xBASE_POINTERS_ADDRESS_WHICH_I_NEED_TO_FIND
#define OFFSET 0xTHE_OFFSET
#define VALUE 90
void MainFunction()
{
while(1)
{
if (GetAsyncKeyState(VK_MENU)&0x8000 && GetAsyncKeyState('C')&0x8000)
MessageBox(0,L"Alt + C was pressed!",L"MessageBox! ",0);
*(int*)((*(int*)BASE) + OFFSET) = VALUE;
Sleep(100); //Let the program rest, otherwise it hogs cpu resources.
}
}
BOOL WINAPI DllMain(HINSTANCE MyInstance,DWORD reason_for_call,LPVOID PointerToVoid)
{
if (reason_for_call == DLL_PROCESS_ATTACH) CreateThread(0,0,(LPTHREAD_START_ROUTINE)&MainFunction,0,0,0);
return true;
}
By the way i am trying to hack the hp! ~ Oh , wait , i already said that , oh well , whatever ;)
Thank you guys, god bless you all!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为你误解了作弊引擎的目标。
CE 允许您修改以持久方式存储在内存中的值。例如,在堆上,或者在程序的静态数据中。
例如,C++ 对象以确定性方式分配,因此它们永远不会移动。这就是为什么它们可以通过在对象的整个生命周期中保持不变的指针来引用。该对象有时由另一个对象拥有。如果您找到指向所有者对象的指针,您就找到了所谓的基指针。
例如:
现在假设您有一个包含 3 个
Object
的嵌套树。这意味着您有一个根Object
(n°1),其child
是另一个Object
(n°2),其child
是另一个对象
(n°3)。想象一下您做了这样的事情:您有兴趣弄乱 n°3 的
someField
值。您知道someField
相对于Object
的地址为+sizeof(bool) = 1
。所以
(void*)&(object n°3) + 1
是指向您想要的someField
的指针。现在,如何找到指向对象 n°3 的指针?
知道
child
的相对地址是+sizeof(bool)+sizeof(int) = 5
。我们知道指向对象 n°3 的指针是(void*)&(object n°2) +
5。对象 n°2 的地址也是如此,我将其保留为一个练习。
但是对象 n°1 呢?它没有分配在堆上。它在堆栈上。废话。所以我们必须找到另一种方法来找到对象n°1存储的地址。
局部变量存储在堆栈中。在汇编中,它们通过相对于寄存器
EBP
(或ESP
,如果函数不更改堆栈)的偏移量来标识。EBP
是栈顶,而ESP
是栈底。在此示例中:
当调用 foo 时,堆栈将增加刚好足以容纳 a 和 b,即 sizeof(int) + sizeof(double),即 12 个字节。 a 将存储在
EBP - sizeof(int) = EBP - 4
(与ESP + 8
相同),b 将存储在EBP - sizeof(int) ) - sizeof(double) = EBP - 12
(与ESP
相同)。 注意!编译器可以更改此顺序,因此变量的声明顺序在内存中不一定相同。优化也可以彻底改变这一点。但让我们保持简单好吗?回到我们的主要例子。我们有哪些局部变量?仅根。因此根目录将直接位于
EBP - 9
。但这仅当 main 是调用堆栈顶部的函数时才有效。没有调试器,你就无法做到这一点。假设调用 main 时,我们的
EBP
为 0028FF28(取自新编译的 C 程序)。根位于 (0x0028FF28 - 9) = 0x0028FF1F;
指向 root.child 的指针位于 (0x0028FF1F + 5) = (0x0028FF24);
因此,
root.child
位于*0x0028FF24。指向
root.child->child
的指针位于 (*0x0028FF24 + 5) = (比方说 10000)那么
root.child->child
位于*10000。最后,
root.child->child.someField
位于*10000 + 3。总结一下:你只需要找到root的静态地址即可找到其余的。
root 不在堆或任何类型的持久内存上,但它在主堆栈上,该堆栈几乎在整个程序中持续存在,因此几乎就好像它是永久的。
CE 通过扫描整个进程内存空间来帮助您找到静态地址
考虑到所有这些,您应该能够计算
hp
在堆栈上的相对地址并找到指向它的静态指针(main每次启动程序时非常非常非常有可能有一个静态帧地址)。如果您需要帮助,请使用调试器!我推荐免疫调试器。I think you are misunderstanding the goal of Cheat Engine.
CE allows you to modify values that are stored in a durable way in memory. For example, on the heap, or in the program's static data.
For example, C++ objects are allocated in a deterministic way, and hence, they never move. This is why they can be referenced by a pointer that remains constant all over the object's lifetime. This object is sometime owned by another. If you find a pointer to the owner object, you found what is called a base pointer.
For example :
Now imagine you have a nested tree of 3
Object
. Meaning that you have a rootObject
(n°1), whosechild
is anotherObject
(n°2), whosechild
is anotherObject
(n°3). Imagine you do something like this :You're interested in messing with n°3's
someField
value. You know that the address ofsomeField
, relative to anObject
, is of+sizeof(bool) = 1
.So
(void*)&(object n°3) + 1
is a pointer to thesomeField
you want.Now, how do you find a pointer to object n°3 ?
Knowing that the relative address of
child
is+sizeof(bool)+sizeof(int) = 5
. We know that a pointer to object n°3 is(void*)&(object n°2) +
5.Same goes for the address of object n°2, I'll leave that as an exercise.
But what about object n°1 ? It's not allocated on the heap. It's on the stack. Crap. So we must find another way to find the address where object n°1 is stored.
Local variables are stored on the stack. In assembly, they are identified by their offset relative to the register
EBP
(orESP
if the function does not change the stack).EBP
is the top of the stack, whileESP
is the bottom of the stack.In this example :
When foo is called, the stack will be increased just enough to hold a and b, that is, sizeof(int) + sizeof(double), or 12 bytes. a will be stored at
EBP - sizeof(int) = EBP - 4
(same asESP + 8
) and b will be stored atEBP - sizeof(int) - sizeof(double) = EBP - 12
(same asESP
). Attention! The compiler can change this order, so the declaration order of your variables isn't necessarily the same in memory. Optimizations can also change this completely. But let's keep this simple okay ?So back to our main example. What local variables do we have ? root only. Therefore root will be located at
EBP - 9
directly. But this, ONLY when main is the function on top of the call stack. Without a debugger, you can't do it.Let's assume that our
EBP
is 0028FF28 when main is called (taken from a freshly compiled C program).root is then at (0x0028FF28 - 9) = 0x0028FF1F;
the pointer to
root.child
is at (0x0028FF1F + 5) = (0x0028FF24);Therefore,
root.child
is located at *0x0028FF24.The pointer to
root.child->child
is at (*0x0028FF24 + 5) = (let's say 10000)Then
root.child->child
is at *10000.Finally,
root.child->child.someField
is at *10000 + 3.To sum up: you just need to find the static address of root to find the rest.
root is NOT on the heap or any kind of durable memory, but it is on main's stack, which lasts during almost all the program, so it's almost as if it were permanent.
CE helps you find a static address by scanning the entire process memory space
With all this in mind, you should be able to calculate
hp
's relative address on the stack and find a static pointer to it (main is very, very, very likely to have a static frame address every time you launch the program). If you need help, use a debugger ! I recommend Immunity Debugger.