Analyze acprotect’s use of hardware debug register lunar of arteam

Abstract Trong thế gới “bự” này . Nó là thế giới của RCE Reverse Code Engineer, phần cứng cũng như phần mềm đều rất quan trọng. Bởi một kỹ sư nghiên cứu mã (reverse engineer) đều phải từng học qua Assembly, và học làm thế nào để debug một chương trình, họ nhanh chóng tiếp cận, đối diện với những “bức tường mạnh” chính là việc nó sử dụng phần cứng thay vì dùng phần mềm thuần túy để ngăn chặn những kỹ sư ấy. Lúc này sự hiểu biết về x86 lại trở nên rất hữu dụng, bạn có thể dùng sự hiểu biết đó để chống lại chương trình đó – và tuy nhiên chương trình đó cũng biết dùng chính những thứ bạn dùng để chống lại bạn (hi hi, câu này hay ta). Trong bài viết này, chúng ta sẽ tìm hiểu xem ACProtect (cũng như UltraProtect) sử dụng những thanh ghi debug thuộc về phần cứng (dòng chip x86 ), dùng làm gì nhỉ? Hề hề, trình bảo vệ sử dụng chúng để giải mã chương trình được bảo vệ, đồng thời ngăn chặn việc chúng ta dùng những thanh ghi đó.

pdf10 trang | Chia sẻ: tlsuongmuoi | Lượt xem: 2208 | Lượt tải: 0download
Bạn đang xem nội dung tài liệu Analyze acprotect’s use of hardware debug register lunar of arteam, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
Analyze ACProtect’s use of HardWare Debug Register Lunar of ARTeam 1. Abstract Trong thế gới “bự” này …. Nó là thế giới của RCE Reverse Code Engineer, phần cứng cũng như phần mềm đều rất quan trọng. Bởi một kỹ sư nghiên cứu mã (reverse engineer) đều phải từng học qua Assembly, và học làm thế nào để debug một chương trình, họ nhanh chóng tiếp cận, đối diện với những “bức tường mạnh” chính là việc nó sử dụng phần cứng thay vì dùng phần mềm thuần túy để ngăn chặn những kỹ sư ấy. Lúc này sự hiểu biết về x86 lại trở nên rất hữu dụng, bạn có thể dùng sự hiểu biết đó để chống lại chương trình đó – và tuy nhiên chương trình đó cũng biết dùng chính những thứ bạn dùng để chống lại bạn (hi hi, câu này hay ta). Trong bài viết này, chúng ta sẽ tìm hiểu xem ACProtect (cũng như UltraProtect) sử dụng những thanh ghi debug thuộc về phần cứng (dòng chip x86 ), dùng làm gì nhỉ? Hề hề, trình bảo vệ sử dụng chúng để giải mã chương trình được bảo vệ, đồng thời ngăn chặn việc chúng ta dùng những thanh ghi đó. 2. The Meat of the Matter ? (Miếng mồi ngon hay vấn nạn cần giải quyết?) Đầu tiên, ta sơ lược thanh ghi debug cái đã. Trong bộ xử lý Intel và cả AMD cũng vậy, đều có khái niệm về những thanh ghi debug. Có 2 cách để ta đặt một điểm ngắt bên trong chương trình: - Cách đầu tiên là dùng Interrupt. Ví dụ như dùng chỉ lệnh “int 3”. - Cách thứ 2 là đặt một điểm ngắt bằng cách sử dụng những thanh ghi debug. Lý do chính để dùng cách này là để chống lại CRC check. Vì chỉ lệnh “int 3” sẽ ghi đè lên mã của chương trình, còn khi dùng những thanh ghi debug sẽ không ghi đè mã chương trình. Các bạn có thể tìm thông tin chi tiết về các thanh ghi debug trong course Intel Manuals Volumn 3 chapter 15. Nó sẽ nói đến các thanh ghi debug từ DR0 -> DR7. DR0 -> Dr3 được dùng để thiết lập một địa chỉ cần ngắt. Sau đó, DR7 sẽ cài đặt thêm thông tin về địa chỉ này ( read/write hay access). Bạn nên tìm hiểu volumn nói trên để có thêm chi tiết về vấn đề DEBUG REGISTERs. Trong Olly, Debug Regiser brekpoints, chúng được biết đến như là “hardware breakpoints” Những điểm ngắt phần cứng. Và bạn chỉ có thể có 4 điểm ngắt như vậy (rất dễ giải thích vì sao). Đối với những trình bảo vệ, để phát hiện ra các “int3”, chúng chỉ cần CRC check hoặc kiểm tra xem có mã nhị “int3” (mã hex 0xCC) hay không. Còn đối với những ngắt phần cứng thì các trình bảo vệ sẽ làm như thế nào đây? Đối với ACProtect, nó sẽ dùng những thanh ghi debug để giải mã tiến trình, vì vậy trình debugger không cách nào đặt được ngắt phần cứng. (Các bạn thử nghĩ xem vì sao nhé.) Giờ đây, ta sẽ tìm hiểu chi tiết hơn héng. Cài đặt trình bảo vệ ACProtect, chọn option “Use Debug Register as decode register”, như trong hình: Giờ đây, ta đã có một ứng dụng được bảo vệ bởi ACProtect (sử dụng debug register cho riêng nó). Ta sẽ phân tích xem cái gì sẽ xảy ra khi Olly thiết lập ngắt phần cứng trên OEP của chương trình (trong trường này, OEP là 0x00401750). Load ứng dụng vào Olly, đặt ngắt phần cứng trên OEP 0x00401750, F9 . Trên lý thuyết, Olly sẽ ngắt tại OEP: Nhưng, ta sẽ thấy thế này hỉ: Lưu ý thanh trạng thái của Olly: Đó không phải là điểm ngắt mà ta đã thiết lập. Đây chính là “Hiệu Ứng” của “Use Debug Register as decode register”. HỀ, Lúc này Hardware Breakpoints trở thành “Tài nguyên được bảo vệ”. Nếu bạn đọc trong tài liệu của Intel, các thanh ghi DR0 -> DR3 và DR7 là các thanh ghi đặc quyền được bảo vệ. Nếu ứng dụng có đặc quyền thấp nhất truy xuất đến các thanh ghi thì sẽ phát sinh lỗi bảo vệ? Vậy làm thế nào mà ACProtect có thể truy xuất thay đổi chúng? Nó có liên quan đến vấn đề Windows điều khiển các ngoại lệ (Exceptions) như thế nào. Khi một ngoại lệ xảy ra bên trong chương trình, thì hệ thống Windows sẽ gọi trình điều khiển ngoại lệ (exception handler) mà chương trình đã cài đặt, và sẽ gửi dữ liệu của trình điều khiển ngoại lệ liên quan đến ngoại lệ bằng một con trỏ trỏ đến cấu trúc ngoại lệ (exception record structure), cấu trúc này chứa đựng những giá trị thanh ghi debug. Lúc này, chương trình có thể chỉnh sử giá trị trong thanh ghi debug; sau đó, sẽ trã quyền điều khiển cho hệ thống window (tất nhiên là sau khi trình điều khiển ngoại lệ hoạt động xong). Quay trở lại một chút, ACProtect sẽ phát sinh một ngoại lệ ở vị trí đầu tiên: (BẠn còn giữ Olly chứ. Nếu còn thì tiếp tục). Cuộn cửa sổ window lên một chút, bạn sẽ thấy chỉ lệnh “int3”: Không nghi ngờ gì thêm, đây chính là nơi sẽ bắt đầu xảy ra ngoại lệ, để chắc chắn, bạn hãy restart lại Olly, đặt hardware breakpoints trên vị trí trên: 0x00407198. Đúng thực là chương trình bị ngắt tại vị trí INT3 trên: Lưu ý, hình trên cho ta biết trình điều khiển ngoại lệ đang ở vị trí nào, khi mà INT3 được “bóp cò” (triggered). (Ừm, SE = Structured Exception) Chúng ta sẽ đi đến đó hỉ: Đây chính là đoạn mã của trình điều khiển ngoại lệ. Chúng ta cần tìm ra đoạn mã mà làm mất giá trị trong thanh ghi debug chúng ta đã thiết lập. Chương trình chỉ có 1 ngoại lệ là INT3. Vì thế chúng ta sẽ tìm 2 thứ: - Loại mã ngoại lệ là cái nào. - Nơi nào trong đoạn mã này sẽ tác động vào các thanh ghi debug. ** Vấn đề đầu tiên, Ngoại lệ nào? Nhìn vào hình trên sẽ nhận ra ngay heng. Ta nói INT3 chính là loại ngoại lệ “80000003” . Nhìn vào đoạn mã ở trên, Chỗ được khoanh vòng màu đỏ í. Nó sẽ kiểm tra Ngoại lệ INT3 ? Nếu đúng thì không nhảy, nếu không đúng thì jmp. Vậy, đoạn mã ngay sau nó sẽ là đoạn mã tác động đến những thanh ghi debug Vậy, nhận xét này sẽ giúp chúng ta đến được đoạn mã cần thiết. Những thông tin sau sẽ được đưa đến trình đềiu khiển ngọai lệ khi nó được gọi. Cấu trúc Ngữ cảnh (CONTEXT structure) là cái ta nên chú ý. Nhìn xuống phía dưới một chút trong cửa sổ của Olly (từ vị trí điểm bắt đầu của trình điều khiển ngoại lệ), ta nhìn ở đây 0x004070B1, ECX sẽ lấy giá trị trong [ESP+0C], đây là một con trỏ tới CONTEXT record (hình trên). Tiếp theo, Chúng ta cần biết – Vị trí của những thanh ghi debug nằm trong trường CONTEXT RECORD? Chúng ta sẽ nhìn đoạn mã mà “hit” chúng. Giờ, ta đã có thông tin trên, và biết được ECX sẽ chứa con trỏ tới CONTEXT record, cuộn màn hình xuống một chút trong cửa sổ diassembling trong Olly, ta thấy được vị trí mà các thanh ghi debug đuợc truy xuất: Ừm, lúc này DR0 bị ghi đè, rồi tới DR1, DR2, DR3; các thanh ghi này sẽ bị ghi đè vài giá trị. Sau đó, nó sẽ ghi đè giá trị trong DR7 – cho phép hardware breakpoints “on execution” với những địa chỉ bên trong DR0 -> DR3. Bi giờ, chúng ta nhìn vào những địa chỉ trong DR0 -> DR3, chúng là những địa chỉ liền kề, liên kết gần nhau. Mã ở vị trí này sẽ được thực thi nhờ vào Hardware Beakpoints.: Khi mà những điểm ngắt này có tác dụng (come in), nó sẽ phát sinh một ngoại lệ, chương trình buộc phải có một trình điều khiển ngoại lệ, nếu không nó sẽ crash. Bạn hãy cuộn màn hình xuống tì vị trí 0x00407140 : Đây là việc kiểm tra cờ “Single step flag”, là ngoại lệ bạn sẽ có khi một Hardware Breakpoints được theo dõi, được đếm. Đây là một điều quan trọng: Hardware Breakpoints có một tín hiệu đến Trình debugger hoặc một trình điều khiển ngoại lệ với một “single step flag” . Cũng cùng một trình điều khiển ngoại lệ trên để điều khiển những ngoại lệ phần cứng này. Vì thế những mã sau đây sẽ điều khiển những ngắt phần cứng mà trình bảo vệ cài đặt: Chúng ta nhìn vào đây hi: Đoạn mã điều khiển các ngắt phần cứng, và các ngoại lệ phần cứng do các hardware breakpoints có tác dụng gây nên.. Đầu tiên, nếu eax chứa giá trị từ con trỏ [EDX], thì sẽ có sự so sánh với một hằng số: 1, sau đo là 2, và 3 . Đây là việc đếm. Đoạn mã sẽ đếm xem có bao nhiêu hardware breakpoints vừa mới có tác dụng (come in). Mỗi lần một hardware breakpoint hoạt động sẽ phát sinh ngoại lệ và trình điều khiển sẽ làm việc để xử lý nó: Lần đầu, đoạn mã này sẽ thực thi: Chúng ta biết rằng ECX chứa cấu trúc CONTEXT record, ta có được thanh ghi Edi sau đây: Cái hardware breakpoint thứ 2 có tác dụng, thì đoạn mã này họat động: Và cái thứ3 có tác dụng thì mã này họat động: Lần cuối cùng, thì sẽ thông qua cái mã nì. Sau khi hardware breakpoint cuối cùng có tác dụng tại 0x004071A0,thì chương trình sẽ tiếp tục ngay sau vị trí 0x004071A0: Lưu ý rằng, trình điều khiển ngoại lệ đã ghi những giá trị cần thiết vào bên trong ECX,EDX,EDI,DR0->DR3. Những thanh ghi này sẽ được dùng để giải mã ứng dụng. VÀ INT3 sẽ vẫn có thể tiếp tục xảy ra cho đến khi ứng dụng được decrypt xong. Vậy câu hỏi đặt ra là liệu những chang trai coder có cơ hội nào cho trình bảo vệ như vậy không? Câu trả lời là có một cách. Đó là hãy làm cái gì đó để restore giá trị bị ghi đè bởi trình bảo vệ. Trước tiên, ta xem xét cơ chế chuyển đổi điều khiển giũa hệ thống Windows với trình điều khiển ngoại lệ: Khi Windows gọi một exception handler, thì nó sẽ dùng một vài mã trong Kernel32.dll và trong NTDLL.dll, các mã này sẽ xem xét exception, và sẽ gọi exception handler tương ứng. Rồi exception handler trả quyền điều khiển cho Windows, rồi windows lại xem xét mã trả về của exception handler, nếu là EXCEPTION_CONTINUE thì nó lại tiếp tục gọi hàm ZwContinue: Bạn nhìn vào vị trí 77F91BBC, EBX sẽ chứa giá trị trong [ESP] = con trỏ tới trường CONTEXT record, đây là trường sẽ bị tác động bởi exception handler. Đoạn mã này không bị trình bảo vệ can thiệp. TỪ đây, có một ý cơ bản là chúng ta hãy hook ZwContinue, chỉnh sửa CONTEXT record tại đây, và đặt trở lại giá trị của chúng ta muốn đặt vào các thanh ghi phần cứng. Tuy nhiên, chúng ta nên nhớ 3 điểm này đối với trình bảo vệ: - Phát sinh một ngoại lệ bằng INT3. - Trong Exception Handler, nó cài đặt DR0 -> DR3. - Khi mỗi hardware breakpoints xảy ra, thì cài đặt một phần của trình giải mã. Do đó, nếu đơn giản chỉ là đặt vào DR0 giá trị của chúng ta sau mỗi lần ZwContinue được gọi, thì bước đầu tiên của trình coder sẽ không bao giờ xảy ra. Vì thế chúng ta phải đếm ngoại lệ. Nếu bạn đang dùng một trình debugger, đầu tiên hãy hook ZwContinue nhưng sau đó bạn cũng cần làm như sau: - Lưu giữ dấu vế của exception INT3. - Sau khi INT3 xảy ra, bắt đầu đếm ngoại lệ single step xảy ra. - Sau khi ngoại lệ single step thứ 2 xảy ra, thiết lập cờ ‘restore DR0 true..” - Đoạn mã hook trong ZwContinue sẽ tìm kiếm cờ “Restore DR0 true” và nếu TRUE thì [EBX] + 0x4 = giá trị bạn muốn cài đặt thành Hardware Breakpoints. - Trình debugger phải thực hiện việc này mỗi lần nó phát hiện INT3 – nó sẽ phải bắt đầu đếm single step exceptions. Hey, cách nay sẽ làm cho 4 thanh ghi phần cứng hoàn thành nhiệm vụ do trình bảo vệ đặt ra, vừa theo ý muốn của ta. Tôi không đưa ra bất kỳ một mã minh họa cho cách làm trên vì nó rất mất thời gian, nhưng về mặt ý tưởng thì hoàn toàn chính xác. Tạm biệt Chúc các bạn may mắn.

Các file đính kèm theo tài liệu này:

  • pdfACProtectDebugRegs_trans.pdf
Tài liệu liên quan