Windows API
Danh sách các hàm: Windows API index - Win32 apps | Microsoft Learn Danh sách các kiểu dữ liệu: Windows Data Types (BaseTsd.h) - Win32 apps | Microsoft Learn
Windows Data Types
-
DWORDlà số nguyên không dấu 32-bit (), dùng trên cả hệ thống 32-bit và 64-bit.DWORD dwVariable = 42;DWORDthực chất là alias củaunsigned long:typedef unsigned long DWORD; -
SIZE_Tbiểu diễn kích thước của một đối tượng. Trên hệ thống 32-bit, nó là số nguyên không dấu 32-bit (). Trên hệ thống 64-bit, nó là số nguyên không dấu 64-bit ().SIZE_T sVariable = sizeof(int);SIZE_Tthực chất là alias củaULONG_PTR:typedef ULONG_PTR SIZE_T; -
ULONG_PTRlà số nguyên không dấu có kích thước bằng kích thước của con trỏ trên kiến trúc hiện tại.ULONG_PTRđược định nghĩa như sau:#if defined(_WIN64) typedef unsigned __int64 ULONG_PTR; #else typedef unsigned long ULONG_PTR; #endifTrong suốt khóa học về lập trình malware này, chúng ta sẽ ép kiểu con trỏ về
ULONG_PTRtrước khi thực hiện các thao tác toán học:PVOID Pointer = malloc(100); // Pointer = Pointer + 10; // not allowed Pointer = (ULONG_PTR)Pointer + 10; // allowed -
PVOIDlà con trỏ đến bất kỳ kiểu dữ liệu nào, có kích thước 4 byte trên hệ thống 32-bit và 8 byte trên hệ thống 64-bit.PVOID pVariable = &SomeData;PVOIDthực chất là alias củavoid*:typedef void* PVOID; -
HANDLElà giá trị đại diện cho một đối tượng mà hệ điều hành quản lý chẳng hạn như tập tin, tiến trình hoặc luồng.HANDLE hFile = CreateFile(...);HANDLEthường là mộtPVOID:typedef PVOID HANDLE; -
HMODULElà handle của một module (có thể là file DLL hoặc file EXE), thường là base address của module.HMODULE hModule = GetModuleHandle(...);HMODULEthường là mộtHANDLE:typedef HANDLE HINSTANCE; typedef HINSTANCE HMODULE; -
LPCSTR/PCSTRlà con trỏ đến một chuỗi hằng bao gồm các ký tự Windows 8-bit (hay còn gọi là ANSI) và kết thúc bằng ký tự null (0x00). ChữLlà viết tắt của “long” và không ảnh hưởng đến kiểu dữ liệu. Trong khi đó, chữCcho biết đây là con trỏ đến chuỗi hằng (là chuỗi mà không thể bị thay đổi giá trị - chỉ đọc).LPCSTR lpcString = "Hello, world!"; PCSTR pcString = "Hello, world!";Cả hai kiểu dữ liệu này đều tương đương với
const char*. -
LPSTR/PSTRtương tự vớiLPCSTR/PCSTRnhưng có quyền thay đổi giá trị (đọc và ghi).LPSTR lpString = "Hello, world!"; PSTR pString = "Hello, world!";Cả hai kiểu dữ liệu này đều tương đương với
char*. -
LPCWSTR\PCWSTRlà con trỏ đến một chuỗi hằng bao gồm các ký tự Windows 16-bit (hay còn gọi là Unicode) và kết thúc bằng ký tự null (0x00).LPCWSTR lpwcString = L"Hello, world!"; PCWSTR pcwString = L"Hello, world!";Cả hai kiểu dữ liệu này đều tương đương với
const wchar*. -
PWSTR\LPWSTRtương tự vớiLPCWSTR\PCWSTRnhưng có quyền thay đổi giá trị.LPWSTR lpwString = L"Hello, world!"; PWSTR pwString = L"Hello, world!";Cả hai kiểu dữ liệu này đều tương đương với
wchar*. -
wchar_ttương tự vớiwchar, được dùng để biểu diễn các ký tự Unicode (wide characters).wchar_t wChar = L'A'; wchar_t* wcString = L"Hello, world!";
Data Types Pointers
Các kiểu dữ liệu có chữ P đằng trước đều là con trỏ. Ví dụ:
PHANDLEis the same asHANDLE*.PSIZE_Tis the same asSIZE_T*.PDWORDis the same asDWORD*.
ANSI & Unicode Functions
Đa số các hàm của Windows API có chữ A và chữ W ở cuối. Chữ A là viết tắt của ANSI còn chữ W là viết tắt của Wide Characters (Unicode). Sự khác biệt giữa các hàm ANSI và các hàm Unicode là các hàm ANSI nhận đối số là các chuỗi ANSI còn các hàm Unicode nhận đối số là các chuỗi Unicode.
In and Out Parameters
Windows API có các tham số với từ khóa IN và OUT. Ví dụ về từ khóa OUT:
BOOL HackTheWorld(OUT int* num){
// Setting the value of num to 123
*num = 123;
// Returning a boolean value
return TRUE;
}
int main(){
int a = 0;
// 'HackTheWorld' will return true
// 'a' will contain the value 123
HackTheWorld(&a);
}Tham số có kiểu OUT giúp lập trình viên biết được rằng giá trị của đối số sẽ bị thay đổi. Việc không dùng từ khóa OUT không làm thay đổi chức năng của hàm.
Windows API Example
Chúng ta sẽ lấy hàm CreateFileW làm ví dụ về cách sử dụng Windows API. Ta sẽ làm theo các bước sau:
Đọc tài liệu: nếu không rõ về các option của hàm cũng như là chức năng của nó thì nên đọc tài liệu. Tài liệu về hàm CreateFileW: CreateFileW function (fileapi.h) - Win32 apps | Microsoft Learn.
Phân tích kiểu trả về và các tham số: theo tài liệu, nếu hàm CreateFileW được thực hiện thành công thì nó sẽ trả về một HANDLE đến tập tin, thiết bị, named pipe hoặc mail slot. Ngoài ra, tất cả các tham số đều có kiểu là IN.
HANDLE CreateFileW(
[in] LPCWSTR lpFileName,
[in] DWORD dwDesiredAccess,
[in] DWORD dwShareMode,
[in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes,
[in] DWORD dwCreationDisposition,
[in] DWORD dwFlagsAndAttributes,
[in, optional] HANDLE hTemplateFile
);Chú ý rằng các từ khóa ở trong ngoặc vuông là không bắt buộc.
Sử dụng:
// This is needed to store the handle to the file object
// the 'INVALID_HANDLE_VALUE' is just to intialize the variable
Handle hFile = INVALID_HANDLE_VALUE;
// The full path of the file to create.
// Double backslashes are required to escape the single backslash character in C
LPCWSTR filePath = L"C:\\Users\\maldevacademy\\Desktop\\maldev.txt";
// Call CreateFileW with the file path
// The additional parameters are directly from the documentation
hFile = CreateFileW(filePath, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// On failure CreateFileW returns INVALID_HANDLE_VALUE
// GetLastError() is another Windows API that retrieves the error code of the previously executed WinAPI function
if (hFile == INVALID_HANDLE_VALUE){
printf("[-] CreateFileW Api Function Failed With Error : %d\n", GetLastError());
return -1;
}Windows API Debugging Errors
Khi một hàm thực thi thất bại thì nó thường trả về những lỗi không rõ ràng. Ví dụ, nếu CreateFileW có lỗi thì nó sẽ trả về INVALID_HANDLE_VALUE nhằm cho biết rằng file không thể được tạo ra. Để biết được chi tiết lý do tại sao file không được tạo ra, ta có thể dùng hàm GetLastError.
Giá trị trả về của GetLastError có thể được tra cứu ở trong System Error Codes (0-499) (WinError.h) - Win32 apps | Microsoft Learn. Một vài mã lỗi phổ biến:
5- ERROR_ACCESS_DENIED2- ERROR_FILE_NOT_FOUND87- ERROR_INVALID_PARAMETER
Windows Native API Debugging Errors
Các hàm thuộc Native API trả về mã lỗi có kiểu là NTSTATUS. Kiểu này là thực chất là một số nguyên không dấu 32-bit và được dùng để biểu diễn trạng thái của một system call hoặc một hàm. Một lời gọi hàm thành công sẽ có giá trị là STATUS_SUCCESS, tương đương với 0. Danh sách các giá trị của NTSTATUS: [MS-ERREF]: NTSTATUS Values | Microsoft Learn.
Đoạn code sau minh họa cách kiểm tra mã lỗi của các system call:
NTSTATUS STATUS = NativeSyscallExample(...);
if (STATUS != STATUS_SUCCESS){
// printing the error in unsigned integer hexadecimal format
printf("[!] NativeSyscallExample Failed With Status : 0x%0.8X \n", STATUS);
}
// NativeSyscallExample succeededNT_SUCCESS Macro
Một cách khác để kiểm tra giá trị trả về của các Native API là sử dụng macro NT_SUCCESS. Macro này sẽ trả về TRUE nếu hàm được gọi thành công và FALSE nếu ngược lại.
Ví dụ sử dụng macro:
NTSTATUS STATUS = NativeSyscallExample(...);
if (!NT_SUCCESS(STATUS)){
// printing the error in unsigned integer hexadecimal format
printf("[!] NativeSyscallExample Failed With Status : 0x%0.8X \n", STATUS);
}
// NativeSyscallExample succeeded