Tin tức và phân tích của tất cả các thiết bị di động

Cách xem các tệp nhị phân từ dòng lệnh Linux

Có một tập tin bí mật? Lệnh tệp Linux sẽ nhanh chóng cho bạn biết loại tệp đó là gì. Nếu đó là một nhị phân, bạn có thể tìm hiểu thêm về nó. tệp có rất nhiều tệp ổn định để giúp bạn phân tích tệp. Chúng tôi sẽ chỉ cho bạn cách sử dụng một số công cụ này.

Xác định các loại tập tin

Các tệp thường có các đặc điểm cho phép các gói phần mềm xác định loại tệp cũng như dữ liệu bên trong nó đại diện. Sẽ không có ý nghĩa gì khi mở tệp PNG trong máy nghe nhạc MP3, vì vậy, việc tệp chứa một số dạng định danh vừa hữu ích vừa thiết thực.

Nó có thể là một vài byte chữ ký ở phần đầu của tệp. Điều này cho phép tệp xác định rõ ràng định dạng và nội dung của nó. Đôi khi loại tệp được suy ra từ khía cạnh đặc trưng của tổ chức bên trong của chính dữ liệu, được gọi là kiến ​​trúc tệp.

Một số hệ điều hành như Windows, chúng hoàn toàn được hướng dẫn bởi phần mở rộng tệp. Bạn có thể gọi nó là cả tin hoặc đáng tin cậy, nhưng hệ thống Windows giả định rằng bất kỳ tệp nào có phần mở rộng DOCX thực sự là tệp soạn thảo văn bản DOCX. Linux thì không như vậy, bạn sẽ sớm khám phá ra thôi. Anh ta muốn bằng chứng và xem xét hồ sơ để tìm thấy nó.

Các công cụ được mô tả ở đây đã được cài đặt trong các bản phân phối Manjaro 20, Fedora 21 và Ubuntu 20.04 mà chúng tôi đã sử dụng để nghiên cứu bài viết này. Hãy bắt đầu điều tra bằng cách sử dụng lệnh file.

Sử dụng lệnh

Trong thư mục hiện tại của chúng tôi, chúng tôi có một bộ sưu tập các loại tệp khác nhau. Chúng là sự kết hợp của tài liệu, mã nguồn, tệp thực thi và tệp văn bản.

Lệnh ls sẽ cho chúng ta biết có gì trong thư mục và tùy chọn -hl (kích thước con người có thể đọc được, danh sách dài) sẽ cho chúng ta biết kích thước của mỗi tệp:

ls -hl

Hãy thử một vài trong số chúng và xem những gì chúng ta nhận được:

file build_instructions.odt
file build_instructions.pdf
file COBOL_Report_Apr60.djvu

tệp build_instructions.odt trong cửa sổ đầu cuối.

Ba định dạng tệp được xác định chính xác. Nếu có thể, tệp cung cấp cho chúng tôi thêm một chút thông tin. PDF đã được báo cáo là ở định dạng phiên bản 1.5.

Ngay cả khi chúng tôi đổi tên tệp ODT để có phần mở rộng với bất kỳ giá trị XYZ nào, tệp vẫn được xác định chính xác, cả trong trình duyệt tệp và trên dòng lệnh với tệp.

Tệp OpenDocument đã được xác định chính xác trong trình duyệt Tệp mặc dù phần mở rộng của nó là XYZ.

Trong trình duyệt tệp, nó có biểu tượng tương ứng. Trên dòng lệnh, tệp bỏ qua phần mở rộng và xem tệp để xác định loại của nó:

file build_instructions.xyz

tệp build_instructions.xyz trong cửa sổ đầu cuối.

Việc sử dụng các tệp trên phương tiện như tệp hình ảnh và nhạc thường cung cấp thông tin về định dạng, mã hóa, độ phân giải, v.v. của chúng:

file screenshot.png
file screenshot.jpg
file Pachelbel_Canon_In_D.mp3

tập tin screenshot.png trong một cửa sổ đầu cuối.

Thật thú vị, ngay cả với các tệp văn bản, tệp không đánh giá tệp sau phần mở rộng của nó. Ví dụ: nếu bạn có tệp có phần mở rộng “.c”, chứa văn bản thuần tiêu chuẩn nhưng không có mã nguồn, thì tệp sẽ không nhầm lẫn với tệp mã nguồn C gốc:

file function+headers.h
file makefile
file hello.c

file function + headers.h trong cửa sổ đầu cuối.

tệp xác định chính xác tệp tiêu đề (“.h”) là một phần của tập hợp các tệp mã nguồn C và biết rằng tệp tạo tệp là một tập lệnh.

Sử dụng tệp có nhị phân

Các tệp nhị phân giống như một “hộp đen” hơn các tệp khác. Có thể xem các tệp hình ảnh, có thể phát các tệp âm thanh và có thể mở các tệp tài liệu bằng gói phần mềm thích hợp. Tuy nhiên, nhị phân là một thách thức.

Ví dụ: các tệp “hello” và “wd” là các tệp thực thi nhị phân. Đây là những chương trình. Tệp có tên “wd.o” là một tệp đối tượng. Khi mã nguồn được biên dịch bởi trình biên dịch, một hoặc nhiều tệp đối tượng được tạo. Chúng chứa mã máy mà máy tính cuối cùng sẽ thực thi khi chương trình hoàn thành được chạy, cùng với thông tin cho trình liên kết. Trình liên kết kiểm tra từng tệp đối tượng để tìm các lệnh gọi hàm đến thư viện. Nó liên kết chúng với bất kỳ thư viện nào được chương trình sử dụng. Kết quả của quá trình này là một tập tin thực thi.

Tệp “watch.exe” là tệp thực thi nhị phân đã được biên dịch để chạy trên hệ thống của bạn Windows:

file wd
file wd.o
file hello
file watch.exe

wd trong cửa sổ đầu cuối.

Bắt đầu với cái cuối cùng, tệp cho chúng ta biết rằng tệp “watch.exe” là chương trình bảng điều khiển PE32+ có thể thực thi cho dòng bộ xử lý x86 trong Microsoft Windows. PE là viết tắt của định dạng thực thi di động có phiên bản 32 bit và 64 bit. PE32 là phiên bản 32-bit và PE32+ là phiên bản 64-bit.

Ba tệp còn lại được gắn nhãn Định dạng có thể thực thi và có thể liên kết (ELF). Đây là tiêu chuẩn cho các tệp thực thi và tệp đối tượng được chia sẻ, chẳng hạn như thư viện. Chúng ta sẽ sớm xem xét định dạng tiêu đề ELF.

Điều có thể thu hút sự chú ý của bạn là hai tệp thực thi (“wd” và “hello”) được xác định là Linux Standard Base (LSB) và tệp đối tượng “wd.o” được xác định là LSB có thể định vị lại. Từ thực thi là rõ ràng khi không có nó.

Các tệp đối tượng có thể định vị lại, nghĩa là mã bên trong chúng có thể được tải vào bộ nhớ ở bất kỳ đâu. Các tệp thực thi được liệt kê dưới dạng các đối tượng dùng chung vì chúng được tạo bởi trình liên kết từ các tệp đối tượng theo cách mà chúng kế thừa khả năng này.

Điều này cho phép Ngẫu nhiên bố cục không gian địa chỉ (ASMR) tải các tệp thực thi vào bộ nhớ tại các địa chỉ bạn chọn. Các tệp thực thi tiêu chuẩn có địa chỉ tải được mã hóa trong tiêu đề của chúng, xác định nơi chúng được tải vào bộ nhớ.

ASMR là một kỹ thuật bảo mật. Tải các tệp thực thi vào bộ nhớ tại các địa chỉ có thể dự đoán được khiến chúng dễ bị tấn công. Điều này là do các điểm vào của chúng và vị trí các chức năng của chúng sẽ luôn bị kẻ tấn công biết. Xếp hạng các tệp thực thi độc lập (PIE) được đặt tại một địa chỉ ngẫu nhiên sẽ khắc phục lỗ hổng này.

Nếu chúng ta biên dịch chương trình của mình bằng trình biên dịch gcc và chỉ định tùy chọn -no-pie, nó sẽ tạo ra một tệp thực thi thông thường.

Tùy chọn -o (tệp đầu ra) cho phép chúng tôi chỉ định tên của tệp thực thi của mình:

gcc -o hello -no-pie hello.c

Chúng tôi sẽ sử dụng tệp trên tệp thực thi mới và xem điều gì đã thay đổi:

file hello

Kích thước của tệp thực thi giống như trước đây (17KB):

ls -hl hello

gcc -o hello -no-pie hello.c trong cửa sổ đầu cuối.

Tệp nhị phân hiện được xác định là tệp thực thi tiêu chuẩn. Chúng tôi chỉ làm điều này cho mục đích trình diễn. Nếu bạn xây dựng các ứng dụng theo cách này, bạn sẽ mất tất cả lợi ích của ASMR.

Tại sao tệp thực thi quá lớn?

Chương trình xin chào mẫu của chúng tôi là 17KB, vì vậy nó hầu như không lớn, nhưng mọi thứ đều tương đối. Mã nguồn là 120 byte:

cat hello.c

Việc hợp nhất một nhị phân sẽ làm gì nếu tất cả những gì nó làm là xuất một chuỗi trong cửa sổ đầu cuối? Chúng tôi biết có một tiêu đề ELF, nhưng nó chỉ dài 64 byte đối với tệp nhị phân 64 bit. Tất nhiên nó phải là một cái gì đó khác:

ls -hl hello

cat hello.c trong cửa sổ terminal.

Hãy quét mã nhị phân bằng các chuỗi như bước đầu tiên để khám phá những gì bên trong. Chúng tôi sẽ làm điều đó trong ít hơn:

strings hello | less

dây chào |  less trong cửa sổ đầu cuối.

Có nhiều chuỗi trong tệp nhị phân ngoại trừ “Xin chào, thế giới Geek!” từ mã nguồn của chúng tôi. Hầu hết chúng là các nhãn vùng trong tệp nhị phân và tên cũng như thông tin liên kết của các đối tượng được chia sẻ. Chúng bao gồm các thư viện và chức năng trong các thư viện mà nhị phân phụ thuộc vào.

Lệnh ldd cho chúng ta thấy các phụ thuộc đối tượng được chia sẻ của tệp nhị phân:

ldd hello

ldd xin chào trong cửa sổ đầu cuối.

Có ba mục trong đầu ra và hai trong số chúng chứa đường dẫn thư mục (mục đầu tiên không):

linux-vdso.so: Đối tượng chia sẻ động ảo (VDSO) là một cơ chế nhân cho phép truy cập vào một tập hợp các thường trình trong không gian nhân thông qua nhị phân không gian người dùng. Điều này tránh được chi phí chuyển ngữ cảnh từ chế độ nhân người dùng. Đối tượng được chia sẻ của VDSO tuân thủ Định dạng tệp liên kết có thể thực thi (ELF), cho phép chúng được liên kết động với tệp nhị phân trong thời gian chạy. VDSO được phân bổ động và sử dụng ASMR. Tiêu chuẩn cung cấp khả năng cho thư viện VDSO GNU C nếu hạt nhân hỗ trợ lược đồ ASMR.
libc.so.6: tệp đối tượng chia sẻ thư viện GNU C.
/lib64/ld-linux-x86-64.so.2: đây là trình liên kết động mà nhị phân muốn sử dụng. Trình liên kết động kiểm tra tệp nhị phân để khám phá những phụ thuộc mà nó có. Đưa các đối tượng được chia sẻ này vào bộ nhớ. Nó chuẩn bị nhị phân để chạy và có thể tìm và truy cập các phụ thuộc trong bộ nhớ. Sau đó, nó bắt đầu chương trình.

tiêu đề ELF

Chúng ta có thể kiểm tra và giải mã tiêu đề ELF bằng tiện ích readelf và tùy chọn -h (tiêu đề tệp):

readelf -h hello

readelf -h xin chào trong một cửa sổ đầu cuối.

Tiêu đề được giải thích cho chúng tôi.

Thoát readelf -h hello trong cửa sổ đầu cuối.

Byte đầu tiên của tất cả các nhị phân ELF được đặt thành giá trị thập lục phân 0x7F. Ba byte tiếp theo được đặt thành 0x45, 0x4C và 0x46. Byte đầu tiên là cờ xác định tệp dưới dạng nhị phân ELF. Để làm rõ, ba byte tiếp theo chứa chữ cái ASCII “ELF”:

Lớp: cho biết tệp nhị phân là tệp thực thi 32 bit hay 64 bit (1 = 32, 2 = 64).
Dữ liệu: Cho biết tệp endianness đang được sử dụng. Mã hóa endian xác định cách lưu trữ các số nhiều byte. Trong mã hóa big-endian, số được lưu trữ với các bit quan trọng nhất trước tiên. Trong mã hóa little-endian, số được lưu trữ với các bit ít quan trọng nhất trước tiên.
Phiên bản: Phiên bản ELF (hiện tại 1).
OS/ABI: Thể hiện loại giao diện nhị phân ứng dụng đang sử dụng. Xác định giao diện giữa hai mô-đun nhị phân như chương trình và thư viện dùng chung.
Phiên bản ABI: Phiên bản ABI.
Loại: Loại tệp nhị phân ELF. Các giá trị điển hình là ET_REL cho tài nguyên có thể định vị lại (chẳng hạn như tệp đối tượng), ET_EXEC cho tệp thực thi được biên dịch với cờ -no-pie và ET_DYN cho tệp thực thi hỗ trợ ASMR.
Máy: kiến ​​trúc tập lệnh. Cho biết nền tảng đích mà tệp nhị phân được tạo.
Phiên bản: luôn được đặt thành 1cho phiên bản ELF này.
Địa chỉ điểm vào: Địa chỉ bộ nhớ trong tệp nhị phân nơi bắt đầu thực thi.

Các mục nhập khác là kích thước và số lượng của các vùng và các phần trong nhị phân để có thể tính toán vị trí của chúng.

Xem nhanh tám byte đầu tiên của tệp nhị phân hexdump sẽ hiển thị byte chữ ký và chuỗi “ELF” trong bốn byte đầu tiên của tệp. Tùy chọn -C (chính tắc) cung cấp cho chúng tôi biểu diễn ASCII của các byte cùng với các giá trị thập lục phân của chúng và tùy chọn -n (số) cho phép chúng tôi chỉ định số lượng byte chúng tôi muốn xem:

hexdump -C -n 8 hello

hexdump -C -n 8 xin chào trong cửa sổ đầu cuối.

objdump và GranularView

Nếu muốn xem chi tiết, bạn có thể sử dụng objdumpcommand với tùy chọn -d (disassemble):

objdump -d hello | less

objdump -d xin chào |  less trong cửa sổ đầu cuối.

Thao tác này sẽ phân tách mã máy thực thi và hiển thị mã đó ở dạng byte thập lục phân cùng với trình biên dịch mã tương đương. Vị trí của địa chỉ tạm biệt đầu tiên trong mỗi hàng được hiển thị bên trái.

Điều này chỉ hữu ích nếu bạn có thể đọc ngôn ngữ lắp ráp hoặc tò mò về những gì đang diễn ra đằng sau bức màn. Có rất nhiều đầu ra, vì vậy chúng tôi đã đưa nó vào ít hơn.

Putput với objdump -d xin chào |  less trong cửa sổ đầu cuối.

Tổng hợp và liên kết

Có nhiều cách để biên dịch một nhị phân. Ví dụ: nhà phát triển quyết định có bao gồm thông tin gỡ lỗi hay không. Cách một tệp nhị phân được liên kết cũng ảnh hưởng đến nội dung và kích thước của nó. Nếu các tham chiếu nhị phân chia sẻ các đối tượng dưới dạng phụ thuộc bên ngoài, thì chúng sẽ nhỏ hơn những đối tượng mà các phụ thuộc liên kết tĩnh.

Hầu hết các lập trình viên đã quen thuộc với các lệnh mà chúng tôi đã trình bày ở đây. Tuy nhiên, đối với những người khác, họ cung cấp những cách dễ dàng để tìm kiếm và xem những gì trong hộp đen nhị phân.

Mục lục