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
-
DWORD
là 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;
DWORD
thực chất là alias củaunsigned long
:typedef unsigned long DWORD;
-
SIZE_T
biể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_T
thực chất là alias củaULONG_PTR
:typedef ULONG_PTR SIZE_T;
-
ULONG_PTR
là 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; #endif
Trong 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_PTR
trướ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
-
PVOID
là 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;
PVOID
thực chất là alias củavoid*
:typedef void* PVOID;
-
HANDLE
là 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(...);
HANDLE
thường là mộtPVOID
:typedef PVOID HANDLE;
-
HMODULE
là 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(...);
HMODULE
thường là mộtHANDLE
:typedef HANDLE HINSTANCE; typedef HINSTANCE HMODULE;
-
LPCSTR/PCSTR
là 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ữL
là viết tắt của “long” và không ảnh hưởng đến kiểu dữ liệu. Trong khi đó, chữC
cho 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/PSTR
tương tự vớiLPCSTR/PCSTR
như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\PCWSTR
là 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\LPWSTR
tương tự vớiLPCWSTR\PCWSTR
như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_t
tươ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ụ:
PHANDLE
is the same asHANDLE*
.PSIZE_T
is the same asSIZE_T*
.PDWORD
is 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 succeeded
NT_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
Related
list
from outgoing([[MalDev - Introduction to Windows API]])
sort file.ctime asc