近日有在写一个小东西
需要在内核态中运行一个WIN32程序
之前提到的插入APC可以满足部分要求
但是一到WIN7 x86平台下就崩溃了
WIN7下只能插入第三方的进程
一插入系统进程就崩溃,但是这样满足不了我们猥琐的想法
- - 后来找到了一段代码 是注入RING3线程的

基本流程就是  查找系统中某个进程 比如explorer.exe
然后遍历线程链表,判断线程是否是RING3的线程,
而且不是被挂起的。(这个无所谓的)。。。
找到符合要求的线程之后在对方进程中申请一段内存来存放我们自己的ShellCode 代码
然后修改线程的_KTRAP_FRAME中的EIP的值,使线程跑起来的时候先运行我们的自己的
代码,运行完了之后跳回到原来的EIP去指定。。。
需要用到两个未公开的函数:ZwSuspendThread,ZwResumeThread
一个是挂起线程来方便我们修改EIP的 一个是恢复线程使它跑起来

再说说在RING0下搜索RING3 API地址的方法
其实就是从_EPROCESS中得到PEB结构
从PEB中的ldr中的InInitializationOrderMoudleList链表中去查找Kernel32.dll的基地址
通常来说WINXP中了链表的第一项就是Kernel32.dll的基地址
而到了win7 它就存在第二项了 win7下第一项是kernelbase.dll的基地址 (这个好像是一个kernel32.dll的壳)
不多说了看代码吧

/***************************************************************************************

*
* 模块: 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[];
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", ) == )) //不区分大小写
{
ULONG api_addr = ; 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*]; //
add edi, ebx; //-----------------------------------
//计算[edi]字符串的hash值
//-----------------------------------
pushad;
xor eax, eax;
cacul_next:
shl eax, ;
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+*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 ;
} /************************************************************************/
/* 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", ) == )) //不区分大小写
{
ULONG api_addr = ; //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*]; //
add edi, ebx; //-----------------------------------
//计算[edi]字符串的hash值
//-----------------------------------
pushad;
xor eax, eax;
cacul_next:
shl eax, ;
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+*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 ;
} /************************************************************************/
/* 获取WINDOWS版本
通过ImageName偏移来判断
*/
/************************************************************************/ WORD GetWindowsVersion()
{
PEPROCESS pSystemProcess = PsGetCurrentProcess();
WORD offset;
for (offset=; offset < PAGE_SIZE; offset++)
{
if(strncmp("System", (PCHAR)pSystemProcess + offset, ) == )
{
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=; OBJECT_ATTRIBUTES oa = {sizeof oa, , 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 = ; ZwCreateSection(&hSection, SECTION_ALL_ACCESS, &oa, ,PAGE_EXECUTE, SEC_IMAGE, hFile); ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, , , , &size, (SECTION_INHERIT), 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+); 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 = ; x < pExportTable->NumberOfFunctions; x++)
{
functionName = (char*)( (BYTE*)hMod + arrayOfFunctionNames[x]); RtlInitString(&ntFunctionName, functionName); functionOrdinal = arrayOfFunctionOrdinals[x] + Base - ; // 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) == )
{
//ZwClose(hSection);
return functionAddress;
}
} //ZwClose(hSection);
return ;
} /************************************************************************/
/* 获取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+)); 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 //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() {
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+)) ){
if ( *(PULONG)i == 0x12345678 )
{
DbgPrint("find modify point\n");
WPOFF();
*(PULONG)i = pTrapFrame->Eip;
WPON();
break;
}
}
} WPOFF();
lpTargetPath = (PVOID)((ULONG)ShellCode + );
memcpy((PUCHAR)(ULONG)ShellCode + , &g_WinExec, ); //填写winexec地址
memset(lpTargetPath, , ); //
WPON(); // 下面的代码是分配空间来放置ShellCode
// 调用一些相应函数来实现更好,我比较懒,就硬编码了
InitializeObjectAttributes(&oa,,,,);
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,
,
&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:\\tool\\dd2.exe";
pathAddr = ((ULONG)pBuff + );
RtlCopyMemory( (PVOID)((ULONG)pBuff + ), path, strlen(path) );//填写运行的路径 path
RtlCopyMemory( (PVOID)((ULONG)pBuff + ), &pathAddr, );//填写路径的地址 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; pProcess = PsGetCurrentProcess();
pListHead = (PLIST_ENTRY)((ULONG)pProcess + g_EProcessOffset.wOffsetFlink); //0x88 //ActiveProcessLinks
pNextEntry = pListHead; // 先找到要注入的进程,通过ZwQuerySystemInformation来查找更稳定一些
// 不过本人很讨厌那个繁琐的函数……
do
{
pProcess = (PEPROCESS)((ULONG)pNextEntry - g_EProcessOffset.wOffsetFlink/*0x88*/);
if ( !_strnicmp((char*)pProcess + g_EProcessOffset.wOffsetName/*0x174*/, 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) == )
{
// 非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

驱动插ring3线程执行代码的更多相关文章

  1. 卸载AppDomain动态调用DLL异步线程执行失败

    应用场景 动态调用DLL中的类,执行类的方法实现业务插件功能 使用Assembly 来实现 但是会出现逻辑线程数异常的问题 使用AppDomain 实现动态调用,并卸载. 发现问题某个插件中开启异步线 ...

  2. 线程执行synchronized同步代码块时再次重入该锁过程中抛异常,是否会释放锁

    一个线程执行synchronized同步代码时,再次重入该锁过程中,如果抛出异常,会释放锁吗? 如果锁的计数器为1,抛出异常,会直接释放锁: 那如果锁的计数器为2,抛出异常,会直接释放锁吗? 来简单测 ...

  3. 构建一个基于事件分发驱动的EventLoop线程模型

    在之前的文章中我们详细介绍过Netty中的NioEventLoop,NioEventLoop从本质上讲是一个事件循环执行器,每个NioEventLoop都会绑定一个对应的线程通过一个for(;;)循环 ...

  4. Java多线程--让主线程等待子线程执行完毕

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  5. java并发编程学习:如何等待多个线程执行完成后再继续后续处理(synchronized、join、FutureTask、CyclicBarrier)

    多线程应用中,经常会遇到这种场景:后面的处理,依赖前面的N个线程的处理结果,必须等前面的线程执行完毕后,后面的代码才允许执行. 在我不知道CyclicBarrier之前,最容易想到的就是放置一个公用的 ...

  6. C#实现每隔一段时间执行代码(多线程)

    总结以下三种方法,实现c#每隔一段时间执行代码: 方法一:调用线程执行方法,在方法中实现死循环,每个循环Sleep设定时间: 方法二:使用System.Timers.Timer类: 方法三:使用Sys ...

  7. java并发:获取线程执行结果(Callable、Future、FutureTask)

    初识Callable and Future 在编码时,我们可以通过继承Thread或是实现Runnable接口来创建线程,但是这两种方式都存在一个缺陷:在执行完任务之后无法获取执行结果.如果需要获取执 ...

  8. Java多线程——<三>简单的线程执行:Executor

    一.概述 按照<Java多线程——<一><二>>中所讲,我们要使用线程,目前都是显示的声明Thread,并调用其start()方法.多线程并行,明显我们需要声明多个 ...

  9. c#等待所有子线程执行完毕方法

    当我们在使用线程中,你会发现主线结束后子线程的结果才显示出来.现在我要等待所以子线程结束,然后在显示结果,怎么做呢? 方法如下: 1.使用 ManualResetEvent,代码如下:  using  ...

随机推荐

  1. 简介python2.x的编码

    python2.x的中文编码真是令人头痛,简单写下自己的一点python编码转换的体会. windows平台用的默认编码格式为gbk >>> s = raw_input() #在wi ...

  2. smarty模板引擎

    1.    使用smarty 1.1 项目引入 // 3, 连接数据库,提取相关数据 $title = "Smarty模板引擎"; $content = "Smarty模 ...

  3. ProcessExplore 最新版

    http://files.cnblogs.com/files/zhangdongsheng/ProcessExplorer.zip

  4. 服务器CGI运行机制

    CGI概括: 定义 通用网关接口(Common Gateway Interface)是HTTP服务器与你的或其它机器上的程序进行"交谈"的一种工具,其程序须运行在网络服务器上. 功 ...

  5. 【所见即所得】textarea 精确限制字数、行数,中、英、全半角混检 。源码带注释

    主要解决难点: 1 中文 全角2字符深深的恶意 2 多行输入textarea 手动,自动换行问题 3 获得每行内容 原创,转载请注明出处! <!DOCTYPE html PUBLIC " ...

  6. 1006. Sign In and Sign Out (25)

    At the beginning of every day, the first person who signs in the computer room will unlock the door, ...

  7. Android导航栏菜单强制转换

    private void getOverflowMenu() { ViewConfiguration viewConfig = ViewConfiguration.get(this); try { F ...

  8. Java知识积累3-XML的DOM解析修改和删除方法

    import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder;import jav ...

  9. javascript 随笔

    document.execCommand("SaveAs",true,"aaa"); //将当前web页面另存为文件.第三个参数为文件名,可以自己设置,为空的时 ...

  10. java中使用队列:java.util.Queue (转)

    Queue接口与List.Set同一级别,都是继承了Collection接口.LinkedList实现了Queue接 口.Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类 ...