cari
Rumahpembangunan bahagian belakangTutorial PythonMengelirukan 'Hello dunia!' mengaburkan pada Python

Obfuscating “Hello world!” obfuscate on Python

cipta program terkabur paling aneh yang mencetak rentetan “Hello world!”. Saya memutuskan untuk menulis penjelasan tentang bagaimana ia berfungsi. Jadi, inilah entrinya, dalam 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>Tersurat rentetan tidak dibenarkan, tetapi saya menetapkan beberapa sekatan lain untuk berseronok: ia mestilah satu ungkapan (jadi tiada pernyataan cetakan) dengan penggunaan terbina yang minimum dan tiada literal integer.<br>
Bermula</p>

<p>Memandangkan kami tidak boleh menggunakan cetakan, kami boleh menulis pada objek fail stdout:<br>
</p>

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

Tetapi mari kita gunakan sesuatu peringkat rendah: os.write(). Kami memerlukan deskriptor fail stdout, iaitu 1 (anda boleh menyemak dengan print sys.stdout.fileno()).

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

Kami mahukan satu ungkapan, jadi kami akan menggunakan import():

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

Kami juga mahu dapat mengaburkan write(), jadi kami akan masukkan getattr():

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

Ini adalah titik permulaan. Semuanya mulai sekarang akan mengaburkan tiga rentetan dan int.
Merangkai rentetan

"os" dan "tulis" agak mudah, jadi kami akan menciptanya dengan menyertai sebahagian daripada nama pelbagai kelas terbina dalam. Terdapat pelbagai cara untuk melakukan ini, tetapi saya memilih yang berikut:

"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]

Kami mula membuat sedikit kemajuan!

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" lebih rumit. Kami akan mengekodnya sebagai integer besar, yang akan dibentuk daripada kod ASCII bagi setiap aksara didarab dengan 256 kepada kuasa indeks aksara dalam rentetan. Dalam erti kata lain, jumlah berikut:
∑n=0L−1cn(256n)

di mana L
ialah panjang rentetan dan cn ialah kod ASCII bagi n

watak ke-dalam rentetan. Untuk mencipta nombor:

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

Sekarang kita memerlukan kod untuk menukar nombor ini kembali kepada rentetan. Kami menggunakan algoritma rekursif mudah:

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

Menulis semula dalam satu baris dengan lambda:

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

Kini kami menggunakan rekursi tanpa nama untuk mengubahnya menjadi satu ungkapan. Ini memerlukan penggabung. Mulakan dengan ini:

>>> 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'

Sekarang kita hanya menggantikan dua definisi ke dalam ungkapan, dan kita mempunyai fungsi kita:

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

Sekarang kita boleh memasukkan ini ke dalam kod kita dari sebelumnya, menggantikan beberapa nama pembolehubah di sepanjang jalan (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
    )
)

Fungsi dalaman

Kami ditinggalkan dengan "" dalam badan fungsi tukar kami (ingat: tiada literal rentetan!), dan sejumlah besar yang perlu kami sembunyikan entah bagaimana. Mari kita mulakan dengan rentetan kosong. Kita boleh membuatnya dengan cepat dengan memeriksa bahagian dalam beberapa fungsi rawak:

(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>Apa yang sebenarnya kami lakukan di sini ialah melihat jadual nombor baris objek kod yang terkandung dalam fungsi tersebut. Oleh kerana ia tanpa nama, tiada nombor baris, jadi rentetan itu kosong. Gantikan 0 dengan _ untuk menjadikannya lebih mengelirukan (tidak mengapa, kerana fungsi itu tidak dipanggil), dan masukkannya ke dalam. Kami juga akan memfaktorkan semula 256 menjadi hujah yang dihantar kepada convert() kami yang tidak jelas. bersama dengan nombor. Ini memerlukan penambahan hujah pada penggabung:<br>
</p>

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

Lencongan

Mari kita atasi masalah yang berbeza untuk seketika. Kami mahukan satu cara untuk mengelirukan nombor dalam kod kami, tetapi ia akan menyusahkan (dan tidak begitu menarik) untuk menciptanya semula setiap kali ia digunakan. Jika kita boleh melaksanakan, katakan, julat(1, 9) == [1, 2, 3, 4, 5, 6, 7, 8], maka kita boleh membungkus kerja semasa kita dalam fungsi yang mengambil pembolehubah yang mengandungi nombor daripada 1 hingga 8, dan gantikan kejadian literal integer dalam badan dengan pembolehubah ini:

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

Walaupun kita perlu membentuk 256 dan 802616035175250124568770929992 juga, ini boleh dibuat menggunakan operasi aritmetik pada lapan nombor "asas" ini. Pilihan 1–8 adalah sewenang-wenangnya, tetapi nampaknya merupakan jalan tengah yang baik.

Kita boleh mendapatkan bilangan hujah yang diambil oleh fungsi melalui objek kodnya:

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

Bina satu tuple fungsi dengan argcount antara 1 dan 8:

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

Menggunakan algoritma rekursif, kita boleh mengubahnya menjadi output julat(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]

Seperti sebelum ini, kami menukar ini kepada bentuk lambda:

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

Kemudian, ke dalam bentuk rekursif tanpa nama:

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

Untuk keseronokan, kami akan memfaktorkan operasi argcount ke dalam argumen fungsi tambahan dan mengelirukan beberapa nama pembolehubah:

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

Terdapat masalah baharu sekarang: kita masih memerlukan cara untuk menyembunyikan 0 dan 1. Kita boleh mendapatkannya dengan memeriksa bilangan pembolehubah setempat dalam fungsi arbitrari:

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

Walaupun badan fungsi kelihatan sama, _ dalam fungsi pertama bukanlah hujah, dan ia juga tidak ditakrifkan dalam fungsi, jadi Python mentafsirkannya sebagai pembolehubah global:

>>> 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'

Ini berlaku tanpa mengira sama ada _ sebenarnya ditakrifkan dalam skop global.

Melaksanakan perkara ini:

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

Kini kita boleh menggantikan nilai fungsi dalam, dan kemudian menggunakan * untuk menghantar senarai integer yang terhasil sebagai lapan pembolehubah berasingan, kita mendapat ini:

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
    )
)

Anjakan bit

Hampir sampai! Kami akan menggantikan n{1..8} pembolehubah dengan , _, , _, dsb., kerana ia menimbulkan kekeliruan dengan pembolehubah yang digunakan dalam fungsi dalaman kita. Ini tidak menyebabkan masalah sebenar, kerana peraturan skop bermakna yang betul akan digunakan. Ini juga merupakan salah satu sebab mengapa kami memfaktorkan semula 256 ke tempat _ merujuk kepada 1 dan bukannya fungsi convert() kami yang dikaburkan. Ia semakin panjang, jadi saya akan menampal separuh masa pertama sahaja:

(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>Hanya dua perkara lagi yang tinggal. Kita akan mulakan dengan yang mudah: 256. 256=28</p>

<p>, jadi kita boleh menulis semula sebagai 1 

</p><p>Kami akan menggunakan idea yang sama dengan 802616035175250124568770929992. Algoritma bahagi-dan-takluk yang mudah boleh memecahkannya kepada jumlah nombor yang merupakan jumlah nombor yang dianjak bersama, dan seterusnya. Sebagai contoh, jika kita mempunyai 112, kita boleh memecahkannya kepada 96 16 dan kemudian (3 >) dalam Python, kedua-duanya adalah herring merah yang melibatkan cara lain untuk melakukan I/O.</p>

<p>Nombor boleh diuraikan dalam pelbagai cara; tiada satu kaedah yang betul (lagipun, kita hanya boleh membahagikannya kepada (1 
</p>

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

Idea asas di sini ialah kami menguji pelbagai kombinasi nombor dalam julat tertentu sehingga kami menghasilkan dua nombor, asas dan anjakan, supaya asas

Argumen untuk julat(), span, mewakili lebar ruang carian. Ini tidak boleh terlalu besar, atau kami akan mendapat num sebagai asas kami dan 0 sebagai anjakan kami (kerana beza adalah sifar), dan kerana asas tidak boleh diwakili sebagai pembolehubah tunggal, ia akan berulang, berulang tanpa had. . Jika terlalu kecil, kita akan mendapat sesuatu seperti (1 span=⌈log1.5|bilangan|⌉ ⌊24−dalam⌋

Menterjemahkan pseudokod ke dalam Python dan membuat beberapa tweak (sokongan untuk hujah mendalam dan beberapa kaveat yang melibatkan nombor negatif), kami mendapat ini:

(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>Sekarang, apabila kita memanggil convert(802616035175250124568770929992), kita mendapat penguraian yang bagus:<br>
</p>

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

Lekatkan ini sebagai pengganti 802616035175250124568770929992, dan satukan semua bahagian:

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

Dan begitulah.
Tambahan: Sokongan Python 3

Sejak menulis siaran ini, beberapa orang telah bertanya tentang sokongan Python 3. Saya tidak memikirkannya pada masa itu, tetapi apabila Python 3 terus mendapat daya tarikan (dan terima kasih untuk itu!), siaran ini jelas sudah lama tertunda untuk kemas kini.

Nasib baik, Python 3 (setakat penulisan, 3.6) tidak memerlukan kami untuk mengubah banyak:

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

Berikut ialah versi penuh Python 3:

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

Terima kasih kerana membaca! Saya terus kagum dengan populariti siaran ini.

Atas ialah kandungan terperinci Mengelirukan 'Hello dunia!' mengaburkan pada Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Bagaimana untuk menyelesaikan masalah kebenaran yang dihadapi semasa melihat versi Python di Terminal Linux?Bagaimana untuk menyelesaikan masalah kebenaran yang dihadapi semasa melihat versi Python di Terminal Linux?Apr 01, 2025 pm 05:09 PM

Penyelesaian kepada Isu Kebenaran Semasa Melihat Versi Python di Terminal Linux Apabila anda cuba melihat versi Python di Terminal Linux, masukkan Python ...

Bagaimana saya menggunakan sup yang indah untuk menghuraikan html?Bagaimana saya menggunakan sup yang indah untuk menghuraikan html?Mar 10, 2025 pm 06:54 PM

Artikel ini menerangkan cara menggunakan sup yang indah, perpustakaan python, untuk menghuraikan html. Ia memperincikan kaedah biasa seperti mencari (), find_all (), pilih (), dan get_text () untuk pengekstrakan data, pengendalian struktur dan kesilapan HTML yang pelbagai, dan alternatif (sel

Modul Matematik dalam Python: StatistikModul Matematik dalam Python: StatistikMar 09, 2025 am 11:40 AM

Modul Statistik Python menyediakan keupayaan analisis statistik data yang kuat untuk membantu kami dengan cepat memahami ciri -ciri keseluruhan data, seperti biostatistik dan analisis perniagaan. Daripada melihat titik data satu demi satu, cuma melihat statistik seperti min atau varians untuk menemui trend dan ciri dalam data asal yang mungkin diabaikan, dan membandingkan dataset besar dengan lebih mudah dan berkesan. Tutorial ini akan menjelaskan cara mengira min dan mengukur tahap penyebaran dataset. Kecuali dinyatakan sebaliknya, semua fungsi dalam modul ini menyokong pengiraan fungsi min () dan bukan hanya menjumlahkan purata. Nombor titik terapung juga boleh digunakan. Import secara rawak Statistik import dari fracti

Bagaimana untuk melakukan pembelajaran mendalam dengan Tensorflow atau Pytorch?Bagaimana untuk melakukan pembelajaran mendalam dengan Tensorflow atau Pytorch?Mar 10, 2025 pm 06:52 PM

Artikel ini membandingkan tensorflow dan pytorch untuk pembelajaran mendalam. Ia memperincikan langkah -langkah yang terlibat: penyediaan data, bangunan model, latihan, penilaian, dan penempatan. Perbezaan utama antara rangka kerja, terutamanya mengenai grap pengiraan

Apakah beberapa perpustakaan Python yang popular dan kegunaan mereka?Apakah beberapa perpustakaan Python yang popular dan kegunaan mereka?Mar 21, 2025 pm 06:46 PM

Artikel ini membincangkan perpustakaan Python yang popular seperti Numpy, Pandas, Matplotlib, Scikit-Learn, Tensorflow, Django, Flask, dan Permintaan, memperincikan kegunaan mereka dalam pengkomputeran saintifik, analisis data, visualisasi, pembelajaran mesin, pembangunan web, dan h

Bagaimana untuk membuat antara muka baris arahan (CLI) dengan python?Bagaimana untuk membuat antara muka baris arahan (CLI) dengan python?Mar 10, 2025 pm 06:48 PM

Artikel ini membimbing pemaju Python mengenai bangunan baris baris komando (CLI). Butirannya menggunakan perpustakaan seperti Typer, Klik, dan ArgParse, menekankan pengendalian input/output, dan mempromosikan corak reka bentuk mesra pengguna untuk kebolehgunaan CLI yang lebih baik.

Bagaimana cara menyalin seluruh lajur satu data ke dalam data data lain dengan struktur yang berbeza di Python?Bagaimana cara menyalin seluruh lajur satu data ke dalam data data lain dengan struktur yang berbeza di Python?Apr 01, 2025 pm 11:15 PM

Apabila menggunakan Perpustakaan Pandas Python, bagaimana untuk menyalin seluruh lajur antara dua data data dengan struktur yang berbeza adalah masalah biasa. Katakan kita mempunyai dua DAT ...

Terangkan tujuan persekitaran maya di Python.Terangkan tujuan persekitaran maya di Python.Mar 19, 2025 pm 02:27 PM

Artikel ini membincangkan peranan persekitaran maya di Python, memberi tumpuan kepada menguruskan kebergantungan projek dan mengelakkan konflik. Ia memperincikan penciptaan, pengaktifan, dan faedah mereka dalam meningkatkan pengurusan projek dan mengurangkan isu pergantungan.

See all articles

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang laluBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang laluBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang laluBy尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Persekitaran pembangunan bersepadu PHP yang berkuasa

Penyesuai Pelayan SAP NetWeaver untuk Eclipse

Penyesuai Pelayan SAP NetWeaver untuk Eclipse

Integrasikan Eclipse dengan pelayan aplikasi SAP NetWeaver.

mPDF

mPDF

mPDF ialah perpustakaan PHP yang boleh menjana fail PDF daripada HTML yang dikodkan UTF-8. Pengarang asal, Ian Back, menulis mPDF untuk mengeluarkan fail PDF "dengan cepat" dari tapak webnya dan mengendalikan bahasa yang berbeza. Ia lebih perlahan dan menghasilkan fail yang lebih besar apabila menggunakan fon Unicode daripada skrip asal seperti HTML2FPDF, tetapi menyokong gaya CSS dsb. dan mempunyai banyak peningkatan. Menyokong hampir semua bahasa, termasuk RTL (Arab dan Ibrani) dan CJK (Cina, Jepun dan Korea). Menyokong elemen peringkat blok bersarang (seperti P, DIV),

SecLists

SecLists

SecLists ialah rakan penguji keselamatan muktamad. Ia ialah koleksi pelbagai jenis senarai yang kerap digunakan semasa penilaian keselamatan, semuanya di satu tempat. SecLists membantu menjadikan ujian keselamatan lebih cekap dan produktif dengan menyediakan semua senarai yang mungkin diperlukan oleh penguji keselamatan dengan mudah. Jenis senarai termasuk nama pengguna, kata laluan, URL, muatan kabur, corak data sensitif, cangkerang web dan banyak lagi. Penguji hanya boleh menarik repositori ini ke mesin ujian baharu dan dia akan mempunyai akses kepada setiap jenis senarai yang dia perlukan.