- vừa được xem lúc

Nirvana Debugging Technique

0 0 3

Người đăng: Vương Lê

Theo Viblo Asia

Nirvana Debugging

Table of Content

  1. [Giới thiệu]
  2. [Nirvana Debugging]
  3. [NtSetInformationProcess]
  4. [Callback_thunk và Register syscall function]
  5. [Xử lý giá trị của r10 và rax trong callback function]
  6. [Kết luận]

Giới thiệu

Tiếp nối bài viết trước đã tìm hiểu về sử dụng Direct Syscall (link bài viết: Direct Syscall Blog), lần này chúng ta sẽ tìm hiểu kỹ thuật Nirvana Debugging, hiểu 1 cách ngắn gọn kỹ thuật này vẫn sẽ cho chúng ta thông tin của API được gọi kể cả nó được gọi bằng phương pháp nào.

Nirvana Debugging

Kỹ thuật sẽ đặt 1 hook sau khi syscall được thực hiện, tức là kết quả của API đã được trả về, lúc này ta sẽ phân tích kết quả trả về để xem thông tin của API đã được gọi.

Như chúng ta thấy, my_callback_hooking_fn sẽ được đặt ngay sau khi syscall function trả về.

NtSetInformationProcess

Để có thể đặt được my_callback_hooking_fn, sử dụng NtSetInformationProcess với ProcessInformationClass = 40, giá trị này không được đề cập trong tài liệu của microsoft.

Cấu trúc của NtSetInformationProcess:

typedef NTSTATUS(WINAPI* NtSetInformationProcessPtr)( HANDLE ProcessHandle, UINT32 ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength
);

Trong đó ProcessInformation là 1 struct trỏ đến thông tin callback:

typedef struct _PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION { ULONG Version; // version 1 = x86, 0 = x64 ULONG Reserved; // 0 PVOID Callback; // pointer to callback function
} PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION, * PPROCESS_INSTRUMENTATION_CALLBACK_INFORMATION; 

Dưới đây là code set callback function:

PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION pici = { 0 };
pici.Version = 0;
pici.Reserved = 0;
pici.Callback = callback_thunk;
HMODULE hNtdll = LoadLibraryA("ntdll.dll");
NtSetInformationProcessPtr NtSetInformationProcessfn = (NtSetInformationProcessPtr)GetProcAddress(hNtdll, "NtSetInformationProcess");
NtSetInformationProcessfn(GetCurrentProcess(), ProcessInstrumentationCallback, &pici, sizeof(pici));

Trong đó callback_thunk là con trỏ đến hàm callback sẽ được gọi, là phần mã asm sẽ được nói đến ở phần dưới.

Callback_thunk và Register syscall function

Điều bây giờ cần quan tâm là Sycall function trả về giá trị nào cần quan tâm và phân tích giá trị đó thế nào, cùng nhìn lại mã asm của 1 Syscall đã nhắc đến trong bài trước (link bài viết: Direct Syscall Blog):

0:031> u NtWriteVirtualMemory
ntdll!NtWriteVirtualMemory:
00007fff`efd8d710 4c8bd1 mov r10,rcx
00007fff`efd8d713 b83a000000 mov eax,3Ah
00007fff`efd8d718 f604250803fe7f01 test byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007fff`efd8d720 7503 jne ntdll!NtWriteVirtualMemory+0x15 (00007fff`efd8d725)
00007fff`efd8d722 0f05 syscall
00007fff`efd8d724 c3 ret
00007fff`efd8d725 cd2e int 2Eh
00007fff`efd8d727 c3 ret

Như ta thấy, có 2 giá trị được đẩy vào 2 thanh ghi r10eax, trong đó, r10 là địa chỉ gọi syscall, eax là syscall code của hàm này, vì vậy ta cần lấy giá trị 2 thanh ghi này để phân tích. Để làm được điều này, sử dụng đoạn mã asm dưới đây:

callback_thunk.asm

.code EXTERN callback : PROC callback_thunk proc ;save all register push rax push rbx push rcx push rdx push rsi push rdi push rbp push rsp sub rsp, 20h ; align stack mov rdx, rax ;arg2 mov rcx, r10 ;arg1 call callback add rsp, 20h ; align stack pop rsp pop rbp pop rdi pop rsi pop rdx pop rcx pop rbx pop rax ret callback_thunk endp
end

EXTERN callback: PROC là 1 hàm viết trong main.c, trong đó việc truyền rax và r10 vào 2 thanh ghi rdx và rcx nhằm push tham số cho hàm callback. Quy ước gọi hàm được microsoft được đề cập tại đây: x64-calling-convention. Sau bước này hàm callback() sẽ nhận được 2 thanh ghi ta cần lấy, bây giờ chỉ cần phân tích giá trị 2 thanh ghi này để lấy ra thông tin API được gọi.

Note: Để gọi đến được callback_thunk, cần khai báo trong main.c như sau:

extern "C" __forceinline PVOID callback_thunk();

Xử lý giá trị của r10 và rax trong callback function

Thanh ghi raxr10 sau khi được trả về từ syscall được lưu 2 giá trị như sau:

  • rax lưu kết quả trả về của syscall</br>
  • r10 lưu địa chỉ gọi hàm ban đầu của syscall

Vậy việc đầu tiên ta sẽ debug xem r10 sẽ trỏ về đâu

R10 có giá trị hiện tại là 0x00007FFFEFD8D2E4 đang trỏ đến lệnh C3 như trên, vậy để có thể lấy được mã syscall ở mov eax, 18h ta thực hiện tính toán con trỏ đến sau lệnh mov r10, rcx (luôn không thay đổi) để lấy giá trị này:

Phần còn lại sẽ sử dụng SymFromAddr API để lấy tên hàm thông qua con trỏ thanh ghi R10:

Lưu ý: Để sử dụng được SymFromAddr, ta cần khởi tạo trước thông qua hàm dưới đây, cần gọi hàm khởi tạo trước khi gọi NtSetInformationProcess, hạn chế gọi các hàm như LoadLibrary ở giữa SymFromAddrSymInitialize

if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) { printf("SymInitialize failed"); return -1;
}

Kết luận

Dưới đây là kết quả sau khi mình test thử với VirtualAllocVirtualProtect

Có thể thấy 2 hàm NT trên đã được in ra, kèm theo đó là 1 số hàm của chương trình chạy để kết thúc. Blog tiếp theo mình sẽ nói về sử dụng NtSetInformationProcess để inject shellcode vào tiến trình.

Source code mình đã up kèm file trên git tại folder code.

Cảm ơn các bạn đã đọc.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tạo ra virus bằng tool (Part1)

Virus. Tác hại của nó để lại cũng nặng nề:. . Gây khó chịu cho chúng ta là tác hại đầu tiên.

0 0 33

- vừa được xem lúc

Phân loại mã độc hiện nay

Trong tài liệu của NIST có một số khác biệt theo định nghĩa và cách hiểu thông thường về Virus máy tính đang thông dụng. Ngay trong tên của tài liệu đã nêu lên sự khác biệt, các tác giả nói tới “Malwa

0 0 45

- vừa được xem lúc

Series tìm hiểu về các phần mềm độc hại xưa và nay (phần 1)

Hưởng ứng sự kiện MayFest2022 của Viblo thì mình cũng muốn làm một series dài dài về các phần mềm độc hại để mọi người có thể dễ follow và tìm đọc. I.

0 0 28

- vừa được xem lúc

Series tìm hiểu về các phần mềm độc hại xưa và nay (phần 2)

I. Giới thiệu.

0 0 21

- vừa được xem lúc

Series tìm hiểu về các phần mềm độc hại xưa và nay (phần 3)

I. Mở đầu.

0 0 24

- vừa được xem lúc

☠️🧪 Thử độc: mã độc Android có đáng sợ? 🤮

Dạo gần đây Netflix đã công chiếu bộ phim Unlocked, kể về quá trình một tên sát nhân hàng loạt điều tra về các nạn nhân và cài phần mềm mã độc gián điệp vào điện thoại của họ. Với phần mềm đó, tên sát

0 0 10