TurboLaunch 5.1.3を簡単に保護するか、3つの方法で破壊します(パッチ、スニファー、keygen)。
対象 :TurboLaunch 5.1.3
ツール :OllyDbg 1.10、Dup2(パッチ作成用)、OllyDbg用CodeRipperプラグイン、Delphi 7(keygen作成用)
退屈な夜だったので、「掘り下げて」みたいプログラムを探していました。 最初に、1バイトを編集してAWBackuper 4.0からトライアルを削除しましたが、それは非常に面白くないように思われ、それから長い間(約4年)コンピューターにあったプログラムを思い出しました-これはSavard SoftwareのTurboLaunchでした。 Keygenが存在します(おそらく10程度)が、それらのいずれにも小さなニュアンスは見られません(全体的には重要な役割を果たしませんが)、それについては少し後になります。
そして、始めましょう...
パッチ
初心者にとっては一番簡単だからです。
犠牲者をOllyDbgにロードします(その後、olya、ollyのみ)。 開始してnag-windowが表示されたら、[登録コードを入力]をクリックします
名前(DimitarSerg)と「正直に購入した」コード1234567890を入力します
非常に奇妙ですが、次のメッセージが表示されます。
テキスト文字列でメッセージテキストを探しましょう。 RMB->検索->すべての参照テキスト文字列。
私たちは見つけます:
もう少し高く、00529CD3からのジャンプ 、つまりそこから来ました。
素晴らしい、そこにあるものを見てみましょう:
「クラシック」:
CALL TurboLau.0053AEB0
TEST AL,AL
JE @TurboLau_00529D99
したがって、チェックがあり、テストの結果に応じてジャンプします。
以下の行があります。
00529D1A |. BA F49D5200 MOV EDX,TurboLau.00529DF4 ; ASCII "REGISTERED TO: "
そしてそのような:
00529D3B |. 68 0C9E5200 PUSH TurboLau.00529E0C ; ASCII "Thank you for registering! Be sure to check out our web site for updated versions of TurboLaunch and other programs written by "
それでは、00529CCCをご覧ください|。 E8 DF110100 CALL TurboLau.0053AEB0
別の呼び出しがあり、登録手順に類似した何かの中にあります。 さて、それなしでできるのに、なぜ検証手順が必要なのでしょうか?!
そのため、540628での登録手順の最初に、「クラシック」パッチを作成します
xor eax,eax // EAX
inc eax // EAX = EAX +1
Retn // return
変更を保存します。 RMB->実行可能ファイルにコピー->すべての変更->ファイルを保存します 。
TurboLaunch1.exeなどの新しい名前で保存します
喜んでいますが、見返りにこれを取得します:
ああああ。 整合性チェック。 まあ、神は彼女と一緒にいる:
デバッガーでプログラムをリロードし、ブレークポイントを設定してMessageBoxA関数を呼び出します
bp MessageBoxA
「メインスレッドの呼び出しスタック」ウィンドウで、どこから来たのかを確認します。
RMB-> Show Callを実行し、アドレスで検索します
00450CA4 |. E8 8F75FBFF CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
上にスクロールして確認してください:
00450C7B |> \84DB TEST BL,BL
00450C7D |. 74 60 JE SHORT TurboLau.00450CDF
もう一度確認してください。
条件付き遷移を無条件に変更し(JE-> JMP)、変更を保存して開始します。 やあ、プログラムが始まる。
購入を求めるウィンドウが表示されなくなったため、[About]ウィンドウに「Registered to」と表示されます。
一般的に、誰かのために登録された、それは良いことです。
Dup2またはuPPPでパッチを作成しても問題はありません。
シリアル番号を検索します。
上記のように、正しい/間違ったシリアル番号に関するメッセージは、結果に応じて形成されます
00529CD1 |. 84C0 TEST AL,AL
そして、上記の行は次のとおりです。
00529CCC |. E8 DF110100 CALL TurboLau.0053AEB0
生成手順全体がここで行われるのは論理的です...
私たちは見ます:
0053AEB0 /$ 8B90 68010000 MOV EDX,DWORD PTR DS:[EAX+168]
0053AEB6 |. 8B80 64010000 MOV EAX,DWORD PTR DS:[EAX+164]
0053AEBC |. E8 67570000 CALL TurboLau.00540628
0053AEC1 \. C3 RETN
0053AEB0にブレークポイントを設定し、名前/登録番号を入力すると、ここで停止し、入力されたデータが読み取られていることを確認します。つまり、最も興味深いのはCALL TurboLau.00540628です。
F7に沿ってトレースし、読み取り、いくつかの変換、他の操作などを確認します。 など、その結果、この手順に注意と忍耐の数分を与えた場合、命令の実行中に
00540758 |. 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]
表示されます:
スタックSS:[0012F1AC] = 00C66E8C、(ASCII「D1F74F-5L3GRT-3WDULJ」)
うーん、正しいシリアル番号ですか?! DimitarSergという名前とシリアル番号D1F74F-5L3GRT-3WDULJを試します。このプログラムは買収を祝福します。
シリアル番号は平文で表示されるため、スニファーシリーズはバタンと書かれています。00540758の直後にあるアドレスのEAXレジスター、つまり0054075Bを調べるだけです。
スニファーシリーズの記述方法については説明しませんが、AT4REチームにはSerial Sniffer Creatorのようなツールがあり、使用できます。次のようになります。
しかし、Unicodeでシリアル番号を盗聴せず、インターフェイスに頻繁に不具合があるため、お勧めしません。
スニファーを作成するためのいくつかの例(テンプレート)が公開されているため、アセンブラーまたはDelphiは手作業で「完成」します。
Keygen
もちろん、最も興味深いのはもちろん、keygenを書くことです。
上で説明したように、生成手順全体は00540628から始まります
登録データ、トレースを入力します。 この場所に注意してください:
この呼び出しをご覧ください。 名前、計算に対して実行されるいくつかの操作が表示されます。 計算の最初の部分が行われ、その結果は少し後で使用されることを事前に言います。 私はアセンブラの「素晴らしい仕様」ではないので、CodeRipperプラグインを使用します。
2つのkeygenメソッドを示します。Delphiのインラインアセンブラコードと、pascalの完全に翻訳されたコードです。
Copy Source | Copy HTML
- プロシージャ GenClick( ダミー :ポインタ;送信者:PControl);
- var NameBuffer、SerNum:ストリング;
- len、sn_tmp: integer ;
- 始める
- Nm.Text <> ''の 場合、開始
- NameBuffer:= Nm.Text;
- len:=長さ(Nm.Text);
- ASM
- プッシュ
- mov ECX、NameBuffer
- mov EBX、len
- @ TurboLau_0053F42E:
- XOR EAX、EAX
- MOV AL、BYTE PTR DS:[ECX]
- SHL EAX、8
- XOR EDX、EAX
- MOV EAX、8
- @ TurboLau_0053F43C:
- テストDH、080h
- JE @ TurboLau_0053F44B
- EDX、EDXを追加
- XOR EDX、01021h
- JMP @ TurboLau_0053F44D
- @ TurboLau_0053F44B:
- EDX、EDXを追加
- @ TurboLau_0053F44D:
- 12月
- JNZ @ TurboLau_0053F43C
- INC ECX
- 12月 ebx
- JNZ @ TurboLau_0053F42E
- MOV EAX、EDX
- EAX、0FFFFh
- mov sn_tmp、EAX
- ポパド
- 終了
- Edit.text:= Int2Hex((sn_tmp)、4);
- 終わり
- 他に
- Edit.Text:= '名前を入力してください' ;
- 終了 ;
手順を個別に持ってきたのはなぜですか? 私にとっては簡単だった、私はすぐにリッピングされたコードの正しい動作を見ることができます。 たとえば、名前がDimitarSergの場合sn_tmp = E330
さて、もう一度、技術的な問題:アドレス5406BCから540752までのCodeRipperプラグインを使用します(これは大きな生成サイクルであることがわかります)。 私が注意したいのは、いくつかの呼び出しです。 CodeRipperは「; <= Jump / Call Address Not Resolved」と書き込みます。それらのほとんどは不要で、削除できますが、ここでは
005406EE |。 E8 F52DECFF || CALL TurboLau.004034E8
以下の理由により、この呼び出しは削除できません。
Copy Source | Copy HTML
- @ TurboLau_004034E8:
- プッシュEBX
- XOR EBX、EBX
- IMUL EDX、DWORD PTR DS:[EBX + 0542008h]、08088405h
- INC EDX
- MOV DWORD PTR DS:[EBX + 0542008h]、EDX
- MUL EDX
- MOV EAX、EDX
- POP EBX
- Retn
これは(当時は知りませんでしたが)これは標準のランダムであり、DWORD PTR DS:[EBX + 0542008h](sn_tmpもあります)-これはRandomSeedです。
そして、リッピングされたコードでは、別のプロシージャとして呼び出すのではなく、単に呼び出しの場所にコピーするだけです。フラグメントを次に示します。
Copy Source | Copy HTML
- @ TurboLau_005406E9:
- MOV EAX、021h
- //-> CALL @ TurboLau_004034E8; <=ジャンプ/解決されないアドレスを呼び出す
- //コンテンツを呼び出します
- プッシュEBX
- XOR EBX、EBX
- IMUL EDX、sn_tmp、08088405h
- INC EDX
- Mov sn_tmp、edx
- MUL EDX
- MOV EAX、EDX
- POP EBX
- MOV EBX、EAX
- INC EBX
- MOV AL、BYTE PTR SS:[EBP-0Dh]
- XOR AL、0FFh
- EAX、0FFh
- EBX、EAXを追加
- Dec Esi
- JNZ @ TurboLau_005406E9
私もラインに注意を払いたい
00540715 |。 BA 1C085400 | MOV EDX、TurboLau.0054081C; ASCII「GF2DSA38HJKL7M4NZXCV5BY9UPT6R1EWQ40I1CP7Z7GOEPQLZ」
登録コードは直接依存しているため、「キー」と呼ぶことができます。 アドレス0054081Cの文字列へのポインタがedxレジスタに書き込まれます。
Asmov挿入と純粋なPascalを備えたDelphi keygenの完全なソースコードが添付されており、そこには複雑なものは何もありません。
さて、そして私が物語を始めたのは、これらすべての世代の後、私たちは止まらず、踏みつけていくつかの名前/ニックネームなどを見る
当然、これは原始的なブラックリストです。
Copy Source | Copy HTML
- @ TurboLau_005407C4:
- MOV EAX、DWORD PTR SS:[EBP-4]; ブラックリスト検証サイクル
- MOV EDX、DWORD PTR DS:[ESI]
- CALL @ TurboLau_00405030
- JNZ @ TurboLau_005407D4
- XOR EBX、EBX
- JMP @ TurboLau_005407DA
- @ TurboLau_005407D4:
- ESIを追加 、4
- 12月エディ
- JNZ @ TurboLau_005407C4
Nitrogen / TSRh TeaM、REVENGE Crew、FiGHTiNG FOR FUN、TEAM VIRILITYなどの興味深いニックネーム... ヒントが得られると思います。
合計44名。 問題なく手動でコピーアンドペーストし、型の文字列配列にハンマーで打ち込む
BlackList:文字列=(...)の配列[0..43]。生成時に、目的の名前がブラックリストにあるかどうかを確認します。 (ファイルBlackList.txtも添付します)。
「完全な幸福」のために、asmを挿入したコードをpascalに変換します。
Copy Source | Copy HTML
- // ...
- var
- ブラックリスト:文字列の配列[ 0 .. 43 ] =( 'zircon / pc97'、 'freeware'、 'registered user'、 <br/> 'NuZ''c97'、 'Registered'、 'kOUGER![CB4] '、' Cosmo Cramer 1997 '、' Cosmo Cramer MJ13 '、 <br/> ' MJ13 Forever '、' cH / Phrozen Crew '、' Everybody '、' iCEMAN [uCF] '、' pank '、' Henry Pan '、 <br/> 'iTR [CORE]'、 'mpbaer'、 'CORE / JES'、 'Chen Borchang'、 'n03l'、 'ODIN 97'、 'lgb / cORE''97'、 <br/> 'MCC '、' blastsoft '、' CORE / DrRhui '、' Vizion / CORE '、' TEAM ViRiLiTY '、' Nambulu '、' NuZPc97 '、 <br/> ' Weazel '、' Phrozen Crew '、' TEAM VIRILITY '、' x3u '、' Reg Name '、' FiGHTiNG FOR FUN '、' RaSCaL [TMG] '、 <br/> ' Nitros ^ 21 '、' TEAM TSRH '、' ttdown.com '、' Nitrogen / TSRh TeaM '、'無料プログラム '、' REVENGE Crew '、 <br/> ' Vladimir Kasho '、' Alexej Melnikov '、' Seth W. Hinshaw ' ;
- // ...
- プロシージャ生成;
- ヴァール
- NameBuffer、SerNum: ストリング ;
- EDX、EAX、len、 i 、 a 、 b 、tmp1: 整数 ;
- テキスト名: PChar ;
- 始める
- len:= GetWindowTextLengthA( TxtNameHwnd );
- len> 1の場合
- 始める
- {名前入力からテキストを取得}
- GetMem( テキスト名、len + 1 );
- GetWindowTextA( TxtNameHwnd、PAnsiChar(テキスト名 )、len + 1 );
- {シリアルを生成}
- KeyStr:= 'GF2DSA38HJKL7M4NZXCV5BY9UPT6R1EWQ40I1CP' ;
- NameBuffer:= String( Textname );
- SerNum:= '' ;
- ランダム化
- EDX:= 0 ;
- for i := 1からlen do
- 始める
- EDX:= EDX xor( ord(NameBuffer [i] )shl 8 );
- EAX:= 8 ;
- 一方、EAX <> 0は
- 始める;
- if( EDX shr 8 and $ 0FF )> = $ 80
- それから
- EDX:= EDX shl 1 xor $ 1021
- 他に
- EDX:= EDX shl 1 ;
- dec( EAX );
- 終わり;
- 終わり;
- RandSeed:= EDXおよび$ 0FFFF;
- i := 1 ;
- i <> $ 13 do
- 始める
- a := 0 ;
- b := $ 13 - i ;
- b > 0の場合
- 始める
- 一方、 b > 0は
- 始める
- a :=ランダム( 33 );
- inc( a );
- i > lenの場合
- tmp1:= ord( NameBuffer [i mod len] )
- 他に
- tmp1:= ord( NameBuffer [i] );
- tmp1:= tmp1 xor $ 0FFおよび$ 0FF;
- a := a + tmp1;
- dec( b );
- 終わり;
- 終わり;
- 一方、 > 21ドル
- 始める
- a := a-$ 21 ;
- 終わり;
- SerNum:= SerNum + KeyStr [ a ];
- inc( i );
- 終わり;
- 挿入( '-'、SerNum、7 );
- 挿入( 「-」、SerNum、14 );
- iの場合 := 0から43
- 始める
- NameBuffer = Black List [ i ]の場合
- 始める
- SerNum:= 'BLACKLISTED NAME' ;
- 休憩
- 他の終わり;
- 終わり;
- {結果を表示}
- SetWindowTextA( TxtSerialHwnd、PChar(SerNum ));
- FreeMem( テキスト名、len + 1 );
- 終わり
- その他
- { 表示エラー}
- SetWindowText( TxtSerialHwnd、 '不十分な文字..' );
- 終わり;
その結果、私はそのようなkeygenを得ました:
サイズ36.5 Kb(アンパック)。このような小さなkeygenサイズは、DelphiのライブラリであるKOL(Key Objects Library)を使用して実現されます。WinApiを使用してロゴを貼り付け、xm / v2mトラックを追加することもできますkeygen and did)、しかし、私のアドバイスは-Delphiでkeygenを記述する場合はVCLを使用しないでください... 400kb以上-これはkeygenのサイズではありません!
純粋なアセンブラーが好きな人-Masm(Fasm、Tasm)を手に。
これが私の話の終わりであり、誰かがこの記事から何かを得ることを願っています。