สารบัญ
ตัวถอดรหัสข้ามเวอร์ชันดั้งเดิมของ Python และตัวถอดรหัสส่วนย่อย ผู้สืบทอดที่จะถอดรหัส, ไม่คอมไพล์ และยกเลิกการคอมไพล์2
uncompyle6 แปล Python bytecode กลับเป็นซอร์สโค้ด Python ที่เทียบเท่า ยอมรับรหัสไบต์จาก Python เวอร์ชัน 1.0 ถึงเวอร์ชัน 3.8 ซึ่งครอบคลุมระยะเวลากว่า 24 ปีของการเปิดตัว Python เรารวมรหัสไบต์ Python 2.5 ของ Dropbox และรหัสไบต์ PyPy บางส่วนไว้ด้วย
โอเค ฉันจะบอกว่าซอฟต์แวร์นี้น่าทึ่งมาก มันเป็นมากกว่าตัวถอดรหัสแฮ็กปกติของคุณ โดยใช้เทคโนโลยีคอมไพเลอร์ โปรแกรมจะสร้างแผนผังการแยกวิเคราะห์ของโปรแกรมตามคำแนะนำ โหนดที่ระดับบนสุดที่ดูคล้ายกับสิ่งที่อาจมาจาก Python AST เล็กน้อย ดังนั้นเราจึงสามารถจำแนกและเข้าใจสิ่งที่เกิดขึ้นในส่วนของ Python bytecode ได้อย่างแท้จริง
จากสิ่งนี้ อีกสิ่งหนึ่งที่ทำให้สิ่งนี้แตกต่างจากตัวถอดรหัสไบต์ของ CPython อื่นๆ คือความสามารถในการแยกวิเคราะห์เพียง ส่วนย่อย ของซอร์สโค้ด และให้ข้อมูลซอร์สโค้ดรอบๆ ออฟเซ็ตโค้ดไบต์ที่กำหนด
ฉันใช้ชิ้นส่วนต้นไม้เพื่อแยกชิ้นส่วนของโค้ด ณ รันไทม์ ภายในดีบักเกอร์ Trepan ของฉัน ด้วยเหตุนี้การชดเชยไบต์โค้ดจะถูกบันทึกและเชื่อมโยงกับส่วนของซอร์สโค้ด จุดประสงค์นี้แม้จะเข้ากันได้กับความตั้งใจเดิม แต่ก็แตกต่างออกไปเล็กน้อย ดูสิ่งนี้สำหรับข้อมูลเพิ่มเติม
การแยกวิเคราะห์แฟรกเมนต์ของ Python ด้วยออฟเซ็ตคำสั่งมีประโยชน์ในการแสดงการติดตามสแต็ก และสามารถรวมเข้ากับโปรแกรมใดๆ ที่ต้องการแสดงตำแหน่งโดยละเอียดมากกว่าแค่หมายเลขบรรทัด ณ รันไทม์ รหัสนี้ยังสามารถใช้ได้เมื่อไม่มีข้อมูลซอร์สโค้ดและมีเพียงไบต์โค้ด อีกครั้งผู้ดีบักเกอร์ของฉันใช้สิ่งนี้
มี (และยังคงมี) ส้อม decompyle, uncompyle, uncompyle2, uncompyle3 จำนวนหนึ่งอยู่รอบ ๆ ส่วนมากมาจากฐานโค้ดเดียวกัน และ (เกือบ?) ทั้งหมดไม่ได้รับการดูแลอย่างแข็งขันอีกต่อไป คนหนึ่งเก่งมากในการถอดรหัส Python 1.5-2.3 และอีกคนเก่งมากกับ Python 2.7 แต่นั่นเท่านั้น อีกอันรองรับ Python 3.2 เท่านั้น อีกอันหนึ่งแพตช์นั้นและจัดการเพียง 3.3.3 คุณได้รับความคิด รหัสนี้จะดึงส้อมทั้งหมดเหล่านี้มารวมกันและ ก้าวไปข้างหน้า มีการปรับโครงสร้างและการล้างข้อมูลอย่างจริงจังในฐานโค้ดนี้เหนือส้อมเก่าเหล่านั้น การปรับโครงสร้างเชิงทดลองเพิ่มเติมยังเกิดขึ้นใน decompyle3
สิ่งนี้แสดงให้เห็นได้อย่างชัดเจนว่าเป็นการดีที่สุดในการถอดรหัส Python ในเวอร์ชัน Python ทั้งหมด และแม้ว่าจะมีโปรเจ็กต์อื่นที่ให้เฉพาะการถอดรหัสสำหรับเซ็ตย่อยของเวอร์ชัน Python เท่านั้น โดยทั่วไปแล้ว เราก็ทำได้ดีกว่าสำหรับเวอร์ชันเหล่านั้นเช่นกัน
เราจะบอกได้อย่างไร? โดยการใช้ Python bytecode ที่มาพร้อมกับ Python เวอร์ชันนั้นและถอดรหัสสิ่งเหล่านี้ ในบรรดาโปรแกรมที่ถอดรหัสได้สำเร็จ เราสามารถตรวจสอบให้แน่ใจว่าโปรแกรมผลลัพธ์นั้นถูกต้องทางวากยสัมพันธ์โดยการเรียกใช้ตัวแปล Python สำหรับเวอร์ชันไบต์โค้ดนั้น ในที่สุด ในกรณีที่โปรแกรมมีการทดสอบด้วยตัวเอง เราสามารถทำการตรวจสอบโค้ดที่ถอดรหัสแล้วได้
เราใช้กระบวนการอัตโนมัติเพื่อค้นหาจุดบกพร่อง ในเครื่องมือติดตามปัญหาสำหรับโปรแกรมถอดรหัสอื่นๆ คุณจะพบจุดบกพร่องจำนวนหนึ่งที่เราพบในระหว่างดำเนินการ มีน้อยมากถึงไม่มีเลยที่ได้รับการแก้ไขในโปรแกรมถอดรหัสอื่นๆ
โค้ดในพื้นที่เก็บข้อมูล git สามารถทำงานได้ตั้งแต่ Python 2.4 จนถึงเวอร์ชัน Python ล่าสุด ยกเว้น Python 3.0 ถึง 3.2 อาสาสมัครยินดีที่จะแก้ไขข้อบกพร่องเหล่านี้หากต้องการทำเช่นนั้น
วิธีการทำคือแยกเวอร์ชัน Python ที่ต่อเนื่องกันออกเป็นสาขา git:
PyPy 3-2.4 และใหม่กว่าก็ใช้งานได้เช่นกัน
ไฟล์ bytecode ที่สามารถอ่านได้ได้รับการทดสอบกับ Python bytecodes จากเวอร์ชัน 1.4, 2.1-2.7 และ 3.0-3.8 และ PyPy เวอร์ชันใหม่กว่า
คุณสามารถติดตั้งจาก PyPI โดยใช้ชื่อ uncompyle6
:
pip ติดตั้ง uncompyle6
หากต้องการติดตั้งจากซอร์สโค้ด โปรเจ็กต์นี้ใช้ setup.py ดังนั้นจึงเป็นไปตามรูทีน Python มาตรฐาน:
$ pip ติดตั้ง -e #ตั้งค่าให้รันจากซอร์สทรี
หรือ:
$ python setup.py install # อาจต้องใช้ sudo
นอกจากนี้ยังมี GNU Makefile ให้ make install
(อาจเป็นรูทหรือ sudo) จะดำเนินการตามขั้นตอนข้างต้น
ทำการตรวจสอบ
มีการเพิ่ม makefile ของ GNU เพื่อให้การตั้งค่าการรันคำสั่งที่ถูกต้องราบรื่นและการรันการทดสอบจากเร็วไปช้าที่สุด
หากคุณติดตั้งการรีเมคแล้ว คุณสามารถดูรายการงานทั้งหมด รวมถึงการทดสอบผ่าน remake --tasks
วิ่ง
$ uncompyle6 * คอมไพล์-python-file-pyc-or-pyo*
สำหรับความช่วยเหลือในการใช้งาน:
$ คลายคอมไพล์ 6 -h
ใน Python เวอร์ชันเก่า คุณสามารถตรวจสอบโค้ดไบต์ได้โดยการถอดรหัสไบต์โค้ด จากนั้นจึงคอมไพล์โดยใช้ตัวแปล Python สำหรับเวอร์ชันโค้ดไบต์นั้น เมื่อทำเช่นนี้ รหัสไบต์ที่สร้างขึ้นสามารถนำมาเปรียบเทียบกับรหัสไบต์ดั้งเดิมได้ อย่างไรก็ตาม เมื่อการสร้างโค้ดของ Python ดีขึ้น สิ่งนี้จึงไม่สามารถทำได้อีกต่อไป
หากคุณต้องการตรวจสอบความถูกต้องของกระบวนการถอดรหัสของ Python ให้เพิ่มตัวเลือก --syntax-verify
อย่างไรก็ตาม เนื่องจากไวยากรณ์ของ Python มีการเปลี่ยนแปลง คุณควรใช้ตัวเลือกนี้หากรหัสไบต์เป็นรหัสไบต์ที่ถูกต้องสำหรับล่าม Python ที่จะตรวจสอบไวยากรณ์
คุณยังสามารถเปรียบเทียบผลลัพธ์กับ uncompyle6 เวอร์ชันอื่นได้ เนื่องจากบางครั้งการถอดรหัสไบต์เฉพาะอาจเกิดการถดถอยเมื่อคุณภาพโดยรวมดีขึ้น
สำหรับ Python 3.7 และ 3.8 โดยทั่วไปโค้ดใน decompyle3 จะดีกว่า
หรือลองใช้ตัวถอดรหัสหลามตัวอื่น เช่น uncompyle2, unpyc37 หรือ pycdc เนื่องจากทั้งสองอย่างหลังทำงานแตกต่างกัน จุดบกพร่องที่นี่จึงมักไม่อยู่ในนั้น และในทางกลับกัน
มีคลาสที่น่าสนใจของโปรแกรมเหล่านี้ที่พร้อมใช้งานซึ่งให้การตรวจสอบที่รัดกุมยิ่งขึ้น: โปรแกรมที่เมื่อรันจะทดสอบตัวเอง ชุดทดสอบของเรามีสิ่งเหล่านี้
และ Python มาพร้อมกับชุดโปรแกรมอีกชุดหนึ่งดังนี้: ชุดทดสอบสำหรับไลบรารีมาตรฐาน เรามีโค้ดบางส่วนใน test/stdlib
เพื่ออำนวยความสะดวกในการตรวจสอบประเภทนี้เช่นกัน
ปัญหาที่ใหญ่ที่สุดที่ทราบและอาจแก้ไขได้ (แต่ยาก) เกี่ยวข้องกับโฟลว์การควบคุมการจัดการ (Python น่าจะเป็นชุดคำสั่งผสมที่หลากหลายและห่วยที่สุดเท่าที่ฉันเคยเห็นมา มีอนุประโยค "อื่น" บนลูปและลองใช้บล็อกที่ฉันสงสัยว่าโปรแกรมเมอร์หลายคนไม่รู้)
ตัวถอดรหัส Python ทั้งหมดที่ฉันเคยดูมามีปัญหาในการถอดรหัสโฟลว์การควบคุมของ Python ในบางกรณีเราสามารถตรวจพบการคอมไพล์ที่ผิดพลาดและรายงานสิ่งนั้นได้
การรองรับ Python นั้นค่อนข้างดีสำหรับ Python 2
ในเวอร์ชันล่างสุดของเวอร์ชัน Python การคอมไพล์ดูเหมือนจะค่อนข้างดี แม้ว่าเราจะไม่มีการทดสอบอัตโนมัติสำหรับการทดสอบแบบกระจายของ Python นอกจากนี้ เราไม่มีล่าม Python สำหรับเวอร์ชัน 1.6 และ 2.0
ในซีรีส์ Python 3 การรองรับ Python นั้นแข็งแกร่งที่สุดประมาณ 3.4 หรือ 3.3 และจะลดลงเมื่อคุณออกห่างจากเวอร์ชันเหล่านั้นมากขึ้น Python 3.0 นั้นแปลกตรงที่มันมีลักษณะคล้ายกับ 2.6 มากกว่า 3.1 หรือ 2.7 ในบางแง่ Python 3.6 เปลี่ยนแปลงสิ่งต่าง ๆ อย่างมากโดยใช้รหัสคำแทนที่จะเป็นรหัสไบต์ เป็นผลให้ฟิลด์ออฟเซ็ตการกระโดดในอาร์กิวเมนต์คำสั่งการกระโดดลดลง สิ่งนี้ทำให้คำสั่ง EXTENDED_ARG
แพร่หลายมากขึ้นในคำสั่งข้าม ก่อนหน้านี้มันหายาก บางทีเพื่อชดเชยคำสั่ง EXTENDED_ARG
เพิ่มเติม จึงมีการเพิ่มการเพิ่มประสิทธิภาพการกระโดดเพิ่มเติม ดังนั้นโดยรวมแล้ว โฟลว์การควบคุมการจัดการแบบเฉพาะกิจหมายความว่าสิ่งที่ทำอยู่ในปัจจุบันแย่ลง
ระหว่าง Python 3.5, 3.6, 3.7 มีการเปลี่ยนแปลงที่สำคัญกับคำสั่ง MAKE_FUNCTION
และ CALL_FUNCTION
Python 3.8 จะลบคำสั่ง SETUP_LOOP
, SETUP_EXCEPT
, BREAK_LOOP
และ CONTINUE_LOOP
ซึ่งอาจทำให้การตรวจจับโฟลว์การควบคุมทำได้ยากขึ้น โดยขาดการวิเคราะห์โฟลว์การควบคุมที่ซับซ้อนมากขึ้นตามที่วางแผนไว้ เราจะเห็น.
ขณะนี้ยังไม่รองรับหมายเลขเวทย์มนตร์ Python ทั้งหมด โดยเฉพาะใน Python บางเวอร์ชัน โดยเฉพาะ Python 3.6 ตัวเลขมหัศจรรย์มีการเปลี่ยนแปลงหลายครั้งภายในเวอร์ชันหนึ่ง
เรารองรับเฉพาะเวอร์ชันที่เผยแพร่เท่านั้น ไม่ใช่เวอร์ชันที่เป็นตัวเลือก อย่างไรก็ตาม โปรดทราบว่าความมหัศจรรย์ของเวอร์ชันที่วางจำหน่ายมักจะเหมือนกับเวอร์ชัน สุดท้าย ก่อนที่จะวางจำหน่าย
นอกจากนี้ยังมีล่าม Python ที่ปรับแต่งโดยเฉพาะ Dropbox ซึ่งใช้เวทย์มนตร์ของตัวเองและเข้ารหัสไบต์โค้ด ยกเว้นล่าม Python 2.5 เก่าของ Dropbox เรื่องประเภทนี้ไม่ได้รับการจัดการ
นอกจากนี้เรายังไม่จัดการ PJOrion หรือโค้ดที่ทำให้สับสนอีกด้วย สำหรับ PJOrion ให้ลอง: PJOrion Deobfuscator เพื่อถอดรหัสไบต์โค้ดเพื่อรับ bytecode ที่ถูกต้องก่อนที่จะลองใช้เครื่องมือนี้ pydecipher อาจช่วยได้
โปรแกรมนี้ไม่สามารถถอดรหัสไฟล์ Microsoft Windows EXE ที่สร้างโดย Py2EXE ได้ แม้ว่าเราอาจสามารถถอดรหัสรหัสได้หลังจากที่คุณแตกรหัสไบต์อย่างถูกต้องแล้ว Pydeinstaller อาจช่วยในการคลายแพ็ก Pyinstaller Bundlers
การจัดการกับรายการสำนวนหรือข้อความที่ยาวจนผิดปกตินั้นทำได้ช้า เราไม่รองรับ Cython หรือ MicroPython ซึ่งไม่ใช้ bytecode
มีข้อบกพร่องมากมายในการถอดรหัส และนั่นก็เป็นจริงสำหรับตัวถอดรหัส CPython อื่นๆ ทุกตัวที่ฉันพบ แม้กระทั่งตัวถอดรหัสที่อ้างว่า "สมบูรณ์แบบ" ในบางเวอร์ชัน เช่น 2.4 ก็ตาม
ในขณะที่ Python ดำเนินขั้นตอนการถอดรหัสก็จะยากขึ้นเนื่องจากการคอมไพล์มีความซับซ้อนมากขึ้นและภาษาเองก็มีความซับซ้อนมากขึ้น ฉันสงสัยว่าความพยายามจะมีความพยายามเฉพาะกิจน้อยลงเช่น unpyc37 (ซึ่งใช้ตัวถอดรหัส 3.3) เพียงเพราะมันยากกว่าที่จะทำเช่นนั้น ข่าวดี อย่างน้อยจากจุดยืนของฉันก็คือ ฉันคิดว่าฉันเข้าใจสิ่งที่จำเป็นในการแก้ไขปัญหาอย่างแข็งแกร่งยิ่งขึ้น แต่ตอนนี้จนกว่าจะถึงเวลาที่โปรเจ็กต์ได้รับเงินทุนที่ดีกว่า ฉันไม่ได้ตั้งใจที่จะพยายามอย่างจริงจังเพื่อสนับสนุน Python เวอร์ชัน 3.8 หรือ 3.9 รวมถึงข้อบกพร่องที่อาจเกิดขึ้น ฉันคิดว่าในบางจุดฉันอาจจะสนใจมัน
คุณสามารถค้นหาจุดบกพร่องได้อย่างง่ายดายด้วยการรันการทดสอบกับชุดการทดสอบมาตรฐานที่ Python ใช้ในการตรวจสอบตัวเอง ในช่วงเวลาใดก็ตาม มีปัญหาที่ทราบหลายสิบปัญหาซึ่งค่อนข้างแยกได้ค่อนข้างดี และสามารถแก้ไขได้หากใครก็ตามจัดสรรเวลาไว้เพื่อดำเนินการดังกล่าว ปัญหาคือมีคนจำนวนไม่มากที่ทำการแก้ไขข้อบกพร่อง
ข้อบกพร่องบางอย่างใน 3.7 และ 3.8 เป็นเพียงเรื่องของการแก้ไขพอร์ตกลับใน decompyle3 มีอาสาสมัครบ้างไหม?
คุณอาจพบจุดบกพร่องที่คุณต้องการรายงาน โปรดดำเนินการดังกล่าวหลังจากอ่านวิธีการรายงานข้อบกพร่องแล้วทำตามคำแนะนำเมื่อเปิดปัญหา
โปรดทราบว่ามันอาจจะไม่ได้รับความสนใจของฉันสักระยะหนึ่ง หากคุณสนับสนุนหรือสนับสนุนโครงการในทางใดทางหนึ่ง ฉันจะจัดลำดับความสำคัญของปัญหาของคุณให้อยู่เหนือคิวของสิ่งอื่นที่ฉันอาจจะทำแทน ในสถานการณ์ที่ไม่ค่อยเกิดขึ้น ฉันสามารถทำการถอดรหัสไบต์โค้ดด้วยมือโดยมีค่าธรรมเนียม อย่างไรก็ตาม สิ่งนี้มีขอบเขตกว้างขวาง ซึ่งมักจะเกินกว่าที่คนส่วนใหญ่ยินดีจ่าย
uncompyle6
decompyle3
-- BlackHat 2024 Asia (วิดีโอ) ขอขอบคุณผู้จัดงานและผู้วิจารณ์เป็นอย่างยิ่งที่ให้ฉันพูด สิ่งเหล่านี้กระตุ้นให้ฉันทำงานในโครงการเช่นนี้uncompyle6
ไม่ถูกต้อง ในขณะที่ผลลัพธ์ uncompyle2
ไม่ใช่ แต่บ่อยครั้งที่ผลลัพธ์ของ uncompyle6 ถูกต้อง เมื่อไม่ได้ uncompyle2 เนื่องจาก uncompyle6
ยึดถือความถูกต้องแม่นยำมากกว่า Python สำนวน uncompyle2
สามารถสร้างโค้ดที่ดูเป็นธรรมชาติมากขึ้นเมื่อถูกต้อง ปัจจุบัน uncompyle2
ได้รับการดูแลเล็กน้อย ดูตัวติดตามปัญหาสำหรับรายละเอียดเพิ่มเติม