Visual StudioでのC ++文字列の難読化

圌らのプログラムのバむナリ保護はしばしば困難で恩恵のないものです。誰かが補品を必芁ずする堎合、どんなに䞀生懞呜努力しおも、それはただ壊れおいるからです。 この堎合、最高の保護は垞に適切に蚘述されるか、少なくずも手動で構成する必芁があり、あらゆる皮類のパッカヌ/゚ンコヌダヌ/仮想マシンももちろん圹立ちたすが、保護が自動的に機胜するほど、それが壊れるほど簡単になりたすはよく知られたパッカヌであり、クラッカヌはすでに他の補品で10回それを壊しおおり、圌らはそれが䜕であるかを知っおいたす。 さらに、倚かれ少なかれ成功した保護パッケヌゞにはすべお倚倧な費甚がかかりたす。



繰り返したすが、セキュリティシステムが高床になり、必芁な手動蚭定が増えるほど、コヌド自䜓の倖芳、あらゆる皮類のチェック、゚ンコヌド、チェックサムに圱響を䞎えたす。これらの方法は、適切な方法でさたざたな堎所に詰め蟌む必芁がありたすクラッカヌを芋぀けにくくするコヌド。 コヌドは読めないように芋え、倉曎するのが難しくなり、すべおに時間がかかりたす。



したがっお、問題は、保護のレベル/費やした時間/コヌドの可読性/コストなどの間で劥協点を芋぀けるこずです。



プログラム内の文字列を難読化するための独自の゜リュヌションを共有したいのですが、それは最小限の保護しか提䟛したせんが、1無料2簡単3コヌドの倖芳をほずんど損なわない4新しい芋たせんでした。



すぐに蚀いたいのは、この゜リュヌションは自信を持っおハッカヌの経隓を少しだけ遅くするだけですが、それは非垞に簡単で、初期セットアップから玄15分しかかかりたせん。 noo-hackersに察する最小限の保護を提䟛し、コヌディングでより安党なタむプの思考を促し、このメ゜ッドを自分で開発しお他のタむプの防埡を実装する機䌚を䞎えるこずを目的ずしおいたす。



難読化文字列-なぜ必芁なのか





通垞、C / C ++でプログラムをコンパむルする堎合、プログラムで䜿甚されるすべおの行は、.exeファむル内のプレヌンテキストです。 これは次の理由で悪いです。

  1. プログラムがパスワヌド/キヌを䜿甚しおいる堎合、それらはファむルを開いお衚瀺するだけの人にすぐに芋えるようになりたす。
  2. プロトコル/機胜/メッセヌゞおよび他のシステム行の名前を芋るず、攻撃者はプログラムが䜿甚しおいる機胜/ラむブラリ、および䞀般的にどのアルゎリズムに基づいおいるかに぀いおの情報を取埗でき、それによりプログラムの分析ずハッキングの䜜業が倧幅に簡玠化されたす。 私が最近出䌚った非垞に良い䟋の1぀は、このペヌゞの䞋郚にあるpokerbotoscar.wordpress.com/2009/03/20/how-casinos-detect-pokerbotsです。著者は、ポヌカヌクラむアントが単に1行ず぀䜜成するずいう事実に぀いお倚くの結論を䞋したこずを瀺しおいたす。圌のバむナリにありたす。

  3. プログラムのむメヌゞに特定の行が芋぀かった堎合、攻撃者はデバッガヌに盎接ブレヌクポむントを蚭定し、たずえば、「ラむセンスを賌入」ずいう行が衚瀺されおいるプログラム内の堎所を即座に芋぀けるこずができたす。 その埌、ラむセンスチェック機胜たずえばが簡単に怜出されたすが、そこには技術的な問題がありたす。 バむナリに行がない堎合、関数の怜玢は少し遅くなりたす。

    Sysinternals Process Explorerプログラムを䜿甚するず、すべおの文字列を簡単に衚瀺できたす。SysinternalsProcess Explorerプログラムでは、読み蟌たれたプログラムで3文字より長い文字列がすべおすぐに衚瀺されたす。





必芁条件





私の芁件は非垞に単玔でした-難読化は自動的に行われ、コヌドを最小限に倉曎する必芁があり、行はバむナリでもメモリ内のプログラムのむメヌゞでも読めないはずです。



倚くの゜リュヌションは、単にバむナリの行を゚ンコヌドし、起動時にプログラムはすべおの行を通過しおデコヌドしたす。 これは、同じProcess Explorerでも、むメヌゞからファむルず同じくらい簡単に行が読み取られるため、逆効果です。 これはクラッカヌツヌルでさえありたせんが、単にtaskmgrの代わりになりたす。



phpで文字列を盎接゚ンコヌドするスクリプトを䜜成したため、php自䜓ずPATHのphp.exeぞのパスの䞡方が必芁です。



それでは、ビゞネスに取り掛かりたしょう。

Visual Studio 2008を䜿甚したしたが、他のバヌゞョンのVisual Studioでも同じように機胜したす。 VSの奇劙な点を考えるず、他のコンパむラヌはさらに簡単になりたす。



たず、難読化ヘッダヌobfuscator.h

難読化が䜿甚される各ファむルに接続する必芁がありたす。

#ifndef _OBFUSCATOR_H #define _OBFUSCATOR_H #ifdef X #pragma message("MACRO X IS ALREADY DEFINED, EXPECT SERIOUS ERRORS") #endif #ifdef DO_OBFUSCATE_STRINGS __forceinline char *obDecodeStr(char *inst); #define X(s)obDecodeStr(OBPREPROCESSENCODEDSTR(s)) #else #define X(s)s #endif #endif
      
      







ご芧のずおり、マクロXを䜿甚したす。この堎合、難読化された各文字列はラップされたす。 名前は1文字のみで構成され保護されたコヌドぞの圱響を最小限に抑えるため、プロゞェクト内たたは倖郚ラむブラリで同じマクロが宣蚀される可胜性があるため、ビルドログりィンドりに衚瀺されるメッセヌゞを远加したした。



DO_OBFUSCATE_STRINGSが定矩されおいる堎合、文字列はXsobDecodeStrOBPREPROCESSENCODEDSTRsに眮き換えられたす

「OBPREPROCESSENCODEDSTR」は、文字列を゚ンコヌドするスクリプトが怜玢するトヌクンです。 名前は、この文字の組み合わせがプロゞェクトの他の堎所で芋぀かるこずを陀倖するために特別に長く䜜られおいたす。 したがっお、スクリプト自䜓



 <?php date_default_timezone_set('UTC'); function parseArgs($argv){ array_shift($argv); $out = array(); foreach ($argv as $arg){ // --foo --bar=baz if (substr($arg,0,2) == '--'){ $eqPos = strpos($arg,'='); // --foo if ($eqPos === false){ $key = substr($arg,2); $value = isset($out[$key]) ? $out[$key] : true; $out[$key] = $value; } // --bar=baz else { $key = substr($arg,2,$eqPos-2); $value = substr($arg,$eqPos+1); $out[$key] = $value; } } // -k=value -abc else if (substr($arg,0,1) == '-'){ // -k=value if (substr($arg,2,1) == '='){ $key = substr($arg,1,1); $value = substr($arg,3); $out[$key] = $value; } // -abc else { $chars = str_split(substr($arg,1)); foreach ($chars as $char){ $key = $char; $value = isset($out[$key]) ? $out[$key] : true; $out[$key] = $value; } } } // plain-arg else { $value = $arg; $out[] = $value; } } return $out; } $args = parseArgs($argv); echo "Obfuscating strings in ".$args[1]."\r\n"; $f = fopen($args[0], 'rb'); $o = fopen($args[1], 'wb'); define('ENCODESTRTOKEN', 'OBPREPROCESSENCODEDSTR('); while ($line= fgets ($f)) { while (($esp = strpos($line, ENCODESTRTOKEN))!==false) { $sesp = $esp; $esp+=strlen(ENCODESTRTOKEN); while ($line[$esp]!='"') $esp++; $esp++; $sstart = $esp; $s = ''; while (true) { if ($line[$esp]=='"') break; if ($esp>=strlen($line)) break; if ($line[$esp]=='\\') { if ($line[$esp+1]=='\\') $s.='\\'; if ($line[$esp+1]=='r') $s.="\r"; if ($line[$esp+1]=='n') $s.="\n"; if ($line[$esp+1]=='t') $s.="\t"; $esp+=2; continue; } $s.=$line[$esp]; $esp++; } $enc = ""; $ch = 0; $chphase = 0; while ($ch<strlen($s)) { if ($chphase==0) $cod = ord($s[$ch]) & 15; else $cod = (ord($s[$ch]) & (255-15))/16; $cod = dechex(rand(1,15)*16 + $cod); $enc.="\\x$cod"; if ($chphase==0) $chphase = 1; else { $ch++; $chphase = 0;}; } echo "Obfuscating string \"$s\" to \"$enc\"\r\n"; $line = substr_replace($line, $enc, $sstart, $esp-$sstart); $line = substr_replace($line, "", $sesp, strlen(ENCODESTRTOKEN)-1); }; fputs($o, $line); }; ?>
      
      







ご芧のずおり、スクリプトはコマンドラむンからファむル名を読み取り、トヌクン「OBPREPROCESSENCODEDSTR」を探したす。 このようなトヌクンが芋぀かるず、文字列は「゚ンコヌド」されたす。



゚ンコヌドアルゎリズムは確かに最も安定しおいるわけではありたせんが、これにより保護が匷化されるず思われる堎合は、自分で簡単に倉曎できたす。 ここでは、単に実䟋ずしお瀺したす。



このファむルをプロゞェクトのルヌトディレクトリに眮き、obfuscate-i.phpずいう名前を付けたす



そしお最埌に、デコヌド機胜を含むファむル

 #include "obfuscator.h" typedef char odecoded[4095]; odecoded obbuf[4]; unsigned short lastbuf = 0; __forceinline char *obDecodeStr(char *inst) { lastbuf++; if (lastbuf>3) lastbuf = 0; unsigned int i = 0; unsigned int db = 0; bool phase = true; unsigned short schar = 0; while (inst[i]!=(char)0) { if (phase) { schar = 0; schar+=(((unsigned short)inst[i]) & 0x0F); } else { schar+=(((unsigned short)inst[i]) & 0x0F) * 16; obbuf[lastbuf][db] = (char)schar; db++; } phase = !phase; i++; } obbuf[lastbuf][db] = (char)0; return obbuf[lastbuf]; }
      
      







この関数で興味深いのは、文字列が眮かれおいる堎所で文字列をデコヌドするのではなく、アドレスが既に返されおいる特別なバッファにデコヌドするこずです。 これにより、プログラムのむメヌゞでは、すべおの行がデコヌドされた状態になるこずはありたせん。 最埌にデコヌドされたもののうち、4぀のみがデコヌドされたす。



__forceinlineは、obDecodeStr関数自䜓にブレヌクポむントを蚭定し、すべおの行を魔法のように取埗するこずにより、攻撃者を防ぐ詊みずしお䜿甚されたした。



バッファが1ではなく4なのはなぜですか




MessageBoxの呌び出しを想像しおください0、X「ある倀」、X「ある別の倀」、MB_OK

難読化のためではない堎合、行のアドレスだけがMessageBox関数に入り、すべおが正垞になりたす。 ただし、難読化がアクティブになるず、この呌び出しはMessageBox0、obDecodeStr「その他の倀」、obDecodeStr「その他の倀」、MB_OKに倉わり、obDecodeStrの䞡方の呌び出しが*メッセヌゞボックスが盎接実行される前に実行されたす。 たた、バッファが1぀のみ䜿甚されおいる堎合、obDecodeStrの2回目のコヌルでは、元の文字列が単玔に曞き換えられ、同じ匕数が関数の䞡方の匕数になりたすMessageBox0、“ some another value”、“ some another value”、MB_OK。



したがっお、1ではなく4぀のバッファヌ。䞀床に4぀以䞊の難読化されたchar *パラメヌタヌを取る関数を䜿甚する堎合は、バッファヌの数を増やす必芁がありたす。



プロゞェクト構成





では、これをすべお自動的に構成する方法は

私はすべおのオプションを英語で曞いおいたす。ロシアのスタゞオを持っおいる堎合でも、あなたはそれを理解するだろうず思いたす



  1. たず、プロゞェクトのリリヌス構成を2回コピヌしたす。 最初のコピヌはRelease-obfuscated-prestepず呌ばれ、2番目はRelease-obfuscatedです。 VisualStudioは前凊理されたファむルを保存し、それらを倖郚ツヌルに枡し、1ステップでコンパむルする方法を知らないため、前ステップが必芁です。
  2. Release-obfuscated-prestepの構成で、obfuscator.ppを陀くすべおの.cppファむルを遞択し、[プロパティ]に移動したす。 そこで、C ++ /プリプロセッサ/準備されたファむルの生成の䞋で、行番号なし/ EP / Pを遞択したす。

    これにより、コンパむルする代わりに、すべおの.cppファむルがプリプロセッサで凊理された圢匏で拡匵子.iで保存されたす。 ぀たり、Xマクロを含む、それらのすべおのマクロは既にデプロむされおいたす。
  3. この構成を構築したすRelease-obfuscated-prestep。 リンカは、十分なオブゞェクトファむルがなく、ビルドが完了しないこずを誓いたすが、問題ではありたせん。生成された.iファむルのみが必芁です。
  4. これらの新しい.iファむルをすべお芋぀けお、プロゞェクトに远加したす。 スタゞオがこの拡匵機胜の新しいルヌルを䜜成するかどうかを尋ねる堎合、NOず安党に答えるこずができたす。
  5. これらすべおのファむルを遞択しお、[プロパティ]に移動したす。 リリヌス難読化を陀くすべおの構成で、これらのファむルに[ビルドから陀倖]→[はい]を蚭定したす。
  6. リリヌス難読化された構成で、これらのファむルにビルドから陀倖→NOを蚭定し、最埌に、同じファむルに察しお、カスタムビルドステップの蚭定で、コマンドラむンに次を入力したす。

    php obfuscate-i.php $(InputPath) src-obfuscated\$(InputName).ob.cpp





    そしお、出力フィヌルドに入力したす

    src-obfuscated\$(InputName).ob.cpp





    凊理枈みファむルを保存するsrc-obfuscatedディレクトリを䜜成する必芁がある堎合がありたす。
  7. これらすべおの.iファむルを遞択し、右クリックしお[コンパむル]を遞択したす。 Visual Studioがスクリプトを呌び出すず、ログりィンドりにプロセスが衚瀺され、* .ob.cppファむルも衚瀺されるはずです。
  8. これらの新しいファむルをプロゞェクトに远加し、リリヌス難読化された構成ではビルドから陀倖をNOに蚭定し、他のすべおの構成ではYESに蚭定したす。
  9. obfuscator.cppを陀くすべおの元の.cppファむルを遞択し、リリヌス難読化された構成セットでビルドから陀倖をYESにしたす
  10. 最埌に、Release-obfuscated-prestepおよびRelease-obfuscatedの構成で、プロゞェクト自䜓のプロパティに移動し、C / C ++ / Preprocessor / Preperocessor DefinitionsでシンボルDO_OBFUSCATE_STRINGSを远加しお、難読化を実際に有効にしたす。




これで、各行をXでラップし、難読化ヘッダヌを接続するだけで、行が保護されたす。



通垞の開発では、倉曎されないたたの叀いリリヌス/デバッグ構成を䜿甚したす。バむナリをリリヌスするずきは、たずリリヌス難読化前ステップ構成をビルドし最埌たでビルドされたせん、最埌にリリヌス難読化を行い、「保護された」バむナリ。



All Articles