Cheat EngineでC言語が使える!? {$luacode}{$ccode}について
Cheat Engine7.3からAAスクリプト内で{$luacode}と{$ccode}が使えるようになりました。この2つはパラメーターを受け取ることができ、レジスタの値をスクリプト内に引っ張ってくることが出来ます。
何ができるのかを要約して言うと
「レジスタの値をスクリプト内に引っ張ってきて、CやLuaでいじくりまわしてそのままレジスタに返す」
といった感じです。
下記がサンプルコードです。
{$CCODE playerbase=RCX newhealth=RBX} <- ここでパラメーターを受け取っている int isplayer=*(*int)(playerbase+0xb8); if (isplayer) newhealth=100000; else newhealth=0; {$ASM}
1行目のRCXとRBXがパラメーターで、パラメーター名が実際のレジスタ名と同じになっています。例えばRCXレジスタの値をスクリプト内で使いたい場合はパラメーターRCXを使うという意味です。つまり、そのままの名称を書けばいいわけです。
上のコードではRCXにプレイヤーベースが、RBXにプレイヤーの新しい体力が格納されています。そこからRCXの値をplayerbaseという変数に、RBXの値をnewhealthという変数に代入しています。それらをC言語の構文を使って最終的にnewhealthに100000を代入して終了といった具合です。そしてこのnewhealthの値はスクリプトのリターン時にそのままレジスタに返されます。つまりRBXレジスタに格納されている値が100000になるということです。正確に言うとif (isplayer)が偽だとnewhealthは0になるんですがそこは説明の便宜上なかったことにしてください。
もうひとつ{$luacode}と{$ccode}を記述したAAスクリプトはターゲットプロセスにインジェクトすることができます。従来からある{$lua}はランタイム時には実行できないためインジェクトすることは出来ません。
このあたり私もまだ100%理解できていないため、説明するのが難しいのですがなんとなく便利そうなのが分かって頂けたと思います。なによりまだ登場して日が浅いのでサンプルコードも少ないです。興味がわいた方はCheat Engine WikiやCheat Engine Forumで調べてみてください。
また分かったことがあれば随時追記していきます。
https://forum.cheatengine.org/viewtopic.php?t=618134
https://wiki.cheatengine.org/index.php?title=Auto_Assembler:CCODE
{$luacode}作成時のエラーに関して
{$luacode}でつまずいたところをご紹介します。
まずCheat Engineのチュートリアルx64版を起動し、Step2まで進めておきます。Healthを減らす命令Tutorial-x86_64.exe+2B4BCに移動し、Tools -> Auto assemble -> Template -> Full Injectionを選択。
ここからnewmem:以下に下記のコードを追加します。
{$luacode decvalue=eax}
print(decvalue)
{$asm}
File -> Assign to current cheat tableとすると以下のエラーメッセージが出ました。
これを解決するにはFull Injectionでテンプレートコードを追加後、そのままFile -> Assign to current cheat tableとします。次に<script>をダブルクリックしてから{$luacode}のコードを追加後、OKをクリックし編集を完了させれば上記のエラーは出なくなります。
が、しかし今度は以下のメッセージが出ました。
これはそのままYesで大丈夫です。これで晴れてluacodeスクリプトを実行できるようになりました。結論としてはこの2つのエラーはおそらく構文チェックによるものです。
参考リンク
https://forum.cheatengine.org/viewtopic.php?t=618134
Dark Byte氏のコメントから引用
As for the lua error, that's just the syntax check. The syntaxcheck does not inject dll's into the target process, so call CELUA_ExecuteFunctionByReference will fail as the dll can't be found yet. But doing an actual run should be fine.
{$ccode}内からAuto Assemblerの変数を参照する
またちょっとしたエラーに遭遇しました。Dark Byte氏によると、{$ccode}内からAuto Assemblerの変数にアクセスできるみたいなので試してみました。構文は以下の通りです。
extern <type> aavarname
ターゲットプロセスは上と同じでCheat Engineのチュートリアルx64版、Step2、インジェクションポイントはTutorial-x86_64.exe+2B4BCです。
まずはalloc(value,4)でAuto Assemblerの変数を作成。
次にnewmem:以下に下記のコードを追加。
{$ccode}
extern int value = 10;
{$asm}
そうすると以下のエラーが出ました。
結果的に、以下のようにすることで解決できました。
{$ccode}
extern int value;
value = 10;
{$asm}
結論:
extern(グローバル変数の宣言)と変数への値の代入は分けて書く。
https://dl.dropboxusercontent.com/s/3z7ptkwbkaiogmm/Tutorial-x86_64.CT
Auto Assembler内からCの変数を参照する
これは簡単で{$ccode}もしくは{$c}内で通常通り変数を宣言し、AAから参照するだけです。
newmem:
{$c}
int value;
value = 0;
{$asm}
push rcx
lea rcx,[rbx+000007F8]
mov [value],rcx <- ここでCの変数を参照している
pop rcx
WindowsAPI関数を呼び出す
define(address,"Tutorial-x86_64.exe"+2B4BC) define(bytes,29 83 F8 07 00 00) [ENABLE] assert(address,bytes) alloc(newmem,$1000,"Tutorial-x86_64.exe"+2B4BC) label(code) label(return) newmem: //{$c} //extern int ShellExecuteA(int, char *, char *, char *, char *, int); //{$asm} {$ccode} #define SW_SHOWNORMAL 0x1 #define NULL 0 const char* path = "C:\\Program Files\\Cheat Engine 7.4\\autorun"; ShellExecuteA(NULL, "explore", path, NULL, NULL, SW_SHOWNORMAL); {$asm} code: sub [rbx+000007F8],eax jmp return address: jmp newmem nop return: [DISABLE] address: db bytes // sub [rbx+000007F8],eax dealloc(newmem)
- 関連記事