C++ , Cheat Engine / OllyDBG 查找基础“静态”多级指针的地址

发布于 2024-11-08 01:58:04 字数 2077 浏览 1 评论 0原文

我又回来了,沮丧并拼命寻求帮助: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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枉心 2024-11-15 01:58:04

我认为你误解了作弊引擎的目标。

CE 允许您修改以持久方式存储在内存中的值。例如,在堆上,或者在程序的静态数据中。

例如,C++ 对象以确定性方式分配,因此它们永远不会移动。这就是为什么它们可以通过在对象的整个生命周期中保持不变的指针来引用。该对象有时由另一个对象拥有。如果您找到指向所有者对象的指针,您就找到了所谓的基指针

例如:

class Object
{
    bool dummy;
    int someField;
    Object* child;
};

现在假设您有一个包含 3 个 Object 的嵌套树。这意味着您有一个根 Object (n°1),其 child 是另一个 Object (n°2),其 child 是另一个对象 (n°3)。想象一下您做了这样的事情:

int main(int argc, char** argv)
{
    Object root; // n°1
    root.child = new Object(); // n°2
    root.child->child = new Object(); // n°3

    return 0;
}

您有兴趣弄乱 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 是栈底。

在此示例中:

function foo()
{
    int a;
    double b;
}

当调用 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 :

class Object
{
    bool dummy;
    int someField;
    Object* child;
};

Now imagine you have a nested tree of 3 Object. Meaning that you have a root Object (n°1), whose child is another Object (n°2), whose child is another Object (n°3). Imagine you do something like this :

int main(int argc, char** argv)
{
    Object root; // n°1
    root.child = new Object(); // n°2
    root.child->child = new Object(); // n°3

    return 0;
}

You're interested in messing with n°3's someField value. You know that the address of someField, relative to an Object, is of +sizeof(bool) = 1.
So (void*)&(object n°3) + 1 is a pointer to the someField 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 (or ESP if the function does not change the stack).
EBP is the top of the stack, while ESP is the bottom of the stack.

In this example :

function foo()
{
    int a;
    double b;
}

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 as ESP + 8) and b will be stored at EBP - sizeof(int) - sizeof(double) = EBP - 12 (same as ESP). 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文