ชนิดของการแปลงรหัสที่ใช้ในไฟล์ที่ปฏิบัติการได้ของ Linux


13

ฉันต้องการถามว่าการเข้ารหัสประเภทใดที่ใช้ในการสร้างไฟล์ที่ปฏิบัติการได้ของ linux เช่น hexadecemal, binary หรืออย่างอื่น มันแปลงเป็นอย่างไร? มีวิธีใดที่จะเรียกคืนรหัสต้นฉบับจากแฟ้มที่ปฏิบัติการนี้ได้หรือไม่?

นี่คือรหัสเล็กน้อยที่ฉันมี:

ELF���������>�����%|�����@�������������������@�8��@���������������������@�������@�����7<�����7<������� ������������������f�����f���������������������� ������[�UPX!L
h�h�8����������?�E�h=��ڊ̓�N�    4���9ISloB�q�w�]ȉ.��,ς��Q䝦����#e��-�N����/�b,���d<��'��-E��6E�s�/�U���ly�V�Y2]"a��S�.�hU�|�S�J�I�2���X}
�G0�;���5d�$���.)

มันหมายความว่าอย่างไร?


แม้ว่ามันจะไม่ช่วยให้คุณได้อะไรกลับมามากมาย แต่มันก็คุ้มค่าที่จะสังเกตว่าstringsโปรแกรมตัวกรองนั้นมีประโยชน์อย่างมากในการระบุว่าโปรแกรมไบนารีตัวใดเป็นหรือทำเพราะมันจะพิมพ์สตริงข้อความแบบฝังทั้งหมดยาวกว่าความยาวที่ระบุ ไฟล์ไบนารีและการดูข้อความในโปรแกรมบางครั้งบอกคุณมากเกี่ยวกับมันคืออะไรและทำอะไร
Joe

เป็นไปได้ / ซ้ำกันบางส่วน? stackoverflow.com/questions/193896/whats-a-good-c-decompiler
arielf

คำตอบ:


29

มันเป็นเลขฐานสอง คอมไพล์ซอร์สโค้ดถูกคอมไพล์แล้ว คุณสามารถดูได้ในตัวแก้ไข (ตัวแก้ไข hex เช่นblessอาจทำการเปลี่ยนแปลงเพิ่มเติม) แต่คุณต้องรู้ว่าคุณกำลังทำอะไรอยู่ มีแนวโน้มที่ดีสำหรับการเปลี่ยนแปลงสตริงเท่านั้น

สำหรับสิ่งใด ๆ ที่ไม่ยอมใครง่ายๆคุณสามารถเริ่มทำการแปลงไบนารีให้เป็นรหัสแอสเซมบลี สิ่งนี้มักถูกมองว่าเป็นภาษาคอมพิวเตอร์ระดับต่ำสุดที่มนุษย์สามารถแยกวิเคราะห์ได้

objdump -d helloworld | less

แต่มันจะรวมเรื่องไร้สาระของคอมไพเลอร์ด้วย ตัวอย่างเช่นหากคุณรวบรวมเรียบง่ายที่สุดhelloworld.cppด้วย G ++ และจากนั้นobjdumpคุณจะจบลงด้วย yuck 226 บรรทัด (208 ปล้น) คุณสามารถเขียน "hello world" ในชุดประกอบเพียง 15 บรรทัดรวบรวมและobjdumpมันก็ยังคงเบ่งบานเป็น 166 บรรทัด (ปล้น)

หากคุณดีพอในการประกอบสิ่งนี้อาจทำให้คุณเข้าถึงได้มากพอที่จะเข้าใจว่าเกิดอะไรขึ้นและให้คุณเปลี่ยนได้ ... แต่เพื่อตอบคำถามเดิมของคุณ:

คุณไม่สามารถหันหลังกลับรหัสเรียบเรียงต้นฉบับรหัสที่มา

ขอโทษ เป็นการแปลงข้อมูลแบบทางเดียวที่สูญเสียข้อมูล (ความคิดเห็นการจัดรูปแบบแนวคิดอัลกอริทึมที่อ่านได้ ฯลฯ ) เชื่อมโยงกับสิ่งอื่น ๆ และมีการปรับให้เหมาะสมโดยทั่วไปในลักษณะที่จะทำให้ไม่สามารถเข้าใจได้ แต่โปรแกรมเมอร์ที่ดีที่สุด

เพื่อให้คุณคิดของขนาดของปัญหาที่ความคิดทั้งหมดของซอฟต์แวร์วิศวกรรมย้อนกลับมีเว็บไซต์กองการแลกเปลี่ยนของตัวเอง


คุณช่วยบอกฉันทีว่าฉันจะทำวิศวกรรมย้อนกลับและรับโค๊ดโค้ดกลับมาได้สูงสุดเท่าไหร่ฉันได้สูญเสียซอร์สโค้ดไปแล้ว
redchief

7
ดูการแก้ไขล่าสุดของฉัน ไม่มีการย้อนกลับไปยังแหล่งดั้งเดิม ด้วยการเรียนรู้และใช้เวลามากมายคุณอาจจะสามารถเขียนซอร์สใหม่โดยใช้รหัสแอสเซมบลีที่ถอดแยกชิ้นส่วนได้ แต่ในกรณีส่วนใหญ่มันจะถูกกว่า (เว้นแต่เวลาของคุณจะไร้ค่า) และง่ายกว่าเพียงแค่เขียนใหม่
Oli

1
วิธีคืนค่าจำนวนรหัสสูงสุดคือการคืนค่าสำเนาสำรองล่าสุด นั่นคือยังบังเอิญที่เพียงวิธีการที่จะได้รับกลับมาได้อย่างน่าเชื่อถือสิ่งที่คล้ายรหัสต้นฉบับ
CVn

1
ไม่เห็นด้วยกับย่อหน้าสุดท้ายเลยเพียงแค่ทราบด้าน: decompilers IME บางคนทำงานได้อย่างยอดเยี่ยมในการกู้คืนโครงสร้างรหัสที่แน่นอน (นอกเหนือจากที่คุณกล่าวถึงความคิดเห็นการจัดรูปแบบชื่อสัญลักษณ์ ... ) หากคุณไม่ได้เขียนโปรแกรมในตอนแรกซอร์สโค้ดที่กู้คืนอาจยังคงไม่สามารถเข้าใจได้ แต่ฉันคิดว่ามันเป็นตัวเลือกที่ดีในการกู้คืน (อย่างน้อยบางส่วน) ซอร์สโค้ดที่หายไป / ซอร์สโค้ดที่ไม่รู้จัก (อย่างน้อยก็ส่วนหนึ่ง) จริงเข้าใจขึ้นอยู่กับรหัสที่เฉพาะเจาะจงและไม่ว่าคุณจะโชคดีเช่นกัน)
คอส

1
นั่นคือสิ่งที่ EULA เหล่านั้นทั้งหมดในโลกซอฟต์แวร์ลิขสิทธิ์บอกว่าคุณไม่ได้รับอนุญาตให้ทำ - ทำวิศวกรรมย้อนกลับ / ถอดแยกชิ้นส่วน พวกเขารวมถึงคำสั่งเช่นนี้เพราะมันเป็นไปได้ที่จะทำ - แต่ไม่ใช่เรื่องง่าย! แต่อย่างที่ @ MichaelKjörlingพูดว่าวิธีที่ดีที่สุดในการได้สิ่งต่าง ๆ มาจากการสำรองข้อมูลหลายระดับสำหรับทุกสิ่งที่คุณสนใจ
Joe

7

ฉันมีคะแนนชื่อเสียงไม่เพียงพอสำหรับความคิดเห็นดังนั้นจึงเป็นคำตอบ:

ไม่ไม่สามารถแปลงเป็น "ย้อนกลับ" ได้ คุณพูดถึง upx packer คุณเคยอ่านคู่มือ upx บ้างไหม?

หากคุณทำแหล่งข้อมูลสูญหายหรือไม่สามารถเข้าถึงรหัสของบุคคลอื่นไม่สำคัญที่นี่ก็เป็นไปไม่ได้

ไบนารีที่ปฏิบัติการได้ถูกสร้างขึ้นด้วยคอมไพเลอร์ไม่เชื่ออะไรที่ระบุไว้ในเว็บไซต์นี้เพียงแค่อ่านคู่มือของคอมไพเลอร์นั้น ๆ จากนั้นคุณสามารถเพิ่มที่นี่ในภาษาที่เขียนรหัสต้นฉบับซึ่งใช้คอมไพเลอร์และจากนั้นคุณอาจสังเกตด้วยตัวคุณเองว่าขั้นตอนนี้ (การประมวลผลก่อนการคอมไพล์การเชื่อมโยงหรือการบรรจุ) อาจไม่กลับรายการทั้งหมด ได้รับการวิเคราะห์สิ่งที่ผู้เขียนต้นฉบับอาจตั้งใจและเขียน


3

นี่อาจเป็นไฟล์ไบนารี (ไฟล์ ELF) ดังที่อธิบายไว้ที่นี่:

https://en.wikipedia.org/wiki/Executable_and_Linkable_Format

หากคุณแก้ไขด้วยเครื่องมือแก้ไขข้อความปกติและบันทึกการเปลี่ยนแปลงของคุณนี่ไม่ใช่ความคิดที่ดีและคุณอาจทำลายมัน


3

ดังที่ Oli ชี้ให้เห็นแล้วในคำตอบของเขาคุณไม่สามารถรับซอร์สโค้ดที่เป็นต้นฉบับของการปฏิบัติการได้

ระหว่างการคอมไพล์ซอร์สโค้ด (การคอมไพล์มีจุดประสงค์เหมือนกับการยอมรับทั่วไปที่กว้างขึ้นดังนั้นในขณะที่กระบวนการทั้งหมดที่ "แปลง" ซอร์สโค้ดไปสู่การปฏิบัติการ) ข้อมูลจำนวนมากจะหายไป

ตัวประมวลผลล่วงหน้า C สำหรับตัวใดตัวหนึ่งจะทำสิ่งต่อไปนี้ (เหนือสิ่งอื่นใด):

  • ตีความดำเนินการและลบคำสั่งของโปรเซสเซอร์ล่วงหน้า (#คำสั่ง)
  • ลบความคิดเห็น
  • ลบช่องว่างที่ไม่จำเป็นออก

ในทางกลับกันสิ่งที่ไม่ได้หายไปในระหว่างการรวบรวมซอร์สโค้ดนั้นสามารถนำกลับมาใช้ใหม่ได้ในทางเทคนิคเป็นซอร์สโค้ดที่เทียบเท่ากับการใช้งาน

นี้เป็นเพราะ:

  • คำแนะนำแบบไบนารีมีความสัมพันธ์แบบ 1: 1 พร้อมคำแนะนำการประกอบ การประกอบของซอร์สโค้ดแอสเซมบลีเป็นเพียงการแปลงของคำสั่งแอสเซมบลีเป็นคำสั่งแบบไบนารีที่ยึดตามตารางของ corrispondencies เท่านั้น คำสั่งไบนารีเดียวสามารถระบุได้เสมอและเปลี่ยนกลับเป็นคำสั่งชุดประกอบเดี่ยวได้ ;
  • แอสเซมบลีคำแนะนำไม่มี 1: 1 corrispondency ด้วยคำแนะนำ C การคอมไพล์ของซอร์สโค้ด C มักไม่ใช่แค่การแปลงคำสั่ง C เป็นคำสั่งแอสเซมบลีตามตารางความสัมพันธ์ในความเป็นจริงมันมักจะเป็นตรงกันข้าม โดยปกติคำสั่ง C จะถูกแปลงเป็นคำสั่งชุดประกอบหลายชุด (มักแตกต่างกันไปตามคอมไพเลอร์) แต่รูปแบบของคำแนะนำการชุมนุมหลายมักจะระบุตัวและแก้ไขกลับคืนเพื่อการเรียนการสอน C เดียว ;

มีเครื่องมือที่เรียกว่า decompilers ซึ่งมีจุดประสงค์เพื่อพยายามที่จะย้อนกลับการปฏิบัติการให้เป็นซอร์สโค้ดที่เทียบเท่ากับการใช้งานได้ อย่างไรก็ตามผลลัพธ์มักจะอยู่ห่างจากซอร์สโค้ดดั้งเดิมมาก (และมักจะไม่สามารถใช้งานได้)

พิจารณาโปรแกรมนี้:

#include <stdio.h>

#define MESSAGE "Literal strings will be recovered" // This preprocessor directive won't be recovered

/*

This comment and the comment above won't be recovered

*/

int main(int argc, char* argv[]) {
    printf(MESSAGE);
    return 0;
}

ด้วยการคอมไพล์มันลงในไฟล์ที่เรียกใช้งานได้และทำการคอมไพล์มันลงในซอร์สโค้ดอีกครั้งนี่คือสิ่งที่คุณมักจะได้รับกลับมามากขึ้นหรือน้อยลง (ในกรณีนี้ที่ฉันใช้gcc/ บูมเมอแรง ):

// address: 0x80483fb
int main(int argc, char **argv, char **envp) {
    printf("Literal strings will be recovered");
    return 0;
}

ตามที่คาดการณ์ไว้:

  • คำสั่งของตัวประมวลผลล่วงหน้าหายไป
  • ความคิดเห็นขาดหายไป (นอกเหนือจาก// address: 0x80483fbซึ่งเพิ่มโดยตัวถอดรหัส)
  • ช่องว่างที่ไม่จำเป็นขาดหายไป (นอกเหนือจาก newlines และ tabulations ซึ่งเพิ่มโดยตัวถอดรหัส)

นี่ก็เป็นผลลัพธ์ที่ดีเช่นกัน ไม่ยากที่จะรับคำแนะนำในการประกอบแบบอินไลน์เข้าไปในรหัส:

asm("assembly_instruction");
__asm__("assembly_instruction");

บรรทัดล่างคือ (ตามที่ระบุไว้แล้วในคำตอบอื่น ๆ ): คุณไม่สามารถรับซอร์สที่เป็นต้นฉบับของไฟล์ปฏิบัติการได้ *

* อย่างไรก็ตามขึ้นอยู่กับความสามารถในการใช้งานและโชคของคุณคุณอาจได้รับบางอย่างโดยใช้ตัวถอดรหัส


2

Executables มักเป็นเลขฐานสองถ้าคุณพูดถึงโปรแกรมที่คอมไพล์แล้ว file path/to/executableท่านสามารถหาข้อมูลเพิ่มเติมได้โดยใช้ คุณสามารถแสดงไบนารีที่ปฏิบัติการได้ในเลขฐานสิบหกโดยใช้เช่นhexdump -C path/to/executable | less(สิ่งที่ดีที่จะทำคุณ) หากคุณต้องการ "แปลงกลับเป็นรูปแบบเดิม" คุณจะต้องใช้ตัวถอดรหัสที่เหมาะสมหากนี่คือสิ่งที่คุณต้องการดูโพสต์นี้เช่นแม้ว่าจะให้รหัสที่อ่านไม่ได้ แต่ไม่ใช่ต้นฉบับที่ถูกรวบรวมมา ถ้าไม่ใช่ไบนารีที่คอมไพล์มันจะเป็นสคริปต์ชนิดหนึ่งซึ่งควรอ่านได้ง่ายในตัวแก้ไขข้อความใด ๆ สิ่งที่คุณแสดงให้เราเห็นที่นี่น่าจะเป็นไฟล์ที่รวบรวมได้ ELF หมายถึง "รูปแบบการปฏิบัติการและการลิงก์" ซึ่งเป็นรูปแบบไบนารีทั่วไปในระบบ Linux / Unix มี'strings path/to/executable


ฉันพยายามที่จะทำวิศวกรรมย้อนกลับด้วย upx packer แต่ไม่ได้ผลและมีการโพสต์ที่คุณแนะนำ ดังนั้นโปรดบอกฉันว่ามีวิธีอื่น
redchief

เสียใจมาก แต่ฉันไม่สามารถบอกอะไรคุณได้มากกว่าสิ่งที่เขียนในโพสต์ที่ยอดเยี่ยมของ @ Oli
Hinz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.