TurboLaunch 5.1.3セキュリティ研究

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



  1. プロシージャ GenClick( ダミー :ポインタ;送信者:PControl);
  2. var NameBuffer、SerNum:ストリング;
  3. len、sn_tmp: integer ;
  4. 始める
  5. Nm.Text <> ''の 場合、開始
  6. NameBuffer:= Nm.Text;
  7. len:=長さ(Nm.Text);
  8. ASM
  9. プッシュ
  10. mov ECX、NameBuffer
  11. mov EBX、len
  12. @ TurboLau_0053F42E:
  13. XOR EAX、EAX
  14. MOV AL、BYTE PTR DS:[ECX]
  15. SHL EAX、8
  16. XOR EDX、EAX
  17. MOV EAX、8
  18. @ TurboLau_0053F43C:
  19. テストDH、080h
  20. JE @ TurboLau_0053F44B
  21. EDX、EDXを追加
  22. XOR EDX、01021h
  23. JMP @ TurboLau_0053F44D
  24. @ TurboLau_0053F44B:
  25. EDX、EDXを追加
  26. @ TurboLau_0053F44D:
  27. 12月
  28. JNZ @ TurboLau_0053F43C
  29. INC ECX
  30. 12月 ebx
  31. JNZ @ TurboLau_0053F42E
  32. MOV EAX、EDX
  33. EAX、0FFFFh
  34. mov sn_tmp、EAX
  35. ポパド
  36. 終了
  37. Edit.text:= Int2Hex((sn_tmp)、4);
  38. 終わり
  39. 他に
  40. Edit.Text:= '名前を入力してください' ;
  41. 終了 ;




手順を個別に持ってきたのはなぜですか? 私にとっては簡単だった、私はすぐにリッピングされたコードの正しい動作を見ることができます。 たとえば、名前がDimitarSergの場合sn_tmp = E330



さて、もう一度、技術的な問題:アドレス5406BCから540752までのCodeRipperプラグインを使用します(これは大きな生成サイクルであることがわかります)。 私が注意したいのは、いくつかの呼び出しです。 CodeRipperは「; <= Jump / Call Address Not Resolved」と書き込みます。それらのほとんどは不要で、削除できますが、ここでは

005406EE |。 E8 F52DECFF || CALL TurboLau.004034E8

以下の理由により、この呼び出しは削除できません。



Copy Source | Copy HTML



  1. @ TurboLau_004034E8:
  2. プッシュEBX
  3. XOR EBX、EBX
  4. IMUL EDX、DWORD PTR DS:[EBX + 0542008h]、08088405h
  5. INC EDX
  6. MOV DWORD PTR DS:[EBX + 0542008h]、EDX
  7. MUL EDX
  8. MOV EAX、EDX
  9. POP EBX
  10. Retn




これは(当時は知りませんでしたが)これは標準のランダムであり、DWORD PTR DS:[EBX + 0542008h](sn_tmpもあります)-これはRandomSeedです。



そして、リッピングされたコードでは、別のプロシージャとして呼び出すのではなく、単に呼び出しの場所にコピーするだけです。フラグメントを次に示します。

Copy Source | Copy HTML



  1. @ TurboLau_005406E9:
  2. MOV EAX、021h
  3. //-> CALL @ TurboLau_004034E8; <=ジャンプ/解決されないアドレスを呼び出す
  4. //コンテンツを呼び出します
  5. プッシュEBX
  6. XOR EBX、EBX
  7. IMUL EDX、sn_tmp、08088405h
  8. INC EDX
  9. Mov sn_tmp、edx
  10. MUL EDX
  11. MOV EAX、EDX
  12. POP EBX
  13. MOV EBX、EAX
  14. INC EBX
  15. MOV AL、BYTE PTR SS:[EBP-0Dh]
  16. XOR AL、0FFh
  17. EAX、0FFh
  18. EBX、EAXを追加
  19. Dec Esi
  20. JNZ @ TurboLau_005406E9




私もラインに注意を払いたい

00540715 |。 BA 1C085400 | MOV EDX、TurboLau.0054081C; ASCII「GF2DSA38HJKL7M4NZXCV5BY9UPT6R1EWQ40I1CP7Z7GOEPQLZ」



登録コードは直接依存しているため、「キー」と呼ぶことができます。 アドレス0054081Cの文字列へのポインタがedxレジスタに書き込まれます。

Asmov挿入と純粋なPascalを備えたDelphi keygenの完全なソースコードが添付されており、そこには複雑なものは何もありません。



さて、そして私が物語を始めたのは、これらすべての世代の後、私たちは止まらず、踏みつけていくつかの名前/ニックネームなどを見る



当然、これは原始的なブラックリストです。

Copy Source | Copy HTML



  1. @ TurboLau_005407C4:
  2. MOV EAX、DWORD PTR SS:[EBP-4]; ブラックリスト検証サイクル
  3. MOV EDX、DWORD PTR DS:[ESI]
  4. CALL @ TurboLau_00405030
  5. JNZ @ TurboLau_005407D4
  6. XOR EBX、EBX
  7. JMP @ TurboLau_005407DA
  8. @ TurboLau_005407D4:
  9. ESIを追加 、4
  10. 12月エディ
  11. 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



  1. // ...
  2. var
  3. ブラックリスト:文字列の配列[ 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'、 'C​​ORE / JES'、 'C​​hen 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 ' ;
  4. // ...
  5. プロシージャ生成;
  6. ヴァール
  7. NameBuffer、SerNum: ストリング ;
  8. EDX、EAX、len、 iab 、tmp1: 整数 ;
  9. テキスト名: PChar ;
  10. 始める
  11. len:= GetWindowTextLengthA( TxtNameHwnd );
  12. len> 1の場合
  13. 始める
  14. {名前入力からテキストを取得}
  15. GetMem( テキスト名、len + 1 );
  16. GetWindowTextA( TxtNameHwnd、PAnsiChar(テキスト名 )、len + 1 );
  17. {シリアルを生成}
  18. KeyStr:= 'GF2DSA38HJKL7M4NZXCV5BY9UPT6R1EWQ40I1CP' ;
  19. NameBuffer:= String( Textname );
  20. SerNum:= '' ;
  21. ランダム化
  22. EDX:= 0 ;
  23. for i := 1からlen do
  24. 始める
  25. EDX:= EDX xor( ord(NameBuffer [i] )shl 8 );
  26. EAX:= 8 ;
  27. 一方、EAX <> 0
  28. 始める;
  29. if( EDX shr 8 and $ 0FF )> = $ 80
  30. それから
  31. EDX:= EDX shl 1 xor $ 1021
  32. 他に
  33. EDX:= EDX shl 1 ;
  34. dec( EAX );
  35. 終わり;
  36. 終わり;
  37. RandSeed:= EDXおよび$ 0FFFF;
  38. i := 1 ;
  39. i <> $ 13 do
  40. 始める
  41. a := 0 ;
  42. b := $ 13 - i ;
  43. b > 0の場合
  44. 始める
  45. 一方、 b > 0
  46. 始める
  47. a :=ランダム( 33 );
  48. inc( a );
  49. i > lenの場合
  50. tmp1:= ord( NameBuffer [i mod len]
  51. 他に
  52. tmp1:= ord( NameBuffer [i] );
  53. tmp1:= tmp1 xor $ 0FFおよび$ 0FF;
  54. a := a + tmp1;
  55. dec( b );
  56. 終わり;
  57. 終わり;
  58. 一方 > 21ドル
  59. 始める
  60. a := a-$ 21 ;
  61. 終わり;
  62. SerNum:= SerNum + KeyStr [ a ];
  63. inc( i );
  64. 終わり;
  65. 挿入( '-'、SerNum、7 );
  66. 挿入( 「-」、SerNum、14 );
  67. iの場合 := 0から43
  68. 始める
  69. NameBuffer = Black List [ i ]の場合
  70. 始める
  71. SerNum:= 'BLACKLISTED NAME' ;
  72. 休憩
  73. 他の終わり;
  74. 終わり;
  75. {結果を表示}
  76. SetWindowTextA( TxtSerialHwnd、PChar(SerNum ));
  77. FreeMem( テキスト名、len + 1 );
  78. 終わり
  79. その他
  80. { 表示エラー}
  81. SetWindowText( TxtSerialHwnd、 '不十分な文字..' );
  82. 終わり;


その結果、私はそのようなkeygenを得ました:

画像



サイズ36.5 Kb(アンパック)。このような小さなkeygenサイズは、DelphiのライブラリであるKOL(Key Objects Library)を使用して実現されます。WinApiを使用してロゴを貼り付け、xm / v2mトラックを追加することもできますkeygen and did)、しかし、私のアドバイスは-Delphiでkeygenを記述する場合はVCLを使用しないでください... 400kb以上-これはkeygenのサイズではありません!

純粋なアセンブラーが好きな人-Masm(Fasm、Tasm)を手に。



これが私の話の終わりであり、誰かがこの記事から何かを得ることを願っています。



All Articles