Windows系统调用学习笔记(一)—— API函数调用过程
Windows系統調用學習筆記(一)—— API函數調用過程
- Windows API
- 實驗1:分析ReadProcessMemory
- 第一步:定位函數
- 第二步:開始分析
- 總結
- 實驗2:分析NtReadVirtualMemory
- 第一步:定位函數
- 第二步:開始分析
- 總結
- 實驗3:編寫一個ReadProcessMemory函數
- 第一步:獲得變量地址
- 第二步:構造自定義ReadProcessMemory
- 第三步:調用自定義ReadProcessMemory
Windows API
描述:
Application Programming Interface,簡稱 API 函數。
Windows有多少個API?
主要是存放在 C:\WINDOWS\system32 下面所有的dll
幾個重要的DLL
Kernel32.dll:最核心的功能模塊,比如管理內存、進程和線程相關的函數等
User32.dll:是Windows用戶界面相關應用程序接口,如創建窗口和發送消息等
GDI32.dll:全稱是Graphical Device Interface(圖形設備接口),包含用于畫圖和顯示文本的函數。比如要顯示一個程序窗口,就調用了其中的函數來畫這個窗口
Ntdll.dll:大多數API都會通過這個DLL進入內核(0環)
實驗1:分析ReadProcessMemory
第一步:定位函數
第二步:開始分析
-
首先將我們傳入的參數進行壓棧
-
調用了其它模塊的函數:NtReadVirtualMemory(函數名紅色說明不在當前模塊)
-
若返回結果小于0,跳轉至loc_7C802204
loc_7C802204調用了sub_7C809419 -
sub_7C809419內部調用了另一個函數RtlNtStatusToDosError
這個函數的作用是設置錯誤號 -
從sub_7C809419出來后,將eax清零,跳轉到loc_7C802F9
loc_7C802F9只做了一件事情,那就是返回
至此,我們可以知道,當調用ReadProcessMemory失敗時,返回結果為0 -
若NtReadVirtualMemory返回結果大于等于0,返回結果為1
總結
實驗2:分析NtReadVirtualMemory
第一步:定位函數
這4行代碼就是NtReadVirtualMemory的所有代碼
第二步:開始分析
-
mov eax, 0BAh
0BAh:編號,對應操作系統內核中某個函數的編號
我們所用到的API函數,只要進0環,都要提供一個編號 -
mov edx, 7FFE0300h
7FFE0300h:函數地址,該函數決定了我們用什么方式進0環 -
該函數的功能:提供一個編號和一個函數,通過這個函數進入0環
總結
真正讀取進程內存的函數在0環實現,我們所用的函數只是系統提供給我們的函數接口
實驗3:編寫一個ReadProcessMemory函數
要求:不使用任何DLL,直接調用0環函數
意義:自己實現的API,可以避免3環程序被惡意掛鉤
第一步:獲得變量地址
運行以下代碼(進程1):
#include <stdio.h>int main() {int num = 0x12345678;printf("&num = %x \n", &num);getchar();return 0; }運行結果:
注意:不要讓進程結束
第二步:構造自定義ReadProcessMemory
代碼如下
void MyReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead) {__asm{lea eax, [ebp+0x14]push eax ; ReturnLengthpush [ebp+0x14] ; BufferLengthpush [ebp+0x10] ; Bufferpush [ebp+0x0C] ; BaseAddresspush [ebp+0x08] ; ProcessHandlemov eax, 0BAhmov edx, espint 02eh ; Windows操作系統提供IDT[0x2e]給用戶進行內核調用add esp, 20} }第三步:調用自定義ReadProcessMemory
完整代碼(進程2):
void MyReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead) {__asm{lea eax, [ebp+0x14]push eax ; ReturnLengthpush [ebp+0x14] ; BufferLengthpush [ebp+0x10] ; Bufferpush [ebp+0x0C] ; BaseAddresspush [ebp+0x08] ; ProcessHandlemov eax, 0BAhmov edx, espint 02eh ; Windows操作系統提供IDT[0x2e]給用戶進行內核調用add esp, 20} }int main() {DWORD pBuffer; // 接收數據的緩沖區HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, PID); // 獲得進程句柄,PID修改為進程1的PIDMyReadProcessMemory(hProcess, (PVOID)0x12ff7c, &pBuffer, 4, 0); // 調用自定義的ReadProcessMemoryprintf("pBuffer = %x \n", pBuffer); // 打印從其他進程中讀取的數據getchar();return 0; }運行結果:
成功從進程1中讀取了變量num的值!
總結
以上是生活随笔為你收集整理的Windows系统调用学习笔记(一)—— API函数调用过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows保护模式学习笔记(十四)—
- 下一篇: Windows系统调用学习笔记(二)——