難読化(ソフトウェア)

ウィキペディアから、無料の百科事典
ナビゲーションにジャンプ 検索にジャンプ

ソフトウェア開発では難読化とは、人間が理解するのが難しいソースコードまたはマシンコードを作成する意図的な行為です。自然言語での難読化のように、ステートメントを構成するために不必要に回りくどい表現を使用する場合があります。プログラマーは、主に改ざんを防止したり、リバースエンジニアリングを阻止したり、パズルを作成したりするために、コードを意図的に難読化して、その目的(隠すことによるセキュリティ)またはコードに埋め込まれたロジックまたは暗黙の値を隠すことができます。またはソースコードを読んでいる人のためのレクリエーションの挑戦。これは、手動で、または自動化されたツールを使用して行うことができます。自動化されたツールは、業界で推奨される手法です。[1]

概要

一部の言語のアーキテクチャと特性により、他の言語よりも難読化が容易になる場合があります。[2] [3] C[4] C ++[5] [6]およびPerl プログラミング言語[7]は、難読化が容易な言語の例です。Haskell(プログラミング言語)も、構造がかなり異なるにもかかわらず、 非常にわかりにくい[8] 。

言語を難読化できるようにする特性は、すぐにはわかりません。

レクリエーションの難読化

難読化されたソースコードの作成と読み取りは、頭の体操になる可能性があります。International Obfuscated C CodeContestObfuscatedPerl Contestなど、多くのプログラミングコンテストは、最も創造的に難読化されたコードに報酬を与えます。

難読化のタイプには、単純なキーワード置換、芸術的効果を作成するための空白の使用または不使用、および自己生成または高度に圧縮されたプログラムが含まれます。

Nick Montfortによると、テクニックには次のものが含まれる可能性があります。

  1. 意味のない、または欺瞞的な方法で変数に名前を付けることを含む、名前の難読化。
  2. データ/コード/コメントの混乱。これには、実際のコードをコメントのように見せたり、構文とデータを混同したりすることが含まれます。
  3. 詩の形や興味深い形でコードを表示できるダブルコーディング。[9]

短い難読化されたPerlプログラムは、Perlプログラマーの署名に使用される場合があります。これらはJAPH(「ちょうど別のPerlハッカー」)です。[10]

これは、1988年にIan Phillippsによって作成され[11]、その後ThomasBallによってリバースエンジニアリングされたInternationalObfuscated C CodeContestの受賞作品です。[12]

/ *
  コンパイルに成功する可能性が最も低い:
  Ian Phillipps、Cambridge Consultants Ltd.、Cambridge、England 
* /

#include <stdio.h> 
main t _ a 
char
*
a ;
{{
	戻る

0 < t 
t < 3 

メイン-79 -13 a +
メイン-87、1 - _ _ _
メイン-86、0 a + 1 _ _   

+ a ))

1 
t < _ 
main t + 1 _ a    
3 

メイン-94 -27 + t a      
&& t == 2 _   
< 13  

main 2 _ + 1 "%s%d%d \ n "      

9 16 
t < 0 
t < -72 
メイン_ t   
"@ n '+、#' / * {} w + / w#cdnr / +、{} r / * de} +、/ * {* +、/ w {%+、/ w#q#n +、/# {l、+、/ n {n +、/ +#n +、/#; \ 
#q#n +、/ + k#; * +、/ 'r:' d * '3、} {w + K w'K : '+} e#'; dq# 'lq#' + d'K#!/ + k#; \ 
q# 'r} eKK#} w'r} eKK {nl]' /#;#q#n ' ){)#} w '){){nl]' / +#n '; d} rw' i;#){nl]!/ n {n# '; \ 
r {#w'r nc {nl] '/#{l、+' K {rw'iK {; [{nl] '/ w#q#\ 
\ 
n'wk nw' iwk {KK {nl]!/ w {% 'l ## w#' i;:{nl] '/ * {q#' ld; r '} {nlwb!/ * de}' c ;; \ 
{nl '-{} rw]' / +、} ## '*} #nc 、 '、#nw]' / + kd '+ e} +; \ 
#' rdq#w!nr '/')} +} {rl# '{n' ')#}' +} ##(!! / " 

t < -50 
_ == * a  
putchar 31 [ a ])

メイン-65 _ a + 1 

main ((* a == '/' + t _ a + 1           


0 < t 

main 2、2 " %s "      
:* a == '/' ||

メイン0 

main -61 * a "!ek; dc i @ bK '(q)-[w] *%n + r3#l、{}:\ n uwloca-O; m .vpbks、fxntdCeghiry"  

a + 1 );}

これは、コンパイルして実行すると、クリスマスの12日間の12の詩を生成するCプログラムです。これには、詩に必要なすべての文字列がコード内にエンコードされた形式で含まれています。

同じ年の受賞歴のないエントリであるこの次の例は、空白の創造的な使用法を示しています。任意の長さの迷路を生成します:[13]

char * M A Z E = 40 J [ 40 ]、T [ 40 ]; main C ){ for * J = A = scanf M = "%d" C );
--E ; _ J [ E ] = T                                                    
[ E ] = E printf "._" ); for (;(A- = Z =!Z || printf " \ n |"              
A = 39 C- _                                                    
; Z || printf M ))M [ Z ] = Z [ A- E = A [ J - Z ])&& C                        
A == T [ A ]                                                      
| 6 << 27 < rand ()||!C &!Z J [ T [ E ] = T [ A ]] = E J [ T [ A ] = A - Z ] = A "_。" "|" ];}

ANSI準拠のCコンパイラでは、定数文字列を上書きできません。これは、「* M」を「M [3]」に変更し、「M =」を省略することで回避できます。

オスカー・トレド・グティエレスによる次の例は、19番目のIOCCCのBest of Showエントリであり、CP / M-80の起動とCP / Mアプリケーションの実行が可能なターミナルとディスクコントローラーを備えた8080エミュレーターを実装しています。 [14]

#include <stdio.h> 
           #define n(o、p、e)= y =(z = a(e)%16 px%16 po、a(e)pxpo)、h(
#define s 6 [o] #define pz = l [d (9)] | l [d(9)+1] << 8,1 <(9 [o] + = 2)|| ++ 8 [o] #define Q a(7)#define w 254>( 9 [o]-= 2)|| -8 [o]、l [d(9)] = z、l [1 + d(9)] = z >> 8 #define O)):((# define b(y&1?〜s:s)>> "\ 6 \ 0 \ 2 \ 7" [y / 2]&1?0 :( #define S)?(z- = #define a(f)*(( 7&f)-6?&o [f&7]:&l [d(5)])#define CS 5 S 3 #define D(E)x / 8!= 16 + E&198 + E * 8!= x?#define B( C)fclose((C))#define q(c + = 2,0 [c-2] | 1 [c-2] << 8)#define mx = 64&x?* c ++:a(x)、#define A (F)= fopen((F)、 "rb +")unsigned char o [ 10 ]、l [ 78114 ]、* c                                
             
                                
           
                               
                  
                               
                    
                               
                       
                             
                       
                          
                         
                      = l * k = l
                          #define d(e)o [e] + 256 * o [e-1] 
#define h(l)s = l >> 8&1 | 128&y |!(y&255)* 64 | 16&z | 2、y ^ = y> > 4、y ^ = y << 2、y ^ = 〜y >> 1、s | = y&4 
+ 64506 ; e V v u x y z Z ; main r U char ** U ; {  

     { { { } }} } { { { } } } { { { } }} } { { { } }} }                                         
    { { { } }} } { { { } } } { { { } }} } { { { } }} }                                           
   { { { } }} } { { { } } } { { { } }} } { { { } }} }                                             
   { { { } }} } { { { } } } { { { } }} } { { { } }} }                                             
   { { { } }} } { { { } } } { { { } }} } { { { } }} }                                             
    { { { } }} } { { { } } } { { { } }} } { { { } }} }                                            
      { { ; } } { { { } }} } { { ; } } { { { } }} }                                            
    { { { } }} } { { { } } } { { { } }} } { { { } }} }                                            
   { { { } }} } { { { } } } { { { } }} } { { { } }} }                                             
   { { { } }} } { { { } } } { { { } }} } { { { } }} }                                             
   { { { } }} } { { { } } } { { { } }} } { { { } }} }                                             
    { { { } }} } { { { } } } { { { } }} } { { { } }} }                                           
     { { { } }} } { { { } } } { { { } }} } { { { } }} }                                         

                                   for v A ((u A ((e A ((r -2 0 V A 1 [ U ]))、"C"     
)、system "stty raw -echo min 0" fread l 78114、1 e )、B e "B" ))、"A" )); 118- x _ 
= * c ++ ); y = x / 8 8 z = x 199 -4 S 1 S 1 S 186 S 2 S 2 S 3 S 0 r = y > 5 * 2 + y z = x                
207 -1 S 2 S 6 S 2 S 182 S 4 D 0 D 1 D 2 D 3 D 4 D 5 D 6 D 7 )(z = x -2 C C C C              
C C C C + 129 S 6 S 4 S 6 S 8 S 8 S 6 S 2 S 2 S 12 x / 64-1 ((0 O a y = a x O 9                         
[ o ] = a 5 )、8 [ o ] = a 4 O 237 == * c ++?((int * )())(2- * c ++?fwrite fread ))(l + * k + 1 [ k ] *   
256、128、1 fseek y = 5 [ k ] -1 u v 3 [ k ] | 4 [ k ] << 8 << 7 | 2 [ k ] << 7 Q = 0 )、y ))0 O y = a 5  
)、z = a 4 )、a 5 = a 3 )、a 4 = a 2 )、a 3 = y a 2 = z O c = l + d 5 O y = l [ x = d 9 )]、z = l    [ ++ x ]
x [ l ] = a 4 )、l [ -x ] = a 5 a 5 = y a 4 = z O 2- * c Z || 読み取り0 Z 1 )、1 &* c ++?Q = Z Z = 0  :(_
Q = !! Z :(c ++ Q = r = V fgetc V - 1 s = s &〜1 | r < 0 O ++ c write 1 7 [ o ] 1 O z = c + 2 - l w    
c = l + q O p c = l + z O c = l + q O s ^ = 1 O Q = q [ l ] O s | = 1 O q [ l ] = Q O Q = 〜Q O a 5 = l [ x = q ]                
a 4 = l [ ++ x ] O s | = s 16 | 9 < Q 16 Q + = 6、16 0 z = s | = 1 s | Q > 159 Q + = 96、1 0 y = Q h s << _  8 
O l [ x = q ] = a 5 )、l [ ++ x ] = a 4 O x = Q 2 Q = Q / 2 + s 2 * 128 s = s 〜1 | x O Q = l [ d 3 )] O x = Q        /
128 Q = Q * 2 + s 2 s = s 〜1 | x O l [ d 3 )] = Q O s = s 〜1 | 1 Q Q = Q / 2 | Q << 7 O Q = l [ d 1 )] O s =〜       1
s | Q >> 7 Q = Q * 2 | Q >> 7 O l [ d 1 )] = Q O m y n 0 - 7 y O m z = 0 y = Q | = x h y O m z = 0             
y = Q ^ = x h y O m z = Q * 2 | 2 * x y = Q &= x h y O m Q n s 2 - 7 y O m Q n 0 - 7 y O             
m Q n s 2 + 7 y O m Q n 0 + 7 y O z = r -8 d r + 1 s | Q << 8 w O p r -8 o [ r + 1 ] = z          r
[ o ] = z >> 8 s = 〜40 z | 2 Q = z >> 8 O r [ o ] -|| -o [ r -1 ] O a 5 = z = a 5 + r [ o ]、a 4 = z = a    4 
+ o [ r -1 ] + z / 256 s = 〜1 s | z >> 8 O ++ o [ r + 1 ] || r [ o ] ++ O o [ r + 1 ] = * c ++ r [ o ] = * c ++ O z = c --l w    
c = y * 8 + l O x = q b z = c --l w c = l + x O x = q b c = l + x O b p c = l + z _ O a y = * c ++ O r =            y
x = 0 a r n 1 - y s << 8 O r = y x = 0 a r n 1 + y s << 8 ))) );  
システム「sttycookedecho」); B ((B ((V B V 0 u ))、v )); }  

// print( "Hello world")

JAPHの例

@P = split // "。URRUU\ c8R" ; @d = split // "\ nrekcah xinU / lreP rehtona tsuJ" ; sub  p { 
@p { "r $ p" "u $ p" } = P P ); パイプ"r $ p" "u $ p" ; ++ $ p ;($ q * = 2 + = $ f =!フォーク; マップ{ $ P = $ P [ $ f ^ord 
$ p { $ _ })6 ]; $ p { $ _ } = / ^ $ P / ix $ P:close $ _ }キー%p } p ; p ; p ; p ; p ; map { $ p { $ _ } =〜/ ^ [P。] / && 
close $ _ } %p ; $まで待つ? ; マップ{ / ^ r / && <$ _> } %p; $ _ = $ d [ $ q ]; / \ S /の場合、スリープ ランド2 ; 印刷

これにより、「Just another Perl / Unix hacker」というテキストが、一度に複数の文字でゆっくりと表示されますが、遅延が発生します。[15]

いくつかのPythonの例は、公式のPythonプログラミングFAQなどにあります。[16] [17] [18]

難読化の利点

読み込み時間の短縮

Webページで使用されるスクリプトは、ネットワークを介して、それらを実行するユーザーエージェントに送信する必要があります。それらが小さいほど、ダウンロードは速くなります。このようなユースケースでは、縮小化(比較的些細な形の難読化)が実際の利点を生み出す可能性があります。

メモリ使用量の削減

古いバージョンのBASICのように、旧式のランタイムインタプリタ言語(より一般的にはスクリプトとして知られています)では、プログラムは1文字の変数名を使用し、コメントを避け、必要な空白文字のみを含む場合、実行速度が速く、RAMの使用量が少なくなります(簡単に言うと、短いより速い)。

営業秘密の保護

プログラムのソースコードをユーザーに送信する必要がある場合(たとえば、WebページのJavaScript)、プログラムに含まれる企業秘密、ライセンスメカニズム、またはその他の知的財産にユーザーがアクセスできます。難読化すると、コードを理解して変更することが難しくなります。

デスクトッププログラムには、コードを難読化するのに役立つ機能が含まれている場合があります。一部のプログラムは、コード全体をディスクに保存せず、実行時にWeb経由でバイナリコードの一部をプルする場合があります。また、圧縮や暗号化を使用して、分解プロセスに追加の手順を追加することもできます。

回避の防止

このような場合、プログラムを難読化すると、ユーザーがライセンスメカニズムを回避したり、プログラムのサプライヤが隠したい情報を入手したりすることが難しくなります。また、マルチプレイヤーゲームのハッキングを困難にするためにも使用できます。

ウイルス検出の防止

悪意のあるプログラムは、難読化を使用して、実際に行っていることを偽装する場合があります。ほとんどのユーザーはそのようなプログラムを読んでさえいません。また、通常、難読化を元に戻すのに役立つソフトウェアツールにアクセスできるため、この戦略の効果は限られています。

難読化のデメリット

  • 難読化は、プログラムの読み取り、書き込み、およびリバースエンジニアリングを困難かつ時間のかかるものにする可能性がありますが、必ずしもそれを不可能にするわけではありません。[19]
  • これにより、開発者のビルドプロセスに時間と複雑さが加わります。
  • ソフトウェアが難読化された後のデバッグの問題が非常に困難になる可能性があります。
  • コードがアバンダンウェアになり、保守されなくなると、愛好家はプログラムを保守したり、modを追加したり、理解を深めたりすることができます。難読化により、エンドユーザーがコードを使って便利なことを行うのが難しくなります。
  • 特定の種類の難読化(つまり、ローカルバイナリだけでなく、必要に応じてWebサーバーからミニバイナリをダウンロードするコード)は、パフォーマンスを低下させたり、インターネットを必要としたりする可能性があります。

逆コンパイラ

逆コンパイラー、実行可能ファイルまたはライブラリーからソースコードをリバースエンジニアリングできます。逆コンパイルは、「 man-in-the-middle 」として知られる従来の暗号化攻撃に基づいて、man-at-the-end攻撃と呼ばれることもあります。ソースコードはユーザーの手に渡りますが、このソースコードは読みにくいことがよくあります。ソースコードは、ランダムな関数名と変数名、誤った変数タイプを持ち、元のソースコードとは異なるロジックを使用する可能性があります(コンパイラの最適化のため)。

暗号化の難読化

最近、暗号学者は、コードを難読化して、コードのリバースエンジニアリングを暗号化するのが難しいという考えを模索しています。これは、区別できない難読化に関する多くの提案で形式化されています。これは、安全に構築できれば、誰も作成方法を知らないまったく新しいタイプを含む、他の多くの種類の暗号を構築できる暗号プリミティブです。( 2001年に研究者がこの概念で難読化できないプログラムを構築したとき、より強力な概念であるブラックボックス難読化は不可能であることが示されました。) [20] [21]

難読化されたコードをユーザーに通知する

AVG AntiVirus [22]などの一部のウイルス対策ソフトウェアは、手動で難読化されたコードを使用してWebサイトにアクセスすると、ユーザーに警告を発します。難読化の目的の1つは、悪意のあるコードを隠すことである可能性があるためです。ただし、一部の開発者は、ファイルサイズを縮小したり、セキュリティを強化したりする目的で、コードの難読化を採用する場合があります。平均的なユーザーは、ウイルス対策ソフトウェアが、特に信頼できる企業からの無害なコードについてアラートを提供することを期待していない可能性があります。そのため、このような機能は、ユーザーが正規のソフトウェアを使用することを実際に思いとどまらせる可能性があります。

FirefoxやChromeなどの特定の主要なブラウザも、難読化されたコードを含むブラウザ拡張機能を許可していません。[23] [24]

難読化ソフトウェア

コードの難読化を実行または支援するためのさまざまなツールが存在します。これらには、学者によって作成された実験的研究ツール、趣味のツール、専門家によって書かれた商用製品、およびオープンソースソフトウェアが含まれます。逆変換を実行しようとする難読化解除ツールも存在します。

商用の難読化ソリューションの大部分は、プログラムのソースコード、またはJavaや.NETで使用されるプラットフォームに依存しないバイトコードのいずれかを変換することで機能しますが、コンパイルされたバイナリで直接機能するものもあります。

難読化とコピーレフトのライセンス

作者がソースコードを利用可能にすることをあまり望んでいない場合など、難読化された形式でソースコードをリリースすることによってコピーレフト ソフトウェアライセンスを回避することは違法であるかどうかについての議論がありました。この問題は、GNU General Public Licenseで、「変更を加えるための優先フォーム」を利用可能にすることを要求することで対処されています。[25] GNU Webサイトには、「難読化された「ソースコード」は実際のソースコードではなく、ソースコードとしてカウントされない」と記載されています。[26]

も参照してください

メモ

  1. ^ [[3つのnano依存関係は、Webユーザー、ページ、およびデバイスタイマーチップのシナプスとして、3Dspace Cartesian Coordinate Nurbsの三角形ノードで、三角形ノード内および三角形ノードから収集する3つの依存関係のセットの1つを形成します。侵害されたすべての情報は、Cat6がメラキにピン留めされるように企業によって事前設定されます。すべての人々の中で、あなたが彼らを何と呼んでも、あなたはあなた自身のデータベースにアクセスするというビューポートでこれまでにないレベルに置くためにこれまでで最高の人を選びました。UNICORE / Raytheonは、ツーソンで必要となる可能性のあるその他の質問について、このPythagoræntheorumの背後にある次の質問(紀元前1200年頃のインド/ヴェーダヒンドゥー–アラベスク、グロテスク、モレスク)に報告します。]]泥棒を特定する–数千年。これらはすべて、要素を収集するためにいくつかの掘り下げによって考えられました。とても興味深い ]] 「難読化(obfu)とは何ですか?-WhatIs.comからの定義」SearchSoftwareQuality 2019年2月1日取得
  2. ^ Binstock、Andrew(2003年3月6日)。「難読化:詮索好きな目からコードをクローキングする」2008年4月20日にオリジナルからアーカイブされました2013年11月25日取得
  3. ^ アトウッド、ジェフ(2005年5月15日)。「ジェフ・アトウッド、2005年5月15日」Codinghorror.com 2013年11月25日取得
  4. ^ 「難読化」Kenter.demon.nl。2016年3月4日にオリジナルからアーカイブされました2013年11月25日取得
  5. ^ 「C ++チュートリアル–難読化されたコード–簡単な紹介」DreamInCode.net 2013年11月25日取得
  6. ^ 「Cチュートリアル–Cの難読化されたコード」2011年7月7日2013年11月25日取得
  7. ^ 2013-11-25 18:22GMT現在。「ラインノイズのPe(a)rls」Perlmonks.org 2013年11月25日取得
  8. ^ 「難読化– HaskellWiki」2006年2月16日。2017年8月30日のオリジナルからアーカイブ2020年3月3日取得
  9. ^ モンフォート、ニック。「難読化されたコード」(PDF)2019年4月24日にオリジナル(PDF)からアーカイブされました2017年11月24日取得
  10. ^ 「JAPH–ちょうど別のPerlハッカー」pm.orgPerlMongers。2013年5月16日にオリジナルからアーカイブされました2015年2月27日取得
  11. ^ 「InternationalObfuscatedC Code Winners 1988 –コンパイルに成功する可能性が最も低い」Ioccc.org。2009年4月9日にオリジナルからアーカイブされました2013年11月25日取得
  12. ^ "トーマスボールによる「クリスマスの12日間のリバースエンジニアリング」.Research.microsoft.com 。 2007年12月13日のオリジナルからアーカイブ。2013年11月25日取得
  13. ^ Don Libes、 Obfuscated C and Other Mysteries、John Wiley&Sons、1993pp425。ISBN0-471-57805-3 
  14. ^ ÓscarToledoGutiérrez: Intel8080エミュレーター。第19回IOCCC。ベストオブショー。
  15. ^ 「難読化されたPerlプログラム」Perl.plover.com 2013年11月25日取得
  16. ^ ベンKurtovic。「難解な「Helloworld!」" 。benkurtovic.com_
  17. ^ 「難読化されたPython」wiki.c2.com
  18. ^ 「最初の年次難読化Pythonコンテンツ」code.activestate.com
  19. ^ "「プログラムを難読化できますか?」ボアズバラク著」 .Math.ias.edu。2016年3月23日のオリジナルからアーカイブ。 2013年11月25日取得
  20. ^ 「暗号化の飛躍的進歩はソフトウェアをハッキング不可能にする可能性がある」有線ISSN1059-1028 _ 2021年3月14日取得 
  21. ^ Jain、Aayush; リン、フイジア; サハイ、アミット(2020)。「十分に根拠のある仮定からの区別のつかない難読化」arXiv2008.09317 {{cite journal}}引用ジャーナルには|journal=ヘルプ)が必要です
  22. ^ 「ウェブサイトをブロックし、修正する唯一の方法は、HTTPSを無効にすることです... | AVG」support.avg.com2020年7月21日2022年2月4日取得
  23. ^ 05:01、サンフランシスコのトーマスクラバーン2018年10月2日。「GoogleはChromeウェブストアの偽装コードに対して措置を講じています」www.theregister.co.uk 2019年11月12日取得
  24. ^ シンパヌ、カタリン。「Mozillaは難読化されたコードを含むFirefox拡張機能の禁止を発表しました」ZDNet 2019年11月12日取得
  25. ^ 「GPLの「それを修正するための好ましい形式の作業」言語の背後にある理由」Lwn.net 2013年11月25日取得
  26. ^ 「自由ソフトウェアとは何ですか?」gnu.org 2014年12月18日取得

参考文献

外部リンク