#16のKG(コンソール)


はい〜。こんにちは。
16にやってきました。
これは、ちょっとややこしいけど、全体を把握しながらやっていけば簡単です。
時間もないのでチャチャっと書きます。
まず全体を見てみましょう。

12345-67890-ABCDE-FGHIJ
こうあるとすれば
FGHIJからABCDEを作り・・・と後ろから作ってゆけば良かったですね。
途中で一部 '-' を読みとる部分がありました。

普通にトレースすると、最後らへんの
00401419 |> 0FBE4431 04 |/MOVSX EAX,BYTE PTR DS:[ECX+ESI+4]
ここです。どう考えても'-'を使います。

それでは、変数から作りましょう。今回は全部最初に作ります。
言い忘れましたが、このKGはは2種類作れます。
パスを表示する方法、と、KEYファイルを作る方法です。
今回はKEYファイルを作ろうと思っています。
では、変数に戻りまして。
まずループがあります。ループの中にループがあるので
int i,j;
です。次は、パスを保管する変数、パスの一区切りを保管する変数、256個のキーを保存する変数です。
char seri[4][6],id[6]="-",key[256];
さて、seriが気になったと思います。
これは、一区切りずつを配列の配列で表そうと思ったのでこう書きました。
idは、一区切りを保存します。(いい名前が思いつかなかった:汗)
"-" が最初から設定しているのは、上でも書いた通り'-'を使うので最初に書いておきました。

さて、あとはキーを作る時に計算が入ります。二つ必要なので
unsigned long x,y;
ファイルを出力するので
FILE *fp;
FILEは全部大文字です。

さて、中身に入っていきます。
まず最後の5文字を作りましょう。
最後は

1文字目は1〜9、2文字目はA〜Z、3文字目はa〜z、4文字目はE〜U、5文字目はk〜s と考えられます。 (図書室調べ)

ですので、範囲内で考えましょう。
作るのに当たって15でも使ったrand()を使います。
まず、同じパターンにならないように
srand((unsigned)time(NULL));
を書きます。次にランダムで文字を決めるのですが、範囲内に持ってくるために
seri[3][0] = id[1] = rand()%9 + 0x30;
seri[3][1] = id[2] = rand()%25 + 0x41;
seri[3][2] = id[3] = rand()%25 + 0x61;
seri[3][3] = id[4] = rand()%16 + 0x45;
seri[3][4] = id[5] = rand()%8 + 0x6B;

こうします。
最後の部分から作るのでseriにも書き込んでおきます。

後で書くとめんどくさいのでseriに'-'も書き込んでおきましょう
seri[0][5] = seri[1][5] = seri[2][5] = '-';

これで、最後の5文字は決定しました。
計算に入って行きます。
004013EB |. B9 03000000 MOV ECX,3
004013F0 |> 51 /PUSH ECX
ここから大きなループがあります。
3回ループなので
for(i=3;i>0;i--){
回ってくるたびにxを初期化しましょう。
x=0;

さて、次行きます。

004013F1  |. B9 05000000    |MOV ECX,5
004013F6  |. 33D2           |XOR EDX,EDX
004013F8  |> C1E2 04        |/SHL EDX,4
004013FB  |. 0FBE4431 05    ||MOVSX EAX,BYTE PTR DS:[ECX+ESI+5]
00401400  |. 83E0 0F        ||AND EAX,0F
00401403  |. 0BD0           ||OR EDX,EAX
00401405  |.^E2 F1          |\LOOPD SHORT crkme16.004013F8

この部分は、5回ループですね。
for(j=5;j>0;j--){
で、SHL4がありますので
x <<= 4;
その後は、入力したパスから1文字読みとって&0xfをしてEDXにおさめています。ですので
x |= id[j] & 0xf;
}

これでイイです。(id[0]は'-'なので)

次は256キーを作ります。

0040102E  |. B9 00010000    MOV ECX,100
00401033  |> 51             /PUSH ECX
00401034  |. 8BC3           |MOV EAX,EBX
00401036  |. B9 3E000000    |MOV ECX,3E
0040103B  |. 33D2           |XOR EDX,EDX
0040103D  |. F7F1           |DIV ECX
0040103F  |. 83FA 09        |CMP EDX,9
00401042  |. 77 05          |JA SHORT crkme16.00401049
00401044  |. 83C2 30        |ADD EDX,30
00401047  |. EB 0D          |JMP SHORT crkme16.00401056
00401049  |> 83FA 23        |CMP EDX,23
0040104C  |. 77 05          |JA SHORT crkme16.00401053
0040104E  |. 83C2 37        |ADD EDX,37
00401051  |. EB 03          |JMP SHORT crkme16.00401056
00401053  |> 83C2 3D        |ADD EDX,3D
00401056  |> 59             |POP ECX
00401057  |. 8891 7F304000  |MOV BYTE PTR DS:[ECX+40307F],DL
0040105D  |. 81F3 5B7CCB3D  |XOR EBX,3DCB7C5B
00401063  |. 81C3 F56ED76F  |ADD EBX,6FD76EF5
00401069  |. C1C3 07        |ROL EBX,7
0040106C  |.^E2 C5          \LOOPD SHORT crkme16.00401033

EBXをEAXに写し3Eで割っています。
とりあえず、xの値をyに保管しましょう
y=x;
次に、xを0x3Eで割るのですが、あまりを使っているので
x %= 0x3e;
となります。さて、次は、数字か大文字か小文字に分けています。
分け方は個人の自由です。そのまんまでもイイですし、私の場合は、成り行きに任せていたらこうなりました。
if(x > 9){
if(x >0x23){
x += 0x3d;
} else {
x += 0x37;
}
} else {
x += 0x30;
}

そして、その結果keyに保存していきます。
注意は、0は最後に通らないので
key[j-1] = x;
こうなります。いや、めんどくさかったら最初に0xFF>=0、でもいいんですよ。
いや、むしろそっちの方が・・・
で、最後に計算があります。見たまんまですので、説明はしません
x = _lrotl(((y ^ 0x3dcb7c5b) + 0x6fd76ef5),7);
}

解らなかったら掲示板にでも・・・と、逃げてみる(^^;
これで、256keyが作れました。

おぅ、あと20分しかない(私の勝手な時間ですが:笑)
ラストスパートです。

00401410  |. B9 05000000    |MOV ECX,5
00401415  |. C60439 00      |MOV BYTE PTR DS:[ECX+EDI],0
00401419  |> 0FBE4431 04    |/MOVSX EAX,BYTE PTR DS:[ECX+ESI+4]
0040141E  |. F7E1           ||MUL ECX
00401420  |. BB FF000000    ||MOV EBX,0FF
00401425  |. F7F3           ||DIV EBX
00401427  |. 0FBE82 8030400>||MOVSX EAX,BYTE PTR DS:[EDX+403080]
0040142E  |. 884439 FF      ||MOV BYTE PTR DS:[ECX+EDI-1],AL
00401432  |.^E2 E5          |\LOOPD SHORT crkme16.00401419

この部分をやっちゃいましょう。
まずは5ループ
for(j=5;j>0;j--){
でパスを作り出す文字の4文字目から321文字と抜き取り最後に'-'を抜き取ります。
作り出す部分ですので、今のid[6]でいいです。
その抜き出した文字にECX=ループ回数をかけて、0xFFを割ります。
あまりを使うので%を使います。
x = (id[j-1]*j) % 0xff;
j-1の部分は4文字目からだからです。
そして、その結果のxを使い、key[x]でパスが抜き取れます。ループする計算に向けてidとパスに書き込んでおきましょう
seri[i-1][j-1] = id[j] = key[x];
}
}

これで、終わりです。
ループがすべて終わるとあとは、ファイルに書き出すだけです。
まずファイルをオープンします。
fp = fopen("crackme16.ini","w+");

crackme16.iniを言うファイルをw+と言うモードで開きます。
w+、というのは、ファイルがあれば上書きで作り直し、無ければ作る。というモードです。
ですので、何度実行しても、ファイルは一つと言うことです。
一応、ファイルが無かった場合の処理を書きます。(何かで作れなかった場合など)
if(fp == NULL){
printf("きゃ〜。緊急脱出!");
exit(-1);
}

exitは、プログラムを終了します。
急に終了しても意味がわからないので、何かメッセージを書いておきましょう。
そして、ファイルに書き込みます。
fprintf(fp, "%s", "[Regist]\nSerial=");
fprintf(fp, "%s",seri);

printfにfを付け加えただけです
最初のfpは、そのファイルに書くか、後はprintfと同じです。
seriは多重配列(だったかな?)ですが、こう書けば最初から書き出していってくれます。終わりまで
あとは、ファイルをクローズして、出力したメッセージを書きます。
fclose(fp);

printf("keyファイル[crackme16.ini]を出力しました。\n"
"crkme16.exeと同じフォルダーに入れて起動して下さい。");
getch();
return 0;
}

で、終わりです。
まとめたソース書いておきます。


#include <tdio.h>
#include <dlib.h>
#include <time.h>
#include <conio.h>

int main(){
        char seri[4][6],id[6]="-",key[256];
        int i,j;
        unsigned long x,y;
        FILE *fp;
        
        srand((unsigned)time(NULL));
        
        seri[3][0] = id[1] = rand()%9  + 0x30;
        seri[3][1] = id[2] = rand()%25 + 0x41;
        seri[3][2] = id[3] = rand()%25 + 0x61;
        seri[3][3] = id[4] = rand()%16 + 0x45;
        seri[3][4] = id[5] = rand()%8  + 0x6B;
        seri[0][5] = seri[1][5] = seri[2][5] = '-';
        
        for(i=3;i>0;i--){
                x=0;
                
                /*
                004013F8  |> C1E2 04        |/SHL EDX,4
                〜
                00401405  |.^E2 F1          |\LOOPD SHORT crkme16.004013F8
                */
                for(j=5;j>0;j--){
                        x <<= 4;
                        x |= id[j] & 0xf;
                }
                
                /*キーワード作り
                0040102E  |. B9 00010000    MOV ECX,100
                00401033  |> 51             /PUSH ECX
                00401034  |. 8BC3           |MOV EAX,EBX
                〜
                00401069  |. C1C3 07        |ROL EBX,7
                0040106C  |.^E2 C5          \LOOPD SHORT crkme16.00401033
                */
                for(j=0x100;j>0;j--){
                        y=x;
                        x %= 0x3e;
                        if(x > 9){
                                if(x >0x23){
                                        x += 0x3d;
                                } else {
                                        x += 0x37;
                                }
                        } else {
                                x += 0x30;
                        }
                        key[j-1] = x;
                        x = _lrotl(((y ^ 0x3dcb7c5b) + 0x6fd76ef5),7);
                }
                
                /*
                00401410  |. B9 05000000    |MOV ECX,5
                00401415  |. C60439 00      |MOV BYTE PTR DS:[ECX+EDI],0
                00401419  |> 0FBE4431 04    |/MOVSX EAX,BYTE PTR DS:[ECX+ESI+4]
                0040141E  |. F7E1           ||MUL ECX
                00401420  |. BB FF000000    ||MOV EBX,0FF
                00401425  |. F7F3           ||DIV EBX
                00401427  |. 0FBE82 8030400>||MOVSX EAX,BYTE PTR DS:[EDX+403080]
                0040142E  |. 884439 FF      ||MOV BYTE PTR DS:[ECX+EDI-1],AL
                00401432  |.^E2 E5          |\LOOPD SHORT crkme16.00401419
                */
                
                for(j=5;j>0;j--){
                        x = (id[j-1]*j) % 0xff;
                        seri[i-1][j-1] = id[j] = key[x];
                }
        }
        
        fp = fopen("crackme16.ini","w+");
        
        if(fp == NULL){
                printf("きゃ〜。緊急脱出!");
                exit(-1);
        }
        
        fprintf(fp, "%s", "[Regist]\nSerial=");
        fprintf(fp, "%s",seri);
        
        fclose(fp);
        
        printf("keyファイル[crackme16.ini]を出力しました。\n"
                "crkme16.exeと同じフォルダーに入れて起動して下さい。");
        getch();
        return 0;
}

はい、終わりです。
今回は、説明が少なかったかと思います。
ちょっと解らないことは、自分なりに考えてみてください。
それでも、ダメなら気軽に聞いて下さいね〜♪
それでは、#16を終わります。例っ!(笑