1. 程式人生 > >Win7 64位的SSDTHOOK(2)---64位SSDT hook的實現

Win7 64位的SSDTHOOK(2)---64位SSDT hook的實現

上篇文章知道了尋找SSDT表的方法,這篇記錄一下如何實現SSDT表的Hook。

下面以Hook NtOpenProcess為例,之前我查SSDT表發現NtOpenProcess函式的標號為35,用XT等工具也能檢視。

廢話不多說,上程式碼。

首先感謝老大(Tesla.Angela)對我的幫助

//相關宣告
__int64 __readmsr(int register);
unsigned __int64 __readcr0(void);
void __writecr0( 
	unsigned __int64 Data 
	);
void _disable(void);
void _enable(void);

//_SYSTEM_SERVICE_TABLE結構宣告
typedef struct _SYSTEM_SERVICE_TABLE{
	PVOID  		ServiceTableBase; 
	PVOID  		ServiceCounterTableBase; 
	ULONGLONG  	NumberOfServices; 
	PVOID  		ParamTableBase; 
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;

//_SERVICE_DESCRIPTOR_TABLE結構宣告
typedef struct _SERVICE_DESCRIPTOR_TABLE{
	SYSTEM_SERVICE_TABLE ntoskrnl;  // ntoskrnl.exe (native api)
	SYSTEM_SERVICE_TABLE win32k;    // win32k.sys   (gdi/user)
	SYSTEM_SERVICE_TABLE Table3;    // not used
	SYSTEM_SERVICE_TABLE Table4;    // not used
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE;

//宣告要尋找程序名用的函式
NTKERNELAPI UCHAR * PsGetProcessImageFileName(PEPROCESS Process);

//定義NTOPENPROCESS
typedef NTSTATUS (__stdcall *NTOPENPROCESS)(OUT PHANDLE  ProcessHandle,
									IN ACCESS_MASK  DesiredAccess,
									IN POBJECT_ATTRIBUTES  ObjectAttributes, 
									IN OPTIONAL PCLIENT_ID  ClientId);
NTOPENPROCESS OldOpenProcess = NULL;
ULONG OldTpVal;

//定義自己的NtOpenProcess
NTSTATUS __stdcall Fake_NtOpenProcess(OUT PHANDLE  ProcessHandle,
									   IN ACCESS_MASK  DesiredAccess,
									   IN POBJECT_ATTRIBUTES  ObjectAttributes, 
									   IN OPTIONAL PCLIENT_ID  ClientId)
{
	PEPROCESS process = NULL;
	NTSTATUS st = ObReferenceObjectByHandle(<span style="font-family: Arial, Helvetica, sans-serif;">ClientId->processid</span>
,0,*PsProcessType,KernelMode,&process,NULL);
	DbgPrint("進入HOOK函式.\n");
	if (NT_SUCCESS(st))
	{
		if (!_stricmp((char*)PsGetProcessImageFileName(process),"CrackMe3.exe"))
		{
			
			return STATUS_ACCESS_DENIED;
		}
		else
		{
			return OldOpenProcess(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);
		} 
	}
	else
	{
		return STATUS_ACCESS_DENIED;
	}
}

//關閉頁面保護
KIRQL WPOFFx64()
{
	KIRQL irql=KeRaiseIrqlToDpcLevel();
	UINT64 cr0=__readcr0();
	cr0 &= 0xfffffffffffeffff;
	__writecr0(cr0);
	_disable();
	return irql;
}
//開啟頁面保護
void WPONx64(KIRQL irql)
{
	UINT64 cr0=__readcr0();
	cr0 |= 0x10000;
	_enable();
	__writecr0(cr0);
	KeLowerIrql(irql);
}

//老外定位KeServiceDescriptorTable的方法
ULONGLONG GetKeServiceDescriptorTable64() 
{
	char KiSystemServiceStart_pattern[] = "\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x25\xFF\x0F\x00\x00";	//特徵碼
	ULONGLONG CodeScanStart = (ULONGLONG)&_strnicmp;
	ULONGLONG CodeScanEnd = (ULONGLONG)&KdDebuggerNotPresent;
	UNICODE_STRING Symbol;
	ULONGLONG i, tbl_address, b;
	for (i = 0; i < CodeScanEnd - CodeScanStart; i++)
	{
		if (!memcmp((char*)(ULONGLONG)CodeScanStart +i, (char*)KiSystemServiceStart_pattern,13))
		{ 
			for (b = 0; b < 50; b++)
			{
				tbl_address = ((ULONGLONG)CodeScanStart+i+b);
				if (*(USHORT*) ((ULONGLONG)tbl_address ) == (USHORT)0x8d4c)
					return ((LONGLONG)tbl_address +7) + *(LONG*)(tbl_address +3);
			}
		}
	}
	return 0;
}

//根據KeServiceDescriptorTable找到SSDT基址
PULONG GetSSDTBaseAddress()
{
	PULONG addr = NULL;
	PSYSTEM_SERVICE_TABLE ssdt = (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
	addr = (PULONG)(ssdt->ServiceTableBase);
	return addr;
}

//根據標號找到SSDT表中函式的地址
ULONGLONG GetFuncAddr(ULONG id)
{
	LONG dwtmp = 0;
	ULONGLONG addr = 0;
	PULONG stb = NULL;
	stb = GetSSDTBaseAddress();
	dwtmp = stb[id];
	dwtmp = dwtmp >> 4;
	addr = (LONGLONG)dwtmp + (ULONGLONG)stb;
	DbgPrint("SSDT TABLE BASEADDRESS:%llx",addr);
	return addr;
}

//設定函式的偏移地址,注意其中引數的處理。低四位放了引數個數減4個引數。如果引數小於等於4的時候為0
#define SETBIT(x,y) x|=(1<<y) //將X的第Y位置1
#define CLRBIT(x,y) x&=~(1<<y) //將X的第Y位清0
#define GETBIT(x,y) (x & (1 << y)) //取X的第Y位,返回0或非0
ULONG GetOffsetAddress(ULONGLONG FuncAddr, CHAR paramCount)
{
	LONG dwtmp = 0,i;
	CHAR b = 0, bits[4] = {0};
	PULONG stb = NULL;
	stb = GetSSDTBaseAddress();
	dwtmp = (LONG)(FuncAddr - (ULONGLONG)stb);
	dwtmp = dwtmp << 4;
	if (paramCount>4)
	{
		paramCount = paramCount - 4;
	}
	else
	{
		paramCount = 0;
	}
	memcpy(&b,&dwtmp,1);
	for (i=0;i<4;i++)
	{
		bits[i] = GETBIT(paramCount,i);
		if (bits[i])
		{
			SETBIT(b,i);
		}
		else
		{
			CLRBIT(b,i);
		}
	}
	memcpy(&dwtmp,&b,1);
	return dwtmp;
}

//核心中用不到的方法,二次跳轉用(自己的NtOpenProcess跳到KeBugCheckEx函式,然後再KeBugCheckEx函式跳到要Hook的NtOpenProcess)
VOID FuckKeBugCheckEx()
{
	KIRQL irql;
	ULONGLONG myfun;
	UCHAR jmp_code[]="\xFF\x25\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
	myfun=(ULONGLONG)Fake_NtOpenProcess;
	memcpy(jmp_code+6,&myfun,8);
	irql=WPOFFx64();
	memset(KeBugCheckEx,0x90,15);
	memcpy(KeBugCheckEx,jmp_code,14);
	WPONx64(irql);
}

//Hook ssdt
VOID HookSSDT()
{
	KIRQL irql;
	LONG dwtmp = 0;
	PULONG stb = NULL;
	//1.get old address
	OldOpenProcess = (NTOPENPROCESS)GetFuncAddr(35);
	DbgPrint("Old_NtOpenProcess:%llx",(ULONGLONG)OldOpenProcess);
	//2.show new address
	stb = GetSSDTBaseAddress();
	//3.get offset value
	dwtmp = GetOffsetAddress((ULONGLONG)KeBugCheckEx,4);
	//set kebugcheckex
	FuckKeBugCheckEx();
	//4.record  old offset  value
	OldTpVal = stb[35];
	irql = WPOFFx64();
	stb[35] = GetOffsetAddress((ULONGLONG)KeBugCheckEx,2);
	WPONx64(irql);
	DbgPrint("KeBugCheckEx:%llx",(ULONGLONG)KeBugCheckEx);
	DbgPrint("New_NtOpenProcess:%llx",GetFuncAddr(35));
}

//UN hook
VOID UnhookSSDT()
{
	KIRQL irql;
	PULONG stb=NULL;
	stb = GetSSDTBaseAddress();
	//老函式的地址複製回來
	irql=WPOFFx64();
	stb[35]=OldTpVal;
	WPONx64(irql);
}

相關解釋:

1.為什麼要二次跳轉?

WIN64核心裡的每個驅動都不在同一個4GB裡,4位元組的整數只能表示4GB的範圍,所以不管怎麼修改這個4位元組都不會跳到你的代理函式,因為你的驅動不可能跟NTOSKRNL在同一個4GB裡面。

2.引數的處理:

函式地址的低四位存放了函式引數個數減4的數字,如果引數為5,那麼低四位的數字為1,如果引數個數小於等於4個,低四位的數位0,可以再WINDBG裡面檢視到。

相關推薦

Win7 64SSDTHOOK(2)---64SSDT hook實現

上篇文章知道了尋找SSDT表的方法,這篇記錄一下如何實現SSDT表的Hook。 下面以Hook NtOpenProcess為例,之前我查SSDT表發現NtOpenProcess函式的標號為35,用XT等工具也能檢視。 廢話不多說,上程式碼。 首先感謝老大(Tesla.A

MySQL基礎環境_安裝配置教程(Windows7 64或Centos7.2 64、MySQL5.7)

secure https http cti -s entos 重啟 init data MySQL基礎環境_安裝配置教程(Windows7 64或Centos7.2 64、MySQL5.7) 安裝包版本 1) VMawre-workstation版本包 地址:

Oracle欄保留2小數點number型別

*問題背景*:昨天調阿里發票平臺的申請發票介面時發生了一個異常,原因是發票金額至少保留兩位小數,我查了下記錄,確實表中的記錄為600,所以查出來的資料不會帶小數點。 由於用的oracle,我查了下欄位是否能像mysql一樣設定保留小數點呢。查了網上很多

win7 64TensorFlow1.2.1的安裝

遇到的兩個主要問題: (1)超時報錯Readtimedout。解決方法:pip --default-timeout=100 install -U pip (2)pip版本問題。解決方法:python

Win10 64 Apache 2.4+MySQL 5.7+PHP 7環境搭建

ble read def 文本編輯 x64 得到 c11 next gin 軟件版本及獲取 Apache 2.4.25 win64 | MySQL Server 5.7.17 win64 | PHP 7.0 x64 Thread Safe Apache 2.4.25 wi

WIN7 環境下搭建 PHP7(64 )操作步驟

再次 丟失 word srv sql ram 安裝目錄 only mys WIN7 環境下搭建 PHP7(64 位)操作步驟 一、安裝與配置 Apache 1、下載 Apache下載地址:https://www.apachelounge.com/download/ 2、

新版火狐瀏覽器(61.0.2 (64 ))如何進行元素定位

com 恢復 分享 http bubuko 一個 src 開始 選擇 ---恢復內容開始--- 我們在寫自動化腳本進行web測試時,經常會用到元素定位,之前我們用的都是Firebug+Firepath,但瀏覽器總要更新的,所以就有了這篇筆記,新版的火狐瀏覽器整合掉了這兩個小

騰訊雲CentOS 7.2 64安裝Mongodb

如果 .com () epo 查看 bsp logs 無法連接 inline 一、安裝步驟:1、配置MongoDB的yum源:創建yum源文件:vim /etc/yum.repos.d/mongodb-org-3.4.repo 2、mongodb-org-3.4.repo

阿里雲伺服器安裝PHP執行環境(CentOS6.8 64|Vsftpd2.2.2)的 錯誤

1. ERROR: unable to bind listening socket for address '127.0.0.1:9000': Address already in use (98) [16-Nov-2018 18:48:17] ERROR: FPM initialization

Linux_CentOS 7.2 64之安裝apache-activemq-5.15.6步驟

下載檔案: 1. 解壓: tar -xvf apache-activemq-5.15.6-bin.tar.gz 2. 找到檔案解壓位置: [[email protected]_0_13_centos apache-activemq-5.15.6]# pwd /w

linux_CentOS 7.2 64 騰訊雲 80埠未啟用解決方法

描述:在購買的騰訊雲伺服器,自己選擇的安裝映象CentOS 7.2 64位,然後自己搭建好環境後,發現有限埠沒有啟動 尤其是預設的網路訪問埠:80沒有自己啟用。一開始以為是防火牆的問題。這裡面遇到了一些小坑 1  CentOS 7.2 64位 之後的防火牆沒有直接使用se

winrar 4.2 64註冊碼

在winrar的安裝目錄下 新建一個RarReg.key的檔案,複製下面的程式碼進去即可  RAR registration data Federal Agency for Education 1000000 PC usage license UID=b621cca9a8

VC 32(或64win7作業系統的登錄檔操作

1、登錄檔位置 Windows7 64bit系統的登錄檔分32 位登錄檔項和64位登錄檔項兩部分。 在64bit系統下,通過regedit中檢視到指定路徑下的登錄檔項均為64位登錄檔項,而32位登錄檔項被重定位到:   HKEY_LOCAL_MACHINE\Software\WOW6432Node。 應用

64CentOS6.2安裝erlang及rabbitmqServer

CentOS 6.2 64bit 安裝erlang及RabbitMQ Server 1、作業系統環境(CentOS 6.2 64bit) 01.[root@leekwen ~]# cat /etc/issue 02.CentOS release 6.2 (Fin

linux-Centos-7-642、 安裝Tomcat並配置

將下載好的tomcat放到/mnt/share下 建立 /data 下資料夾tomcat, 並在資源目錄share下複製一份tomcat壓縮包 mkdir /data/tomcat cp /mnt/share/apache-tomcat-9.0.0.M4.ta

CentOS7.2 64yum安裝與配置MySQL

CentOS7.2 64位yum安裝與配置MySQL 1、配置YUM源 在MySQL官網中下載YUM源rpm安裝包:https://dev.mysql.com/downloads/repo/yum/ 下載mysql源安裝包 shell> wget http://dev.my

【Linux\雲伺服器】CentOS 7.2 64 視覺化桌面的安裝與解除安裝

CentOS 7.2 視覺化桌面的安裝和解除安裝        終於開始寫第一篇CSDN部落格了,心情有點兒小激動,前兩天,小D在阿里雲出購買了一臺學生優惠的ECS雲伺服器,購買之前並沒有學習過任何有關Linux的知識,於是乎,那會兒就有了想安裝一個視

JDK or JRE是32還是642種檢視方法

1、java -version 2、執行java程式 public class Test{     public static void main(String[] args){     String arch = System.getProperty("sun.arch

win7硬碟安裝Ubuntu12.04 64時顯示Error 15: File not found.

安裝Ubuntu12.04 -64位時,用EasyBCD建好引導檔案重啟電腦後出現如下錯誤: Error 15: File not found 原因一個是安裝檔案所在碟符不對,另一個是檔名。Ubuntu12.04 32位的ISO包解壓後casper資料夾下核心檔案為v

centos7.2 64--ruby的安裝與解除安裝---想安裝什麼版本就安裝什麼版本

先吐槽 , 網上這麼多教程,沒一個好使 。。。 渣渣。。。。。 先安裝(一定要裝): yum install gcc-c++ 看正文: 先教你們怎麼下載(網址在這裡不用謝我) : https://ca