zoukankan      html  css  js  c++  java
  • windows内核Api的学习

    windows内核api就是ntoskrnl.exe导出的函数。我们可以跟调用应用层的api一样,调用内核api。不过内核api需要注意的是,如果函数导出了,并且函数文档化(也就是可以直接在msdn上搜索到)。ExFreePool函数导出,并且文档化,那么我们可以直接调用。导出了未文档化,那么我们就要声明。什么叫文档化和未文档化呢?大家来看一个函数:

    UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process);

    文档化:就是假设函数导出了,并且在msdn上可以搜索到。就是文档化我们调用文档化的函数就是直接调用。

    未文档化:就是假设函数已经导出了,但是在msdn上没有搜到,就是未文档化函数我们要调用它,就得自己手动声明。

    内核编程就跟应用层一样,都是api的调用,都是Hook,都是Hook,一样的编程思维。它们本质的区别只是在于一个先后顺序,比如看图-什么叫本质的区别:顺序掉

    ring3SSDT层主体实现函数的调用顺序:

    OpenProcesss-->ntdll!ZwOpenProcess-->ntos!ZwOpenProcess-->ntos!NtOpenProcess-->后面。如果你以内核层和应用的角度去理解,那么就是openprocess一直调用到NtOpenProcess还有后面。

    示例代码:

    KernelApiCode.c

    #include <ntifs.h>
    #include <ntimage.h>
    
    //调用功能号
    #define SystemModuleInformation 11
    #define SystemProcessesAndThreadsInformation 5
    
    
    // 系统进程信息结构体
    typedef struct _SYSTEM_PROCESSES
    {
    	ULONG NextEntryDelta;
    	ULONG ThreadCount;
    	ULONG Reserved[6];
    	LARGE_INTEGER CreateTime;
    	LARGE_INTEGER UserTime;
    	LARGE_INTEGER KernelTime;
    	UNICODE_STRING ProcessName;        //进程的名称
    	KPRIORITY BasePriority; 
    	ULONG ProcessId;                   //进程的PID
    	ULONG InheritedFromProcessId;
    	ULONG HandleCount;
    	ULONG Reserved2[2];
    	VM_COUNTERS VmCounters;
    	IO_COUNTERS IoCounters;
    } _SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;
    
    // 系统模块信息结构体节点
    typedef struct _SYSTEM_MODULE_INFORMATION  
    {
    	ULONG  Reserved[2];  
    	ULONG  Base;            //模块的基址
    	ULONG  Size;            //模块的大小    
    	ULONG  Flags;        
    	USHORT Index;       
    	USHORT Unknown;     
    	USHORT LoadCount;   
    	USHORT ModuleNameOffset;
    	CHAR   ImageName[256];  //模块的名称
    } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
    
    //模块链结构
    typedef struct _tagSysModuleList
    {
    	ULONG ulCount;
    	SYSTEM_MODULE_INFORMATION smi[1];
    } MODULES, *PMODULES;
    
    //ZwQuerySystemInformation函数导出了,但是未文档化,所以要手动声明
    NTSTATUS __stdcall ZwQuerySystemInformation(
    	ULONG_PTR SystemInformationClass,  //调用功能号
    	PVOID SystemInformation,           //信息结构体
    	ULONG SystemInformationLength,     //信息结构体的字节长度
    	PULONG ReturnLength                //返回的实际长度
    	);
    
    //在驱动层遍历进程
    VOID EnumProcessList()
    {
    	//声明变量
    	NTSTATUS status;
    	ULONG NeededSize,i;
    	PVOID pBuffer = NULL; //用来指向缓冲区
    	PSYSTEM_PROCESSES pInfo = NULL; //指向SYSTEM_PROCESSES的指针
    
    	__try
    	{
    		//获取存放系统的进程和线程信息的实际字节长度
    		status = ZwQuerySystemInformation(
    			SystemProcessesAndThreadsInformation,
    			NULL,
    			0,
    			&NeededSize);
    		if (status != STATUS_INFO_LENGTH_MISMATCH)
    		{
    			//长度不匹配 
    			DbgPrint("!= STATUS_INFO_LENGTH_MISMATCH");
    
    			return;
    		}
    
    		//根据获取的NeededSize申请非分页内存
    		pBuffer = ExAllocatePool(NonPagedPool, NeededSize);
    		if (pBuffer != NULL)
    		{
    			DbgPrint("NeededSize:%d
    ", NeededSize);
    
    			//使用5号功能来获取系统的进程和线程的信息
    			status = ZwQuerySystemInformation(
    				SystemProcessesAndThreadsInformation, //SystemProcessesAndThreadsInformation = 5 
    				pBuffer,
    				NeededSize, 
    				NULL);
    			//如果调用成功
    			if (NT_SUCCESS(status)) 
    			{
    				DbgPrint("ZwQuerySystemInformation() success
    ");
    
    				//指针类型转换
    				pInfo = (PSYSTEM_PROCESSES)pBuffer;
    
    				while (TRUE)
    				{
    					//PID=0,系统的
    					if (pInfo->ProcessId == 0)
    					{
    						DbgPrint("PID %5d System Idle Process
    ", pInfo->ProcessId);
    					}
    					else
    					{	//打印进程的PID和进程的名称
    						DbgPrint("PID %5d %ws
    ", pInfo->ProcessId, pInfo->ProcessName.Buffer);//这里是unicode
    					}
    
    					//如果没有下一个就结束
    					if (pInfo->NextEntryDelta == 0)
    					{
    						break;
    					}
    
    					//遍历下一个
    					pInfo = (PSYSTEM_PROCESSES)(((PUCHAR)pInfo) + pInfo->NextEntryDelta);
    				}
    			}
    		}
    
    	}
    	//异常的处理 
    	__except(EXCEPTION_EXECUTE_HANDLER)
    	{
    		//输出异常信息code
    		DbgPrint("%08x
    ", GetExceptionCode());
    	}
    
    	//释放申请的非分页内存资源
    	if (pBuffer != NULL)
    	{
    		ExFreePool(pBuffer);
    		pBuffer = NULL;
    	}
    
    }
    
    //驱动层遍历系统模块
    VOID GetKernelModuleInfo()
    {
    	//变量的声明
    	NTSTATUS status;
    	ULONG NeededSize, i;
    	PVOID pBuffer = NULL; //用来指向缓冲区
    	PMODULES pModuleList = NULL; //指向MODULES指针
    
    	__try
    	{
    		//获取存放系统模块信息结构体的缓冲区的大小
    		status = ZwQuerySystemInformation(
    			SystemModuleInformation, 
    			NULL,
    			0,
    			&NeededSize);
    		if (status != STATUS_INFO_LENGTH_MISMATCH)
    		{
    			DbgPrint("!= STATUS_INFO_LENGTH_MISMATCH");
    
    			return;
    		}
    
    		//根据NeededSize的大小,申请非分页内存的大小
    		pBuffer = ExAllocatePool(NonPagedPool, NeededSize);
    		if (pBuffer)
    		{
    			//调用功能号11来获取系统的模块的信息
    			status=ZwQuerySystemInformation(
    				SystemModuleInformation, //SystemModuleInformation = 11
    				pBuffer,
    				NeededSize,
    				NULL);
    			if (NT_SUCCESS(status))
    			{
    				//指针类型转换
    				pModuleList = (PMODULES)pBuffer;
    
    				//遍历系统的模块的信息
    				for (i = 0; i< pModuleList->ulCount; i++)
    				{
    					//打印系统模块的基址、模块的大小、模块的名称
    					DbgPrint("0x%08X:%d:%s
    ", pModuleList->smi[i].Base, pModuleList->smi[i].Size, pModuleList->smi[i].ImageName);
    				}
    			}
    		}
    
    	}
    	__except(EXCEPTION_EXECUTE_HANDLER)
    	{
    		//打印异常的代码
    		DbgPrint("%08x
    ", GetExceptionCode());
    	}
    
    	//释放申请的非分页内存资源
    	if (pBuffer)
    	{
    		ExFreePool(pBuffer);
    		pBuffer = NULL;
    	}
    		
    }
    
    /*
    *创建注册表
    *SafeKey注册表的路径
    *Reg_Type注册表的键值类型
    *ValueName注册表的键值的名称
    *Value注册表的键值的值
    */
    BOOLEAN Safe_CreateValueKey(PWCHAR SafeKey, ULONG_PTR Reg_Type, PWCHAR ValueName, PWCHAR Value)
    {
    	//声明变量
    	OBJECT_ATTRIBUTES objectAttributes;
    	UNICODE_STRING RegUnicodeString, Unicode_ValueName;
    	NTSTATUS ntStatus;
    	HANDLE hRegister;
    	ULONG_PTR ulValue_DWORD;
    	ULONG_PTR ulResult = 0;
    	BOOLEAN bRetOK = FALSE;
    
    	//WCHAR字符串转UNICODE_STRING字符串
    	RtlInitUnicodeString(&Unicode_ValueName, ValueName); //键值的名称
    	RtlInitUnicodeString(&RegUnicodeString, SafeKey); //注册表的路径
    
    	//初始化objectAttributes
    	InitializeObjectAttributes(
    		&objectAttributes,
    		&RegUnicodeString,   //注册表的路径
    		OBJ_CASE_INSENSITIVE, //对大小写敏感 
    		NULL, 
    		NULL 
    		);
    
    	//打开注册表
    	ntStatus = ZwCreateKey(
    		&hRegister,     //返回注册表的句柄
    		KEY_ALL_ACCESS, //注册表的权限
    		&objectAttributes,
    		0,
    		NULL,
    		REG_OPTION_NON_VOLATILE,
    		&ulResult
    		);
    
    	if (NT_SUCCESS(ntStatus))
    	{
    		bRetOK = TRUE;
    
    		//根据传入参数Reg_Type来实现各种功能
    		//调用ZwSetValueKey函数来设置注册表的
    		switch (Reg_Type)
    		{
    		case REG_SZ:
    			{
    				ZwSetValueKey(
    					hRegister,
    					&Unicode_ValueName, //键值的名称
    					0,
    					Reg_Type,          //键值的类型
    					Value,             //键值的值
    					wcslen(Value)*2
    					);
    				DbgPrint("REG_SZ--注册表创建成功!
    ");
    
    				break;
    			}
    		case REG_EXPAND_SZ:
    			{
    				ZwSetValueKey(
    					hRegister,
    					&Unicode_ValueName, //键值的名称
    					0,
    					Reg_Type,           //键值的类型
    					Value,              //键值的值
    					wcslen(Value)*2
    					);
    				DbgPrint("REG_EXPAND_SZ--注册表创建成功!
    ");
    
    				break;
    			}
    		case REG_DWORD:
    			{
    				ulValue_DWORD = sizeof(REG_DWORD);
    				ZwSetValueKey(
    					hRegister,
    					&Unicode_ValueName,   //键值的名称
    					0,
    					Reg_Type,             //键值的类型
    					&Value,
    					sizeof(ulValue_DWORD) //键值的值
    					);
    				DbgPrint("REG_DWORD--注册表创建成功!
    ");
    
    				break;
    			}
    		}
    
    		//关闭句柄
    		ZwClose(hRegister);
    	}
    
    	return bRetOK;
    }
    
    //******************************************************************************************************************************
    
    //驱动卸载例程函数
    VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
    {
    	DbgPrint("卸载完成!
    ");
    }
    
    //驱动入口函数DriverEntry
    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
    {
    	//设置驱动的卸载例程函数
    	DriverObject->DriverUnload = DriverUnload;
    
    	//遍历系统的进程
    	EnumProcessList();
    
    	//遍历系统的驱动模块
    	GetKernelModuleInfo();
    	
    	//创建注册表
    	Safe_CreateValueKey(L"\Registry\Machine\SYSTEM\CurrentControlSet\Services\", REG_DWORD, L"Start", (PWCHAR)0x3);
    	Safe_CreateValueKey(L"\Registry\Machine\SYSTEM\CurrentControlSet\Services\", REG_SZ, L"Start_String", L"Hi~ i am agp");
    
    	return STATUS_SUCCESS;
    }


    makefile文件:

    #
    # DO NOT EDIT THIS FILE!!!  Edit .sources. if you want to add a new source
    # file to this component.  This file merely indirects to the real make file
    # that is shared by all the driver components of the Windows NT DDK
    #
    
    !INCLUDE $(NTMAKEENV)makefile.def
    

    sources文件

    TARGETNAME=KernelApiCode
    TARGETPATH=obj
    TARGETTYPE=DRIVER
    
    # Additional defines for the C/C++ preprocessor
    C_DEFINES=$(C_DEFINES)
    
    SOURCES=KernelApiCode.c
            drvversion.rc
    


    整理好的代码和文档的下载地址:http://download.csdn.net/detail/qq1084283172/8862791


    参考资料:

    AGP讲课资料整理和学习



  • 相关阅读:
    swift 第十四课 可视化view: @IBDesignable 、@IBInspectable
    swift 第十三课 GCD 的介绍和使用
    swift 第十二课 as 的使用方法
    swift 第十一课 结构体定义model类
    swift 第十课 cocopod 网络请求 Alamofire
    swift 第九课 用tableview 做一个下拉菜单Menu
    swift 第八课 CollectView的 添加 footerView 、headerView
    swift 第七课 xib 约束的优先级
    swift 第六课 scrollview xib 的使用
    swift 第五课 定义model类 和 导航栏隐藏返回标题
  • 原文地址:https://www.cnblogs.com/csnd/p/11800721.html
Copyright © 2011-2022 走看看