PlayerBase Entity Listの見つけ方

・プレイヤーオブジェクトとはメモリに実体化されたプレイヤーの構造体 インスタンスまたはエンティティとも言う
・プレイヤーベースポインターとはメモリに実体化されたプレイヤーオブジェクトの先頭アドレスを保持しているポインタ変数

PlayerBaseの見つけ方

仮にHPのアドレスを見つけたとします。
次にHPのアドレスにアクセスしている命令を調べmov [edi+E4],eaxとなっていれば、おそらくediがプレイヤーオブジェクトの先頭アドレスです。
あとはediの値でアドレス検索すれば緑色のベースポインターのアドレスがヒットするはずです。
ヒットしない場合はポインタースキャンを使ってください。

また、プレイヤーオブジェクトを見つければ必ずしも情報がざくざく見つかるわけではありません。
例えば風来のシレン5plusの場合、2D画面上の座標はありましたが、肝心のHP、満腹度、経験値は別の構造体にありました。
これはゲームを作成したプログラマーが構造体をどう定義するかによって変わってきます。
assault cubeのように1つの構造体にHP、名前、座標、弾丸などたくさんの値を定義していれば連鎖的に値を見つけることができます。

まずは何でもいいので値を見つけていき、ポインタースキャンInjection copyを使用して次回起動時からもその値を参照できるようにしておきます。
次にその値の近辺(同じ構造体)に他の情報がないかダンプ画面とdissect data structureを使用してゲームを動かしながら探します。
流れとしてはこんな感じです。

Entity Listとは

赤枠がプレイヤーベースポインター(PlayerBase)、青枠がプレイヤーオブジェクトの先頭アドレスです。

風来のシレン5plus

Counter Strike Source

Entity ListとはEntity(実体)が格納されている配列のことです。
上の画像のオフセットに注目してみると風来のシレンは0x8バイトずつ、CSSは0x10バイトずつアドレスが離れていることが分かります。
この2つのゲームの場合ポインター配列になっており、ポインターのアドレスが規則正しく並んでいるのが特徴的ですね。
Entity Listを見つける際はこの特徴を利用します。
どちらもオフセット0、つまり配列の先頭にプレイヤーの実体があるのも重要な点です。

参考URL

Cheat Engineのちょっとしたお役立ち情報

値を一気に固定する方法

固定したい値の行を選択してからスペースキーを押すと一気に固定できます。
下の画像でDaveとHALを固定したい場合はCtrlキーを押しながらDaveとHALを選択してスペースキーを押します。
EricからKITTまでを選択したい場合はまずEricをクリックして、Shiftキーを押しながらKITTをクリックすると連続して選択できます。
全選択するにはアドレスリストのどこかをクリックしてからCtrl+Aを押します。


スクリプト内の文字を一括変換

Cheat Engineでスクリプトを書いていると特定の文字を一括変換したいときがあります。
そういったときはテキストエディタをアクティブにした状態でCtrl + Rを押しましょう。
そうするとReplaceダイアログボックスが出現するので、Textに変更したい文字を、Replaceに変更後の文字を入力しReplace allをクリックすればすべて置換されます。
DirectionをForwardにするとカーソルがある位置から前を、Backwardにした場合はカーソルの位置から後ろにある文字を置換します。


Excuteボタンについて

Cheat Engineのスクリプトを学び始めてすぐにハマりがちなのがこのExtuteボタンです。
Cheat Engineのスクリプトが画期的なのはオンにすると改造コードに書き換えられ、オフにすると元のコードに戻るところにあります。
ただこのボタンを押してしまうと改造コードが書き込まれるだけで元に戻すことが出来ません。
したがってスクリプトを実行する場合はメニューバーのFileからAssign to current cheat tableを選択し、チートテーブルに追加してから実行するようにしましょう。



メインウインドウに戻るとAuto Assemble scriptというスクリプトが追加されており、赤枠部分をクリックすれば実行できます。

AAスクリプト内でのメモリの確保について

Auto assemblerスクリプトでメモリを確保する方法は2パターンあります。
alloc(val1,4)

label(val2)
val2:
  dd 0
です。
上の例では4バイトのメモリval1とval2を確保しています。どちらのやり方でも良いのですが、少し気になったので両者の違いを調べてみました。


テンプレートを使用してスクリプトを作成している場合、alloc(newmem,$1000)と始めに0x1000バイト分のスクリプト用のメモリが確保されます。上の画像だと1F0000から1F0FFFまでがnewmemになります。
allocで確保したメモリval1のアドレスは1F1000となっており、最初に0x1000バイトのメモリを確保しているにもかかわらず、また新たな領域にメモリを確保していることが分かります。
一方、val2はnewmem内にアドレスがあるため、こちらの方がメモリを無駄に使わずクリーンなやり方といえます。
正確に言うと元から確保してあるメモリ領域(newmem)に4バイト分0で初期化しただけということになります。
海外の方が作成したスクリプトを見てみるとやはりlabelを使用しているためこのやり方が推奨です。
label(val2)
code:
  sub [ebx+000004AC],eax
  mov [val2],ebx
  jmp return
val2:
  dd 0

逆アセンブラウインドウのコメント

アセンブリ言語を追いかけていると途中で何をやっていたのか分からなくなることがよくあります。
そういったときに役立つのがコメントです。
コメントを書き込みたい場合は右端にあるCommentの列をダブルクリックして入力することが出来ます。
Cheat EngineのメインウインドウでCtrl + Sを押してチートテーブルを上書き保存すればコメントも一緒に保存され次回起動時にも表示されるようになります。ぜひ解析に役立ててください。


ダンプ画面でのフェードアウト時間の変更

Cheat Engineで値を連鎖的に見つけるのに非常に役に立つのがダンプ画面です。
値が変化すると赤くなるのですが、元に戻るのが早すぎてどこだったかな?となりがちです。
そのような場合にダンプ画面上を右クリックからChange fade timerでフェードアウト時間を変更できます。
デフォルトだと1秒(1000ミリ秒)になっているので、5秒か8秒あたりにするとちょうど良いかなと思います。


XMMレジスタの値を確認する方法

64ビットのゲームを解析していると出てくるxmmレジスタですが、初見だとどうやって値を確認するの?となりますよね。
方法としてはまず該当の命令にブレークポイントを設置しブレークさせてから、↓画像の青矢印部分 > をクリックすると値を確認できます。


ゲームを一時停止する方法

Cheat Engineメインウインドウの左下にあるAdvanced Optionsをクリックし、赤矢印部分のアイコンをクリックすれば一時停止できます。


情報収集

Cheat Engineの各種使い方などを調べる際は以下のサイトを使っています。
検索のコツとしてはSearchをクリックしサイト内検索からgoogle searchを使用することです。
このgoogle searchが非常に優秀で自分が検索したキーワードに関連するスレッドを的確にリストアップしてくれます。
一番下のdiscordはチャットのようなもので、参加している人たちが自分の疑問をなげると、それに答えてくれる人がいて質疑応答のようになっています。ちょうどそれ自分も知りたかったことだ!となることがあり、かなり有益なのでおすすめです。

FearLess Cheat Engine
Cheat Engine Forum
Guided Hacking
CHEAT THE GAME - discord

Cheat Engineで風来のシレン5Plusをチートしよう! HPと満腹度、お金を無制限化

風来のシレン5PlusのHPと満腹度、お金をチートして無制限化する方法を紹介します。
正式名称は「不思議のダンジョン 風来のシレン5plus フォーチュンタワーと運命のダイス」
2020年12月3日に発売されたSteam版です。
各値をどのようにして見つけたかは後日時間があるときに追記します。
必要なのものはゲーム本体とCheat Engineの2つ。
それではやっていきましょう。

※始める前に
ゲームがクラッシュする可能性があるのでセーブデータのバックアップを取るか、新たに冒険データを作りそちらで実行するなどの対策をお願いします。クラッシュしてゲームが終了した場合、ダンジョン内で倒れたときと同様に持っている道具お金を失います。預けているものは失いません。

Array of byteを使用してアドレスを見つけよう

書き換えたい命令が4か所あるため、それらのアドレスを検索して見つけていきます。
下の太字になっている文字列がバイト配列(Array of byte)です。

address1
44 89 ? ? 33 C8 89 4F ? 45 85 ? 75 ? 41 3B ? 75 ? 8B F3
address2
89 57 ? 33 C8
address3
89 4F ? 45 85 ? 75 ? 41 3B ? 75 ? 8B F3
address4
89 4F ? 85 D2 75 ? 3B C2

それではゲームとCheat Engineを起動し、ShirenTheWanderer5plus.exeにアタッチしましょう。


次にCheat EngineメインウインドウにあるMemory Viewをクリックしてから、Ctrl + AでAuto assemble画面を開き、下にあるAAスクリプトをコピペしておいてください。
テンプレートみたいなもので後で書き換えます。

Auto Assemblerスクリプト(AAスクリプト)
[ENABLE]
assert(address1,44 89 ? ? 33 C8 89 4F ? 45 85 ? 75 ? 41 3B ? 75 ? 8B F3)
assert(address2,89 57 ? 33 C8)
assert(address3,89 4F ? 45 85 ? 75 ? 41 3B ? 75 ? 8B F3)
assert(address4,89 4F ? 85 D2 75 ? 3B C2)
address1:
  db 
address2:
  db 
address3:
  db 
address4:
  db 
[DISABLE]
address1:
  db 
address2:
  db 
address3:
  db 
address4:
  db 


メインウインドウに戻りArray of byteで検索する前に設定を変更します。
Memory Scan OptionsにあるWritableのチェックをクリックして黒い四角に変えてください。


Value TypeはArray of byteに変更します。


検索する準備ができたので、赤枠のようにバイト配列を入力し、First Scanをクリックしましょう。
上記の場合address1を検索しています。


そうすると↑画像のようにアドレスが一つだけヒットすると思います。
2つ以上あったり何もヒットしない場合は失敗です。


検索結果のアドレスを右クリックからDisassemble this memory regionを選択します。


逆アセンブラウインドウが出現し、目的の命令が選択された状態になりました。
必要なのは緑枠のAddressと赤枠のBytesの2つです。


命令の行を右クリックしてCopy to clipboardからBytesを選択し、アドレスとバイトをコピーしましょう。
私の場合アドレスがShirenTheWanderer5plus.exe+189CCB、バイトが44 89 5F 20となっているのでこれを例にとって解説します。
まずコピーしたアドレスShirenTheWanderer5plus.exe+189CCBをAAスクリプトピンク字のaddress1の部分と入れ替えてください。
次にバイトの44 89 5F 20を90 90 90 90に書き換え、命令を潰します。
address1:の次の行のdbの後ろに90 90 90 90を付け足します。

そうするとAAスクリプトは以下のようになると思います。
assert(ShirenTheWanderer5plus.exe+189CCB,44 89 ? ? 33 C8 89 4F ? 45 85 ? 75 ? 41 3B ? 75 ? 8B F3)
ShirenTheWanderer5plus.exe+189CCB:
  db 90 90 90 90

[DISABLE]セクションにもaddress1があるので、そちらは
ShirenTheWanderer5plus.exe+189CCB:
  db 44 89 5F 20
というふうにdbの後ろに元のバイトを入力しましょう。
この作業を残りのaddress2,3,4の3つ全て行ってください。

全ての作業が終わればAAスクリプトは↓画像のようになります。
これでAAスクリプトは完成です。


メニューバーのFileからAssign to current cheat tableを選択し、スクリプトをチートテーブルに追加します。


メインウインドウに戻ると上記画像のようにスクリプトが追加されていると思います。
あとは赤枠の部分をクリックしてスクリプトを有効にすれば完成です!
チェックをはずせば書き換えられたコードが元に戻ります。

お金を無限に引き出す

下記のコードをテキストファイルにコピペしてファイル名をShirenTheWanderer5plus.ctに拡張子ごと変更します。
そうするとCheat Engineのアイコンに変わると思うのでダブルクリックして起動してください。
<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="34">
  <CheatEntries>
    <CheatEntry>
      <ID>0</ID>
      <Description>"pointerscan result"</Description>
      <VariableType>4 Bytes</VariableType>
      <Address>"ShirenTheWanderer5plus.exe"+0093E448</Address>
      <Offsets>
        <Offset>16C</Offset>
        <Offset>C8</Offset>
      </Offsets>
    </CheatEntry>
    <CheatEntry>
      <ID>2</ID>
      <Description>"pointerscan result"</Description>
      <VariableType>4 Bytes</VariableType>
      <Address>"ShirenTheWanderer5plus.exe"+0093E448</Address>
      <Offsets>
        <Offset>44</Offset>
        <Offset>80</Offset>
        <Offset>C8</Offset>
      </Offsets>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols/>
</CheatTable>
まず銀行に行きお金をいくらか預けます。
次に↓画像のように引き出す金額を決める画面になったところでCheat Engineの方に移りましょう。



Valueの数字が現在預けている金額と一致するのを確認したあと、数字のあたりをダブルクリックして希望の金額を入力しOKをクリックします。
あとはゲーム画面に戻りそのまま決定ボタンを押せばチート成功です!


HPを減らないようにする

シレンのみHPが減らないようになります。
[ENABLE]
aobscanmodule(inf_health,ShirenTheWanderer5plus.exe,46 41 03 C9 41 89 4A 04 33 CA)
alloc(newmem,$1000,inf_health)
label(other)
label(hero)
label(return)

newmem:
  cmp [r10+A4c],1
  je hero
  jmp other
hero:
  //mov [r10+04],ecx
  xor ecx,edx
  //mov [r10],ecx
  jmp return
other:
  mov [r10+04],ecx
  xor ecx,edx
  mov [r10],ecx
  jmp return
inf_health+04:
  jmp newmem
  nop
  nop
  nop
  nop
return:
registersymbol(inf_health)

[DISABLE]
inf_health+04:
  db 41 89 4A 04 33 CA 41 89 0A
unregistersymbol(inf_health)
dealloc(newmem)