検索
ホームページバックエンド開発Python チュートリアル「Hello world!」を難読化するPython で難読化する

Obfuscating “Hello world!” obfuscate on Python

文字列「Hello world!」を出力する最も奇妙な難読化されたプログラムを作成します。それがどのように機能するかについての説明を書くことにしました。 Python 2.7 のエントリは次のとおりです:

(lambda _, __, ___, ____, _____, ______, _______, ________:
    getattr(
        __import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
        ().__class__.__eq__.__class__.__name__[:__] +
        ().__iter__().__class__.__name__[_____:________]
    )(
        _, (lambda _, __, ___: _(_, __, ___))(
            lambda _, __, ___:
                chr(___ % __) + _(_, __, ___ // __) if ___ else
                (lambda: _).func_code.co_lnotab,
            _ 



<p>文字列リテラルは許可されていませんでしたが、楽しみのために他の制限を設定しました。組み込みの使用を最小限に抑え、整数リテラルを使用しない単一の式 (つまり print ステートメントなし) である必要がありました。<br>
はじめに</p>

<p>print を使用できないため、stdout ファイル オブジェクトに書き込むことができます。<br>
</p>

<pre class="brush:php;toolbar:false">import sys
sys.stdout.write("Hello world!\n")

しかし、より低いレベルのもの、os.write() を使用しましょう。 stdout のファイル記述子が必要です。これは 1 です (print sys.stdout.fileno() で確認できます)。

import os
os.write(1, "Hello world!\n")

必要な式は 1 つなので、import():
を使用します。

__import__("os").write(1, "Hello world!\n")

write() を難読化できるようにしたいので、getattr():
をスローします。

getattr(__import__("os"), "write")(1, "Hello world!\n")

これが出発点です。今後はすべて、3 つの文字列と int が難読化されます。
紐を繋ぐ

「os」と「write」は非常に単純なので、さまざまな組み込みクラスの名前の一部を結合して作成します。これを行うにはさまざまな方法がありますが、私は次の方法を選択しました:

"o" from the second letter of bool: True.__class__.__name__[1]
"s" from the third letter of list: [].__class__.__name__[2]
"wr" from the first two letters of wrapper_descriptor, an implementation detail in CPython found as the type of some builtin classes’ methods (more on that here): ().__class__.__eq__.__class__.__name__[:2]
"ite" from the sixth through eighth letters of tupleiterator, the type of object returned by calling iter() on a tuple: ().__iter__().__class__.__name__[5:8]

少しずつ前進し始めています!

getattr(
    __import__(True.__class__.__name__[1] + [].__class__.__name__[2]),
    ().__class__.__eq__.__class__.__name__[:2] +
    ().__iter__().__class__.__name__[5:8]
)(1, "Hello world!\n")

「Hello world!n」はさらに複雑です。これを大きな整数としてエンコードします。この整数は、各文字の ASCII コードに、文字列内の文字のインデックスの 256 乗を乗算して形成されます。つまり、次の合計:
∑n=0L−1cn(256n)

ここで L
は文字列の長さ、cn は n

の ASCII コードです。 文字列内の

番目の文字。番号を作成するには:

>>> codes = [ord(c) for c in "Hello world!\n"]
>>> num = sum(codes[i] * 256 ** i for i in xrange(len(codes)))
>>> print num
802616035175250124568770929992

次に、この数値を文字列に変換するコードが必要です。単純な再帰アルゴリズムを使用します:

>>> def convert(num):
...     if num:
...         return chr(num % 256) + convert(num // 256)
...     else:
...         return ""
...
>>> convert(802616035175250124568770929992)
'Hello world!\n'

ラムダで 1 行で書き換えます:

convert = lambda num: chr(num % 256) + convert(num // 256) if num else ""

次に、匿名再帰を使用してこれを 1 つの式に変換します。これにはコンビネータが必要です。まずはこれから始めましょう:

>>> comb = lambda f, n: f(f, n)
>>> convert = lambda f, n: chr(n % 256) + f(f, n // 256) if n else ""
>>> comb(convert, 802616035175250124568770929992)
'Hello world!\n'

ここで、2 つの定義を式に代入するだけで、関数が完成します。

>>> (lambda f, n: f(f, n))(
...     lambda f, n: chr(n % 256) + f(f, n // 256) if n else "",
...     802616035175250124568770929992)
'Hello world!\n'

これで、これを以前のコードに貼り付け、途中でいくつかの変数名を置き換えることができます (f → 、n → _):

getattr(
    __import__(True.__class__.__name__[1] + [].__class__.__name__[2]),
    ().__class__.__eq__.__class__.__name__[:2] +
    ().__iter__().__class__.__name__[5:8]
)(
    1, (lambda _, __: _(_, __))(
        lambda _, __: chr(__ % 256) + _(_, __ // 256) if __ else "",
        802616035175250124568770929992
    )
)

関数の内部

変換関数の本体には "" が残り (文字列リテラルがないことを覚えておいてください!)、何らかの方法で隠さなければならない大量の数値が残ります。空の文字列から始めましょう。ランダムな関数の内部を調べることで、その場で関数を作成できます。

(lambda _, __, ___, ____, _____, ______, _______, ________:
    getattr(
        __import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
        ().__class__.__eq__.__class__.__name__[:__] +
        ().__iter__().__class__.__name__[_____:________]
    )(
        _, (lambda _, __, ___: _(_, __, ___))(
            lambda _, __, ___:
                chr(___ % __) + _(_, __, ___ // __) if ___ else
                (lambda: _).func_code.co_lnotab,
            _ 



<p>ここで実際に行っていることは、関数内に含まれるコード オブジェクトの行番号テーブルを確認することです。匿名なので行番号がなく、文字列は空です。より混乱させるために 0 を _ に置き換えて (関数が呼び出されないので問題ありません)、それを挿入します。また、256 を難読化された Convert() に渡される引数にリファクタリングします。番号も一緒に。これには、コンビネータに引数を追加する必要があります:<br>
</p>

<pre class="brush:php;toolbar:false">import sys
sys.stdout.write("Hello world!\n")

寄り道

少し別の問題に取り組みましょう。コード内の数値を難読化する方法が必要ですが、使用するたびに数値を再作成するのは面倒です (特に面白くもありません)。たとえば、 range(1, 9) == [1, 2, 3, 4, 5, 6, 7, 8] を実装できれば、次の数値を含む変数を受け取る関数で現在の作業をラップできます。 1 ~ 8 を指定し、本文内の整数リテラルの出現箇所を次の変数に置き換えます:

import os
os.write(1, "Hello world!\n")

256 と 802616035175250124568770929992 も形成する必要がありますが、これらはこれら 8 つの「基本的な」数値の算術演算を使用して作成できます。 1 ~ 8 の選択は任意ですが、適切な中間点と思われます。

関数が受け取る引数の数は、コード オブジェクトを介して取得できます。

__import__("os").write(1, "Hello world!\n")

argcounts が 1 ~ 8 の関数のタプルを構築します。

getattr(__import__("os"), "write")(1, "Hello world!\n")

再帰アルゴリズムを使用すると、これを range(1, 9) の出力に変えることができます:

"o" from the second letter of bool: True.__class__.__name__[1]
"s" from the third letter of list: [].__class__.__name__[2]
"wr" from the first two letters of wrapper_descriptor, an implementation detail in CPython found as the type of some builtin classes’ methods (more on that here): ().__class__.__eq__.__class__.__name__[:2]
"ite" from the sixth through eighth letters of tupleiterator, the type of object returned by calling iter() on a tuple: ().__iter__().__class__.__name__[5:8]

前と同様に、これをラムダ形式に変換します。

getattr(
    __import__(True.__class__.__name__[1] + [].__class__.__name__[2]),
    ().__class__.__eq__.__class__.__name__[:2] +
    ().__iter__().__class__.__name__[5:8]
)(1, "Hello world!\n")

次に、匿名再帰形式に変換します。

>>> codes = [ord(c) for c in "Hello world!\n"]
>>> num = sum(codes[i] * 256 ** i for i in xrange(len(codes)))
>>> print num
802616035175250124568770929992

楽しみのために、argcount 演算を追加の関数引数に分解し、いくつかの変数名を難読化します。

>>> def convert(num):
...     if num:
...         return chr(num % 256) + convert(num // 256)
...     else:
...         return ""
...
>>> convert(802616035175250124568770929992)
'Hello world!\n'

ここで新たな問題が発生しています。0 と 1 を非表示にする方法がまだ必要です。これらは、任意の関数内のローカル変数の数を調べることで取得できます。

convert = lambda num: chr(num % 256) + convert(num // 256) if num else ""

関数本体は同じに見えますが、最初の関数の _ は引数ではなく、関数内で定義されていないため、Python はそれをグローバル変数として解釈します。

>>> comb = lambda f, n: f(f, n)
>>> convert = lambda f, n: chr(n % 256) + f(f, n // 256) if n else ""
>>> comb(convert, 802616035175250124568770929992)
'Hello world!\n'

これは、_ が実際にグローバル スコープで定義されているかどうかに関係なく発生します。

これを実践してみましょう:

>>> (lambda f, n: f(f, n))(
...     lambda f, n: chr(n % 256) + f(f, n // 256) if n else "",
...     802616035175250124568770929992)
'Hello world!\n'

これで funcs in の値を代入し、* を使用して結果の整数リストを 8 つの個別の変数として渡すことができ、次のようになります。

getattr(
    __import__(True.__class__.__name__[1] + [].__class__.__name__[2]),
    ().__class__.__eq__.__class__.__name__[:2] +
    ().__iter__().__class__.__name__[5:8]
)(
    1, (lambda _, __: _(_, __))(
        lambda _, __: chr(__ % 256) + _(_, __ // 256) if __ else "",
        802616035175250124568770929992
    )
)

ビットをシフトする

もうすぐです! n{1..8} 変数を 、_、_ などに置き換えます。これは、で使用される変数と混乱を招くためです。私たちの内なる機能。スコープ ルールは適切なルールが使用されることを意味するため、これによって実際に問題が発生することはありません。これは、難読化された Convert() 関数の代わりに、_ が 1 を参照するように 256 をリファクタリングした理由の 1 つでもあります。長くなったので前半だけ貼ります:

(lambda _, __, ___, ____, _____, ______, _______, ________:
    getattr(
        __import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
        ().__class__.__eq__.__class__.__name__[:__] +
        ().__iter__().__class__.__name__[_____:________]
    )(
        _, (lambda _, __, ___: _(_, __, ___))(
            lambda _, __, ___:
                chr(___ % __) + _(_, __, ___ // __) if ___ else
                (lambda: _).func_code.co_lnotab,
            _ 



<p>あと 2 つだけ残っています。まずは簡単な方から始めましょう: 256. 256=28</p>

<p> なので、1 

</p><p>同じアイデアを 802616035175250124568770929992 にも使用します。単純な分割統治アルゴリズムを使用して、それを、一緒にシフトされた数値の合計である数値の合計に分割できます。たとえば、112 がある場合、それを 96 16、そして (3 >)、どちらも他の I/O 方法を伴う危険な行為です。</p>

<p>数値はさまざまな方法で分解できます。どれが正しいという方法はありません (結局のところ、(1 
</p>

<pre class="brush:php;toolbar:false">import sys
sys.stdout.write("Hello world!\n")

ここでの基本的な考え方は、基数とシフトという 2 つの数値が見つかるまで、特定の範囲内の数値のさまざまな組み合わせをテストして、基数

range() の引数、span は、検索スペースの幅を表します。これは大きすぎることはできません。そうしないと、ベースとして num を取得し、シフトとして 0 を取得することになります (diff が 0 であるため)。また、base は単一の変数として表すことができないため、無限に再帰的に繰り返されます。 。小さすぎると、上記の (1 スパン=⌈log1.5|数値|⌉ ⌊24−深さ⌋

疑似コードを Python に変換し、いくつかの調整 (深さ引数のサポート、および負の数に関するいくつかの注意事項) を行うと、次のようになります。

(lambda _, __, ___, ____, _____, ______, _______, ________:
    getattr(
        __import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
        ().__class__.__eq__.__class__.__name__[:__] +
        ().__iter__().__class__.__name__[_____:________]
    )(
        _, (lambda _, __, ___: _(_, __, ___))(
            lambda _, __, ___:
                chr(___ % __) + _(_, __, ___ // __) if ___ else
                (lambda: _).func_code.co_lnotab,
            _ 



<p>ここで、convert(802616035175250124568770929992) を呼び出すと、素晴らしい分解が得られます。<br>
</p>

<pre class="brush:php;toolbar:false">import sys
sys.stdout.write("Hello world!\n")

802616035175250124568770929992 の代わりにこれを貼り付け、すべてのパーツを組み立てます:

import os
os.write(1, "Hello world!\n")

これで完成です。
追記: Python 3 のサポート

この記事を書いて以来、数人から Python 3 のサポートについて質問を受けました。当時は思いつきませんでしたが、Python 3 が勢いを増し続けているため (そして感謝しています!)、この投稿の更新がかなり遅れていることは明らかです。

幸いなことに、Python 3 (執筆時点では 3.6) では大きな変更は必要ありません。

__import__("os").write(1, "Hello world!\n")

Python 3 の完全なバージョンは次のとおりです:

getattr(__import__("os"), "write")(1, "Hello world!\n")

読んでいただきありがとうございます!この投稿の人気には驚き続けています。

以上が「Hello world!」を難読化するPython で難読化するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
Pythonアレイをどのようにスライスしますか?Pythonアレイをどのようにスライスしますか?May 01, 2025 am 12:18 AM

Pythonリストスライスの基本的な構文はリストです[start:stop:step]。 1.STARTは最初の要素インデックス、2。ストップは除外された最初の要素インデックスであり、3.ステップは要素間のステップサイズを決定します。スライスは、データを抽出するためだけでなく、リストを変更および反転させるためにも使用されます。

どのような状況で、リストは配列よりもパフォーマンスが向上しますか?どのような状況で、リストは配列よりもパフォーマンスが向上しますか?May 01, 2025 am 12:06 AM

ListSoutPerformArraysIn:1)ダイナミシジョンアンドフレーケンティオン/削除、2)ストーリングヘテロゼンダタ、および3)メモリ効率の装飾、ButmayhaveslightPerformancostsinceNASOPERATIONS。

PythonアレイをPythonリストに変換するにはどうすればよいですか?PythonアレイをPythonリストに変換するにはどうすればよいですか?May 01, 2025 am 12:05 AM

toconvertapythonarraytoalist、usetheList()constructororageneratorexpression.1)importhearraymoduleandcreateanarray.2)useList(arr)または[xforxinarr] toconvertoalistは、largedatatessを変えることを伴うものです。

Pythonにリストが存在する場合、配列を使用する目的は何ですか?Pythonにリストが存在する場合、配列を使用する目的は何ですか?May 01, 2025 am 12:04 AM

choosearraysoverlistsinperbetterperformance andmemoryeficiencyspecificscenarios.1)largeNumericaldatasets:Araysreducememoryusage.2)パフォーマンス - クリティカル操作:ArraysOfferSpeedBoostsfortsfortsclikeappendedoring.3)タイプリー:Arrayesenforc

リストの要素と配列を繰り返す方法を説明します。リストの要素と配列を繰り返す方法を説明します。May 01, 2025 am 12:01 AM

Pythonでは、ループに使用し、列挙し、包括的なリストを通過することができます。 Javaでは、従来のループを使用し、ループを強化してアレイを通過することができます。 1。Pythonリストトラバーサル方法は、ループ、列挙、およびリスト理解のためのものです。 2。Javaアレイトラバーサル法には、従来のループとループ用の強化が含まれます。

Python Switchステートメントとは何ですか?Python Switchステートメントとは何ですか?Apr 30, 2025 pm 02:08 PM

この記事では、バージョン3.10で導入されたPythonの新しい「マッチ」ステートメントについて説明します。これは、他の言語のスイッチステートメントに相当するものです。コードの読みやすさを向上させ、従来のif-elif-elよりもパフォーマンスの利点を提供します

Pythonの例外グループとは何ですか?Pythonの例外グループとは何ですか?Apr 30, 2025 pm 02:07 PM

Python 3.11の例外グループは、複数の例外を同時に処理することで、同時シナリオと複雑な操作でエラー管理を改善します。

Pythonの関数注釈とは何ですか?Pythonの関数注釈とは何ですか?Apr 30, 2025 pm 02:06 PM

Pythonの関数注釈は、タイプチェック、ドキュメント、およびIDEサポートの関数にメタデータを追加します。それらはコードの読みやすさ、メンテナンスを強化し、API開発、データサイエンス、ライブラリの作成において重要です。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター