アドレス
 ストレートにいうと、読み書きする場所です。大抵は、頭に0xを付けた16進数もしくは10進数で書きますが、特殊な演算を必要とする場合、「アドレスコーディング」と呼ばれる計算式で書くことも出来ます。
0x400000
4194304
_ 0x400 * 52 +10
_ 0x400 * (52 +10)
_ [: 0x400000 :]
_ [_ [: 0x400000 :] _]
 上から2行はただの数値ですので、改めて説明する必要はないと思います。どちらもアドレスは0x40000になります。
難解度「AA」
 問題はその下、アンダーバー(_)ではじまる「アドレスコーディング」を用いた計算式です。アドレスコーディングでは、数値(オペランド)の他に演算子を含むことができ、すべての演算子を処理した結果(必ず数値になる)が、実際に読み書きするアドレスになります。
演算子※ 説明 ※
+ 加算演算子。算術演算子の一つ。前後2つのオペランドを加算します。
_ 0x400+0x20
※この結果は0x0420 です。
- 減算演算子。算術演算子の一つ。前のオペランドから後ろのオペランドを減算します。
_ 0x400-0x20
※この結果は0x03E0 です。
* 乗算演算子。算術演算子の一つ。前後2つのオペランドを乗算(掛け合わせる)します。
_ 0x400*0x20
※この結果は0x8000 です。
/ 除算演算子。算術演算子の一つ。前のオペランドを後ろのオペランドで除算した(割った)商を返します。
_ 0x400/0x20
※この結果は0x20 です。
% 除算演算子。算術演算子の一つ。前のオペランドを後ろのオペランドで除算した(割った)剰余(余り)を返します。
_ 0x400%0x20
※この結果は0 です。
& ビットごとのAND演算子。算術演算子の一つ。前後2つのオペランドでビットごとに論理積を取ります。
_ 0x400&0x20
※この結果は0 です。
^ ビットごとのXOR演算子。算術演算子の一つ。前後2つのオペランドでビットごとに排他論理和を取ります。
_ 0x421^0x20
※この結果は0x401 です。
| ビットごとのOR演算子。算術演算子の一つ。前後2つのオペランドでビットごとに論理和を取ります。
_ 0x400|0x20
※この結果は0x420 です。
~ ビットごとのNOT演算子。拡張された算術演算子の一つ。後ろのオペランドに0でないビットが存在するとき、前のオペランドの対応するビットを反転(論理否定)させます。
_ 0x430~0x20
※この結果は0x410 です。
(0x30は2進数で11 0000。0x20は2進数で10 0000。0x10は2進数で01 0000。)
< 関係演算子の一つ。前のオペランドが後ろのオペランドより小さいなら、1 を返し、それ以外なら0 を返します。
_ 0x400<0x20
※この結果は0 です。
<= 関係演算子の一つ。前のオペランドが後ろのオペランド以下なら、1 を返し、それ以外なら0 を返します。
_ 0x400<=0x20
※この結果は0 です。
> 関係演算子の一つ。前のオペランドが後ろのオペランドより大きいなら、1 を返し、それ以外なら0 を返します。
_ 0x400>0x20
※この結果は1 です。
>= 関係演算子の一つ。前のオペランドが後ろのオペランド以上なら、1 を返し、それ以外なら0 を返します。
_ 0x400>=0x20
※この結果は1 です。
== 等値演算子の一つ。前後2つのオペランドが等しいときは1 を、そうでなければ0 を返します。
_ 0x400==0x20
※この結果は0 です。
!= 等値演算子の一つ。前後2つのオペランドが等しくなければ1 を、等しければ0 を返します。
_ 0x400!=0x20
※この結果は1 です。
&& 論理AND演算子。論理演算子の一つ。前後のオペランドが 0 以外の値のとき、1 を返します。どちらかのオペランドが 0 のときは、0 を返します。なお前のオペランドが 0 のときは、後ろのオペランドを評価しません。
_ 0x400&&0x20
※この結果は1 です。
|| 論理OR演算子。論理演算子の一つ。前後のオペランドが 0 のとき、0 を返します。どちらかのオペランドが 0 以外のときは、1 を返します。前のオペランドが 0 以外のときは、後ろのオペランドを評価しません。
_ 0x400||0x20
※この結果は1 です。
[: :]
難解度「AA+」
ポインタ変換演算子。括ったオペランドをポインタと見なし、そのアドレスにある4バイトの数値を返します。
_ [: 0x400000 :]
※この結果は、アドレス0x400000 にある4バイトの数値です。

なお、所得を4バイト未満にしたい場合は、閉じ括りにバイト数を挟むことで可能になります。
_ [: 0x400000 :3]
_ [: 0x400000 :2]
_ [: 0x400000 :1]
[_ _] アドレス補正演算子。括ったオペランドに、[adjustment]によるアドレス補正をかけた値を返します。
_ [_ 0x400000 _]
※この結果は、0x400000 にアドレス補正をかけた数値です。アドレス補正属性がないなら、0x400000 がそのまま使われます。
[. .] オフセット演算子。括ったオペランドに、[replace]によるオフセット値を加算した値を返します。
_ [. 0x400000 .]
※この結果は、0x400000 に[replace]のオフセット値を加算した数値です。オフセット値がないなら、0x400000 がそのまま使われます。
[~ ~] エンディアン反転演算子。括ったオペランドに、4バイト単位でエンディアン反転を行った値を返します。
_ [~ 0xFF00AA55 ~]
※この結果は、0x55AA00FF です。

なお、反転するバイト範囲を4バイト未満にしたい場合は、閉じ括りにバイト数を挟むことで可能になります。
_ [~ 0x400000 ~3]
_ [~ 0x4000 ~2]
※バイト単位での反転なので、1バイト用はありません。
MName:: モジュールアドレス演算子。次に続く文字オペランドをモジュール名に持つモジュールの、開始アドレスを返します。
_ MName::GDI32.dll
※この結果は、対象プロセスにおけるモジュール「GDI32.dll」の開始アドレスです。

なお、オペランドの連続は許されていないので、「MName::GDI32.dll 0x400」といった書き方はあり得ませんが、読みにくいようなら、()による表記で対応しても良いでしょう。
_ (MName::GDI32.dll) + 0x400
_ 200 - (MName::KERNEL32.dll) + 0x20
※モジュール名は、大文字小文字を区別しません。
HNumber:: ヒープアドレス演算子。次に続く数値オペランド番目のヒープの、開始アドレスを返します。
_ HNumber::1
※この結果は、対象プロセスにおける1番目のヒープ(Heap1)の開始アドレスです。
※ヒープ番号は、1から始まります。
$変数名 擬似変数。演算子ではなくオペランドの一種です。次に説明する変数代入と組み合わせて使います。「変数名」の指す変数の値を返します。
_ $tmp + 2
※変数「tmp」が一度も代入されていないため、$tmpは0として扱われ、この結果は2になります。
=> 変数名 変数代入演算子。「=>」に続く変数名の変数を定義し、前のオペランドの値を代入します。ただし、$Valは予約語変数のため、ここでは使用できません。
_ 0x400 => tmp; $tmp+0x10;
※この結果は、0x410 です。
なお、例中の「;」については、次節「アドレスコーディングの分割」を参照してください。
各演算子の優先順位は、高い順に並べると
MName::, HNumber::
*, /, %
+, -
=>
<, >, <=, >=
==, !=
&, ^, |
&&, ||
[: :], [~ ~], [. .], [_ _]
です。同順位の演算子は、前にある方から処理されます。なお、括弧()を使って、演算の順位を変えることも出来ます。
 多くの場合アドレスコーディングを使うことはありませんが、一部特殊な変換を必要とするプロセスの場合、その威力を発揮します。必要になってから学んでもいいかもしれません(笑)

 ※一括系等でアドレスを羅列したリストの場合、ちょっと注意が必要です。項目自体のアドレスには[replace]のオフセット加算やアドレス補正が適用されますが、リスト内のアドレスは、数値変換のみ行われます。リスト内のアドレスにも変換を行う場合は、アドレスコーディングを使って明示してください。

なお、主にアドレス補正属性等で使用する手ですが、以下のように対象プロセスのヒープやモジュールの開始アドレスを示す指定法もあります。
heap1
module1
heapNは、N番目のヒープの開始アドレスを指します。
moduleNは、N番目のモジュールの開始アドレスを指します。
ともに、添字Nは1から始まります。


難解度「AA+」
アドレスコーディングの分割
 変数代入演算子の説明で使用していますが、アドレスコーディングはセミコロン(;)単位で分割することが出来ます。この場合、最後の処理結果が採用されるわけですが、今のところ変数代入演算子を使わない限り、利用価値はないと思われます。
 もうひとつ、アドレスコーディングは'_'から始まると書きましたが、@から始める記述法もあります。この場合、別ファイルにアドレスコーディングを記述できます。書式は
@チェインファイル名
となります。(ファイル指定の詳細は、《C-ファイル指定》を参照。)
 このようにして呼び出されるチェインファイル内には、複数行に渡ってアドレスコーディングを記述できます。(最初に'_'は不要)
[subject]体力:calc,@チェインファイル,0,99

チェインファイル.CHN
[:0x400000:] + [:0x400010:] => フラグ;
[: $フラグ :] + $フラグ;
 アドレスコーディング部分が長くなりすぎる場合などに利用すると、分かりやすく記述できるでしょう。




ねくすと せくしょん⇒

≪せくしょん ばっく