#08のKG(コンソール)


さて、KGを作っていこうと思っていますが、KGを作る時に解析できないと作れないと思っていますか?
実は、完璧に解析できなくても作れたりします(^^;
どこで、パスが作られているかわかれば作れます。(解析??)
一応は、解けた人を対象としています。
私の場合KGを作って解いたCrkmeもあります。(19なんかがそうですが)

それでは、#08のパスが作られている部分を見てみましょう。
図書室から拝借して・・・

004012AB  |. 33C0           XOR EAX,EAX          ← eax 初期化、ここに生成した値が入る
004012AD  |. 8B75 08        MOV ESI,DWORD PTR SS:[EBP+8]  ← 入力名のポインタが入る
004012B0  |> 0FBE0E        /MOVSX ECX,BYTE PTR DS:[ESI]  ← 入力名から一文字取り出しています。
004012B3  |. 83F9 00        |CMP ECX,0           ← ecx には入力名が一文字入っています。null文字(入力名の終端)か どうかを比較しています。
004012B6  |. 74 09          |JE SHORT CRKME08.004012C1   ← 入力名が終端ならチェック終了
004012B8  |. 03C1           |ADD EAX,ECX          ← eax に ecx(入力名文字)を足しています。eax にどんどん値が積み重なっていくことがわかります。
004012BA  |. F7E0           |MUL EAX            ← これは eax * eax を示しています。つまり2乗です。
004012BC  |. 33D2           |XOR EDX,EDX          ← mulを行うとedxとeaxに値がまたがって格納されますが、上位4バイトを消しています。
004012BE  |. 46             |INC ESI            ← esi は入力名のポインタ、これをインクリメントすることで次の文字にポインタが合わさります。
004012BF  |.^EB EF          \JMP SHORT CRKME08.004012B0   ← ループです。ぐるぐる回ります。ぐるぐるループを回ったところで、入力名のポインタが終端を
                                                           指したらループを脱出し、004012c1 に抜けます。
004012C1  |> 05 2BA43F18   ADD EAX,183FA42B        ← eax には入力名から作った値が入っていますが、これに値を足しています。
004012C6  |. 83F8 FF        CMP EAX,-1           ← これは eax と FFFFFFFFh とを比較しています。
004012C9  |. 75 01          JNZ SHORT CRKME08.004012CC   ← eax!=FFFFFFFFhならジャンプ、値生成終了。
004012CB  |. 48             DEC EAX            ← eax = FFFFFFFFh ならデクリメントして eax = FFFFFFFEh にします。

ここでパスが生成されているみたいですねぇ。
#08は、名前から数字に変え計算した結果がそのままパスになるので逆算はいらないですね
この部分がKGと言うわけです(^^;

では、作っていきましょう!

CPadなら起動して書いて行きます。。

まず、名前を取得するために変数を作ります。
char name[256];
まぁ、256バイト有れば十分でしょう(^^;

で、次にパスは数字になるので数字の変数です。
FFFFFFFFhまで数字があるので
long pas=0;
としたい所ですが、コレは負の数は使わないので
unsigned long pas=0;
にします。最近のintは4バイトになっている物が多いのでintでも大丈夫だと思います。
初期化しておきましょう。
(たいがいKG作る時の計算部分の変数はunsignedになります。)

途中でループが入っているので
int i;
これも作っておきましょう。
とりあえず、変数はだいたいはこんなものでしょうか?

次に中身を作っていきましょう。
名前を入力するために
fgets(name,256,stdin);
こうです。これで、名前を取得できるはずです。

次に、名前から数字に変えるループがありますね。
ループから抜けるには、文字が無くなったら抜けると有ります。
fgetsは改行も含めて取得しているので、改行がきたら抜け出すようにしましょう。
for(i=0;name[i] != '\n';i++){
こんな感じでよいと思います。

ループの中身は、ECXに文字を取り出し、EAXに足し、EAXを2乗しています。
charからintにするには、実はそのまま代入しちゃっていいんです。ですので
pas += name[i];
pas *= pas;

}
これでOKです。ついでに、いきなり計算から入っているので最初にpasを初期化しておきました。

ループから抜け出た後にADD EAX,183FA42Bという計算があるので
pas += 0x183FA42B;
ですね。

アフターケアで(笑)FFFFFFFFなら、DECしてくれています。
if(pas==0xffffffff)
pas--;

こんなでしょうか。もうできあがってますがソースにしてみましょう〜


#include <stdio.h>
#include <conio.h>

int main(){
        unsigned long pas=0;            //計算から始まるので先に初期化
        char name[256];                 //名前を入力する変数
        int i;                          //ループで使う変数

        printf("NAME:");                        //NAME:と表示して入力を促す
        fgets(name ,256 ,stdin);                //名前を取得

        for(i=0;name[i]!='\n';i++){             //name[i]が\nに来ると抜ける
                pas += name[i];         //pasにname[i]の数字(ASCIIコード)を代入
                pas *= pas;             //pasを2乗する
        }                               //ループの終端

        pas += 0x183FA42B;                      //pasに16進数の183FA42Bを足す

        if(pas==0xffffffff)             //もしpasが0xffffffffなら
                pas--;                  //0xfffffffeにする

        printf("PASS:%08X\n",pas);               //パスの表示%08Xで8桁で表示
        getch();                                //処理を一旦停止

        return 0;                               //終了
}

はい、今回はそのまんまCのソースにしただけって感じで簡単でしたね。
わからない部分や、間違っている部分が有れば突っ込んで下さい。