BEMの例を使用して登録から.NETプログラムを取り除く

少し前に、私は勉強し、同時に1つのライブラリを修正して、このライブラリで実行されているプログラムをライセンスから解放することにしました。



それはすべて、どういうわけか私が財務諸表のプログラム、予算オプション1Cを手に入れたという事実から始まりました。 このプログラムの開発者が保証しているように、ハッキングに対してほとんど保護され、抵抗力があります。 開発者の過度の自信に反論するようになったのは、この自慢でした。



Reflectorを介してプログラムに夢中になって、私はプログラムのすべての主要なライブラリがサードパーティの会社によって書かれていること、そして特定のプロジェクトのために書かれているのではなく、フレームワーク全体であることを発見しました。 このフレームワークは、会計プログラム専用に作成されました。 このようなフレームワーク指向では、通常、多くの不要な機能がプッシュされました(たとえば、FTPでの作業)。 膨大な量のシステム名前空間が再定義されました。



また、このフレームワークのライブラリの1つで名前空間が定義され、そのクラスがライセンスの正当性をチェックする役割を果たしました。 この点で、このフレームワークの情報とドキュメントを検索するためにグーグルに決めました。 数分の検索の後、このフレームワークが閉じていることが明らかになりました。 なぜ閉じたのですか? -はい、それは未知の基準に従って配布されるため、少なくとも開発者のウェブサイトでこれに関する情報を見つけることができませんでした。 また、開発者のサイトでは、このフレームワークに関する参照情報を見つけることができませんでした。 上記のように、このフレームワークに基づいたすべてのプログラムのライセンスシステムは同じであるため、プログラムのライセンス供与を担当したのはこのフレームワークであるという事実によって、このフレームワークのkeygenを見つけると単純に信じられていたという事実によって、私はこのすべての情報を探しました。 これは、このフレームワーク上のプログラムのいずれかの誰かがkeygenを作成したことを意味しました。 しかし、残念ながら、検索は失敗しました。



ところで、NetDec Frameworkの名前。



また、ライセンスのチェックを担当するクラスが配置されているライブラリの分析では、ライセンスを担当するネームスペース全体を含む、一部のクラスが難読化されていることが示されました。 難読化解除とその後の再コンパイルに煩わされることはありませんでした。特に目標は、ライセンスジェネレーターまたはパッチャーを作成することでした。







ライセンスを確認する方法は非常に迅速に見つかりました。必要なのは、ライセンス入力フォームの[OK]ボタンをクリックするためのハンドラーを追跡することだけでした。







コード分​​析の利便性のため、難読化解除機能を搭載したReflectorアナログのみを探す必要がありました。 それがDisSharpであることが判明しました。



ご覧のとおり、プログラムのライセンスはDSAアルゴリズムのデジタル署名です。 デジタル署名を作成するために、いわゆるコンピューターコードが取得され(このコードの生成には関与しませんでした)、コンピューターコードはシリアル番号に接続され、DSACryptoServiceProvider :: VerifyDataメソッドでデジタル署名で検証されます。



DSAを復元するために、XMLテキストが変数text1のメソッドに渡されます。 少し掘り下げた後、XMLファイルが見つかりました。このファイルにはDSAリカバリー用のオブジェクトがありました。 キャストされた最初のことは、秘密キー(まあ、冗談ではない)を見つけることです。もちろん、開発者はそれを取り除きました。 XMLファイル自体は、ライブラリリソースに埋め込まれていました。 最初のステップは、DSAを生成し、結果のXMLをライブラリリソースに埋め込み、古いXMLを置き換えることでした。



以前は、このようなことをする必要がなかったため、リソースを置き換えるプログラムを検索しても結果が得られませんでした。 はい。プログラムをアクティブにするための完全に自動化されたソリューションを作りたかったのです。 もちろん、このdllに同様のプログラムでパッチを適用してから、標準のDLLをパッチャーに置き換えることはできましたが、どういうわけかこれは見た目が良くありません。 この製品の開発者に評価のために送信するために、完全に自動化されたソリューションを作成したいと思います。



プログラムでリソースを置き換えるというトピックの検索では、適切な解決策は得られませんでした。 手は何とか手放します。 原則として、DSAオブジェクトをライブラリに埋め込むことでライセンスをバイパスし、同じオブジェクトにライセンスジェネレーターを作成できることを証明しました。

しばらくの間、私はこのすべてを遠い箱に落とし、仕事に取り掛かる必要がありました。 しばらくして、再び誰かがこのプログラムとそのセキュリティについて教えてくれました。 再び分析を始めました。



座ってしばらく考えた後、ILコンパイラが文字列をコンパイルしないことを思い出して、アイデアが思いついた(多くの人は非常に原始的で愚かだと思うだろう)と簡単なメモ帳を通してライブラリの内部を見るようになりました。 はい、メモ帳を開きます。 DSAKeyValueキーワードを検索すると、すぐにDSAオブジェクトのXMLデータが取得されました。 このオブジェクトをプログラムで自分のものに置き換えるために、正規表現のアイデアがすぐに思い浮かびました。 彼は自分の計画を実現したため、コーディングを始め、図書館がまったく機能しなかったという事実に直面しました。 同様の結果を予想して、完全に置き換える前に、オブジェクトの部分的な置き換えを試みました。その後、ライブラリは正常に機能しましたが、公式ライセンスさえ食べませんでした。



以前は、XMLファイルと私のファイルの公式DSAオブジェクトの長さ(長さは文字数を意味します)をチェックしました。サイズは完全に一致していました。



さらに、プログラム全体でライブラリ全体をバイトの配列に読み取り、dsaオブジェクトを読み取る際のxmlの最初と最後の出現を修正し、これらのバイトを自分のバイトに置き換えて、ファイルに保存し直しました。

DSAオブジェクトがオンザフライで生成されたことを忘れていましたが、xmlで生成される場合、データに秘密キーを追加するかどうかを指定できます。元の署名にはないため、この値をfalseに設定します。 DSAが初期化されるとすぐに、シリアル番号でデジタル署名が作成され、ライセンスファイルに保存されました。



上記の手順を完了すると、xml DSAオブジェクトがリフレクターに反映されるはずです。 プログラムを実行しようとするだけでした。 目を細めて、プログラムを実行しようとしました。 予想どおり、プログラムはライセンスの問題なしで起動しました。



しばらくして、 Mono.Cecilライブラリを使用してサードパーティアセンブリにMSILコードを挿入することに関するハブに関する記事を見つけまし 。 数分後、ライセンス検証メソッドの最初に単純な戻り値を追加するコードが作成され、ライセンスが正常に確認されました!



private void Injector(string path) { var assembly = AssemblyDefinition.ReadAssembly (path); foreach (var typeDef in assembly.MainModule.Types) { foreach (var method in typeDef.Methods) { string mp = "("; for (int i = 0; i < method.Parameters.Count; i++) { mp += method.Parameters[i].ParameterType+","; } mp = mp.Trim(' '); mp = mp.Trim(','); mp += ")"; if (mp == "(System.Byte[],System.String,System.String)") { var ilProc = method.Body.GetILProcessor(); Instruction badInstruction = Instruction.Create (OpCodes.No); Instruction firstInstruction = ilProc.Body.Instructions [0]; ilProc.InsertBefore (firstInstruction, Instruction.Create (OpCodes.Ret, firstInstruction)); ilProc.InsertBefore (firstInstruction, badInstruction); } } } assembly.Write(path); }
      
      







このフレームワークでライセンスをチェックする原理は信じられないほど単純であるため、この方法は機能します。 ライセンス検証メソッドを呼び出すメソッドに例外ハンドラーがインストールされます。ライセンス検証メソッドで例外が発生した場合、ライセンスが正しくないかまったくない場合、例外がない場合はすべてを順番に開始できます。



すべてのメソッドは難読化されているため、Mono.Cecilを使用して名前でメソッドを検索しても意味がありません。 リフレクターを見ると、このライブラリーには、同じタイプとシーケンスで同じ引数を持っている人はいないことに気付きました。 したがって、引数によってメソッドを割り当てることが決定されました。



 if (mp == "(System.Byte[],System.String,System.String)"){ //… }
      
      







それは基本的にそれです。



PSこの記事は、クラッキングの補助などを意図したものではありません。 上記で実行されたアクションが原始的であり、実装がとんでもないことを理解するために、プログラミングの第一人者である必要はありません。



All Articles