C++,Cheat Engine/OllyDBG从多级指针中查找基本的"静态"地址

Chr*_*ian 6 c++ pointers offset memory-address

我又回来了,沮丧,拼命寻求帮助:D.

我试图为一个简单的程序创建一个作弊,它基本上是一个.dll文件,当它使用它的基地址注入它时,它将改变主程序的整数值.问题是,我找不到使用作弊引擎主要是因为有多个级别指针与NEGATIVE?偏移.例如:

//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**
Run Code Online (Sandbox Code Playgroud)

所以我继续使用"找出什么是......"来找到下一个指针,但是当使用T-SEARCH和第二级指针地址时,我会得到7到8个新的静态地址.

问题是,我不知道哪一个是正确的,因为作弊引擎REFUSES让我使用NEGATIVE添加指针?偏移.

例:

Base Pointer:
**mov eax,[epb-18] !!!** // Notice the **MINUS**
Run Code Online (Sandbox Code Playgroud)

并且除了一切之外,Cheat Engine拒绝接受具有负偏移的指针!

那么,是否有另一种从多个级别指针中查找基址的方法?欢迎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;
}
Run Code Online (Sandbox Code Playgroud)

我想要做的是用这个.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;
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我试图破解惠普!〜哦,等等,我已经说过了,哦,好吧,等等;)

谢谢你们,上帝保佑你们!

use*_*016 20

我认为你误解了Cheat Engine的目标.

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

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

例如 :

class Object
{
    bool dummy;
    int someField;
    Object* child;
};
Run Code Online (Sandbox Code Playgroud)

现在假设你有一个3的嵌套树Object.意味着你有一个根Object(n°1),它child是另一个Object(n°2),它child是另一个Object(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;
}
Run Code Online (Sandbox Code Playgroud)

你有兴趣搞乱n°3的someField价值.你知道someField相对于a 的地址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;
}
Run Code Online (Sandbox Code Playgroud)

当调用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)中.注意!编译器可以更改此顺序,因此变量的声明顺序在内存中不一定相同.优化也可以完全改变这一点.但是,让我们保持这个简单的好吗?

回到我们的主要例子.我们有哪些局部变量?只有根.因此root将直接位于EBP - 9.但是,这只是当main是调用堆栈顶部的函数时.没有调试器,你就无法做到.

让我们假设EBP在调用main时我们是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不在堆上或任何类型的持久内存中,但是它位于main的堆栈上,它几乎在所有程序中持续存在,因此它几乎就像是永久性的.CE通过扫描整个进程内存空间来帮助您找到静态地址

考虑到所有这些,您应该能够计算hp堆栈上的相对地址并找到一个静态指针(每次启动程序时,main都非常非常非常可能有静态帧地址).如果您需要帮助,请使用调试器!我推荐Immunity Debugger.