Chuyển tới nội dung chính
Version: 4.1

Bản phát hành được làm rối mã

Các tệp nhị phân hitechcloud và hitechadmin được phát hành có thể được build bằng garble, công cụ viết lại mã nguồn của chương trình trước khi biên dịch để các tên trong tệp nhị phân hoàn chỉnh không còn mang ý nghĩa gì.

Trang này tồn tại vì người ta dễ thổi phồng lợi ích của việc làm rối mã. Phần dưới đây là những gì nó thực sự mang lại và những gì nó không làm được.

Những gì nó làm​

  • Tên biến mất. Đường dẫn package, tên kiểu, tên hàm, tên phương thức và tên trường struct được thay bằng các tên ngắn được sinh ra. internal/modules/backups trở thành thứ gì đó như fse7a9pk. Người đọc tệp nhị phân vẫn thấy một hàm tồn tại và nó làm gì; họ không còn thấy được nó tên là RestoreFromS3.
  • Manifest của module biến mất. Một tệp nhị phân Go thông thường nhúng danh sách đầy đủ các module dùng để build nó, đọc được bằng go version -m. Tệp đã làm rối báo unknown.
  • Luồng điều khiển khó theo dõi hơn. Mã đã bị viết lại và inline, không có tên nào để bám vào, mất nhiều thời gian đọc hơn đáng kể so với cùng mã đó khi còn định danh gốc.

Gộp lại, việc này biến "mở tệp nhị phân và đọc bố cục package" thành "ngồi xuống với trình dịch ngược và tự mò". Nó làm tăng chi phí. Nó là một gờ giảm tốc, không phải bức tường.

Những gì nó không làm​

  • Nó không ngăn dịch ngược. Tệp nhị phân là mã máy. Mọi công cụ trước đây có thể disassemble hoặc decompile nó vẫn làm được; kết quả chỉ khó đọc hơn. Không gì ở đây ngăn được người quyết tâm.
  • Nó không ngăn chương trình bị chạy, trace hay quan sát. Tệp nhị phân vẫn chạy trên phần cứng do khách hàng kiểm soát. strace, ltrace, trình gỡ lỗi, bắt gói tin, /proc và eBPF probe đều hoạt động y như trước. Mọi thứ panel gửi qua mạng, ghi xuống đĩa hay chuyển cho MySQL đều quan sát được đầy đủ.
  • Nó không che giấu bí mật. Mọi thứ chương trình cần lúc chạy - khoá, token, endpoint API - vẫn nằm trong tệp nhị phân và vẫn khôi phục được. Một bí mật nằm trong tệp nhị phân là bí mật đã công khai, dù có làm rối hay không.
  • Nó không phải cơ chế thực thi giấy phép. Nó khiến việc vá phần kiểm tra giấy phép tẻ nhạt hơn. Nó không khiến việc đó trở nên khó.
  • Nó không xoá chuỗi. Thông điệp nhật ký, SQL, tên template và URL vẫn còn nguyên dạng văn bản thô.

Khi nào một bản phát hành thực sự kèm tệp nhị phân đã làm rối​

Làm rối mã là việc viết lại toàn bộ chương trình, và lỗi của nó âm thầm chứ không ồn ào. Panel render mọi trang bằng html/template, vốn phân giải {{ .Title }} bằng cách tra trường struct theo tên lúc chạy. Đổi tên trường mà trình biên dịch vẫn hoàn toàn vui vẻ; trang chỉ ngừng render giữa chừng. Điều tương tự áp dụng cho mọi thứ khác hoạt động dựa trên tên lúc chạy - struct tag của encoding/json, quét cột của database/sql, reflection dưới mọi hình thức.

Vì vậy workflow phát hành không chỉ đơn giản làm rối rồi xuất bản. Với mỗi tệp nhị phân, nó:

  1. chạy toàn bộ bộ kiểm thử của module đó với mọi package đã làm rối, và chạy bản thường trước làm đối chứng, để bộ kiểm thử vốn đã hỏng không bị đổ lỗi cho việc làm rối;
  2. build tệp nhị phân đã làm rối song song với bản thường;
  3. chạy tệp nhị phân đã làm rối và kiểm tra nó khởi động và báo đúng phiên bản đã được gắn.

Chỉ tệp nhị phân vượt qua cả ba bước mới thay thế bản thường. Nếu có bước nào thất bại, bản build thường được xuất bản và kết quả của job cho biết bước nào thất bại và vì sao. Một panel không khởi động được tệ hơn nhiều so với một panel mà ai đó đọc được.

Vì quyết định đó được đưa ra cho từng bản phát hành và từng kiến trúc, tệp BUILD-PROVENANCE.txt của chính bản phát hành mới là câu trả lời chính thức, không phải trang này:

hitechcloud-linux-amd64
sha256: 6c2f…
obfuscated: yes
reason: obfuscated build passed the gate and its startup check
go: go1.25.0
garble: v0.15.0
garble-seed: 0zM0+r/+dlXm994JTmp+dg==

BUILD-PROVENANCE.txt được SHA256SUMS bao phủ như mọi tài sản phát hành khác.

NOTE

Tính đến phiên bản 2.1.1, chưa tệp nhị phân nào vượt qua bước kiểm tra, nên các bản phát hành kèm bản build thường. Làm rối panel sẽ đổi tên các trường struct dữ liệu trang mà html/template tra theo tên, và kết quả là 36 trong 67 package kiểm thử của panel thất bại - mọi trang render qua struct đều bị cắt cụt. Cơ chế đã sẵn sàng và sẽ bắt đầu xuất bản tệp nhị phân đã làm rối khi lỗi đó được sửa; cho đến lúc đó, bước kiểm tra đang làm đúng nhiệm vụ bằng cách từ chối.

Đọc báo cáo lỗi từ bản build đã làm rối​

Stack trace từ tệp nhị phân đã làm rối tự nó không cho biết tên nào hữu ích. Để chuyển nó về tên thật, bạn cần garble reverse, chạy trên cùng mã nguồn, cùng phiên bản Go, cùng phiên bản garble và cùng seed đã build ra nó. Cả bốn đều được ghi lại:

  • phiên bản Go, phiên bản garble và seed nằm trong BUILD-PROVENANCE.txt;
  • mã nguồn là git tag mà bản phát hành được tạo từ đó;
  • seed được suy ra từ phiên bản phát hành, nên tái tạo được chứ không phải dùng một lần.

Khớp tệp nhị phân trên máy chủ của khách hàng với một bản build bằng cách băm nó - sha256sum /usr/local/bin/hitechcloud - và tìm giá trị băm đó trong BUILD-PROVENANCE.txt. Tệp nhị phân đã làm rối không mang siêu dữ liệu build nào đọc được, nên giá trị băm của nó chính là định danh.

Số dòng được cố ý giữ lại. Chế độ -tiny của garble sẽ xoá chúng và làm tệp nhị phân nhỏ hơn nữa, đổi lại là các panic không nêu tệp và dòng nào. Sự đánh đổi đó không đáng với phần mềm chạy trên máy chủ của người khác.

Các chi phí cần lưu ý​

  • go version -m không còn hoạt động trên tệp nhị phân đã làm rối, nên việc quét phụ thuộc và lỗ hổng dựa trên tệp nhị phân (govulncheck trên tệp nhị phân) không có gì để đọc. Hãy quét mã nguồn thay thế.
  • Build chậm hơn - garble biên dịch lại thư viện chuẩn và vá trình liên kết.
  • garble gắn với phiên bản Go. garble v0.15.0 chấp nhận go1.25.x và từ chối mọi phiên bản cũ hơn hoặc mới hơn, nên hai giá trị phiên bản cố định trong .github/workflows/release.yml thay đổi cùng nhau.