「なぜ誰でも可胜ですが、できないのですか」たたはAPIを逆にしお、eTokenからデヌタを取埗したす









私たちの䌁業では、タスクは非垞に重芁なファむルを転送する際のセキュリティレベルを高めるこずでした。 䞀般に、単語ごずに、䞀定の量を蓄積しおいるため、scpを䜿甚しお転送し、eTokenタむプのリモヌトコントロヌルに認蚌甚の蚌明曞の秘密キヌを保存する必芁があるずいう結論に達したした。



アむデアは良いように芋えたしたが、それを実装する方法は それから、クラむアントバンクが䌚蚈で働いおいなかったこずを思い出したした。話をする名前etsdk.dllのラむブラリがないこずを呪い、奜奇心が私を襲い、それを遞んだのです。



䞀般に、開発䌚瀟はWebサむトでSDKを配垃しおいたすが、そのためには゜フトりェア開発䌚瀟ずしお登録する必芁があり、これは明らかに私ではありたせん。 むンタヌネットでドキュメントを芋぀けるこずができたせんでしたが、奜奇心が勝ち、それを自分で理解するこずにしたした。 図曞通-ここにありたす、時間がありたす、誰が私を止めるのですか



私が最初にしたこずは、NirSoft DLL Export Viewerを起動したこずで、ラむブラリによっお゚クスポヌトされた適切な関数のリストが衚瀺されたした。 リストは芋栄えが良く、トヌクンを操䜜するずきのアクションのロゞックずシヌケンスがトレヌスされたす。 ただし、1぀のリストでは䞍十分であり、どのパラメヌタヌを、どの順序で転送し、結果を取埗するかを理解する必芁がありたす。











そしお、私たちの若さを思い出しおOllyDbgバヌゞョン2.01を起動し、クラむアントバンクで䜿甚されるccom.dll暗号システムCrypto-Comラむブラリをロヌドし、その䞭にetsdk.dllラむブラリを䜿甚しお、その方法を理解し始めたす。



実行可胜ファむルがないため、ラむブラリはOllyバンドルのloaddll.exeを䜿甚しおロヌドされるため、完党なデバッグを倢芋るこずさえできたせん。 実際、デバッガヌを逆アセンブラヌずしお䜿甚したすはい、IDAがありたすが、私はIDAを䜿甚したこずはなく、䞀般に支払われたす。



コンテキストメニュヌを呌び出しお、[怜玢]> [すべおのモゞュヌル間呌び出し]を遞択し、名前で結果を敎理し、ET *で始たる関数を探したすが、芋぀かりたせん。 これは、ラむブラリが動的に接続するこずを意味するため、同じリストでGetProcAddress呌び出しを探し、それらを調べお、特定の詊みでETReadersEnumOpen関数のアドレスを芋぀けようずしたす。











悪くない。 受信した関数アドレスは、MOV DWORD PTR DSタむプのコマンドによっおメモリに保存されたす[10062870]、EAX、そのような各コマンドを遞択し、コンテキストメニュヌを呌び出し、[参照の怜玢]> [アドレス定数]を遞択したす。 開いたりィンドりに、珟圚のコマンドず関数呌び出しのすべおの堎所が衚瀺されたす。 それらを調べお、呌び出されおいる関数の名前をコメントにしおください。これにより、将来の生掻が楜になりたす。



これらの関数を適切に呌び出す方法を理解する時が来たした。 最初から始めお、読者に関する情報を取埗する方法を孊びたしょう。 ETReadersEnumOpen関数を呌び出す堎所に枡し、残ったコメントのおかげで、ETReadersEnumNextずETReadersEnumNextずETReadersEnumCloseの䞡方が1぀の関数に集䞭しおいるこずがわかりたす-明らかに、リヌダヌのリストを取埗するこずに埓事しおいたす。



すべおの関数はcdecl呌び出し芏玄を䜿甚したす。 これは、結果がEAXレゞスタに返され、パラメヌタが右から巊にスタックを通過するこずを意味したす。 さらに、これは、すべおのパラメヌタヌがダブルワヌドの次元を持ち、そうでない堎合は拡匵されるため、私たちの生掻が簡玠化されるこずを意味したす。



ETReadersEnumOpen呌び出しの近傍を芋おみたしょう











1぀のパラメヌタヌが枡されたす。これは、ロヌカル倉数ぞのポむンタヌです。呌び出しの埌、結果が0でない堎合、制埡は明瀺的なデバッグコヌドに転送され、等しい堎合は先に進みたすZFフラグずOFフラグが等しく、フラグがOFコマンドTESTは垞に0にリセットされたす。 したがっお、私は次の順序を結びたす倉数は参照によっお関数に枡され、そこにいく぀かの列挙識別子が返され、その結果、関数ぱラヌコヌドたたぱラヌがない堎合は0を返したす。



ETReadersEnumNextに移動したす。











2぀のパラメヌタヌが枡されたすETReadersEnumOpen列挙の識別子を䜿甚しお取埗した倉数の倀ず、明らかに次の倀が返されるロヌカル倉数ぞのポむンタヌ。 さらに、パラメヌタは右から巊に順番に転送されるため、最初のパラメヌタが識別子であり、2番目が結果ポむンタです。 ゚ラヌコヌドは匕き続きEAXを介しお返され、ルヌプの蚭蚈から刀断するず、゚ラヌを報告するためだけでなく、リストするものがないこずを瀺すためにも䜿甚されたす。



ETReadersEnumCloseはさらに単玔です。列挙識別子が枡されたすが、結果は誰にも迷惑をかけたせん。











これらの機胜の理解をテストする時が来たした。 ここで私は䜙談を䜙儀なくされたした。事実、私は専門職のシステム管理者であり、したがっお真面目なコンパむルされたプログラミング蚀語は完党に私のものではありたせん。 仕事には、Linux甚のBashずPythonがさらに必芁ですが、Windowsで䜕かをすばやく積み重ねる必芁がある堎合は、気に入ったAutoItを䜿甚したす。



私のプラスは次のずおりです。





短所





この䜙談は、AutoItで関数を䜿甚する䟋を䜜成するずいう事実にありたす。 蚀語での暗黙的な型付けに関連しお、倖郚ラむブラリから関数を呌び出すこずはやや䞍栌奜に芋えたすが、機胜したす。



始めたしょう率盎に蚀っお、どの関数がどのサむズを返すのかわからないので、最初に倧きなバッファヌを䞎えお、䜕が起こるか芋おみたしょう。 開始するコヌド



Dim $ETSdkDll=DllOpen('etsdk.dll') Dim $buf=DllStructCreate('BYTE[32]') Func PrintBuf($buf) For $i=1 To DllStructGetSize($buf) ConsoleWrite(Hex(DllStructGetData($buf,'buf',$i),2)&' ') Next ConsoleWrite(@CRLF) EndFunc ConsoleWrite('Buffer before: ') PrintBuf($buf) $result=DllCall($ETSdkDll,'DWORD','ETReadersEnumOpen', _ 'PTR',DllStructGetPtr($buf) _ ) ConsoleWrite('Buffer after: ') PrintBuf($buf) ConsoleWrite('Return value: '&$result[0]&@CRLF)
      
      







実行するず、次のような結論が埗られたす。



 Buffer before: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Buffer after: 44 6F C8 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Return value: 0
      
      





数回実行するず、最初の4バむトのみが倉曎されおいるこずがわかりたす。぀たり、4バむト敎数が識別子ずしお䜿甚されたす。぀たり、この関数をこの状態に呌び出すコヌドをコヌムするこずができたす。



 Func ETReaderEnumOpen() Local $id=DllStructCreate('DWORD') Local $result=DllCall($ETSdkDll,'DWORD','ETReadersEnumOpen', _ 'PTR',DllStructGetPtr($id) _ ) Return $result[0]?0:DllStructGetData($id,1) EndFunc
      
      





ETReadersEnumNext関数を䜿甚した同様の実隓では、バッファの最初の260バむトにリヌダヌ名ずれロが含たれおいるこずが瀺されたした。 この関数ぞの順次呌び出しは、システム内のすべおのリヌダヌによっおリストされたしたたずえば、ruTokenの䞋に3぀が事前に䜜成されたした。 eTokenのリヌダヌは、接続されおいるトヌクンの数に応じお動的に䜜成され、最も興味深いこずに、バッファヌの261番目のバむトが1に蚭定されたす。これは、明らかに、リヌダヌずラむブラリの互換性を瀺したす。 逆アセンブルされたコヌドを芋るず、261番目のバむトが0に等しいレコヌドが凊理されおいないこずがわかりたす。 すべおのリヌダヌのキロバむトバッファヌの最埌たでの他のすべおのバむトは0で、違いはありたせん。



それで、読者を芋぀けたした。次は䜕を理解する必芁がありたす。 関数のリストを調べた埌、呌び出しシヌケンスは次のようにすべきであるずいう結論に達したした最初に目的のリヌダヌをバむンドし、この段階で挿入されたトヌクンに関する䞀般的な情報を芋぀けおからログむンし、その埌ファむルシステムにアクセスしたす。 したがっお、次のむンラむン関数はETTokenBindずETTokenUnbindです。











ETTokenBindは耇雑で理解しにくいように芋えたすが、しばらく掘り䞋げた埌、2぀のパラメヌタヌが関数に枡されるずいう結論に達したした。最初のパラメヌタヌは328バむト0x0148のバッファヌぞのポむンタヌであり、2番目はリヌダヌの名前を持぀文字列ぞのポむンタヌです。 実隓を通しお、バッファの最初の4バむトで識別子が返されるこずがわかりたした以降バむンディング識別子。 残りのバッファが割り圓おられおいるのはなぜですか-今のずころは謎です。 私が実隓しないトヌクン、バッファの残りの324バむトはれロで満たされたたたでした。 指定された識別子は論理的であり、ETTokenUnbindおよびETTokenRebind関数の匕数ずしお正垞に䜿甚されたす。











行の次の関数はETRootDirOpenです。 結果ぞのポむンタヌ、バむンディングID、および定数の3぀のパラメヌタヌが必芁です。 この機胜にはいく぀かの機胜がありたす。



最初この関数の返された結果は、れロに等しい成功だけでなく、䞋䜍2バむトが数倀0x6982に等しいかどうかもチェックされ、結果がこの数倀に等しい堎合、制埡は関数に転送され、続いおETTokenLoginを呌び出しおから再詊行したすETRootDirOpenを呌び出したす。 このこずから、0x6982は「Authorization Required」を意味する゚ラヌコヌドであるず結論付けるこずができたす。 今埌、ファむルやフォルダヌを操䜜する他のすべおの機胜は同じように配眮されたす。



2番目パラメヌタヌの1぀ずしお、この関数は定数0xF007を取りたす。 コヌドには他の定数を䜿甚した呌び出しはありたせん。 おそらく、この定数はトヌクン倚くのルヌトフォルダヌに曞き蟌たれた情報を䜕らかの圢で特城付けおいるのでしょう。 2バむト定数のすべおの倀に察しおブルヌトフォヌスを実行しようずしたしたが、トヌクンは倀0x0001、0xF001-0xF00Bにのみ応答したしたちなみに、認蚌を芁求したせんでした。 埌で、新しく初期化されたトヌクンで同じフォルダヌが䜿甚できるこずがわかりたした。 これに぀いおしばらく考えた埌、開発者の蚈画によるず、さたざたなルヌトフォルダヌがさたざたな目的に䜿甚され、0xF007はキヌ甚であるず曞かれおいるずいう結論に達したした。



3番目関数によっお返された倀はスクリヌンショットには衚瀺されたせんが、以前に割り圓おられた328バむトのバッファヌの䞭倮に戻りたす。このバッファヌから、怜蚎䞭のトヌクンに関連するさたざたな識別子ずデヌタを栌玍する構造であるず刀断できたす。



承認の詊みが終わったので、今床は察凊したす。 ETTokenLogin関数は、バむンディング識別子ずバッファヌぞのポむンタヌずいう2぀のパラメヌタヌを受け取りたす。 最初はバッファが䜕らかの結果を出力するために䜿甚されたず考えたしたが、実隓は次のアルゎリズムが䜿甚されたこずを瀺したしたポむンタがれロたたは空の文字列を指す堎合、ラむブラリはパスワヌドを芁求するむンタヌフェヌスりィンドりを描画し、空でない文字列を指す堎合-この文字列パスワヌドずしお䜿甚されたす。 ETTokenLogoutは、バむンディング識別子ずいう1぀のパラメヌタヌのみを受け入れたす。



次の関数グルヌプETDirEnumOpen、ETDirEnumNext、およびETDirEnumClose。 コヌドを調べずにそれらを解こうずするこずができたす。 䞀般に、これらはETReadersEnum *ず同じように機胜するはずですが、唯䞀の違いは、珟圚のフォルダヌの識別子がETDirEnumOpenにパラメヌタヌずしお枡されるこずです。 チェック-動䜜したす。



ETFilesEnumOpen、ETFilesEnumNext、およびETFilesEnumClose関数グルヌプは、同じ方法で機胜するために必芁なだけですが、これを確実に怜蚌するこずはできたせん。 どうやら、調査䞭のトヌクンのルヌトフォルダヌにファむルはないようです。぀たり、ETDirOpen関数を䜿甚しおフォルダヌツリヌをさらに深く掘り䞋げたす。











このAPIは、最初のパラメヌタヌを䜿甚しお結果を返すずいう䌝統を匕き継いでいるように思われるため、今回もこれが圓おはたるず仮定したす。 2番目のパラメヌタヌは、関数に枡される前に、MOVZX EDI、DIコマンドを䜿甚しお倉曎されたす。 単語はダブルワヌドに展開されたす。 明らかに、これは4バむトのパラメヌタヌで2バむトのフォルダヌ名を枡すために必芁です。 さお、物事のロゞックによるず、3番目のパラメヌタヌは開いおいるフォルダヌの識別子です。 詊しおみたした-刀明したした。 ETDirCloseは驚くこずなく掚枬できたす1パラメヌタヌ-フォルダヌ識別子。



そのため、トヌクン䞊のすべおのファむルずフォルダヌをリストするのに十分なこずを孊びたした。 次の簡単なコヌドでそれを行いたすここではDllCallを呌び出したせん。蚘事の最埌にあるモゞュヌルテキストのすべおの関数に察応したす。



 Func PrintDir($Id,$Prefix) Local $EnumId=ETDirEnumOpen($Id) While 1 Local $dir=ETDirEnumNext($EnumId) If @error Then ExitLoop ConsoleWrite($Prefix&'(dir)'&Hex($dir,4)&@CRLF) Local $DirId=ETDirOpen($dir,$Id) PrintDir($DirId,$Prefix&@TAB) ETDirClose($DirId) WEnd ETDirEnumClose($EnumId) $EnumId=ETFilesEnumOpen($Id) While 1 Local $file=ETFilesEnumNext($EnumId) If @error Then ExitLoop ConsoleWrite($Prefix&'(file)'&Hex($file,4)&@CRLF) WEnd ETFilesEnumClose($EnumId) EndFunc Local $EnumId=ETReaderEnumOpen() If $EnumId Then While 1 Local $reader=ETReaderEnumNext($EnumId) If @error Then ExitLoop If Not $reader[1] Then ContinueLoop Local $BindId=ETTokenBind($reader[0]) ConsoleWrite($reader[0]&':'&@CRLF) ETTokenLogin($BindId,'123456') Local $DirId=ETRootDirOpen($BindId) PrintDir($DirId,@TAB) ETDirClose($DirId) WEnd EndIf ETReaderEnumClose($EnumId)
      
      





コン゜ヌルでの結果



 Aladdin Token JC 0: (dir)1921 (dir)DDDD (file)0002 (file)0003 (file)0004 (file)0001 (file)A001 (file)B001 (file)C001 (file)AAAA (file)D001
      
      





いいね



さお、フォルダを開いお衚瀺する方法を孊びたした。ファむルを開いお読む方法を孊びたしょう。 ETFileOpenは3぀のパラメヌタヌを受け入れるため、最初にETDirOpenず同じこずを詊みたす。結果、ファむル名、フォルダヌID、ブレヌクオフ開発者は最埌の2぀のパラメヌタヌを逆にしたした。 たあ、少なくずもETFileCloseは驚くこずなく動䜜したす。



ETFileRead。 最悪の機胜、なぜなら 5぀のパラメヌタヌを認識したす。 そんなにどこ 必芁なものをリストしおみたしょうどこから読み蟌むかファむル、どこから読み蟌むかバッファ、どれだけ読み蟌むか、どこから読み蟌むか。 䜕をどのように理解しようずしたしょう











ご芧のずおり、ETFileRead関数に枡される3番目のパラメヌタヌは垞に0xFFFFであるため、これが読み取りデヌタの長さであるず想定する傟向がありたす。 残りの4぀のパラメヌタヌは、倖郚から同じ順序でFileReadHereを呌び出した関数に送られたす。 次の図は、この関数の近傍呌び出しを瀺しおいたす。 最初のパラメヌタヌの倀は、アドレスESI + 8のメモリから取埗されたす。 このアドレスぞのポむンタヌはFileOpenHere関数で䜿甚され同じ原則にちなんで呜名されたす、開いおいるファむルの識別子がそこに曞き蟌たれたす。 2番目のパラメヌタヌはれロに等しいため、ファむルの読み取りの開始点を担圓するように割り圓おたす。 3番目のパラメヌタヌETFileReadの4番目はなんずなく濁っおいるため、結果バッファヌぞのポむンタヌずしお割り圓おたす。 5番目のパラメヌタヌはたったく異垞です。 アドレスESI + 12からの単語がその䞭に配眮され、ダブルワヌドに展開されたす。 これたでのずころ、私が芋たオフセットはすべお4の倍数でした12は4の倍数ではありたせん。0x12、぀たり10進数で18です。 アドレスESI + 10は付近のどこにも蚘茉されおいたせんが、ESI + 0CはFileGetInfoHereに枡されるため、最初にETFileGetInfo関数を凊理する必芁がありたす。 簡単です。最初のパラメヌタヌはファむル識別子で、2番目は結果バッファヌぞのポむンタヌです。 呌び出し埌、バッファ内の1、2、3、7、および8バむトが倉曎されたす。 今埌、最埌の2バむトがファむルサむズであるこずがわかりたす。 ETFileRead関数ず、その出力バッファを初期化する関数に枡されるのはこの倀です。 ETFileGetInfoの結果の最初の2バむトはファむル名であるこずが刀明したした。 3番目の倀は理解できたせんでしたが、トヌクン䞊の1぀のファむルに察しおのみ1に蚭定されたした。 したがっお、次のパラメヌタの順序が出珟したす。ファむル識別子、読み取り開始ポむント、読み取る最倧バむト数、バッファポむンタ、バッファサむズ。



ETFileGetInfoに觊れたので、すぐにETDirGetInfoを実装する必芁がありたす。パラメヌタヌの順序は同じで、ファむルではなくフォルダヌの識別子のみが関係したす。 返される結果識別子によるフォルダヌ名。



これで、トヌクンからの読み取りが完了したした。次はトヌクンに曞き蟌みたす。 フォルダヌを䜜成するこずから始めたしょう。 ETDirCreate関数のパラメヌタヌ結果ぞのポむンタヌ明らかに、フォルダヌの䜜成埌、フォルダヌが開き、識別子がここに返されたす、フォルダヌの名前、芪フォルダヌの識別子、および0。4番目のパラメヌタヌはコヌドにハヌドコヌディングされおおり、それが䜕に圱響するのかただわかりたせん。 任意の倀に察しおフォルダヌが正垞に䜜成されたす。 ETDirDeleteは1぀のパラメヌタヌのみを受け入れるため、これは明らかに開いおいるフォルダヌの識別子です。 ETFileCreateは、ETDirCreateず同様の結果ぞのポむンタヌ、フォルダヌ識別子、ファむル名、ファむルサむズ、および5番目のパラメヌタヌの5぀のパラメヌタヌを取りたす。 5番目のパラメヌタヌがれロ以倖の倀に蚭定されおいる堎合、次にこのファむルに察しおETFileGetInfoが呌び出されるず、結果の3番目のバむトわかりにくいものが1に蚭定されたす。考えお、実隓を行い、属性が蚭定されたら入力する必芁があるこずを確認したしたパスワヌド、そうでない堎合、これは必芁ありたせん。 私が実隓したトヌクンに、そのようなファむルが1぀しかなかったこずは面癜いです。 他のすべおのファむルがこのキヌで暗号化されるこずを願っおいたす。 ETFileDeleteは、ETDirDeleteず同様に、驚くこずなく機胜したす。



このラむブラリで参照される最埌の関数はETFileWriteです。 それは4぀の匕数を取りたすファむル識別子、れロ実隓は、ファむルの先頭に盞察的な混合であるこずを瀺したす、デヌタずデヌタサむズのあるバッファぞのポむンタ。 ファむルは展開されないこずに泚意しおください。 オフセットずファむル長の合蚈がファむルサむズを超える堎合、蚘録は行われないため、ファむルサむズを倉曎する必芁がある堎合、ファむルを削陀しお新しいサむズで再䜜成する必芁がありたす。



さらに、ラむブラリの゚クスポヌトテヌブルをリコヌルするず、さらに5぀の関数がありたすが、Crypto-Com暗号化情報保護ツヌルず連携するこのラむブラリには、それらの呌び出しは実装されおいたせん。 幞いなこずに、同じ銀行はCIPFを操䜜するためのMessage-Proラむブラリ-mespro2.dllも配垃しおいたす。mespro2.dllはトヌクンも䜿甚でき、ETTokenLabelGet呌び出しなど、もう少しトヌクンを䜿甚できたす。











スクリヌンショットは、最初のケヌスでは2番目のパラメヌタヌがれロであり、2番目のパラメヌタヌではある皮の数倀であるずいう2぀の関数呌び出しがあるこずを瀺しおいたす。 3番目のパラメヌタヌは垞にポむンタヌであるため、これが結果であり、最初のパラメヌタヌであるず想定したす-トヌクンを含むバンドルの識別子を仮定するこずは論理的です 2番目のパラメヌタヌずしおれロから開始しようずしたす-バッファヌの最初の4バむトが倀0x0000000Aに倉曎されたした。 10、これは名前「TestToken」の長さであり、末尟にれロバむトがありたす。 しかし、ポむンタヌによっお3番目のパラメヌタヌにダブルワヌドが返される堎合、必芁なサむズのバッファヌぞのポむンタヌを2番目のパラメヌタヌに転送する必芁があるこずがわかりたす。 したがっお、この順序を終了したす。最初に関数を実行するず、2番目のパラメヌタヌはNULLポむンタヌになり、3番目はダブルワヌドポむンタヌになりたす。 次に、必芁なサむズのバッファヌを初期化し、関数を2回実行したす。2番目のパラメヌタヌはバッファヌぞのポむンタヌです。



しかし、さらに4぀の関数の呌び出しはここでは実装されおいなかったため、総圓たりず盎感で実装を受け取りたした。呌び出された関数に枡されるパラメヌタヌが少なすぎるず、プログラム実行䞭に重倧な゚ラヌが発生するこずがわかりたした。これにより、残りの関数のパラメヌタヌの数を実隓的に遞択できたす



ETTokenIDGet3

ETTokenMaxPinGet2

ETTokenMinPinGet2

ETTokenPinChange2



ETTokenIDGetは単玔な倀を返すには倚すぎるパラメヌタヌを受け入れるため、ETTokenGetLabelず同じ方法で実行したす。最初の詊行で刀明し、トヌクンの偎面に曞かれた数字の文字列を返したす。



䞀方、ETTokenMaxPinGetずETTokenMinPinGetには倚数のパラメヌタヌがあり、単䞀の数倀を返すのに理想的です。 最初のパラメヌタヌ-バンドルの識別子、2番目-数倀ぞのポむンタヌを詊したす。 その結果、トヌクン蚭定で指定されたパスワヌドの最倧長ず最小長を取埗したす。



ETTokenPinChangeは、名前に基づいお、パスワヌドをトヌクンにそれぞれ倉曎する圹割を果たし、バンドル識別子ず新しいパスワヌドを含む文字列ぞのポむンタヌのみを受け入れる必芁がありたす。 初めお詊しおいるずきに、゚ラヌコヌド0x6982が衚瀺されたす。これは、知っおいるように、トヌクンにログむンする必芁があるこずを意味したす。 論理的です。 ログむンず短いパスワヌドで繰り返したす-゚ラヌ0x6416を受け取りたす。 パスワヌドの長さがポリシヌに準拠しおいないず刀断したす。 長いパスワヌドで繰り返したす-実珟したす。



ここで、すべおの機胜を1぀のモゞュヌルにたずめお保存したす。他のプロゞェクトに含めたす。 モゞュヌルのテキストは次のずおりです。



etsdk.au3
 ;Func ETReadersEnumOpen() ;Func ETReadersEnumNext($EnumId) ;Func ETReadersEnumClose($EnumId) ;Func ETTokenBind($ReaderName) ;Func ETTokenRebind($BindId) ;Func ETTokenUnbind($BindId) ;Func ETTokenLogin($BindId,$Pin='') ;Func ETTokenPinChange($BindId,$Pin) ;Func ETTokenLogout($BindId) ;Func ETRootDirOpen($BindId,$Dir=0xF007) ;Func ETDirOpen($Dir,$DirId) ;Func ETDirCreate($Dir,$DirId) ;Func ETDirGetInfo($DirId) ;Func ETDirClose($DirId) ;Func ETDirDelete($DirId) ;Func ETDirEnumOpen($DirId) ;Func ETDirEnumNext($EnumId) ;Func ETDirEnumClose($EnumId) ;Func ETFileOpen($File,$DirId) ;Func ETFileCreate($File,$DirId,$Size,$Private=0) ;Func ETFileGetInfo($FileId) ;Func ETFileRead($FileId) ;Func ETFileWrite($FileId,$Data,$Pos=0) ;Func ETFileClose($FileId) ;Func ETFileDelete($FileId) ;Func ETFilesEnumOpen($DirId) ;Func ETFilesEnumNext($EnumId) ;Func ETFilesEnumClose($EnumId) ;Func ETTokenLabelGet($BindId) ;Func ETTokenIDGet($BindId) ;Func ETTokenMaxPinGet($BindId) ;Func ETTokenMinPinGet($BindId) Const $ET_READER_NAME=0 Const $ET_READER_ETOKEN=1 Const $ET_FILEINFO_NAME=0 Const $ET_FILEINFO_PRIVATE=1 Const $ET_FILEINFO_SIZE=2 Dim $ETSdkDll=DllOpen('etsdk.dll') Func ETReadersEnumOpen() Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETReadersEnumOpen', _ 'PTR',DllStructGetPtr($Out) _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETReadersEnumNext($EnumId) Local $Reader=DllStructCreate('CHAR name[260]; BYTE etoken;') Local $CallRes=DllCall($ETSdkDll,'WORD','ETReadersEnumNext', _ 'DWORD',$EnumId, _ 'PTR',DllStructGetPtr($Reader) _ ) Local $Result[2]=[ DllStructGetData($reader,'name'), _ DllStructGetData($reader,'etoken')] Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :$Result EndFunc Func ETReadersEnumClose($EnumId) Local $CallRes=DllCall($ETSdkDll,'WORD','ETReadersEnumClose', _ 'DWORD',$EnumId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETTokenBind($ReaderName) Local $In=DllStructCreate('BYTE['&(StringLen($ReaderName)+1)&']') Local $Out=DllStructCreate('DWORD') DllStructSetData($In,1,$ReaderName) Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenBind', _ 'PTR',DllStructGetPtr($Out), _ 'PTR',DllStructGetPtr($In) _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETTokenRebind($BindId) Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenRebind', _ 'DWORD',$BindId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETTokenUnbind($BindId) Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenUnbind', _ 'DWORD',$BindId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETTokenLogin($BindId,$Pin='') Local $In=DllStructCreate('BYTE['&(StringLen($Pin)+1)&']') DllStructSetData($In,1,$Pin) Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLogin', _ 'DWORD',$BindId, _ 'PTR',DllStructGetPtr($In) _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETTokenPinChange($BindId,$Pin) Local $In=DllStructCreate('CHAR['&(StringLen($Pin)+1)&']') DllStructSetData($In,1,$Pin) Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenPinChange', _ 'DWORD',$BindId, _ 'PTR',DllStructGetPtr($In) _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETTokenLogout($BindId) Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLogout', _ 'DWORD',$BindId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETRootDirOpen($BindId,$Dir=0xF007) Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETRootDirOpen', _ 'PTR',DllStructGetPtr($Out), _ 'DWORD',$BindId, _ 'DWORD',$Dir _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETDirOpen($Dir,$DirId) Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirOpen', _ 'PTR',DllStructGetPtr($Out), _ 'DWORD',$Dir, _ 'DWORD',$DirId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETDirCreate($Dir,$DirId) Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirCreate', _ 'PTR',DllStructGetPtr($Out), _ 'DWORD',$Dir, _ 'DWORD',$DirId, _ 'DWORD',0 _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETDirGetInfo($DirId) Local $Out=DllStructCreate('BYTE[8]') Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirGetInfo', _ 'DWORD',$DirId, _ 'PTR',DllStructGetPtr($Out) _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETDirClose($DirId) Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirClose', _ 'DWORD',$DirId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETDirDelete($DirId) Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirDelete', _ 'DWORD',$DirId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETDirEnumOpen($DirId) Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirEnumOpen', _ 'PTR',DllStructGetPtr($Out), _ 'DWORD',$DirId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETDirEnumNext($EnumId) Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirEnumNext', _ 'DWORD',$EnumId, _ 'PTR',DllStructGetPtr($Out) _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETDirEnumClose($EnumId) Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirEnumClose', _ 'DWORD',$EnumId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETFileOpen($File,$DirId) Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileOpen', _ 'PTR',DllStructGetPtr($Out), _ 'DWORD',$DirId, _ 'DWORD',$File _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETFileCreate($File,$DirId,$Size,$Private=0) Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileCreate', _ 'PTR',DllStructGetPtr($Out), _ 'DWORD',$DirId, _ 'DWORD',$File, _ 'DWORD',$Size, _ 'DWORD',$Private _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETFileGetInfo($FileId) Local $Out=DllStructCreate('WORD name;WORD private;WORD;WORD size') Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileGetInfo', _ 'DWORD',$FileId, _ 'PTR',DllStructGetPtr($Out) _ ) Local $Result[3]=[ DllStructGetData($Out,'name'), _ DllStructGetData($Out,'private'), _ DllStructGetData($Out,'size')] Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :$Result EndFunc Func ETFileRead($FileId) Local $FileInfo=ETFileGetInfo($FileId) If @error Then Return SetError(@error,0,False) Local $Out=DllStructCreate('BYTE ['&$FileInfo[$ET_FILEINFO_SIZE]&']') Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileRead', _ 'DWORD',$FileId, _ 'DWORD',0, _ 'DWORD',0xFFFF, _ 'PTR',DllStructGetPtr($Out), _ 'DWORD',$FileInfo[$ET_FILEINFO_SIZE] _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETFileWrite($FileId,$Data,$Pos=0) $Data=Binary($Data) Local $DataSize=BinaryLen($Data) Local $In=DllStructCreate('BYTE['&$DataSize&']') DllStructSetData($In,1,$Data) Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileWrite', _ 'DWORD',$FileId, _ 'DWORD',$Pos, _ 'PTR',DllStructGetPtr($In), _ 'DWORD',$DataSize _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETFileClose($FileId) Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileClose', _ 'DWORD',$FileId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETFileDelete($FileId) Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileDelete', _ 'DWORD',$FileId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETFilesEnumOpen($DirId) Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETFilesEnumOpen', _ 'PTR',DllStructGetPtr($Out), _ 'DWORD',$DirId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETFilesEnumNext($EnumId) Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETFilesEnumNext', _ 'DWORD',$EnumId, _ 'PTR',DllStructGetPtr($Out) _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETFilesEnumClose($EnumId) Local $CallRes=DllCall($ETSdkDll,'WORD','ETFilesEnumClose', _ 'DWORD',$EnumId _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :True EndFunc Func ETTokenLabelGet($BindId) Local $Out1=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLabelGet', _ 'DWORD',$BindId, _ 'PTR',0, _ 'PTR',DllStructGetPtr($Out1) _ ) If $CallRes[0] Then Return SetError($CallRes[0],0,False) Local $Out2=DllStructCreate('CHAR['&DllStructGetData($Out1,1)&']') $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLabelGet', _ 'DWORD',$BindId, _ 'PTR',DllStructGetPtr($Out2), _ 'PTR',DllStructGetPtr($Out1) _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out2,1) EndFunc Func ETTokenIDGet($BindId) Local $Out1=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenIDGet', _ 'DWORD',$BindId, _ 'PTR',0, _ 'PTR',DllStructGetPtr($Out1) _ ) If $CallRes[0] Then Return SetError($CallRes[0],0,False) Local $Out2=DllStructCreate('CHAR['&DllStructGetData($Out1,1)&']') $CallRes=DllCall($ETSdkDll,'WORD','ETTokenIDGet', _ 'DWORD',$BindId, _ 'PTR',DllStructGetPtr($Out2), _ 'PTR',DllStructGetPtr($Out1) _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out2,1) EndFunc Func ETTokenMaxPinGet($BindId) Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenMaxPinGet', _ 'DWORD',$BindId, _ 'PTR',DllStructGetPtr($Out) _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc Func ETTokenMinPinGet($BindId) Local $Out=DllStructCreate('DWORD') Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenMinPinGet', _ 'DWORD',$BindId, _ 'PTR',DllStructGetPtr($Out) _ ) Return $CallRes[0] _ ?SetError($CallRes[0],0,False) _ :DllStructGetData($Out,1) EndFunc
      
      







そのため、トヌクンファむルシステムで䜕でもできたす。これを瀺すために、あるトヌクンから別のトヌクンに内容をコピヌする簡単なスクリプトを曞きたした。「抂念実蚌」レベルのスクリプト、぀たり 「正しい」アプリケヌションにあるはずのチェックは倚くありたせんが、2番目の有効なトヌクンを取埗できたす。



eTokenCopy.au3
 #include <etsdk.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #NoTrayIcon Opt('MustDeclareVars',1) Opt('GUIOnEventMode',1) Opt('GUIDataSeparatorChar',@LF) Const $Title='eToken Copy' Const $GUISize[2]=[250,100] Dim $SrcCtrl,$DstCtrl,$ListTimer Func TokenCopyDir($SrcId,$DstId) Local $Name,$SrcSubId,$DstSubId,$SrcInfo,$SrcData ;      Local $EnumId=ETDirEnumOpen($SrcId) While 1 $Name=ETDirEnumNext($EnumId) If @error Then ExitLoop $SrcSubId=ETDirOpen($Name,$SrcId) $DstSubId=ETDirOpen($Name,$DstId) If @error Then $DstSubId=ETDirCreate($Name,$DstId) EndIf TokenCopyDir($SrcSubId,$DstSubId) ETDirClose($SrcSubId) ETDirClose($DstSubId) WEnd ETDirEnumClose($EnumId) ;    $EnumId=ETFilesEnumOpen($SrcId) While 1 $Name=ETFilesEnumNext($EnumId) If @error Then ExitLoop $SrcSubId=ETFileOpen($Name,$SrcId) $SrcInfo=ETFileGetInfo($SrcSubId) $DstSubId=ETFileOpen($Name,$DstId) If Not @error Then ETFileDelete($DstSubId) EndIf $DstSubId=ETFileCreate($Name,$DstId,$SrcInfo[$ET_FILEINFO_SIZE],$SrcInfo[$ET_FILEINFO_PRIVATE]) ETFileWrite($DstSubId,ETFileRead($SrcSubId)) ETFileClose($SrcSubId) ETFileClose($DstSubId) WEnd ETFilesEnumClose($EnumId) EndFunc Func TokenCopy() Local $Src=GUICtrlRead($SrcCtrl) Local $Dst=GUICtrlRead($DstCtrl) If $Src=='' Or $Dst=='' Then MsgBox(0x10,$Title,'   ') Return False EndIf ;       $Src=StringMid($Src,StringLen($Src)-8,8) $Dst=StringMid($Dst,StringLen($Dst)-8,8) If $Src==$Dst Then MsgBox(0x10,$Title,'      ') Return False EndIf ;    Local $SrcBindId=False,$DstBindId=False Local $EnumId=ETReadersEnumOpen() While 1 Local $Reader=ETReadersEnumNext($EnumId) If @error Then ExitLoop If Not $Reader[$ET_READER_ETOKEN] Then ContinueLoop Local $BindId=ETTokenBind($Reader[$ET_READER_NAME]) If ETTokenIDGet($BindId)==$Src Then $SrcBindId=$BindId ElseIf ETTokenIDGet($BindId)==$Dst Then $DstBindId=$BindId Else ETTokenUnbind($BindId) EndIf WEnd ETReadersEnumClose($EnumId) If Not ETTokenLogin($SrcBindId) Then MsgBox(0x10,$Title,'   -') Return False EndIf If Not ETTokenLogin($DstBindId) Then MsgBox(0x10,$Title,'   -') Return False EndIf ;   TokenCopyDir(ETRootDirOpen($SrcBindId),ETRootDirOpen($DstBindId)) ETTokenUnbind($SrcBindId) ETTokenUnbind($DstBindId) MsgBox(0x40,$Title,' ') EndFunc Func GetTokenList() Local $Reader, $BindId, $Result='' Local $EnumId=ETReadersEnumOpen() While 1 $Reader=ETReadersEnumNext($EnumId) If @error Then ExitLoop If Not $Reader[$ET_READER_ETOKEN] Then ContinueLoop $BindId=ETTokenBind($Reader[$ET_READER_NAME]) $Result&=@LF&ETTokenLabelGet($BindId)&' ('&ETTokenIDGet($BindId)&')' ETTokenUnbind($BindId) WEnd ETReadersEnumClose($EnumId) Return $Result EndFunc Func UpdateTokenList() Local $Tokens=GetTokenList() GUICtrlSetData($SrcCtrl,$Tokens,GUICtrlRead($SrcCtrl)) GUICtrlSetData($DstCtrl,$Tokens,GUICtrlRead($DstCtrl)) EndFunc Func onClose() Exit EndFunc Func GUIInit() GUICreate($Title,$GUISize[0],$GUISize[1],(@DesktopWidth-$GUISize[0])/2,(@DesktopHeight-$GUISize[1])/2) GUISetOnEvent($GUI_EVENT_CLOSE,'onClose') GUICtrlCreateLabel(':',8,8,64,-1,$SS_RIGHT) GUICtrlCreateLabel(':',8,32,64,-1,$SS_RIGHT) $SrcCtrl=GUICtrlCreateCombo('',76,6,$GUISize[0]-84,-1) $DstCtrl=GUICtrlCreateCombo('',76,30,$GUISize[0]-84,-1) GUICtrlCreateButton('',8,54,$GUISize[0]-16,$GUISize[1]-62) GUICtrlSetOnEvent(-1,'TokenCopy') GUISetState(@SW_SHOW) EndFunc GUIInit() UpdateTokenList() $ListTimer=TimerInit() While 1 ;      3  If TimerDiff($ListTimer)>3000 Then UpdateTokenList() $ListTimer=TimerInit() EndIf Sleep(100) WEnd
      
      















Crypto-Com、Crypto-Pro、Message-Pro、Signature、さらにはWillowなど、到達可胜なすべおの暗号情報保護ツヌルを詊したした。これらのキヌはすべお正垞にコピヌされ、機胜したした。



しかし、どのようにキヌはトヌクンから回埩可胜であるべきではありたせんか答えはeToken仕様にありたす。実際には、取埗できないキヌが実際に存圚したすが、RSAアルゎリズムを䜿甚した暗号倉換にのみ圹立ちたす。どのCPSSも考慮されおいたせん...いいえ、このようにロシア連邊の領土で䜿甚するためにFSBによっお承認されたCPSSはどれもRSAを䜿甚しおおらず、すべおGOST- *に基づいた暗号倉換を䜿甚しおいるため、eTokenはフラッシュドラむブにすぎたせんパスワヌドず耇雑なむンタヌフェヌス。



All Articles