以OpenProcess这个内核交互函数为例
Windwos需要进行内核交互的函数调用进内核的3种方式:
1.int 2E
2.sysenter
3.syscall
win7 x32 以OpenProcess为例
exe(OpenProcess) -> kernel32.dll(openProcess)
kernel32.dll(openProcess) -> kernelbase.dll(NTOpenProcess)
kernelbase.dll(NTOpenProcess) -> ntdll.dll(KiFastSystemCall)
ntdll.dll(KiFastSystemCall) -> ntdll.dll(sysenter) -> 内核(nt!KiFastSystemEntry)
X86OS
x32.debug.exe:
1.主模块->kernel32.dll
2.kernel32.dll->kernelBase.dll(ntopenprocess)
3.kernelbase.dll(ntopenprocess)->ntdll.dll(zwopenprocess)
4.ntdll.dll(zwopenprocess)->sysenter(内核)
x32.release.exe:
1.主模块->kernel32.dll
2.kernel32.dll->kernelBase.dll(ntopenprocess)
3.kernelbase.dll(ntopenprocess)->ntdll.dll(zwopenprocess)
4.ntdll.dll(zwopenprocess)->sysenter(内核)
X64OS
x32.debug.exe:
1.主模块->kernel32.dll
2.kernel32.dll->kernelBase.dll(ntopenprocess)
3.kernelbase.dll(ntopenprocess)->ntdll.dll
4.ntdll.dll->Wow64(为64OS,模拟32OS,转发进内核)
x32.relesae.exe:
1.主模块->kernel32.dll
2.kernel32.dll->kernelBase.dll(ntopenprocess)
3.kernelbase.dll(ntopenprocess)->ntdll.dll
4.ntdll.dll->Wow64(为64OS,模拟32OS,转发进内核)
x64.debug.exe:
1.主模块->kernel32.dll
2.kernel32.dll->kernelBase.dll(ntopenprocess)
3.kernelbase.dll(ntopenprocess)->ntdll.dll(ntopenprocess)
4.ntdll.dll(ntopenprocess)->syscall(内核)
x64.relesae.exe:
1.主模块->kernel32.dll
2.kernel32.dll->kernelBase.dll(ntopenprocess)
3.kernelbase.dll(ntopenprocess)->ntdll.dll(ntopenprocess)
4.ntdll.dll(ntopenprocess)->syscall(内核)
#include <iostream>
#include <windows.h>
//WINAPI,这个宏不能少,不然会报错
EXTERN_C typedef FARPROC(WINAPI* MyGetProcAddress)(_In_ HMODULE hModule, _In_ LPCSTR lpProcName);
EXTERN_C typedef HMODULE(WINAPI* MyLoadLibrary)(_In_ LPCWSTR lpLibFileName);
EXTERN_C typedef int(WINAPI* MyMessageBox)(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType);
EXTERN_C typedef VOID(WINAPI* MyExitProcess)(_In_ UINT uExitCode);
DWORD Getkerlen32adders()
{
_TEB* pTeb = NtCurrentTeb();
//pTeb里面是指针,把它转成PBYTE(字节为单位)+0x30,定位到了指向PEB的指针的位置,
又因为指向PEB的是指针,指针在x86OS站4字节,
所以把定位到的那个位置转成4字节的指针即 (PUINT/PDWORD),
然后在“*”取值即:把定位到的那个位置往后数4给字节里面的值取出来,
在对值进行取值,就得到了PEB结构体,又因为后面需要用PEB结构体,
所以又把PEB结构体的首地址转成PBYTE。
PBYTE pPeb = (PBYTE) * (PUINT)((PBYTE)pTeb + 0x30);
PBYTE pLdr = (PBYTE) * (PUINT)(pPeb + 0x0C);
PUINT InloadorderrmoudleList = (PUINT)(pLdr + 0xc);
PUINT pExe = (PUINT)*InloadorderrmoudleList;
PUINT pNtdll = (PUINT)*pExe; //因为_LIST_ENTRY嵌在_LDR_DATA_TABLE_ENTRY的首位,所以可以*pExe、*pNtdll一直取到Kernel32.dll的位置
PBYTE pKernel32dll = (PBYTE)*pNtdll;
UINT Kernel32DllBase = *(PUINT)(pKernel32dll + 0x18);
return Kernel32DllBase;
}
DWORD GetProcAddressFun()
{
DWORD DllBase = Getkerlen32adders();
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)Getkerlen32adders();
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((PBYTE)pDos + pDos->e_lfanew);
PIMAGE_EXPORT_DIRECTORY pEm = (PIMAGE_EXPORT_DIRECTORY)(pNt->OptionalHeader.DataDirectory[0].VirtualAddress + DllBase);
PDWORD NameTable = (PDWORD)(DllBase + pEm->AddressOfNames);
for (size_t i = 0; i < pEm->NumberOfNames; i++)
{
if (!NameTable[i])
{
continue;
}
PCHAR szFuncName = (PCHAR)(NameTable[i] + DllBase);
if (!strcmp(szFuncName,"GetProcAddress"))
{
DWORD index = ((PWORD)(pEm->AddressOfNameOrdinals + DllBase))[i];
DWORD Funcaddrs= ((PDWORD)(pEm->AddressOfFunctions + DllBase))[index];
return Funcaddrs + DllBase;
}
}
}
int main()
{
MyGetProcAddress pMyGetProcAddress = (MyGetProcAddress)GetProcAddressFun();
HMODULE kernelHandle = (HMODULE)Getkerlen32adders();
MyLoadLibrary pMyLoadLibrary = (MyLoadLibrary)pMyGetProcAddress(kernelHandle, "LoadLibraryW");
HMODULE hUser32 = pMyLoadLibrary(L"User32.dll");
MyMessageBox pMyMessageBox = (MyMessageBox)pMyGetProcAddress(hUser32, "MessageBoxA");
MyExitProcess pMyExitProcess = (MyExitProcess)pMyGetProcAddress(kernelHandle, "ExitProcess");
pMyMessageBox(NULL, "0.0", "Meg", MB_OK);
pMyExitProcess(0);
}
双机调试步骤:
双机调试步骤: (注意空格)
1 windbg断下来
2 ! process 0 0 (查看当前所有进程信息)
3 . process /i 地址 (切换到指定进程上下文)
4 windbg按F5执行断下
5 !process (查看指定的进程信息)
6 dt _teb 地址 (查看这个地址,按_TEB结构解析)
7 dt _peb 地址
8 dt _peb_ldr_data 地址
9 dt _ldr_data_table_entry 地址 (是主模块的)
10 dt _ldr_data_table_entry 地址 (一般是ntdll.dll)
11 dt _ldr_data_table_entry 地址 (一般是kernel32.dll)
dt _list_entry (查看_list_entry结构的)
!peb (查看打开进程的PEB地址)
!teb (查看打开进程的TEB地址)