海哥/火哥/周壑内核/麦洛科菲/科锐

麦洛科菲系统安全高级班

高质量C/C++编程指南 C语言中 “%z” 的使用;

//格式化描述符的安全性问题
//printf的安全性问题:栈上内存泄露,内存被修改(%n)
#include <stdio.h>
void MyPrint(char* buf)
{
    printf("%s\n",buf);
    printf(buf);
}

int main() {
    MyPrint((char*)"hello");
    printf("\n");
    MyPrint((char*)"%x");
    return 0;
}

main函数的问题

//先于main()执行
#include<stdio.h>
#include<windows.h>

int before_main1()
{
	printf("before_main1()\n");
	return 0;
}

int before_main2()
{
	printf("before_main2()\n");
	return 0;
}

int after_main()
{
	printf("after_main()\n");
	return 0;
}

typedef int func();

#pragma data_seg(".CRT$XIU")
static func* before1[] = { before_main1 };

#pragma data_seg(".CRT$XCU")
static func* before2[] = { before_main2 };

#pragma data_seg()

int main()
{
	_onexit(after_main);
	printf("helloworld\n");
	return 0;
}

sizeof 和函数的区别:使用 sizeof 在编译阶段就能确定,使用函数需要在运行阶段才能确定

//结构体对齐、栈对齐
//为啥要对齐:CPU读取数据更快
//指定对齐大小:#pragma pack(1)
typedef struct x
{
	char a;
	long b;
	char c;
	double d;
}x;

typedef struct y
{
	char a;
	char c;
	long b;
	double d;
}y;
int main()
{
	printf("%d\n", sizeof(x));
	printf("%d\n", sizeof(y));
	return 0;
}

内存寻址的三种模型

虚拟内存地址(VA)=装载地址(ImageBase)+节偏移+文件偏移地址
相对虚拟地址(RVA)=VA-ImageBase
VOffsetVA节起始地址相对与ImageBase的偏移量
ROffsetPointerToRawData节起始地址对于文件起始位置的偏移量

调用约定

thiscall是C++类成员函数缺省的调用约定,但它没有显示的声明形式。thiscall意味着
参数入栈:参数从右向左入栈
this指针入栈:如果参数个数确定,this指针通过ecx传递给被调用者;如果参数个数不确定,this指针在所有参数压栈后被压入堆栈
堆栈恢复:对参数个数不定的,调用者清理堆栈,否则函数自己清理堆栈。
x64与x86的fastcall的区别
1,比ecx(rcx),edx(rdx)寄存器多了2r8,r9
2,参数入栈,会对齐到8个字节
3,函数的前4个参数存放到了rcx,rdx,r8,r9四个寄存器中,但在栈上也会预留4个空间
4,调用者来负责栈的平衡

驱动开发环境搭建

//作业
1、计算一个整数的二进制中有多少个 1。如 10 的二进制为 1010,所以有 2  1
2、请设计一个函数,把十进制的正整数转化为三十六进制字符串。三十六进制的规则为 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ”。比如:1=0001”,10=000A”,20=000K”,35=000Z”,36=0010”;
3、判断一个平台是低位优先还是高位优先;
4、改变一个整数的存储方式 (0x12345678 0x78563412)
5、将一个字符串按照单词逆置,如”hello world world hello”;
6、将一个字符串,左旋 N 个字符。如左旋 3 个字符:”hello world lo worldhel”;
7、通过异或实现一个只带一个指针域的双向链表;
//1、计算一个整数的二进制中有多少个 1。如 10 的二进制为 1010,所以有 2 个 1。
//Brian Kernighan 算法
#include <stdio.h>

int countOnes(int num) {
    int count = 0;
    while (num) {
        num &= (num - 1);
        count++;
    }
    return count;
}

int main() {
    int number;
    printf("请输入一个整数: ");
    scanf("%d", &number);
    int result = countOnes(number);
    printf("该整数的二进制表示中有 %d 个1\n", result);
    return 0;
}
//2、请设计一个函数,把十进制的正整数转化为三十六进制字符串。
#include <stdio.h>
#include <string.h>

// 将十进制数转换为三十六进制字符串
void decimalToBase36(int decimal, char* result) {
    const char base36Digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int index = 3;
    result[4] = '\0';
    while (decimal > 0 && index >= 0) {
        result[index--] = base36Digits[decimal % 36];
        decimal /= 36;
    }
    while (index >= 0) {
        result[index--] = '0';
    }
}

int main() {
    int decimal;
    char result[5];
    printf("请输入一个十进制整数: ");
    if (scanf("%d", &decimal) != 1) {
        printf("输入错误,请输入一个有效的整数。\n");
        return 1;
    }
    decimalToBase36(decimal, result);
    printf("对应的4位定长三十六进制字符串为: %s\n", result);
    return 0;
}
//3、判断一个平台是低位优先还是高位优先;
#include <stdio.h>

int isLittleEndian() {
    int num = 1;
    return *((char*)&num);
}

int main() {
    if (isLittleEndian()) {
        printf("The platform is little - endian.\n");
    } else {
        printf("The platform is big - endian.\n");
    }
    return 0;
}
//4、改变一个整数的存储方式 (0x12345678 0x78563412);
#include <stdio.h>

unsigned int reverseBytes(unsigned int num) {
    return ((num & 0xFF000000) >> 24) | ((num & 0x00FF0000) >> 8) | ((num & 0x0000FF00) << 8) | ((num & 0x000000FF) << 24);
}

int main() {
    unsigned int num1 = 0x12345678;
    unsigned int num2 = 0x78563412;
    printf("Before reversing: 0x%X\n", num1);
    printf("After reversing: 0x%X\n", reverseBytes(num1));
    printf("Before reversing: 0x%X\n", num2);
    printf("After reversing: 0x%X\n", reverseBytes(num2));
    return 0;
}
//5、将一个字符串按照单词逆置,如”hello world” “world hello”;
#include <stdio.h>
#include <string.h>

void reverseWords(char* str) {
    int len = strlen(str);
    char temp[len + 1];
    int j = 0;
    for (int i = len - 1; i >= 0; i--) {
        if (str[i] =='') {
            for (int k = i + 1; k <= len - 1 && str[k]!=''; k++) {
                temp[j++] = str[k];
            }
            temp[j++] ='';
        }
        if (i == 0) {
            for (int k = 0; k <= len - 1 && str[k]!=''; k++) {
                temp[j++] = str[k];
            }
        }
    }
    temp[j] = '\0';
    strcpy(str, temp);
}

int main() {
    char str[] = "hello world";
    reverseWords(str);
    printf("%s\n", str);
    return 0;
}
//6、将一个字符串,左旋 N 个字符。如左旋 3 个字符:”hello world” “lo worldhel”;
#include <stdio.h>
#include <string.h>

void leftRotate(char* str, int n) {
    int len = strlen(str);
    n = n % len;
    char temp[n + 1];
    strncpy(temp, str, n);
    temp[n] = '\0';
    for (int i = 0; i < len - n; i++) {
        str[i] = str[i + n];
    }
    strcat(str, temp);
}

int main() {
    char str[] = "hello world";
    leftRotate(str, 3);
    printf("%s\n", str);
    return 0;
}
//7、通过异或实现一个只带一个指针域的双向链表;
#include <stdio.h>
#include <stdlib.h>

// 定义节点结构
typedef struct XorNode {
    int data;
    struct XorNode* ptr;
} XorNode;

// 辅助函数:获取两个指针的异或
XorNode* Xor(XorNode* a, XorNode* b) {
    return (XorNode*)((unsigned long)(a) ^ (unsigned long)(b));
}

// 创建新节点
XorNode* createNode(int data) {
    XorNode* newNode = (XorNode*)malloc(sizeof(XorNode));
    newNode->data = data;
    newNode->ptr = NULL;
    return newNode;
}

// 在头部插入节点
void insertAtHead(XorNode** head, int data) {
    XorNode* newNode = createNode(data);
    if (*head!= NULL) {
        newNode->ptr = Xor(*head, NULL);
        (*head)->ptr = Xor(Xor((*head)->ptr, NULL), newNode);
    }
    *head = newNode;
}

// 打印链表
void printList(XorNode* head) {
    XorNode* prev = NULL;
    XorNode* curr = head;
    XorNode* next;
    while (curr!= NULL) {
        printf("%d ", curr->data);
        next = Xor(prev, curr->ptr);
        prev = curr;
        curr = next;
    }
    printf("\n");
}

// 释放链表内存
void freeList(XorNode* head) {
    XorNode* prev = NULL;
    XorNode* curr = head;
    XorNode* next;
    while (curr!= NULL) {
        next = Xor(prev, curr->ptr);
        free(curr);
        prev = curr;
        curr = next;
    }
}

int main() {
    XorNode* head = NULL;
    insertAtHead(&head, 1);
    insertAtHead(&head, 2);
    insertAtHead(&head, 3);
    printList(head);
    freeList(head);
    return 0;
}

驱动框架

//框架
#include <ntddk.h>

#define DEVICE_NAME L"\\device\\ntmodeldrv"//设备名
#define LINK_NAME L"\\dosdevices\\ntmodeldrv"//符号链接

#define IOCTRL_BASE 0x800

#define MYIOCTRL_CODE(i) \
	CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTRL_BASE+i, METHOD_BUFFERED,FILE_ANY_ACCESS)

#define CTL_HELLO MYIOCTRL_CODE(0)
#define CTL_PRINT MYIOCTRL_CODE(1)
#define CTL_BYE MYIOCTRL_CODE(2)

NTSTATUS DispatchCommon(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS DispatchRead(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	PVOID pReadBuffer = NULL;
	ULONG uReadLength = 0;
	PIO_STACK_LOCATION pStack = NULL;
	ULONG uMin = 0;
	ULONG uHelloStr = 0;

	uHelloStr = (wcslen(L"hello world") + 1) * sizeof(WCHAR);

	//第一步,拿到缓存的地址和长度
	//从头部拿缓存地址
	pReadBuffer = pIrp->AssociatedIrp.SystemBuffer;
	//从栈上拿缓存长度
	pStack = IoGetCurrentIrpStackLocation(pIrp);
	uReadLength = pStack->Parameters.Read.Length;

	//第二步:读,写等操作
	uMin = uReadLength > uHelloStr ? uHelloStr : uReadLength;
	RtlCopyMemory(pReadBuffer, L"hello world", uMin);

	//第三步,完成IRP
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = uMin;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;

}

NTSTATUS DispatchWrite(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	PVOID pWriteBuff = NULL;
	ULONG uWriteLength = 0;
	PIO_STACK_LOCATION pStack = NULL;

	PVOID pBuffer = NULL;

	pWriteBuff = pIrp->AssociatedIrp.SystemBuffer;

	pStack = IoGetCurrentIrpStackLocation(pIrp);
	uWriteLength = pStack->Parameters.Write.Length;

	pBuffer = ExAllocatePoolWithTag(PagedPool, uWriteLength, 'TSET');
	if (pBuffer == NULL)
	{
		pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
		pIrp->IoStatus.Information = 0;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	memset(pBuffer, 0, uWriteLength);

	RtlCopyMemory(pBuffer, pWriteBuff, uWriteLength);

	ExFreePool(pBuffer);
	pBuffer = NULL;


	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = uWriteLength;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;

}

NTSTATUS DispatchIoctrl(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	ULONG uIoctrlCode = 0;
	PVOID pInputBuff = NULL;
	PVOID pOutputBuff = NULL;

	ULONG uInputLength = 0;
	ULONG uOutputLength = 0;
	PIO_STACK_LOCATION pStack = NULL;

	pInputBuff = pOutputBuff = pIrp->AssociatedIrp.SystemBuffer;

	pStack = IoGetCurrentIrpStackLocation(pIrp);
	uInputLength = pStack->Parameters.DeviceIoControl.InputBufferLength;
	uOutputLength = pStack->Parameters.DeviceIoControl.OutputBufferLength;


	uIoctrlCode = pStack->Parameters.DeviceIoControl.IoControlCode;

	switch (uIoctrlCode)
	{
	case CTL_HELLO:
		DbgPrint("Hello iocontrol\n");
		break;
	case CTL_PRINT:
		DbgPrint("%ws\n", pInputBuff);
		break;
	case CTL_BYE:
		DbgPrint("Goodbye iocontrol\n");
		break;
	default:
		DbgPrint("Unknown iocontrol\n");

	}

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;

}

NTSTATUS DispatchClean(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS DispatchClose(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}


VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	UNICODE_STRING uLinkName = { 0 };
	RtlInitUnicodeString(&uLinkName, LINK_NAME);
	IoDeleteSymbolicLink(&uLinkName);

	IoDeleteDevice(pDriverObject->DeviceObject);

	DbgPrint("Driver unloaded\n");

}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
	PUNICODE_STRING pRegPath)
{
	UNICODE_STRING uDeviceName = { 0 };
	UNICODE_STRING uLinkName = { 0 };
	NTSTATUS ntStatus = 0;
	PDEVICE_OBJECT pDeviceObject = NULL;
	ULONG i = 0;

	DbgPrint("Driver load begin\n");

	RtlInitUnicodeString(&uDeviceName, DEVICE_NAME);
	RtlInitUnicodeString(&uLinkName, LINK_NAME);

	RtlInitUnicodeString(&uDeviceName,DEVICE_NAME);
	RtlInitUnicodeString(&uLinkName,LINK_NAME);


	IoCreateDevice(pDriverObject,0,&uDeviceName,FILE_DEVICE_UNKNOWN,0,FALSE,&pDeviceObject);


	ntStatus = IoCreateDevice(pDriverObject,
		0, &uDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);

	if (!NT_SUCCESS(ntStatus))
	{
		DbgPrint("IoCreateDevice failed:%x", ntStatus);
		return ntStatus;
	}

	//DO_BUFFERED_IO规定R3和R0之间read和write通信的方式:
	//1,buffered io
	//2,direct io
	//3,neither io
	pDeviceObject->Flags |= DO_BUFFERED_IO;

	ntStatus = IoCreateSymbolicLink(&uLinkName, &uDeviceName);
	if (!NT_SUCCESS(ntStatus))
	{
		IoDeleteDevice(pDeviceObject);
		DbgPrint("IoCreateSymbolicLink failed:%x\n", ntStatus);
		return ntStatus;
	}

	for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION + 1; i++)
	{
		pDriverObject->MajorFunction[i] = DispatchCommon;
	}

	pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
	pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctrl;
	pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchClean;
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;

	pDriverObject->DriverUnload = DriverUnload;

	DbgPrint("Driver load ok!\n");

	return STATUS_SUCCESS;
}
#include <windows.h>  
#include <winsvc.h>  
#include <conio.h>  
#include <stdio.h>
#include <winioctl.h>

#define DRIVER_NAME "ntmodeldrv"
#define DRIVER_PATH ".\\ntmodeldrv.sys"

#define IOCTRL_BASE 0x800

#define MYIOCTRL_CODE(i) \
	CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTRL_BASE+i, METHOD_BUFFERED,FILE_ANY_ACCESS)

#define CTL_HELLO MYIOCTRL_CODE(0)
#define CTL_PRINT MYIOCTRL_CODE(1)
#define CTL_BYE MYIOCTRL_CODE(2)

//装载NT驱动程序
BOOL LoadDriver(char* lpszDriverName,char* lpszDriverPath)
{
	//char szDriverImagePath[256] = "D:\\DriverTest\\ntmodelDrv.sys";
 	char szDriverImagePath[256] = {0};
 	//得到完整的驱动路径
 	GetFullPathName(lpszDriverPath, 256, szDriverImagePath, NULL);

	BOOL bRet = FALSE;

	SC_HANDLE hServiceMgr=NULL;//SCM管理器的句柄
	SC_HANDLE hServiceDDK=NULL;//NT驱动程序的服务句柄

	//打开服务控制管理器
	hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );

	if( hServiceMgr == NULL )  
	{
		//OpenSCManager失败
		printf( "OpenSCManager() Failed %d ! \n", GetLastError() );
		bRet = FALSE;
		goto BeforeLeave;
	}
	else
	{
		////OpenSCManager成功
		printf( "OpenSCManager() ok ! \n" );  
	}

	//创建驱动所对应的服务
	hServiceDDK = CreateService( hServiceMgr,
		lpszDriverName, //驱动程序的在注册表中的名字  
		lpszDriverName, // 注册表驱动程序的 DisplayName 值  
		SERVICE_ALL_ACCESS, // 加载驱动程序的访问权限  
		SERVICE_KERNEL_DRIVER,// 表示加载的服务是驱动程序  
		SERVICE_DEMAND_START, // 注册表驱动程序的 Start 值  
		SERVICE_ERROR_IGNORE, // 注册表驱动程序的 ErrorControl 值  
		szDriverImagePath, // 注册表驱动程序的 ImagePath 值  
		NULL,  //GroupOrder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList
		NULL,  
		NULL,  
		NULL,  
		NULL);  

	DWORD dwRtn;
	//判断服务是否失败
	if( hServiceDDK == NULL )  
	{  
		dwRtn = GetLastError();
		if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS )  
		{  
			//由于其他原因创建服务失败
			printf( "CrateService() Failed %d ! \n", dwRtn );  
			bRet = FALSE;
			goto BeforeLeave;
		}  
		else  
		{
			//服务创建失败,是由于服务已经创立过
			printf( "CrateService() Failed Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS! \n" );  
		}

		// 驱动程序已经加载,只需要打开  
		hServiceDDK = OpenService( hServiceMgr, lpszDriverName, SERVICE_ALL_ACCESS );  
		if( hServiceDDK == NULL )  
		{
			//如果打开服务也失败,则意味错误
			dwRtn = GetLastError();  
			printf( "OpenService() Failed %d ! \n", dwRtn );  
			bRet = FALSE;
			goto BeforeLeave;
		}  
		else 
		{
			printf( "OpenService() ok ! \n" );
		}
	}  
	else  
	{
		printf( "CrateService() ok ! \n" );
	}

	//开启此项服务
	bRet= StartService( hServiceDDK, NULL, NULL );  
	if( !bRet )  
	{  
		DWORD dwRtn = GetLastError();  
		if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING )  
		{  
			printf( "StartService() Failed %d ! \n", dwRtn );  
			bRet = FALSE;
			goto BeforeLeave;
		}  
		else  
		{  
			if( dwRtn == ERROR_IO_PENDING )  
			{  
				//设备被挂住
				printf( "StartService() Failed ERROR_IO_PENDING ! \n");
				bRet = FALSE;
				goto BeforeLeave;
			}  
			else  
			{  
				//服务已经开启
				printf( "StartService() Failed ERROR_SERVICE_ALREADY_RUNNING ! \n");
				bRet = TRUE;
				goto BeforeLeave;
			}  
		}  
	}
	bRet = TRUE;
//离开前关闭句柄
BeforeLeave:
	if(hServiceDDK)
	{
		CloseServiceHandle(hServiceDDK);
	}
	if(hServiceMgr)
	{
		CloseServiceHandle(hServiceMgr);
	}
	return bRet;
}

//卸载驱动程序  
BOOL UnloadDriver( char * szSvrName )  
{
	BOOL bRet = FALSE;
	SC_HANDLE hServiceMgr=NULL;//SCM管理器的句柄
	SC_HANDLE hServiceDDK=NULL;//NT驱动程序的服务句柄
	SERVICE_STATUS SvrSta;
	//打开SCM管理器
	hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );  
	if( hServiceMgr == NULL )  
	{
		//带开SCM管理器失败
		printf( "OpenSCManager() Failed %d ! \n", GetLastError() );  
		bRet = FALSE;
		goto BeforeLeave;
	}  
	else  
	{
		//带开SCM管理器失败成功
		printf( "OpenSCManager() ok ! \n" );  
	}
	//打开驱动所对应的服务
	hServiceDDK = OpenService( hServiceMgr, szSvrName, SERVICE_ALL_ACCESS );  

	if( hServiceDDK == NULL )  
	{
		//打开驱动所对应的服务失败
		printf( "OpenService() Failed %d ! \n", GetLastError() );  
		bRet = FALSE;
		goto BeforeLeave;
	}  
	else  
	{  
		printf( "OpenService() ok ! \n" );  
	}  
	//停止驱动程序,如果停止失败,只有重新启动才能,再动态加载。  
	if( !ControlService( hServiceDDK, SERVICE_CONTROL_STOP , &SvrSta ) )  
	{  
		printf( "ControlService() Failed %d !\n", GetLastError() );  
	}  
	else  
	{
		//打开驱动所对应的失败
		printf( "ControlService() ok !\n" );  
	} 
	

	//动态卸载驱动程序。  

	if( !DeleteService( hServiceDDK ) )  
	{
		//卸载失败
		printf( "DeleteSrevice() Failed %d !\n", GetLastError() );  
	}  
	else  
	{  
		//卸载成功
		printf( "DelServer:deleteSrevice() ok !\n" );  
	}  

	bRet = TRUE;
BeforeLeave:
//离开前关闭打开的句柄
	if(hServiceDDK)
	{
		CloseServiceHandle(hServiceDDK);
	}
	if(hServiceMgr)
	{
		CloseServiceHandle(hServiceMgr);
	}
	return bRet;	
} 

void TestDriver()
{
	//测试驱动程序  
	HANDLE hDevice = CreateFile("\\\\.\\NTmodeldrv",  
		GENERIC_WRITE | GENERIC_READ,  
		0,  
		NULL,  
		OPEN_EXISTING,  
		0,  
		NULL);  
	if( hDevice != INVALID_HANDLE_VALUE )  
	{
		printf( "Create Device ok ! \n" );  
	}
	else  
	{
		printf( "Create Device Failed %d ! \n", GetLastError() ); 
		return;
	}
	CHAR bufRead[1024]={0};
	WCHAR bufWrite[1024]=L"Hello, world";

	DWORD dwRead = 0;
	DWORD dwWrite = 0;

	ReadFile(hDevice, bufRead, 1024, &dwRead, NULL);
	printf("Read done!:%ws\n",bufRead);
	printf("Please press any key to write\n");
	getch();
	WriteFile(hDevice, bufWrite, (wcslen(bufWrite)+1)*sizeof(WCHAR), &dwWrite, NULL);

	printf("Write done!\n");

	printf("Please press any key to deviceiocontrol\n");
	getch();
	CHAR bufInput[1024] ="Hello, world";
	CHAR bufOutput[1024] = {0};
	DWORD dwRet = 0;

	WCHAR bufFileInput[1024] =L"c:\\docs\\hi.txt";

	printf("Please press any key to send PRINT\n");
	getch();
	DeviceIoControl(hDevice, 
		CTL_PRINT, 
		bufFileInput, 
		sizeof(bufFileInput), 
		bufOutput, 
		sizeof(bufOutput), 
		&dwRet, 
		NULL);
	printf("Please press any key to send HELLO\n");
	getch();
	DeviceIoControl(hDevice, 
		CTL_HELLO, 
		NULL, 
		0, 
		NULL, 
		0, 
		&dwRet, 
		NULL);
	printf("Please press any key to send BYE\n");
	getch();
	DeviceIoControl(hDevice, 
		CTL_BYE, 
		NULL, 
		0, 
		NULL, 
		0, 
		&dwRet, 
		NULL);
	printf("DeviceIoControl done!\n");
	CloseHandle( hDevice );
} 

int main(int argc, char* argv[])  
{
	//加载驱动
	BOOL bRet = LoadDriver(DRIVER_NAME,DRIVER_PATH);
	if (!bRet)
	{
		printf("LoadNTDriver error\n");
		return 0;
	}
	//加载成功

	printf( "press any key to create device!\n" );  
	getch();  

	TestDriver();

	//这时候你可以通过注册表,或其他查看符号连接的软件验证。  
	printf( "press any key to stop service!\n" );  
	getch();  

	//卸载驱动
	bRet = UnloadDriver(DRIVER_NAME);
	if (!bRet)
	{
		printf("UnloadNTDriver error\n");
		return 0;
	}
	return 0;  
}

查看SSDT 查看shadowSSDT 反调试

//反反调试
反反调试的思路也就出来了。针对清零DebugPort来防止调试的方法,可以通过对DebugPort内存地址下内存断点
ba w4 debugport_addr
这样一旦有程序代码在修改DebugPort,就会被断下,从而找到对应的清零DebugPort的反调试代码,然后对这部分代码进行patch(用机器码0x90(nop)或者0xC3(ret)取代),从而让它失去作用,当然有的程序会对代码进行校验,一旦发现代码被篡改,就会采取保护措施,比如抛出异常或者退出程序。
针对调用系统函数如KdDisableDebugger()来检测调试器存在从而禁止被调试的方法,可以在对应的这些函数的地址下断点,然后对相关的代码进行patch,然后使该函数判断失效。比如:
bp KdDisableDebuggereb  xxx
针对通过HOOK系统函数来防止进程被调试的方法,可以直接将这些系统函数的钩子直接恢复,可以通过内核驱动程序或者借助一些ARK工具(比如Pchunter)就可以直接检测和恢复这些函数钩子。

花指令 系统引导

//强删文件
#include <ntddk.h>
#include <ntimage.h>
#include <ntdef.h>
#include "DelFile.h"


PDEVICE_OBJECT	g_HookDevice;

NTSTATUS dfQuerySymbolicLink(
	IN PUNICODE_STRING SymbolicLinkName,
	OUT PUNICODE_STRING LinkTarget
	)                                  
{
    OBJECT_ATTRIBUTES oa;
    NTSTATUS status;
    HANDLE handle;
   
    InitializeObjectAttributes(
		&oa, 
		SymbolicLinkName,
		OBJ_CASE_INSENSITIVE,
        0, 
		0);
   
    status = ZwOpenSymbolicLinkObject(&handle, GENERIC_READ, &oa);
    if (!NT_SUCCESS(status))
    {
        return status;
    }
   
    LinkTarget->MaximumLength = 1024*sizeof(WCHAR);
    LinkTarget->Length = 0;
    LinkTarget->Buffer = ExAllocatePoolWithTag(PagedPool, LinkTarget->MaximumLength, 'A0');
    if (!LinkTarget->Buffer)
    {
        ZwClose(handle);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(LinkTarget->Buffer, LinkTarget->MaximumLength);
   
    status = ZwQuerySymbolicLinkObject(handle, LinkTarget, NULL);
    ZwClose(handle);
   
    if (!NT_SUCCESS(status))
    {
        ExFreePool(LinkTarget->Buffer);
    }
   
    return status;
}

BOOLEAN dfCloseFileHandle(WCHAR *name)
{
	
	NTSTATUS					 status;
	PVOID						 buf   = NULL;
	PSYSTEM_HANDLE_INFORMATION 	 pSysHandleInfo;
	SYSTEM_HANDLE_TABLE_ENTRY_INFO handleTEI;

	ULONG						size  = 1;
	ULONG						NumOfHandle = 0;
	ULONG						i;
	CLIENT_ID 					cid;
	HANDLE						hHandle;
	HANDLE						hProcess;
	HANDLE 						hDupObj;
	HANDLE						hFile;
	HANDLE						link_handle;
	OBJECT_ATTRIBUTES 			oa;
	ULONG						FileType; 
	ULONG						processID;
	UNICODE_STRING 				uLinkName;
	UNICODE_STRING				uLink;
	OBJECT_ATTRIBUTES 			objectAttributes;
	IO_STATUS_BLOCK 		 	IoStatus;
	ULONG 						ulRet;
    PVOID    			 		fileObject;
	POBJECT_NAME_INFORMATION 	pObjName;
	UNICODE_STRING				delFileName = {0};
	int							length;
	WCHAR						wVolumeLetter[3];
	WCHAR						*pFilePath;
	UNICODE_STRING				uVolume;
	UNICODE_STRING				uFilePath;
	UNICODE_STRING 				NullString = RTL_CONSTANT_STRING(L"");
	BOOLEAN					bRet = FALSE;


	for ( size = 1; ; size *= 2 )
	{
		if ( NULL == ( buf = ExAllocatePoolWithTag(NonPagedPool,size, 'FILE') ) )
		{
			DbgPrint(("alloc mem failed\n"));
			goto Exit;
		}
		RtlZeroMemory( buf ,size );
		status = ZwQuerySystemInformation( SystemHandleInformation, buf, size, NULL );
		if ( !NT_SUCCESS( status ) )
		{
			if ( STATUS_INFO_LENGTH_MISMATCH == status )
			{
				ExFreePool( buf );
				buf = NULL;
			}
			else
			{
				DbgPrint(( "ZwQuerySystemInformation() failed"));
				goto Exit;
			}
		}
		else
		{
			break;
		}
	}

	pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)buf;
	NumOfHandle = pSysHandleInfo->NumberOfHandles;

	

	/* Get the volume character like C: */
	//\??\c:\haha.doc-->\device\harddiskvolume3\haha.doc

	wVolumeLetter[0] = name[4];
	wVolumeLetter[1] = name[5];
	wVolumeLetter[2] = 0;
	uLinkName.Buffer = ExAllocatePoolWithTag(NonPagedPool, 256 + sizeof(ULONG), 'A1');
	uLinkName.MaximumLength = 256;
	RtlInitUnicodeString(&uVolume, wVolumeLetter);
	RtlInitUnicodeString( &uLink, L"\\DosDevices\\");
	RtlCopyUnicodeString(&uLinkName, &uLink);
	
	status = RtlAppendUnicodeStringToString(&uLinkName, &uVolume);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("RtlAppendUnicodeStringToString() failed"));
		return FALSE;
	}
	
	dfQuerySymbolicLink(&uLinkName, &delFileName);
	RtlFreeUnicodeString(&uLinkName);
	KdPrint(("delFileName:%wZ", &delFileName));

	pFilePath = (WCHAR *) &name[6];
	RtlInitUnicodeString( &uFilePath, pFilePath);

	RtlAppendUnicodeStringToString(&delFileName, &uFilePath);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("RtlAppendUnicodeStringToString() failed"));
		return FALSE;
	}

	KdPrint(("delFile:%wZ", &delFileName));

	for(i = 0; i < NumOfHandle ;i++)
	{
		handleTEI = pSysHandleInfo->Handles[i];
		if (handleTEI.ObjectTypeIndex != 25 && handleTEI.ObjectTypeIndex != 28)//28文件,25设备对象
			continue;
		processID = (ULONG) handleTEI.UniqueProcessId;
		cid.UniqueProcess = (HANDLE)processID;
		cid.UniqueThread = (HANDLE)0;
		hHandle = (HANDLE)handleTEI.HandleValue;
		InitializeObjectAttributes( &oa ,NULL ,0 ,NULL ,NULL );
		status = ZwOpenProcess( &hProcess ,PROCESS_DUP_HANDLE ,&oa ,&cid );
		if ( !NT_SUCCESS( status ) )
		{
			KdPrint(( "ZwOpenProcess:%d Fail ", processID));
			continue;
		}

		status = ZwDuplicateObject( hProcess ,hHandle ,NtCurrentProcess() ,&hDupObj ,\
		 PROCESS_ALL_ACCESS ,0 ,DUPLICATE_SAME_ACCESS );
		if ( !NT_SUCCESS( status ) )
		{
			DbgPrint(( "ZwDuplicateObject1 : Fail " ));
			continue;
		}
		status = ObReferenceObjectByHandle(
			  hDupObj,
			  FILE_ANY_ACCESS,
			  0,
			  KernelMode,
			  &fileObject,
			  NULL);
		
		if (!NT_SUCCESS(status))
		{
			DbgPrint(( "ObReferenceObjectByHandle : Fail " ));
			continue;
		}  

		pObjName = (POBJECT_NAME_INFORMATION) ExAllocatePoolWithTag(NonPagedPool, \
		    sizeof (OBJECT_NAME_INFORMATION) + 1024 * sizeof (WCHAR), 'A1');

		if (STATUS_SUCCESS != (status = ObQueryNameString(fileObject, pObjName, \
		    sizeof (OBJECT_NAME_INFORMATION) + 1024 * sizeof (WCHAR), &ulRet)))
		{
		   ObDereferenceObject(fileObject);
		   continue;
		}
		if (RtlCompareUnicodeString(&pObjName->Name, &delFileName, TRUE) == 0)
		{

			ObDereferenceObject(fileObject);
			ZwClose(hDupObj);

			status = ZwDuplicateObject( hProcess ,hHandle ,NtCurrentProcess() ,&hDupObj ,\
			 PROCESS_ALL_ACCESS ,0 ,DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE );
			if ( !NT_SUCCESS( status ) )
			{
				DbgPrint(( "ZwDuplicateObject2 : Fail " ));
				//return FALSE;
			}
			else
			{
				ZwClose(hDupObj);
				bRet = TRUE;
				//return TRUE;
			}
			break;

		}
			
		ExFreePool(pObjName);
		pObjName = NULL;

		ObDereferenceObject(fileObject);
		ZwClose( hDupObj );
		ZwClose( hProcess );

	}

Exit:
	if (pObjName != NULL)
	{
		ExFreePool(pObjName);
		pObjName = NULL;
	}
	if (delFileName.Buffer != NULL)
	{
		ExFreePool(delFileName.Buffer);	
	}
	if ( buf != NULL )
	{
		ExFreePool( buf );
		buf = NULL;
	}
	return(bRet);

}

NTSTATUS
dfOpenFile(WCHAR* name,PHANDLE phFileHandle, ACCESS_MASK access,ULONG share)
{

   IO_STATUS_BLOCK iosb;
   NTSTATUS stat;
   OBJECT_ATTRIBUTES oba;
   UNICODE_STRING nameus;

   if(KeGetCurrentIrql()>PASSIVE_LEVEL){return 0;}
   RtlInitUnicodeString(&nameus,name);
   InitializeObjectAttributes(
		&oba,
		&nameus,
		OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,
		0,
		0);
   stat=IoCreateFile(
		phFileHandle,
		access,
		&oba,
		&iosb,
		0,
		FILE_ATTRIBUTE_NORMAL,
		share,
		FILE_OPEN,
		0,
		NULL,
		0,
		0,
		NULL,
		IO_NO_PARAMETER_CHECKING);

	return stat;
}

NTSTATUS
dfSkillSetFileCompletion(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    )
{
    Irp->UserIosb->Status = Irp->IoStatus.Status;
    Irp->UserIosb->Information = Irp->IoStatus.Information;

    KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE);

    IoFreeIrp(Irp);

    return STATUS_MORE_PROCESSING_REQUIRED;
}
BOOLEAN dfDelFile(WCHAR* name)
{
    NTSTATUS        ntStatus = STATUS_SUCCESS;
    PFILE_OBJECT    fileObject;
    PDEVICE_OBJECT  DeviceObject;
    PIRP            Irp;
    KEVENT          event;
    FILE_DISPOSITION_INFORMATION  FileInformation;
    IO_STATUS_BLOCK ioStatus;
    PIO_STACK_LOCATION irpSp;
    PSECTION_OBJECT_POINTERS pSectionObjectPointer;
    HANDLE handle;

    ntStatus = dfOpenFile(name, &handle, FILE_READ_ATTRIBUTES|DELETE,FILE_SHARE_DELETE);
	if (ntStatus == STATUS_OBJECT_NAME_NOT_FOUND ||
		ntStatus == STATUS_OBJECT_PATH_NOT_FOUND )
	{
		KdPrint(("No such file"));
		return FALSE;
	}
	else if (!NT_SUCCESS(ntStatus))
	{
		if (dfCloseFileHandle(name))//遍历全局句柄表,关闭独占打开的句柄
		{
			ntStatus = dfOpenFile(name, &handle, FILE_READ_ATTRIBUTES|DELETE,FILE_SHARE_DELETE);
			if (!NT_SUCCESS(ntStatus))
				return FALSE;
		}
		else
		{
			return FALSE;
		}
	}

    ntStatus = ObReferenceObjectByHandle(handle,
        DELETE,
        *IoFileObjectType,
        KernelMode,
        &fileObject,
        NULL);

    if (!NT_SUCCESS(ntStatus))
    {
    	DbgPrint("ObReferenceObjectByHandle()");
		ZwClose(handle);
        return FALSE;
    }  

    DeviceObject = IoGetRelatedDeviceObject(fileObject);
    Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);

    if (Irp == NULL)
    {
        ObDereferenceObject(fileObject);
		ZwClose(handle);
        return FALSE;
    }

    KeInitializeEvent(&event, SynchronizationEvent, FALSE);
   
    FileInformation.DeleteFile = TRUE;

    Irp->AssociatedIrp.SystemBuffer = &FileInformation;
    Irp->UserEvent = &event;
    Irp->UserIosb = &ioStatus;
    Irp->Tail.Overlay.OriginalFileObject = fileObject;
    Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
    Irp->RequestorMode = KernelMode;
   
    irpSp = IoGetNextIrpStackLocation(Irp);
    irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
    irpSp->DeviceObject = DeviceObject;
    irpSp->FileObject = fileObject;
    irpSp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);
    irpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;
    irpSp->Parameters.SetFile.FileObject = fileObject;

    IoSetCompletionRoutine(
            Irp,
            dfSkillSetFileCompletion,
            &event,
            TRUE,
            TRUE,
            TRUE);
			
	//删除正在运行中的exe所做的处理
    pSectionObjectPointer = fileObject->SectionObjectPointer;
    if(pSectionObjectPointer)
	{
		pSectionObjectPointer->ImageSectionObject = 0;
		pSectionObjectPointer->DataSectionObject = 0;
	}
    ntStatus = IoCallDriver(DeviceObject, Irp); 
    if (!NT_SUCCESS(ntStatus))
    {
    	 ObDereferenceObject(fileObject);
		 ZwClose(handle);
         return FALSE;
    }  

    KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL);
	//IoFreeIrp(Irp);
    ObDereferenceObject(fileObject);
    ZwClose(handle);
    return TRUE;

}


NTSTATUS OnUnload(IN PDRIVER_OBJECT DriverObject)
{
	UNICODE_STRING          deviceLinkUnicodeString;
	PDEVICE_OBJECT	   p_NextObj;


	DbgPrint("OnUnload called\n");

	p_NextObj = DriverObject->DeviceObject;

	if (p_NextObj != NULL)
	{

		RtlInitUnicodeString( &deviceLinkUnicodeString, deviceLinkBuffer );
		IoDeleteSymbolicLink( &deviceLinkUnicodeString );

		IoDeleteDevice( DriverObject->DeviceObject );
	}
	return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	NTSTATUS                ntStatus;
	UNICODE_STRING          deviceNameUnicodeString;
    UNICODE_STRING          deviceLinkUnicodeString;

	RtlInitUnicodeString (&deviceNameUnicodeString,
	    deviceNameBuffer );
	RtlInitUnicodeString (&deviceLinkUnicodeString,
	    deviceLinkBuffer );

	ntStatus = IoCreateDevice ( DriverObject,
	    0,
	    &deviceNameUnicodeString,
	    FILE_DEVICE_SWAP,
	    0,
	    TRUE,
	    &g_HookDevice );

	if(! NT_SUCCESS(ntStatus))
	{
	      DbgPrint(("Failed to create device!\n"));
	      return ntStatus;
	 }

	/* We test the DelFile() function here */	
	if (dfDelFile(L"\\??\\c:\\haha.doc"))
	{
		KdPrint(("Deleted"));
	}
	else
	{
		KdPrint(("Failed"));
	}
	if (dfDelFile(L"\\??\\c:\\filedelet.exe"))
	{
		KdPrint(("Deleted"));
	}
	else
	{
		KdPrint(("Failed"));
	}

	ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
	    &deviceNameUnicodeString );
	if(! NT_SUCCESS(ntStatus)) 
	{
		 IoDeleteDevice(DriverObject->DeviceObject);
	        DbgPrint("Failed to create symbolic link!\n");
	        return ntStatus;
	 }

	DriverObject->DriverUnload  = OnUnload;
	return STATUS_SUCCESS;
}

IRQL 中断请求级别 线程 多线程 强杀进程

#include <ntddk.h>
#include <ntimage.h>
#include <ntdef.h>
#include "Ioctlcmd.h"

const WCHAR deviceLinkBuffer[]  = L"\\DosDevices\\KillProc";
const WCHAR deviceNameBuffer[]  = L"\\Device\\KillProc";

typedef NTSTATUS (*NTQUERYSYSTEMINFORMATION)(
		
		IN ULONG                        SystemInformationClass,
		OUT PVOID                        SystemInformation,
		IN ULONG                        SystemInformationLength,
		OUT PULONG                        ReturnLength OPTIONAL  );
typedef unsigned long DWORD;	
NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;
#define	SystemModuleInformation	11	
typedef struct _SYSTEM_MODULE_INFORMATION
{
		ULONG  Reserved[2];
		PVOID  Base;
		ULONG  Size;
		ULONG  Flags;
		USHORT Index;
		USHORT Unknown;
		USHORT LoadCount;
		USHORT ModuleNameOffset;
		CHAR   ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

PDEVICE_OBJECT g_HookDevice;
NTSTATUS  PsLookupProcessByProcessId(ULONG ProcessId,PEPROCESS *Process);

typedef  NTSTATUS  (*PSPTERPROC) ( PEPROCESS Process, NTSTATUS ExitStatus );
PSPTERPROC MyPspTerminateProcess = NULL ;


NTSTATUS OnUnload(IN PDRIVER_OBJECT DriverObject)
{
	UNICODE_STRING          deviceLinkUnicodeString;
	PDEVICE_OBJECT	   p_NextObj;


	DbgPrint("OnUnload called\n");

	p_NextObj = DriverObject->DeviceObject;

	if (p_NextObj != NULL)
	{

		RtlInitUnicodeString( &deviceLinkUnicodeString, deviceLinkBuffer );
		IoDeleteSymbolicLink( &deviceLinkUnicodeString );

		IoDeleteDevice( DriverObject->DeviceObject );
	}
	return STATUS_SUCCESS;
}

NTSTATUS 
DispatchControl(
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp)
{
    PIO_STACK_LOCATION      irpStack;
    PVOID                   inputBuffer;
    PVOID                   outputBuffer;
    PVOID			     userBuffer;
    ULONG                   inputBufferLength;
    ULONG                   outputBufferLength;
    ULONG                   ioControlCode;
    NTSTATUS		     ntstatus;

    unsigned int i;

    unsigned total = 0;
    ULONG count = 0;

    HANDLE handle;


    ULONG cnt;

    PEPROCESS Eprocess = NULL;
    DWORD pid;


    ntstatus = Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    irpStack = IoGetCurrentIrpStackLocation (Irp);

    inputBuffer             = Irp->AssociatedIrp.SystemBuffer;
    inputBufferLength       = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outputBuffer            = Irp->AssociatedIrp.SystemBuffer;
    outputBufferLength      = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
    ioControlCode           = irpStack->Parameters.DeviceIoControl.IoControlCode;

    
    
    switch (irpStack->MajorFunction)
   {
    case IRP_MJ_CREATE:
        break;

    case IRP_MJ_SHUTDOWN:
        break;

    case IRP_MJ_CLOSE:
        break;

    case IRP_MJ_DEVICE_CONTROL:

        if(IOCTL_TRANSFER_TYPE(ioControlCode) == METHOD_NEITHER) 
	{
            outputBuffer = Irp->UserBuffer;
        }

        
	switch (ioControlCode ) 
	{

	case IOCTL_PROC_KILL:
				if(MyPspTerminateProcess==NULL)
				{
					*(DWORD*)outputBuffer = -1;
					Irp->IoStatus.Information = sizeof(DWORD);
				}
				else
				{
					pid = *(DWORD*)inputBuffer;
					{
						
						ntstatus = PsLookupProcessByProcessId(pid , &Eprocess);
						if(!NT_SUCCESS(ntstatus))
						{
							DbgPrint("Failed to lookup process 0x%x, status %8.8x\n", pid , ntstatus);
							*(DWORD*)outputBuffer = 1;
							Irp->IoStatus.Information = sizeof(DWORD);
							break;
						}
						DbgPrint("Lookup of process 0x%x, PEPROCESS at %8.8x\n", pid, Eprocess);
						ntstatus = MyPspTerminateProcess(Eprocess, 0);
						if(!NT_SUCCESS(ntstatus))
						{
							DbgPrint("Failed to terminate process 0x%x, status %8.8x\n", pid, ntstatus);
							*(DWORD*)outputBuffer = 2;
							Irp->IoStatus.Information = sizeof(DWORD);
							break;
						}
						*(DWORD*)outputBuffer = 0;
						Irp->IoStatus.Information = sizeof(DWORD);
						DbgPrint("Process 0x%x terminated\n", pid);
					}
				}
				break;
					
      
	default:
			break;
    	}
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
     
    }
    return ntstatus;  
}

NTSTATUS DispatchCreate (
		IN PDEVICE_OBJECT	pDevObj,
		IN PIRP		pIrp)
{

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
	return STATUS_SUCCESS;
}

ULONG GetFunctionAddr( IN PCWSTR FunctionName)
	{
		UNICODE_STRING UniCodeFunctionName;
		
		RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
		return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );    
		
	}

VOID DoFind(IN PVOID pContext)
	{
		NTSTATUS ret;
		PSYSTEM_MODULE_INFORMATION  module = NULL;
		ULONG n=0;
		void  *buf    = NULL;
		ULONG ntosknlBase;
		ULONG ntosknlEndAddr;
		ULONG curAddr;
		ULONG code1_sp3=0x8b55ff8b,code2_sp3=0xA16456EC,code3_sp3=0x00000124,code4_sp3=0x3B08758B;
		ULONG i;
		
		NtQuerySystemInformation=(NTQUERYSYSTEMINFORMATION)GetFunctionAddr(L"NtQuerySystemInformation");
		if (!NtQuerySystemInformation) 
		{
			DbgPrint("Find NtQuerySystemInformation faild!");
			goto Ret;
		}
		ret=NtQuerySystemInformation(SystemModuleInformation,&n,0,&n);
		if (NULL==( buf=ExAllocatePoolWithTag(NonPagedPool, n, 'DFSP')))
		{
			DbgPrint("ExAllocatePool() failed\n" );
			goto Ret;
		}
		ret=NtQuerySystemInformation(SystemModuleInformation,buf,n,NULL);
		if (!NT_SUCCESS(ret))	{
			DbgPrint("NtQuerySystemInformation faild!");
			goto Ret;
		} 
		module=(PSYSTEM_MODULE_INFORMATION)((PULONG)buf+1);
		ntosknlEndAddr=(ULONG)module->Base+(ULONG)module->Size;
		ntosknlBase=(ULONG)module->Base;
		curAddr=ntosknlBase;
		ExFreePool(buf);
		for (i=curAddr;i<=ntosknlEndAddr;i++)
		{
				if (*((ULONG *)i)==code1_sp3) 
				{
					if (*((ULONG *)(i+4))==code2_sp3) 
					{
						if (*((ULONG *)(i+8))==code3_sp3) 
						{
							if (*((ULONG *)(i+12))==code4_sp3) 
							{
								MyPspTerminateProcess=(PSPTERPROC)i;
								break;
							}
						}
					}
				}
		}
Ret:
	PsTerminateSystemThread(STATUS_SUCCESS);
	}

VOID GetPspAddr()
{
		HANDLE hThread;
		PVOID objtowait=0;
		NTSTATUS dwStatus = 
			PsCreateSystemThread(
			&hThread,
	              0,
		       NULL,
			(HANDLE)0,
	              NULL,
		       DoFind,
			NULL
			);
		NTSTATUS st;
		if ((KeGetCurrentIrql())!=PASSIVE_LEVEL)
		{
			st=KfRaiseIrql(PASSIVE_LEVEL);
		
		}
		if ((KeGetCurrentIrql())!=PASSIVE_LEVEL)
		{
			
			return;
		}
		
		ObReferenceObjectByHandle(
			hThread,
			THREAD_ALL_ACCESS,
			NULL,
			KernelMode,
			&objtowait,
			NULL
			); 

		st=KeWaitForSingleObject(objtowait,Executive,KernelMode,FALSE,NULL); //NULL表示无限期等待.
		return;
	
	
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	NTSTATUS rc;
	
	RTL_OSVERSIONINFOW osvi;
	NTSTATUS                ntStatus;
	UNICODE_STRING          deviceNameUnicodeString;
       UNICODE_STRING          deviceLinkUnicodeString;   

	RtlInitUnicodeString (&deviceNameUnicodeString,
	    deviceNameBuffer );
	RtlInitUnicodeString (&deviceLinkUnicodeString,
	    deviceLinkBuffer );

	ntStatus = IoCreateDevice ( DriverObject,
	    0,
	    &deviceNameUnicodeString,
	    FILE_DEVICE_SWAP,
	    0,
	    TRUE,
	    &g_HookDevice );

	if(! NT_SUCCESS(ntStatus))
	{
	      DbgPrint(("Failed to create device!\n"));
	      return ntStatus;
	 }		
	ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
	    &deviceNameUnicodeString );
	if(! NT_SUCCESS(ntStatus)) 
	{
		 IoDeleteDevice(DriverObject->DeviceObject);
	        DbgPrint("Failed to create symbolic link!\n");
	        return ntStatus;
	 }
        DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]        =
        DriverObject->MajorFunction[IRP_MJ_CREATE]          =   DispatchCreate;
        DriverObject->MajorFunction[IRP_MJ_CLOSE]           =    
	 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = DispatchControl;

	DriverObject->DriverUnload  = OnUnload;

	GetPspAddr();
	if(MyPspTerminateProcess == NULL)
	{
		DbgPrint("PspFunc Not Find!\n");
	}
	return STATUS_SUCCESS;
}

zw*、nt*系列函数区别 驱动加载监控 DLL链接

//反调试
1TLS回调函数先于程序入口执行,调试器加载主程序的时候会在OEP处设置软件断点,通过TLS回调得到程序的OEP然后判断入口是否为int 3断点
2IsDebuggerPresent()
3、通过SEH查询context里面的DRX寄存器是否为0
4、进程堆里另外一个标志,ForceFlags,他由一组标志组成,正常情况下,该值为0
5HEAP_FREE_CHECKING_ENABLED
6CheckRemoteDebuggerPresent()
7OutputDebugString()
8ZwYieldExecution()
//进程枚举
1Ring3枚举进程CreateToolhelp32Snapshot()+Process32First()+Process32Next()ZwQuerySystemInformation(SystemProcessesAndThreadsInformation)EnumWindows()
2PspCidTable
3PsLookupProcessByProcessId
//几个重要的内核结构体
//https://www.cnblogs.com/wf751620780/p/10588949.html
//https://www.cnblogs.com/Tempt/p/10185570.html
0: kd> dt nt!_KTRAP_FRAME
   +0x000 DbgEbp           : Uint4B
   +0x004 DbgEip           : Uint4B
   +0x008 DbgArgMark       : Uint4B
   +0x00c DbgArgPointer    : Uint4B
   +0x010 TempSegCs        : Uint2B
   +0x012 Logging          : UChar
   +0x013 Reserved         : UChar
   +0x014 TempEsp          : Uint4B
   +0x018 Dr0              : Uint4B
   +0x01c Dr1              : Uint4B
   +0x020 Dr2              : Uint4B
   +0x024 Dr3              : Uint4B
   +0x028 Dr6              : Uint4B
   +0x02c Dr7              : Uint4B
   +0x030 SegGs            : Uint4B
   +0x034 SegEs            : Uint4B
   +0x038 SegDs            : Uint4B
   +0x03c Edx              : Uint4B
   +0x040 Ecx              : Uint4B
   +0x044 Eax              : Uint4B
   +0x048 PreviousPreviousMode : Uint4B
   +0x04c ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x050 SegFs            : Uint4B
   +0x054 Edi              : Uint4B
   +0x058 Esi              : Uint4B
   +0x05c Ebx              : Uint4B
   +0x060 Ebp              : Uint4B
   +0x064 ErrCode          : Uint4B
   +0x068 Eip              : Uint4B
   +0x06c SegCs            : Uint4B
   +0x070 EFlags           : Uint4B
   +0x074 HardwareEsp      : Uint4B
   +0x078 HardwareSegSs    : Uint4B
   +0x07c V86Es            : Uint4B
   +0x080 V86Ds            : Uint4B
   +0x084 V86Fs            : Uint4B
   +0x088 V86Gs            : Uint4B


0: kd> dt _EPROCESS
nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x098 ProcessLock      : _EX_PUSH_LOCK
   +0x0a0 CreateTime       : _LARGE_INTEGER
   +0x0a8 ExitTime         : _LARGE_INTEGER
   +0x0b0 RundownProtect   : _EX_RUNDOWN_REF
   +0x0b4 UniqueProcessId  : Ptr32 Void
   +0x0b8 ActiveProcessLinks : _LIST_ENTRY
   +0x0c0 ProcessQuotaUsage : [2] Uint4B
   +0x0c8 ProcessQuotaPeak : [2] Uint4B
   +0x0d0 CommitCharge     : Uint4B
   +0x0d4 QuotaBlock       : Ptr32 _EPROCESS_QUOTA_BLOCK
   +0x0d8 CpuQuotaBlock    : Ptr32 _PS_CPU_QUOTA_BLOCK
   +0x0dc PeakVirtualSize  : Uint4B
   +0x0e0 VirtualSize      : Uint4B
   +0x0e4 SessionProcessLinks : _LIST_ENTRY
   +0x0ec DebugPort        : Ptr32 Void
   +0x0f0 ExceptionPortData : Ptr32 Void
   +0x0f0 ExceptionPortValue : Uint4B
   +0x0f0 ExceptionPortState : Pos 0, 3 Bits
   +0x0f4 ObjectTable      : Ptr32 _HANDLE_TABLE
   +0x0f8 Token            : _EX_FAST_REF
   +0x0fc WorkingSetPage   : Uint4B
   +0x100 AddressCreationLock : _EX_PUSH_LOCK
   +0x104 RotateInProgress : Ptr32 _ETHREAD
   +0x108 ForkInProgress   : Ptr32 _ETHREAD
   +0x10c HardwareTrigger  : Uint4B
   +0x110 PhysicalVadRoot  : Ptr32 _MM_AVL_TABLE
   +0x114 CloneRoot        : Ptr32 Void
   +0x118 NumberOfPrivatePages : Uint4B
   +0x11c NumberOfLockedPages : Uint4B
   +0x120 Win32Process     : Ptr32 Void
   +0x124 Job              : Ptr32 _EJOB
   +0x128 SectionObject    : Ptr32 Void
   +0x12c SectionBaseAddress : Ptr32 Void
   +0x130 Cookie           : Uint4B
   +0x134 Spare8           : Uint4B
   +0x138 WorkingSetWatch  : Ptr32 _PAGEFAULT_HISTORY
   +0x13c Win32WindowStation : Ptr32 Void
   +0x140 InheritedFromUniqueProcessId : Ptr32 Void
   +0x144 LdtInformation   : Ptr32 Void
   +0x148 VdmObjects       : Ptr32 Void
   +0x14c ConsoleHostProcess : Uint4B
   +0x150 DeviceMap        : Ptr32 Void
   +0x154 EtwDataSource    : Ptr32 Void
   +0x158 FreeTebHint      : Ptr32 Void
   +0x160 PageDirectoryPte : _HARDWARE_PTE
   +0x160 Filler           : Uint8B
   +0x168 Session          : Ptr32 Void
   +0x16c ImageFileName    : [15] UChar
   +0x17b PriorityClass    : UChar
   +0x17c JobLinks         : _LIST_ENTRY
   +0x184 LockedPagesList  : Ptr32 Void
   +0x188 ThreadListHead   : _LIST_ENTRY
   +0x190 SecurityPort     : Ptr32 Void
   +0x194 PaeTop           : Ptr32 Void
   +0x198 ActiveThreads    : Uint4B
   +0x19c ImagePathHash    : Uint4B
   +0x1a0 DefaultHardErrorProcessing : Uint4B
   +0x1a4 LastThreadExitStatus : Int4B
   +0x1a8 Peb              : Ptr32 _PEB
   +0x1ac PrefetchTrace    : _EX_FAST_REF
   +0x1b0 ReadOperationCount : _LARGE_INTEGER
   +0x1b8 WriteOperationCount : _LARGE_INTEGER
   +0x1c0 OtherOperationCount : _LARGE_INTEGER
   +0x1c8 ReadTransferCount : _LARGE_INTEGER
   +0x1d0 WriteTransferCount : _LARGE_INTEGER
   +0x1d8 OtherTransferCount : _LARGE_INTEGER
   +0x1e0 CommitChargeLimit : Uint4B
   +0x1e4 CommitChargePeak : Uint4B
   +0x1e8 AweInfo          : Ptr32 Void
   +0x1ec SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   +0x1f0 Vm               : _MMSUPPORT
   +0x25c MmProcessLinks   : _LIST_ENTRY
   +0x264 HighestUserAddress : Ptr32 Void
   +0x268 ModifiedPageCount : Uint4B
   +0x26c Flags2           : Uint4B
   +0x26c JobNotReallyActive : Pos 0, 1 Bit
   +0x26c AccountingFolded : Pos 1, 1 Bit
   +0x26c NewProcessReported : Pos 2, 1 Bit
   +0x26c ExitProcessReported : Pos 3, 1 Bit
   +0x26c ReportCommitChanges : Pos 4, 1 Bit
   +0x26c LastReportMemory : Pos 5, 1 Bit
   +0x26c ReportPhysicalPageChanges : Pos 6, 1 Bit
   +0x26c HandleTableRundown : Pos 7, 1 Bit
   +0x26c NeedsHandleRundown : Pos 8, 1 Bit
   +0x26c RefTraceEnabled  : Pos 9, 1 Bit
   +0x26c NumaAware        : Pos 10, 1 Bit
   +0x26c ProtectedProcess : Pos 11, 1 Bit
   +0x26c DefaultPagePriority : Pos 12, 3 Bits
   +0x26c PrimaryTokenFrozen : Pos 15, 1 Bit
   +0x26c ProcessVerifierTarget : Pos 16, 1 Bit
   +0x26c StackRandomizationDisabled : Pos 17, 1 Bit
   +0x26c AffinityPermanent : Pos 18, 1 Bit
   +0x26c AffinityUpdateEnable : Pos 19, 1 Bit
   +0x26c PropagateNode    : Pos 20, 1 Bit
   +0x26c ExplicitAffinity : Pos 21, 1 Bit
   +0x26c Spare1           : Pos 22, 1 Bit
   +0x26c ForceRelocateImages : Pos 23, 1 Bit
   +0x26c DisallowStrippedImages : Pos 24, 1 Bit
   +0x26c LowVaAccessible  : Pos 25, 1 Bit
   +0x270 Flags            : Uint4B
   +0x270 CreateReported   : Pos 0, 1 Bit
   +0x270 NoDebugInherit   : Pos 1, 1 Bit
   +0x270 ProcessExiting   : Pos 2, 1 Bit
   +0x270 ProcessDelete    : Pos 3, 1 Bit
   +0x270 Wow64SplitPages  : Pos 4, 1 Bit
   +0x270 VmDeleted        : Pos 5, 1 Bit
   +0x270 OutswapEnabled   : Pos 6, 1 Bit
   +0x270 Outswapped       : Pos 7, 1 Bit
   +0x270 ForkFailed       : Pos 8, 1 Bit
   +0x270 Wow64VaSpace4Gb  : Pos 9, 1 Bit
   +0x270 AddressSpaceInitialized : Pos 10, 2 Bits
   +0x270 SetTimerResolution : Pos 12, 1 Bit
   +0x270 BreakOnTermination : Pos 13, 1 Bit
   +0x270 DeprioritizeViews : Pos 14, 1 Bit
   +0x270 WriteWatch       : Pos 15, 1 Bit
   +0x270 ProcessInSession : Pos 16, 1 Bit
   +0x270 OverrideAddressSpace : Pos 17, 1 Bit
   +0x270 HasAddressSpace  : Pos 18, 1 Bit
   +0x270 LaunchPrefetched : Pos 19, 1 Bit
   +0x270 InjectInpageErrors : Pos 20, 1 Bit
   +0x270 VmTopDown        : Pos 21, 1 Bit
   +0x270 ImageNotifyDone  : Pos 22, 1 Bit
   +0x270 PdeUpdateNeeded  : Pos 23, 1 Bit
   +0x270 VdmAllowed       : Pos 24, 1 Bit
   +0x270 CrossSessionCreate : Pos 25, 1 Bit
   +0x270 ProcessInserted  : Pos 26, 1 Bit
   +0x270 DefaultIoPriority : Pos 27, 3 Bits
   +0x270 ProcessSelfDelete : Pos 30, 1 Bit
   +0x270 SetTimerResolutionLink : Pos 31, 1 Bit
   +0x274 ExitStatus       : Int4B
   +0x278 VadRoot          : _MM_AVL_TABLE
   +0x298 AlpcContext      : _ALPC_PROCESS_CONTEXT
   +0x2a8 TimerResolutionLink : _LIST_ENTRY
   +0x2b0 RequestedTimerResolution : Uint4B
   +0x2b4 ActiveThreadsHighWatermark : Uint4B
   +0x2b8 SmallestTimerResolution : Uint4B
   +0x2bc TimerResolutionStackRecord : Ptr32 _PO_DIAG_STACK_RECORD

EPROCESS和ETHREAD都是双向链表组织管理,一个EPROCESS中包含一个KPROCESS,这个KPROCESS中指向一个ETHREAD结构,在ETHREAD中又包含一个KTHREAD结构

//结束线程
1NtTerminateThread()
2PspTerminateThreadByPointer()
3Insert APC



保护模式

#include<ntifs.h>

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{

}


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver,PUNICODE_STRING pReg)
{
    pDriver->DriverUnload=DriverUnload;
    return STATUS_SUCCESS;
}

CPU的两种架构:RISC(arm)、CISC(x86) “几乎所有的冯·诺伊曼型计算机的CPU,其工作都可以分为5个阶段:取指令、指令译码、访存取数、执行指令、结果写回” 增量链接

//裸函数
void __declspec(naked) fn(){}

羽夏看Win系统内核——简述

//以下很多内容选自“羽夏的博客”
相关主页:https://www.cnblogs.com/wingsummer

CPU的三个模式:实模式、保护模式(保护内存非法访问和特权指令的使用)、虚拟8086模式  段寄存器有这几个:ES、CS、SS、DS、FS、GS、LDTR、TR,它们各有自己特殊的用途。

Mov指令MOV AX,ES,但只能读16位的可见部分;MOV DS,AX写段寄存器,写的是96位。
读写LDTR的指令为SLDT/LLDT
读写TR的指令为STR/LTR
//注意在学习保护模式的时候不要把操作系统的概念扯进去,还没到操作系统层面

GDT:全局描述符表 LDT:局部描述符表 寄存器GDTR(48位)存储了GDT表的位置和大小

r gdtr    //读取GDT表地址
r gdtl    //读取GDT表的大小
dq 8003f000 l30    //0x8003f000为GDT表的地址(0x30=48)

段选择子、段描述符拆解分析

CPLCPU当前的权限级别
DPL:如果你想访问我,你应该具备什么样的权限(CPL
RPL:用什么权限去访问一个段
对于一致代码段,也称为共享段:

特权级高的程序不允许访问特权级低的数据:核心态不允许访问用户态的数据
特权级低的程序可以访问到特权级高的数据,但特权级不会改变:用户态还是用户态
对于非一致代码段:

只允许同级访问
绝对禁止不同级别的访问:核心态不是用户态,用户态也不是核心态
//代码段间跳转的执行流程
1、段选择子拆分
2、查表得到段描述符
3、权限检查
4、加载段描述符
5、代码执行

调用门执行流程如下所示:

指令格式:CALL CS:EIP (EIP是废弃的)

执行步骤:
1、根据CS的值查GDT表,找到对应的段描述符且该描述符是一个调用门。
2、在调用门描述符中存储另一个代码段的段选择子,将其加载到CS中
3、选择子指向的段的Base + 偏移地址就是真正要执行的地址。
IDT表包含3种门描述符:任务门描述符、中断门描述符、陷阱门描述符
指令格式:INT N (N为中断门索引号)

执行步骤:
1、在没有权限切换时,会向堆栈顺次压入EFLAGCS和EIP;如果有权限切换,会向堆栈顺次压入SSESPEFLAGCS和EIP
2CPU会索引到IDT表。后面的N表示查IDT表项的下标。对比调用门,中断门没有了RPL,故CPU只会校验CPL
3、在中断门中,不能通过RETF返回,而应该通过IRET/IRETD指令返回
总结:
1CS的权限一旦改变SS的权限也要随着改变CS与SS的等级必须一样
2JMP FAR只能跳转到同级非一致代码段,但CALL FAR可以通过调用门提权,提升CPL的权限

调用门总结:
1、当通过门,权限不变的时候,只会PUSH两个值CS和返回地址,新的CS的值由调用门决定
2、当通过门,权限改变的时候,会PUSH四个值SSESPCS和返回地址,新的CS的值由调用门决定,新的SS和ESP由TSS提供
3、通过门调用时,要执行哪行代码由调用门决定,但使用RETF返回时,由堆栈中压入的值决定,这就是说,进门时只能按指定路线走,出门时可以FQ,即只要改变堆栈里面的值就可以想去哪去哪。
任务段(TSSTask-state segment
任务门的执行流程:
1、通过INT N的指令进行触发任务门
2、查IDT表,找到任务门描述符
3、通过任务门描述符,查GDT表,找到TSS段描述符
4、使用TSS段中的值修改TR寄存器
5IRETD返回


驱动

普通程序 内核
malloc ExAllocatePoolWithTag
memset RtlFillMemory
memcpy RtlMoveMemory
free ExFreePool

系统调用

并不是所有的API必须进0环的,可以在3环完全实现;比如Ntdll.dll导出的memcmp函数
_KUSER_SHARED_DATA

SSDT的全称是System Services Descriptor Table,意为系统服务描述符表。在32XP中,我们可以通过ETHREAD结构体加偏移的方式进行访问。在内核文件中,有一个变量是导出的:KeServiceDescriptorTable。通过它我们可以访问SSDT

进程与线程

每个windows进程在0环都有一个对应的结构体:EPROCESS; 每个Windows线程在0环都有一个对应的结构体ETHREAD;

KPCR中存储了CPU本身要用的一些重要数据GDTIDT以及线程相关的一些信息
当线程进入0环时,FS:[0]指向KPCR3环时FS:[0]指向 TEB
每个CPU都有一个KPCR结构体,即一个核一个。

句柄表

 句柄是给3环用的,而不是给内核用的;Windows所有涉及句柄的API,一旦到了真正函数实现的部分,就立刻使用ObReferenceObjectByHandle把它转化为真正的指向内核对象的指针

APC

APC的本质


同步