# Cheat Engine

## Cheat Engine

Cheat Engine é uma ferramenta para modificação de jogos offline, voltada principalmente para jogos de um jogador. No entanto, ela oferece um conjunto robusto de utilitários que a tornam útil para diversas outras finalidades, não se limitando ao contexto de jogos.

Algumas das ferramentas mais úteis disponíveis são:

* *Scanner* de memória;
* *Debugger*;
* *Disassembler*;
* *Assembler*;
* *Speedhack*;
* *Trainer Maker*;
* E muito mais...

Além disso, o Cheat Engine possui suporte a *scripts*, o que facilita o compartilhamento de modificações automatizadas.

Nas próximas seções, serão demonstradas as funcionalidades mais básicas da aplicação, utilizando como alvo o próprio **Tutorial (x32)** incluso com a instalação padrão. Note que os passos do tutorial não estarão em ordem, eles vão estar dentro da seção que descreve as funcionalidades dele.

## Buscar valores na memória

Buscar por valores na memória é a funcionalidade mais básica do Cheat Engine, e já está presente logo na tela inicial:

![Tela Inicial](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-cbac88c0e2ba59121266ec941d8e5b3b3aaa2778%2Ftela_inicial_cheat.png?alt=media)

O lado direito da interface é responsável pela configuração da busca: é possível definir o tipo de busca, o tipo do valor, o valor desejado, entre outras opções. O lado esquerdo mostra os resultados da busca, incluindo o endereço na memória, o valor atual armazenado e o valor encontrado na busca inicial.

Na parte inferior temos a ***Cheat Table***, onde ficam armazenados os valores que queremos manipular ou monitorar, assim como *scripts* que podem ser ativados ou desativados. No topo da interface estão as opções para abrir um processo, carregar uma *Cheat Table* ou salvar a atual.

Para abrir o tutorial, vá em ***Help*****&#x20;→ Cheat Engine Tutorial**, e em seguida abra o processo correspondente ao tutorial por meio do botão de seleção de processos. Este tutorial é um guia prático que ensina, passo a passo, as funcionalidades mais básicas do Cheat Engine. Cada etapa só pode ser completada utilizando as ferramentas ensinadas.

### Passo 2: Buscar e modificar a vida

Ao avançar a introdução, chegamos ao **Passo 2**, que solicita a modificação do valor da vida para 1000. O primeiro passo é localizar esse valor na memória.

![Setup](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-16a151d96453a68dbcc77336f62e9a6fc954d1a4%2Fsetup_step_2.png?alt=media)

Neste caso, a configuração padrão da busca já é suficiente. Precisamos apenas:

* Informar o valor atual da vida (`100`);
* Selecionar o tipo de valor como `4 Bytes`;
* Escolher o tipo de busca como ***Exact Value*** (Valor Exato).

{% hint style="info" %}
Em muitos casos não saberemos o valor exato ou o tipo de dado que estamos procurando. O Cheat Engine permite buscar por **valores desconhecidos** e **todos os tipos de dados**, o que é útil para experimentação.
{% endhint %}

Após definir os parâmetros corretamente, clique em ***First Scan*** para realizar a primeira varredura.

![Resultado da primeira busca](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-88da429b613f00945c6873cceb8e83cba9996365%2Fresult_1_step_2.png?alt=media)

Como resultado, apareceram vários endereços com valor `100` (43 no exemplo). Uma abordagem ingênua seria alterar todos esses valores para `1000`, mas isso pode causar o encerramento do processo ou comportamentos indesejados.

O próprio tutorial fornece uma opção chamada ***Hit me***, que diminui o valor da vida. Após clicar, o valor passou para `99`. No exemplo, apenas um dos 43 endereços mudou de `100` para `99`, facilitando sua identificação. Contudo, em muitos casos reais, **vários valores podem mudar simultaneamente**, e essa identificação requer uma busca mais refinada.

Neste momento, novas opções de busca se tornam úteis: é possível procurar por **valores aumentados, diminuídos, alterados, ou inalterados**. No caso, como sabemos o valor exato (`99`), é mais eficaz continuar com uma busca exata.

{% hint style="warning" %}
Para refinar a busca, clique em ***Next Scan***. A opção ***New Scan*** reinicia a busca do zero.
{% endhint %}

Resultado da segunda busca:

![Resultado da segunda busca](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-a79187d3c5557656bdb499355a906ec4bf4049a9%2Fresult_2_step_2.png?alt=media)

Dando dois cliques no endereço encontrado, ele será adicionado à *Cheat Table*. A partir dali é possível:

* Travar o valor ativando a opção `Active`;
* Modificar o valor diretamente (basta dar dois cliques sobre ele);
* Alterar o tipo de dado (isso muda apenas como o Cheat Engine interpreta o valor, e **não** como o jogo o trata);
* Mudar o nome/descritivo da entrada.

Para completar o passo, basta alterar o valor da vida para `1000`.

### Passo 3 e 4: Valores desconhecidos e ponto flutuante

O **Passo 3** do tutorial trata de valores inicialmente desconhecidos, simulando uma barra de vida, onde é necessário usar buscas baseadas em mudanças (aumentou/diminuiu/etc). Já o **Passo 4** introduz a busca de valores em ponto flutuante, como `float` ou `double`.

Apesar da diferença nos tipos de dado e na forma de busca, o procedimento geral continua o mesmo do **Passo 2**:

* Realizar uma busca inicial;
* Realizar ações no tutorial que alterem o valor;
* Refinar a busca com base nas alterações observadas;
* Localizar o endereço correto;
* Adicionar à *Cheat Table* e modificar conforme necessário.

## Ponteiros

Ponteiros são valores na memória que armazenam o endereço de outra região da memória, a qual pode conter dados importantes, como a vida de um personagem em um jogo. A importância de se encontrar ponteiros, ao invés de apenas endereços diretos, reside no fato de que sistemas operacionais modernos aplicam técnicas de segurança como o **ASLR** (*Address Space Layout Randomization*), que faz com que os endereços de memória utilizados por um processo sejam aleatórios a cada execução.

Com isso, todos os endereços encontrados nos passos anteriores serão inutilizados assim que o processo for encerrado.

O mesmo problema acontece com ponteiros simples: o endereço armazenado por eles pode mudar a cada execução. Felizmente, há dois conceitos que nos ajudam a contornar esse problema:

* *Offsets*;
* Endereços base (*base addresses*).

### Offsets

*Offsets* são valores fixos, utilizados como deslocamento em relação a um endereço inicial para acessar uma posição específica da memória. Para ilustrar isso, considere a seguinte estrutura em C:

{% code title="struct.c" overflow="wrap" lineNumbers="true" %}

```c
struct Teste {
	int x;
	int y;
};
```

{% endcode %}

Essa estrutura contém dois inteiros. O campo `x` está no início da estrutura, portanto tem *offset* 0. Já o campo `y` vem logo após `x`. Como `x` é um `int` (`4 Bytes`), o campo `y` estará a um *offset* de 4.

Assim, se tivermos um endereço de uma estrutura `Teste`, podemos acessar `y` somando 4 a esse endereço.

Em resumo:

* Os *offsets* são fixos e são independentes do ASLR ou da execução do processo;
* Podem ser usados para navegar dentro de regiões da memória de forma confiável.

### Endereços base (*Base Addresses*)

Endereços base são endereços fixos que servem como ponto de partida para cálculos de posições relativas. Eles representam o início de uma região alocada por um módulo carregado pelo processo, como o próprio executável (`.exe`) ou bibliotecas dinâmicas (`.dll`). Apesar do ASLR alterar esses endereços a cada execução, eles podem ser identificados por nome (por exemplo, `Tutorial-i386.exe`) e o Cheat Engine sabe resolver esses nomes para o endereço correto a cada execução.

Isso significa que podemos usar nomes simbólicos para referenciar essas bases, o que torna possível criar ponteiros duráveis, mesmo em meio à aleatoriedade do ASLR. Você pode testar isso:

1. Vá em *Add Address Manually*;
2. No campo *Address*, digite `Tutorial-i386.exe`;
3. Reinicie o tutorial algumas vezes, abra o processo novamente no Cheat Engine, e verá que o endereço base se manterá correto.

Esses endereços base, quando combinados com *offsets*, nos permitem calcular endereços relativos de forma consistente. Por exemplo, se sabemos que a vida do jogador está localizada a `+28` do início do módulo `Tutorial-i386.exe`, podemos sempre calcular esse valor independentemente da execução específica.

{% hint style="info" %}
Em ferramentas como o Cheat Engine, você pode referenciar endereços usando a notação simbólica: `Tutorial-i386.exe+28`. Esse tipo de referência continuará funcionando mesmo que o processo seja reiniciado.
{% endhint %}

### Ponteiros Multinível (*Multilevel Pointers*)

Quando o valor que queremos acessar não está diretamente no endereço base, mas em uma cadeia de ponteiros, temos o que chamamos de ponteiros *multilevel*.

Por exemplo:

1. Um ponteiro A armazena o endereço de B;
2. B armazena o endereço de C;
3. C contém o valor desejado (ex.: vida).

Nesse caso, para alcançar o valor final, você precisará de vários *offsets*, aplicados sequencialmente. Isso é importante:

{% hint style="warning" %}
Os *offsets* de ponteiros multinível não são somados de uma vez. Cada *offset* é aplicado ao conteúdo do ponteiro anterior.
{% endhint %}

Por exemplo, se você tem:

* Endereço base `X`;
* Offsets: `[2, 5]`.

A sequência será:

1. `Y = [X + 2]` → leia o valor apontado por `X + 2`;
2. `Z = [Y + 5]` → leia o valor apontado por `Y + 5`;
3. `Z` contém o valor final.

Em Assembly, o acesso a ponteiros é feito com colchetes. Então:

```asm
mov eax, [edi+04]
```

Significa: *carregue em EAX o valor armazenado no endereço* `EDI + 4`, onde `EDI` pode conter um endereço base e `4` seria o *offset*.

### Passo 6: Encontrando ponteiros com o Cheat Engine

Neste passo, o objetivo é encontrar um ponteiro que leve até um determinado valor no tutorial e, em seguida, fixar esse valor em 5000. Antes de explorarmos os métodos para encontrar ponteiros, precisamos primeiro localizar o valor desejado usando a ferramenta de busca do Cheat Engine.

Utilize o botão de alteração de valor no tutorial e a funcionalidade de busca do Cheat Engine para encontrar o endereço onde esse valor está armazenado. Uma vez identificado, há duas formas principais de localizar ponteiros que apontam para ele: através de uma busca manual na memória (*scan*) ou utilizando o recurso de *pointer scan*.

#### Achando ponteiros por meio de *scan*

Uma das abordagens para encontrar ponteiros consiste em procurar por regiões da memória que armazenam o endereço do valor que desejamos. Essas regiões funcionam como "ponteiros", ou seja, locais que contêm o endereço de outro local na memória.

{% hint style="warning" %}
*Ponteiros têm tamanhos diferentes de acordo com a arquitetura do processo.* Em processos de 32 bits, os ponteiros ocupam `4 Bytes`, enquanto em 64 bits ocupam `8 Bytes`. Portanto, certifique-se de configurar o tipo de dado corretamente ao fazer a busca.
{% endhint %}

Com isso em mente, execute uma busca pelo valor do endereço (por exemplo, `0x0178FA90`). Se o valor realmente for acessado via ponteiro simples, você poderá encontrar um endereço que contenha esse valor, o que indica um ponteiro direto.

![Resultado da primeira busca](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-88ad45608b54bbe6eb039c960bee3e20694b5229%2Fresult_1_step_6.png?alt=media)

Neste exemplo, encontramos um ponteiro que é calculado com base na imagem principal do executável (`Tutorial-i386.exe`). Isso significa que o ponteiro usa um endereço base, que é mais estável mesmo após reiniciar o processo, tornando-o um bom candidato.

Por padrão, ao adicionarmos esse resultado à *Cheat Table*, ele é tratado como um valor comum, não como um ponteiro. Para torná-lo um ponteiro:

1. Clique duas vezes sobre o endereço adicionado;
2. Marque a opção ***Pointer***;
3. No campo principal (acima de *Add Offset*), insira o endereço base, como `Tutorial-i386.exe+2426B0`;
4. Como não há *offset* neste caso (o ponteiro acessa diretamente o valor), defina um *offset* de `0`.

![Ponteiro](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-8062516ac34c4393f7b54cdfd0f3496dbc445dbd%2Fchange_pointer_step_6.png?alt=media)

Agora o valor pode ser alterado para 5000, e travado clicando na caixinha ao lado dele.

{% hint style="warning" %}
Se a busca não retornar resultados, isso pode indicar que:

* O valor não é acessado diretamente por um ponteiro;
* Ele é acessado via uma cadeia de ponteiros, cada um com seu *offset*. Para investigar isso, clique com o botão direito sobre o valor encontrado e selecione ***Find out what accesses this address***. Esse recurso permite descobrir quais instruções estão manipulando o valor e nos ajudará na análise de ponteiros *multilevel*, como veremos mais adiante.
  {% endhint %}

#### Usando *Pointer Scan*

O problema da abordagem anterior é que ela só encontra ponteiros diretos. Se o valor estiver acessível apenas através de uma cadeia de ponteiros com múltiplos *offsets*, essa busca não funcionará. É aí que entra o recurso ***Pointer Scan*** do Cheat Engine.

Esse recurso realiza uma varredura na memória em busca de cadeias de ponteiros (*multilevel pointers*) que levam até o endereço desejado. Ele considera automaticamente os *offsets* necessários em diferentes níveis.

Para usar:

1. Clique com o botão direito sobre o valor encontrado;
2. Selecione ***Pointer scan for this address***.

Aparecerá uma janela com opções para configurar a busca. A configuração padrão (buscar por ponteiros que apontam diretamente para o endereço) já é suficiente para a maioria dos casos. No entanto, se a busca não retornar resultados, você pode tentar ajustar opções como o número máximo de níveis (*max level*), ou ampliar o intervalo de memória a ser escaneado.

![Primeiro pointer scan](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-1bc01e750a03d2099f50611efc29b60a7b9f20e9%2Fpointer_scan_step_6.png?alt=media)

Após clicar em **OK**, o Cheat Engine solicitará que você salve os resultados da varredura. Esse arquivo é útil para análises futuras ou para refinar os resultados. A varredura então será iniciada, e uma lista de possíveis ponteiros será exibida.

![Resultado do primeiro pointer scan](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-12f17adb0830e131fdfe4c73a8f194a88f1e57b7%2Fresult_2_step_6.png?alt=media)

Nem todos os ponteiros retornados são válidos após reiniciar o processo. Para garantir que o ponteiro seja confiável, é necessário validar sua persistência.

Faça isso assim:

1. Use a opção ***Change Pointer*** no tutorial para forçar uma mudança no endereço do valor;
2. Selecione ***Pointer Scanner***, selecionando ***Rescan memory*** e forneça o novo endereço do valor.

{% hint style="info" %}
Se você tiver fechado a janela do *Pointer Scanner*, basta ir em ***Memory View*****&#x20;→&#x20;*****Tools*****&#x20;→&#x20;*****Pointer scan***, e abrir o arquivo anterior com ***File*****&#x20;→&#x20;*****Open***.
{% endhint %}

![Resultado do segundo pointer scan](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-6ef69f82388ddc4f264784381ddb60ef7392c7bb%2Fresult_3_step_6.png?alt=media)

O objetivo é encontrar ponteiros que continuem funcionando mesmo após o endereço do valor ter mudado. Quando isso acontece, podemos ter mais confiança de que o ponteiro encontrado é estável. Se apenas um ponteiro persistir, como no exemplo acima, ele é um bom candidato.

Adicione-o à *Cheat Table* com um duplo clique. Diferente da busca manual, o *Pointer scan* já adiciona o ponteiro com seus respectivos *offsets*, sem necessidade de edição manual.

Com o ponteiro adicionado, basta travar o valor em 5000.

### Passo 8: Ponteiros multinível

Este passo é bastante similar ao **Passo 6**: precisamos encontrar um ponteiro que aponte para o valor desejado e, em seguida, travar esse valor em 5000. No entanto, a diferença aqui é que estamos lidando com um ponteiro multinível, ou seja, um ponteiro que referencia outro ponteiro, que referencia outro, e assim por diante. Neste exemplo, são 4 níveis, portanto 4 *offsets*.

Embora possamos encontrar esse tipo de ponteiro facilmente com a funcionalidade *Pointer scan* do Cheat Engine, aqui demonstraremos como fazer isso manualmente, utilizando apenas a busca direta por ponteiros na memória.

Primeiro, encontramos o valor desejado no tutorial através da funcionalidade de alteração de valor. Suponha que o endereço encontrado seja `0x0173AD20`.

Com esse endereço, fazemos uma busca na memória procurando por qualquer local que contenha esse valor, ou seja, estamos procurando **por ponteiros que apontem diretamente para ele**.

![Resultado da primeira busca](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-11ebe7815c184f81a6ae8432b4204e76c69bb786%2Fresult_1_step_8.png?alt=media)

No exemplo acima, nenhum resultado foi retornado. Isso geralmente indica que o valor **não é acessado diretamente**, mas sim por meio de um *offset* a partir de outro endereço.

Como a busca direta falhou, clicamos com o botão direito sobre o valor e selecionamos a opção: ***Find out what accesses this address***.

Isso abrirá uma nova janela, inicialmente vazia. A partir desse momento, o Cheat Engine começará a monitorar o processo, observando quais instruções acessam o endereço monitorado.

Para ver as instruções, simplesmente alteramos o valor no tutorial, isso fará com que as instruções envolvidas no acesso apareçam na janela.

![Instrução de acesso](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-747cdc9287105d7380d406dbf68ef5f32ecddb3e%2Faccess_1_step_8.png?alt=media)

Duas instruções apareceram:

* `mov [esi + 18], eax`;
* `mov eax, [esi + 18]`.

Essas instruções indicam que o valor desejado está localizado em **`ESI + 0x18`**. Ou seja, `ESI` contém o endereço-base, e o valor fica em um *offset* de `0x18` a partir desse endereço.

{% hint style="warning" %}
Esse método exige atenção aos detalhes. É comum que instruções como `mov esi, [esi + 18]` confundam a análise, pois atualizam o registrador com um novo valor, e o valor mostrado pelo Cheat Engine será **após** a execução. Por isso, é essencial compreender o comportamento da instrução e o momento da captura.
{% endhint %}

Para descobrir qual valor `ESI` continha no momento da execução, clicamos sobre a instrução (clicar duas vezes abre uma nova janela com as informações). O Cheat Engine mostrará os valores utilizados.

![Valores nos registradores](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-1dacf3f408bd989310845104a584d980122a582e%2Faccess_2_step_8.png?alt=media)

Neste exemplo, `ESI` contém `0x0173AD08`, e: `0x0173AD08 + 0x18 = 0x0173AD20`.

Portanto, esse é o endereço intermediário, nosso próximo candidato a ser pesquisado. Buscamos por ele na memória da mesma forma que antes.

![Resultado da segunda busca](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-953546af4b88774dcc4f1beca69492be5e272f4f%2Fresult_2_step_8.png?alt=media)

Agora a busca retorna um resultado, que precisa ser convertido para ponteiro para mostrar o valor esperado.

![Corrigindo ponteiro](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-757af75b8011980c86eea76bf34ffe389192f1c0%2Fchange_1_step_8.png?alt=media)

Com esse novo endereço encontrado, repetimos os mesmos passos:

1. Buscar pelo endereço na memória (se houver um retorno direto, o *offset* é 0);
2. Usar a opção ***Find out what accesses this address*** novamente, caso a busca não retorne mais ponteiros diretos;
3. Observar os registros e os *offsets* usados para chegar ao valor;
4. Repetir até obtermos um ponteiro com todos os níveis necessários.

Como estamos lidando com um ponteiro multinível de 4 níveis, esse processo deverá ser repetido até descobrirmos todos os níveis intermediários, ou seja, até montarmos a cadeia completa de ponteiros e *offsets* que levam ao valor final.

Assim que tivermos o ponteiro completo (com todos os níveis e *offsets* corretamente configurados), basta definir o valor como 5000 e ativar a opção para travá-lo, assim como nos passos anteriores.

## *Auto Assembler*

Assembly é uma linguagem legível que serve para um "montador" converter em código binário que a máquina possa entender. O *Auto Assembler* é o montador usado pelo Cheat Engine, que consegue entender mais do que apenas Assembly.

Antes de nos aprofundarmos no *Auto Assembler*, é interessante ver alguns outros mecanismos que o Cheat Engine possui relacionados a Assembly.

O primeiro é a opção ***Memory View***, que nos mostra a memória do processo, mais especificamente, a parte de código Assembly. Ou seja, podemos ver o código da aplicação em Assembly da mesma forma que faríamos em outras ferramentas, como o Ghidra. Aqui também podemos procurar por valores na memória, buscar instruções específicas, usar ferramentas de *debug* como *breakpoints*, entre outras.

![Memory View](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-44aac75570581060ab883592b767e294337b3deb%2Fmemory_view.png?alt=media)

O segundo é a opção ***Find out what writes to this address***, que é muito similar à opção vista anteriormente, usada para ver o que **acessa** o endereço. Esta opção será discutida com mais detalhes no **Passo 5**.

### Passo 5: Buscando uma instrução

Existem diversas formas de se modificar um valor. Uma delas é encontrar o ponteiro para ele e alterá-lo diretamente. Mas e se quisermos, por exemplo, não tomar dano? Podemos travar o ponteiro da vida, mas isso pode ser uma solução forçada. A outra opção é modificar o código que altera a vida.

Neste passo, devemos identificar o valor especificado e alterar a instrução que o modifica, para que ele não seja alterado. A primeira etapa é encontrar esse valor.

Após encontrá-lo, clique com o botão direito sobre ele e vá em ***Find out what writes to this address***. Isso abrirá uma janela inicialmente vazia, que mostrará todas as instruções utilizadas para escrever nesse endereço. Para descobrir a instrução que modifica nosso valor, basta alterá-lo no tutorial.

![Instruções que escrevem no valor](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-93835e3e5356fef85eb31f16cfe65b26bd1057c6%2Fwrites_step_5.png?alt=media)

Essa janela é muito similar à usada para descobrir o que acessa o endereço, mas aqui estamos vendo quais instruções modificam o valor. Também podemos ver os valores dos registradores e até usar o ***Show disassembler***, que nos leva diretamente ao código no ***Memory View***. Porém, como nossa intenção aqui é simplesmente impedir que o valor seja alterado, podemos usar a opção ***Replace***, que substituirá a instrução inteira por um `nop`, que é uma instrução que não faz nada.

Pronto, basta alterar o valor no tutorial e verificar que ele não será mais modificado.

### Passo 7: Injeção de código

Neste passo, veremos o ***Auto Assembler*** em ação. O objetivo aqui é fazer com que o valor especificado não diminua, mas sim aumente em dois. Inicialmente, devemos procurar por esse valor e ver qual instrução o modifica.

![Instruções que escrevem no valor](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-5d3f458495e8f3ea73f008047783a0f837292829%2Fwrites_step_7.png?alt=media)

Uma vez encontrada a instrução, usamos o ***Show disassembler*** para ir à janela de ***Memory View***. Em seguida, vamos em ***Tools*****&#x20;→&#x20;*****Auto Assemble*** ou simplesmente pressionamos `Ctrl + A`.

Isso abrirá uma nova janela, onde podemos escrever o *script* que o Cheat Engine montará e injetará no lugar da instrução original. O interessante é que podemos ir em ***Template*** e visualizar *templates* prontos.

É recomendado usar o ***Full injection***, pois ele já vem com um *template* completo que permite ativar e desativar o *script*, mantendo-o na *Cheat Table*.

![Full Injection](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-8b1050f90c9bd557ee1749324baeb5e621d27d1c%2Ffull_injection_1_step_7.png?alt=media)

Esse *script* basicamente aloca um espaço para o novo código, identificado por `newmem`. No endereço original da instrução (identificado por `address`), ele altera o fluxo de execução para fazer um salto (`jmp`) para o `newmem`. Mas antes disso, ele salva a instrução original de `address`, para restaurá-la quando o *script* for desativado.

A *label* `code` contém o código original, e podemos escrever nela ou em `newmem`, apenas mantendo o `jmp return` no final. Substituindo a instrução para adicionar 2, o código fica assim:

![Script finalizado](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-2946c8509fff64036f8de159efce78ef4eeb996f%2Ffull_injection_2_step_7.png?alt=media)

Após modificar, podemos usar o botão ***Execute*** para injetar o código, ou ir em ***File*****&#x20;→&#x20;*****Assign to current cheat table*** para adicionar o *script* à *Cheat Table*, permitindo ativá-lo ou desativá-lo.

Feito isso, basta alterar o valor e verificar que ele aumenta em 2.

### Passo 9: Código compartilhado

Esse passo não mostra nenhuma funcionalidade nova, mas sim uma situação comum que ocorre em jogos, à qual devemos ficar atentos: códigos compartilhados entre entidades. Por exemplo, o código de "levar dano" pode ser compartilhado entre o jogador e os inimigos. Nesse caso, se removermos a instrução de dano, todos ficarão imortais.

Nessas situações, precisamos encontrar algum valor que identifique apenas as entidades desejadas, e então, no código de injeção, fazer comparações com esse valor.

O tutorial nos fornece 4 valores, representando 4 entidades de dois times diferentes. Inicialmente, encontre esses valores.

{% hint style="info" %}
Uma forma mais fácil de encontrar esses valores é buscar um deles. Após encontrar o primeiro, vá até a instrução que modifica sua vida no ***Memory View***. Clique com o botão direito sobre ela e vá em ***Find out what addresses this instruction accesses***. Isso abrirá uma nova janela, onde, ao modificar os outros 3 valores, eles aparecerão automaticamente.
{% endhint %}

Usando esse método de observar os endereços acessados pela instrução, uma funcionalidade adicional fica disponível: ***Open dissect data with selected addresses***. Essa opção faz com que o Cheat Engine tente descobrir se os endereços fazem parte de uma mesma estrutura. Se encontrar algo coerente, ele exibirá os outros campos da estrutura. Note que é necessário marcar os endereços que serão usados na estrutura.

Selecionando os 4 endereços e usando essa opção, obtemos a seguinte estrutura:

![Estrutura Entity](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-e2cad06a9df97484c08d6a8f312cc5c800cd19d4%2Fstruct_step_9.png?alt=media)

Note que o valor no *offset* `0x10` parece servir como identificador: 1 para as duas primeiras entidades, 2 para as duas últimas. Com isso, podemos escrever um *script* que verifique se o valor é 1 e, nesse caso, impeça que o dano seja aplicado.

![Script](https://3136530646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsIzz1GS79zTX2bE4IBNm%2Fuploads%2Fgit-blob-cfade5670e2e9dcdb139211e72ed9990fc73e0f6%2Fscript_step_9.png?alt=media)

Com o *script* pronto, basta usar a opção do tutorial, e ele será concluído com sucesso.

{% hint style="warning" %}
Caso você não utilize a funcionalidade de estrutura, será necessário encontrar outra forma de identificar os times. Neste exemplo, é possível observar os valores dos registradores no momento da execução da instrução. O registrador `ESI` contém o valor 1 para as entidades do time 2, enquanto para o time 1 os valores são 2 e 6.
{% endhint %}

## Fontes

[Cheat Engine Wiki](https://wiki.cheatengine.org/index.php?title=Main_Page)
