<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hxd on Roduygo | Blog</title><link>/tags/hxd/</link><description>Recent content in Hxd on Roduygo | Blog</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Thu, 07 May 2026 16:40:00 +0700</lastBuildDate><atom:link href="/tags/hxd/index.xml" rel="self" type="application/rss+xml"/><item><title>Giải phẫu ổ cứng (Forensics)</title><link>/post/giai-phau-o-cung-forensics/</link><pubDate>Thu, 07 May 2026 16:40:00 +0700</pubDate><guid>/post/giai-phau-o-cung-forensics/</guid><description>&lt;p&gt;Ở bài viết trước, chúng ta đã đi qua bức tranh tổng thể của quá trình khởi động. Nhưng đối với một nhà phân tích SOC hay chuyên gia điều tra số (Forensics), &amp;ldquo;nhìn thấy&amp;rdquo; hệ điều hành khởi động là chưa đủ. Chúng ta cần phải nhìn thấu vào từng Byte, từng khối Hex trên mặt đĩa vật lý để biết hacker đang giấu gì. Hôm nay, hãy cùng mình mở công cụ HxD lên và đi sâu vào giải phẫu MBR, GPT, đồng thời thực hành một kịch bản &amp;ldquo;cứu hộ&amp;rdquo; kinh điển: Khôi phục MBR bị mã độc phá hủy.&lt;/p&gt;
&lt;h2 id="1-mbr-master-boot-record-dưới-lăng-kính-hex"&gt;1. MBR (Master Boot Record) dưới lăng kính Hex
&lt;/h2&gt;
 &lt;blockquote&gt;
 &lt;p&gt;💡 &lt;strong&gt;Nhắc lại kiến thức:&lt;/strong&gt; Ở bài viết trước, chúng ta đã tìm hiểu về cấu trúc 512 byte chật chội của MBR (gồm 446 byte Bootstrap, 64 byte Bảng phân vùng và 2 byte Chữ ký). Nếu bạn chưa nắm rõ phần này, hãy xem lại bài viết &lt;strong&gt;&lt;a class="link" href="/p/windows-booting/" &gt;Khởi nguồn hệ thống - Windows Booting&lt;/a&gt;&lt;/strong&gt; trước khi đi tiếp nhé!&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="Ví dụ về một bảng phân vùng" class="gallery-image" data-flex-basis="1510px" data-flex-grow="629" height="109" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="/post/giai-phau-o-cung-forensics/bangphanvung.png" width="686"&gt;&lt;/p&gt;
&lt;h3 id="11-giải-mã-16-byte-của-bảng-phân-vùng-partition-table"&gt;1.1 Giải mã 16 Byte của Bảng phân vùng (Partition Table)
&lt;/h3&gt;&lt;p&gt;Nhìn vào 16 byte của một phân vùng trong HxD, làm sao ta đọc hiểu được nó? Hãy lấy ví dụ một chuỗi Hex chuẩn của phân vùng khởi động:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;80 20 21 00 07 FE FF FF 00 08 00 00 00 B0 23 03
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Đây là cách chúng ta hiểu nó:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Chỉ báo khởi động (Byte 1 - 80):&lt;/strong&gt; Giá trị &lt;code&gt;80&lt;/code&gt; nghĩa là phân vùng này có thể khởi động được (Active/Bootable). Nếu là &lt;code&gt;00&lt;/code&gt; thì đây chỉ là ổ chứa dữ liệu bình thường.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Địa chỉ CHS bắt đầu (Byte 2,3,4 - 20 21 00):&lt;/strong&gt; Tọa độ vật lý (Cylinder-Head-Sector) bắt đầu của đĩa. Ngày nay, thông số này không còn quá quan trọng.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mã hệ thống tệp (Byte 5 - 07):&lt;/strong&gt; Giá trị &lt;code&gt;07&lt;/code&gt; khẳng định đây là phân vùng định dạng NTFS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Địa chỉ CHS kết thúc (Byte 6,7,8 - FE FF FF):&lt;/strong&gt; Tọa độ vật lý kết thúc của phân vùng.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Địa chỉ LBA bắt đầu (Byte 9,10,11,12 - 00 08 00 00):&lt;/strong&gt; Tọa độ logic bắt đầu. Do Windows dùng định dạng Little-Endian (byte thấp đứng trước), ta phải đọc ngược lại thành &lt;code&gt;00 00 08 00&lt;/code&gt;. Đổi chuỗi Hex &lt;code&gt;0800&lt;/code&gt; ra hệ thập phân ta được 2048. Nhân với 512 byte/sector, ta biết phân vùng này bắt đầu tại Offset &lt;code&gt;1048576&lt;/code&gt; trên ổ cứng.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kích thước phân vùng (Byte 13,14,15,16 - 00 B0 23 03):&lt;/strong&gt; Đọc ngược Little-Endian thành &lt;code&gt;03 23 B0 00&lt;/code&gt;. Chuyển sang thập phân là 52,670,464 sectors. Nhân với 512 byte, ta tính ra phân vùng này nặng khoảng 26,967,277,568 bytes (xấp xỉ 26.9 GB).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Mẹo thực hành:&lt;/strong&gt; Trong HxD, bạn có thể bấm &lt;code&gt;Ctrl + G&lt;/code&gt; (Go to), nhập giá trị thập phân &lt;code&gt;1048576&lt;/code&gt; vào ô Offset để nhảy thẳng đến vị trí bắt đầu của hệ điều hành.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Nhớ chọn dec để di chuyển đến vị trí offset" class="gallery-image" data-flex-basis="237px" data-flex-grow="98" height="266" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="/post/giai-phau-o-cung-forensics/goto.png" width="263"&gt;&lt;/p&gt;
&lt;h2 id="2-thử-khôi-phục-mbr-bị-xóa"&gt;2. Thử khôi phục MBR bị xóa
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Kịch bản sự cố:&lt;/strong&gt; Máy chủ cơ sở dữ liệu quan trọng đột nhiên không thể khởi động. Điều tra cho thấy một nhân viên đã vô tình mở email chứa mã độc. Hệ thống bị ép khởi động lại và báo lỗi &amp;ldquo;Operating System not found&amp;rdquo;. Mọi nghi ngờ đổ dồn vào một Bootkit đã phá hủy MBR.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tiến hành phân tích:&lt;/strong&gt; Khi load file Image của ổ cứng nạn nhân vào HxD và soi vào Sector 0, ta phát hiện một điểm chí mạng: Ở Offset &lt;code&gt;000001F0&lt;/code&gt; (cuối Sector 0), thay vì kết thúc bằng chữ ký chuẩn &lt;code&gt;55 AA&lt;/code&gt;, nó lại chứa toàn &lt;code&gt;00 00&lt;/code&gt;. Không có chữ ký này, BIOS không công nhận đây là một ổ đĩa hợp lệ!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cách khôi phục:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Dò tìm VBR (Volume Boot Record):&lt;/strong&gt; Dù MBR bị xóa, nhưng phân vùng chứa hệ điều hành vẫn còn. Theo tiêu chuẩn mặc định của Windows, phân vùng đầu tiên (LBA bắt đầu) thường nằm ở Sector 2048.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Xác nhận:&lt;/strong&gt; Di chuyển tới Sector 2048. Nếu ta nhìn thấy chuỗi chữ ký NTFS hoặc thông điệp lỗi dạng &lt;code&gt;A disk read error occurred... NTLDR is missing&lt;/code&gt;, thì xin chúc mừng, dữ liệu chưa hề mất.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tái tạo:&lt;/strong&gt; Bằng các công cụ chuyên dụng (như Bootrec.exe hoặc TestDisk), ta có thể ghi lại 446 byte mã khởi động và chèn lại chữ ký &lt;code&gt;55 AA&lt;/code&gt; vào vị trí cũ, cứu sống hoàn toàn máy chủ mà không làm mất một bit dữ liệu nào.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="3-sự-tiến-hóa-mang-tên-gpt-guid-partition-table"&gt;3. Sự tiến hóa mang tên GPT (GUID Partition Table)
&lt;/h2&gt;&lt;p&gt;MBR có giới hạn chí mạng: Nó chỉ hỗ trợ tối đa 4 phân vùng và không thể quản lý dung lượng đĩa quá 2 Terabytes. Để đáp ứng các server khổng lồ, UEFI và GPT (hỗ trợ lên đến 9 Zettabyte, 128 phân vùng) ra đời.&lt;/p&gt;
&lt;p&gt;Để đảm bảo tương thích ngược và tránh việc các công cụ định dạng cũ tưởng nhầm đĩa GPT là đĩa trắng rồi &amp;ldquo;vô tình&amp;rdquo; ghi đè, GPT tạo ra một lớp giáp gọi là Protective MBR (MBR bảo vệ).&lt;/p&gt;
&lt;h3 id="31-mbr-bảo-vệ-protective-mbr"&gt;3.1 MBR Bảo vệ (Protective MBR)
&lt;/h3&gt;&lt;p&gt;Nó vẫn nằm ở Sector 0. Cấu trúc của nó y hệt MBR cũ, chứa đủ &lt;code&gt;55 AA&lt;/code&gt; ở cuối, nhưng bảng phân vùng của nó chỉ khai báo đúng 1 phân vùng duy nhất, chiếm toàn bộ đĩa đệm với mã loại (Type) là &lt;code&gt;EE&lt;/code&gt;. Mã &lt;code&gt;EE&lt;/code&gt; là tín hiệu để các hệ thống cũ lùi lại: &amp;ldquo;Đây là đĩa GPT, đừng có đụng vào!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Một gpt bình thường" class="gallery-image" data-flex-basis="272px" data-flex-grow="113" height="590" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="/post/giai-phau-o-cung-forensics/gpt.png" width="671"&gt;&lt;/p&gt;
&lt;h2 id="4-giải-phẫu-gpt-header-và-partition-entry-array"&gt;4. Giải phẫu GPT Header và Partition Entry Array
&lt;/h2&gt;&lt;p&gt;Với GPT, mọi thứ thực sự bắt đầu từ Sector 1 và Sector 2.&lt;/p&gt;
&lt;h3 id="41-gpt-header-sector-1"&gt;4.1 GPT Header (Sector 1)
&lt;/h3&gt;&lt;p&gt;&lt;img alt="gpt header" class="gallery-image" data-flex-basis="1470px" data-flex-grow="612" height="110" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="/post/giai-phau-o-cung-forensics/header.png" width="674"&gt;&lt;/p&gt;
&lt;p&gt;GPT Header chiếm 92 byte đầu tiên của Sector 1. Khi nhìn vào Hex, bạn sẽ thấy nó cực kỳ rõ ràng:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Chữ ký (8 Byte đầu):&lt;/strong&gt; Luôn là &lt;code&gt;45 46 49 20 50 41 52 54&lt;/code&gt; (Dịch ra mã ASCII là &amp;ldquo;EFI PART&amp;rdquo;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bảo vệ toàn vẹn (CRC32):&lt;/strong&gt; GPT lưu mã Hash CRC32 của chính nó. Nếu mã độc sửa đổi dù chỉ 1 byte trong Header, CRC32 sẽ thay đổi, UEFI sẽ lập tức phát hiện và báo lỗi.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LBA dự phòng (Backup LBA):&lt;/strong&gt; Một tính năng tuyệt vời của GPT! Nó khai báo vị trí của một bản sao lưu GPT Header ở tít tận Sector cuối cùng của ổ đĩa. Nếu Header chính bị mã độc phá, ta vẫn có thể dùng bản Backup để hồi sinh hệ thống.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="42-partition-entry-array-mảng-phân-vùng---sector-2-trở-đi"&gt;4.2 Partition Entry Array (Mảng phân vùng - Sector 2 trở đi)
&lt;/h3&gt;&lt;p&gt;GPT hỗ trợ quản lý tới 128 phân vùng, mỗi phân vùng được cấp hẳn 128 Byte để lưu trữ thông tin (thay vì 16 byte chật hẹp như MBR).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Một Partition Entry trong GPT chứa gì?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GUID Loại Phân vùng (16 byte):&lt;/strong&gt; Định danh loại phân vùng. Đặc biệt, nó được lưu dưới dạng Mixed-Endian (Trộn lẫn giữa Little-Endian và Big-Endian). 3 khối byte đầu phải đọc ngược, trong khi 2 khối sau giữ nguyên.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GUID Phân vùng duy nhất (16 byte):&lt;/strong&gt; Căn cước công dân (ID) riêng biệt cho từng phân vùng đĩa.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LBA Bắt đầu &amp;amp; Kết thúc (16 byte):&lt;/strong&gt; Vị trí chính xác của phân vùng.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tên Phân vùng (72 byte):&lt;/strong&gt; Được lưu dưới định dạng chuỗi UTF-16. Nếu ném đoạn Hex này vào tool convert, ta sẽ thấy rõ ràng các tên như &amp;ldquo;Basic data partition&amp;rdquo; hay &amp;ldquo;EFI system partition&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Đặc biệt, hệ điều hành sẽ không boot từ một phân vùng chung chung nữa. Mọi file Bootloader (các file &lt;code&gt;.efi&lt;/code&gt;) đều phải được đặt gọn gàng trong một khu vực riêng gọi là Phân vùng hệ thống EFI (ESP). Mã độc muốn can thiệp quá trình Boot trên máy UEFI buộc phải tìm cách chui lọt qua Secure Boot và ghi dữ liệu vào phân vùng ESP này.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Việc đọc hiểu mã Hex của ổ cứng giúp các SOC và Forensics không bị phụ thuộc vào các công cụ tự động. Khi hệ thống sụp đổ hoặc mã độc ẩn mình dưới lớp vỏ bọc, chính những byte dữ liệu thô này sẽ nói cho chúng ta biết sự thật. Ở bài viết tới, chúng ta sẽ bắt tay vào phân tích sâu hơn hệ thống tệp NTFS và kỹ thuật giấu file bằng Alternate Data Streams. Hẹn gặp lại các bạn!&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>