woaidaima2016 发表于 2022-4-15 20:08:30

如何从Windows内核中启动一个R3的程序

/*
win7x64下 WinExec执行程序,通过把shellcode注入到explorer.exe进程中
使用方法
#include <inject_shellcode.h>
Ring0Win7X64WinExec();
*/
#define PS_CROSS_THREAD_FLAGS_SYSTEM 0x00000010UL

char* path = "D:\\msxboxtest.exe"; //要执行的程序,路劲大小不要超过40字节

typedef struct _SYSTEM_SERVICE_TABLE{
      PVOID                  ServiceTableBase;
      PVOID                  ServiceCounterTableBase;
      ULONGLONG          NumberOfServices;
      PVOID                  ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;

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

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

typedef struct _LDR_DATA_TABLE_ENTRY {
    PVOID Reserved1;
    LIST_ENTRY InMemoryOrderLinks;
    PVOID Reserved2;
    PVOID DllBase;
    PVOID EntryPoint;
    PVOID Reserved3;
    UNICODE_STRING FullDllName;
    BYTE Reserved4;
    PVOID Reserved5;
    union {
      ULONG CheckSum;
      PVOID Reserved6;
    };
    ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;



PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;
pfnZwSuspendThread KeSuspendThread = NULL;
pfnZwSuspendThread KeResumeThread = NULL;
ULONGLONG PsSuspendThreadAddr = 0;
ULONGLONG g_WinExec;
//PUCHAR ShellCode="\x50\x48\xC7\xC0\x50\x8D\x0C\x77\x48\x8D\x0D\x95\x11\x00\x00\xBA\x05\x00\x00\x00\xFF\xD0\x58\xE9\x78\x56\x34\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";

/*
000000013F7F102050                  push      rax
000000013F7F102148 C7 C0 50 8D 0C 77mov         rax,0x770C8D50      ; WinExec
000000013F7F100448 8D 0D 95 11 00 00lea         rcx,
000000013F7F1028BA 05 00 00 00      mov         edx,0x5
000000013F7F102DFF D0               call      rax
000000013F7F102F58                  pop         rax
*/
ULONGLONG GetKeServiceDescriptorTable64();
ULONGLONG GetSSDTFuncCurAddr(ULONG id);
VOID GetKeResumeThreadAddr();
VOID GetPsSuspendThreadAddr();
VOID GetKeSuspendThreadAddr();
ULONGLONG SearchApiWin7x64();
ULONGLONG GetKeServiceDescriptorTable64();
void WPOFFx64();
void WPONx64();
VOID InjectShellCode(PETHREAD pThread,PEPROCESS pProcess);
BOOLEAN Inject(char* strProc, int len);
VOID Ring0Win7X64WinExec();

typedef struct WorkItemContext{
    PWORK_QUEUE_ITEM Item;
    HANDLE Pid;
}WorkItemContext;



ULONGLONG GetKeServiceDescriptorTable64() //我的方法
{
      PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
      PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
      PUCHAR i = NULL;
      UCHAR b1 = 0, b2 = 0, b3 = 0;
      ULONG templong = 0;
      ULONGLONG addr = 0;
      for (i = StartSearchAddress; i<EndSearchAddress; i++)
      {
                if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))
                {
                        b1 = *i;
                        b2 = *(i + 1);
                        b3 = *(i + 2);
                        if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15) //4c8d15
                        {
                              memcpy(&templong, i + 3, 4);
                              addr = (ULONGLONG)templong + (ULONGLONG)i + 7;
                              return addr;
                        }
                }
      }
      return 0;
}


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

*/

ULONGLONG GetSSDTFuncCurAddr(ULONG id)
{
      LONG dwtmp=0;
      PULONG ServiceTableBase=NULL;
      KeServiceDescriptorTable = (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
      DbgPrint("KeServiceDescriptorTable addr:%llx", KeServiceDescriptorTable);
      if (KeServiceDescriptorTable == 0)
      {
                return 0;
      }
      ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase;
      dwtmp=ServiceTableBase;
      dwtmp=dwtmp>>4;
      return (LONGLONG)dwtmp + (ULONGLONG)ServiceTableBase;
}

VOID GetKeResumeThreadAddr()
{
      ULONG32 callcode=0;
      ULONG64 AddressOfPspTTBP=0,AddressOfPsTST=0,i=0; //保存导出PsSuspendThread函数的地址
      ULONG64 AddressOfPsTSTHigh32=0;
      UNICODE_STRING UniCodeFunctionName;
      AddressOfPsTST=GetSSDTFuncCurAddr(79);
      if (AddressOfPsTST == 0)
      {
                return;
      }

      
      DbgPrint("NtResumeThread:%llx\n",AddressOfPsTST);
      if(KeResumeThread==NULL)
      {
                if(AddressOfPsTST==0)
                        return;

                //根据特征码寻找 特征码 01 e8
                for(i=1;i<0xff;i++)
                {
                        if(MmIsAddressValid((PVOID)(AddressOfPsTST+i))!=FALSE)
                        {
                              if(*(BYTE *)(AddressOfPsTST+i)==0x60 && *(BYTE *)(AddressOfPsTST+i+1)==0xe8) //目标地址-原始地址-5=机器码 ==> 目标地址=机器码+5+原始地址
                              {
                                        DbgPrint("AddressOfPsTST+i:%llx\n",AddressOfPsTST+i);
                                        RtlMoveMemory(&callcode,(PVOID)(AddressOfPsTST+i+2),4);
                                        AddressOfPsTSTHigh32=AddressOfPsTST&0xFFFFFFFF00000000;
                                        AddressOfPspTTBP=(ULONG64)(callcode + 5 + (ULONG32)AddressOfPsTST+i+1)+AddressOfPsTSTHigh32;
                                        break;
                              }
                        }
                }
                KeResumeThread=(pfnZwSuspendThread)AddressOfPspTTBP;
                DbgPrint("KeResumeThreadAddr:%llx\n",KeResumeThread);
      
      }

}

VOID GetPsSuspendThreadAddr()
{
      ULONG32 callcode=0;
      ULONG64 AddressOfPspTTBP=0,AddressOfPsTST=0,i=0; //保存导出PsSuspendThread函数的地址
      ULONG64 AddressOfPsTSTHigh32=0;
      UNICODE_STRING UniCodeFunctionName;
      AddressOfPsTST=GetSSDTFuncCurAddr(379);
      if (AddressOfPsTST == 0)
      {
                return;
      }

      
      DbgPrint("NtSuspendThread:%llx\n",AddressOfPsTST);
      if(PsSuspendThreadAddr==0)
      {
                if(AddressOfPsTST==0)
                        return;

                //根据特征码寻找 特征码 01 e8
                for(i=1;i<0xff;i++)
                {
                        if(MmIsAddressValid((PVOID)(AddressOfPsTST+i))!=FALSE)
                        {
                              if(*(BYTE *)(AddressOfPsTST+i)==0x68 && *(BYTE *)(AddressOfPsTST+i+1)==0xe8) //目标地址-原始地址-5=机器码 ==> 目标地址=机器码+5+原始地址
                              {
                                        DbgPrint("AddressOfPsTST+i:%llx\n",AddressOfPsTST+i);
                                        RtlMoveMemory(&callcode,(PVOID)(AddressOfPsTST+i+2),4);
                                        AddressOfPsTSTHigh32=AddressOfPsTST&0xFFFFFFFF00000000;
                                        AddressOfPspTTBP=(ULONG64)(callcode + 5 + (ULONG32)AddressOfPsTST+i+1)+AddressOfPsTSTHigh32;
                                        break;
                              }
                        }
                }
                PsSuspendThreadAddr=AddressOfPspTTBP;
                DbgPrint("PsSuspendThreadAddr:%llx\n",PsSuspendThreadAddr);
      
      }

}

VOID GetKeSuspendThreadAddr()
{
      ULONG64 PspExitThread=0;
      ULONG32 callcode=0;
      ULONG64 AddressOfPsTSTHigh32=0; //用于保存地址的高32位
      
      ULONG64 AddressOfPspTTBP=0,AddressOfPsTST=0,i=0; //保存导出PsTerminateSystemThread函数的地址
      AddressOfPsTST=(ULONG64)PsSuspendThreadAddr;
      DbgPrint("PsSuspendThreadAddr:%llx\n",AddressOfPsTST);
      if(KeSuspendThread==NULL)
      {
                if(AddressOfPsTST==0)
                        return;

                //根据特征码寻找 特征码 8b cd e8
                for(i=1;i<0xff;i++)
                {
                        if(MmIsAddressValid((PVOID)(AddressOfPsTST+i))!=FALSE)
                        {
                              if(*(BYTE *)(AddressOfPsTST+i)==0x8b && *(BYTE *)(AddressOfPsTST+i+1)==0xce && *(BYTE *)(AddressOfPsTST+i+2)==0xe8) //目标地址-原始地址-5=机器码 ==> 目标地址=机器码+5+原始地址
                              {
                                        RtlMoveMemory(&callcode,(PVOID)(AddressOfPsTST+i+3),4);
                                        DbgPrint("callcode:%llx\n",(ULONG64)callcode);
                                        AddressOfPsTSTHigh32=AddressOfPsTST&0xFFFFFFFF00000000;
                                        AddressOfPspTTBP=(ULONG64)(callcode + 5 + (ULONG32)AddressOfPsTST+i+2)+AddressOfPsTSTHigh32;
                                        break;
                              }
                        }
                }
                KeSuspendThread=(pfnZwSuspendThread)AddressOfPspTTBP;
                DbgPrint("KeSuspendThread:%llx\n",KeSuspendThread);
      
      }

}

ULONGLONG SearchApiWin7x64()
{
    PPEB peb = NULL;
      PUCHAR lpname = NULL;
      ULONGLONG peb_ldr_data;
      ULONGLONG ModuleList;
      ULONGLONG dllbase;
      ULONGLONG exe_header;
      ULONGLONG MyOptionalHeader;
      ULONG OutputRva;
      ULONG MyAddressOfNames;
      ULONG MyVirtualAddressVal;
      ULONG AddrOfNamesRva;
      ULONG myFunRva;
      ULONG NumberOfNames;
      ULONGLONG FuncAddr;
      ULONG AddrOfFuncsRva;
      ULONGLONG WinExecAddr;
      ULONG WinExecAddrRva;
      PSTR myFun;
      PLDR_DATA_TABLE_ENTRY data = NULL;
      UNICODE_STRING sFullDllName;
               
      PEPROCESS pSystemProcess = PsGetCurrentProcess();
      PLIST_ENTRY pCurrentList = (PLIST_ENTRY)((PUCHAR)pSystemProcess + 0x188); //ActiveProcessLinks
    PLIST_ENTRY pTempList = pCurrentList;
    PEPROCESS pEProcess = NULL;
      do{
               
                pEProcess = (PEPROCESS)((PUCHAR)pTempList - 0x188);
                peb = (PPEB)(*(PULONGLONG)((PUCHAR)pEProcess + 0x338));//peb
                lpname = (PUCHAR)pEProcess + 0x2e0; // ImageFileName
                //DbgPrint("process %s\n", lpname);
                if((peb != NULL)&&(_strnicmp(lpname, "explorer.exe", 8) == 0)) //找到进程 explorer.exe
                {
                        PKAPC_STATE pKs = (PKAPC_STATE)ExAllocatePool(NonPagedPool, sizeof(PKAPC_STATE));
                        DbgPrint("process %s\n", lpname);
                        KeStackAttachProcess((PKPROCESS)pEProcess,pKs);
                        
                        peb_ldr_data= *(PULONGLONG)((PUCHAR)peb+0x018);
                        DbgPrint("peb_ldr_data: %llx\n", peb_ldr_data);      
                        ModuleList = *(PULONGLONG)((PUCHAR)peb_ldr_data+0x030);
                        data = (PLDR_DATA_TABLE_ENTRY)((PUCHAR)ModuleList-0x020);
                        sFullDllName= data->FullDllName;
                        //找到kernel32.dll
                        while(wcsstr(sFullDllName.Buffer,L"kernel32.dll") == NULL)
                        {
                              ModuleList =*(PULONGLONG) ModuleList; //取下一个模块
                              data = (PLDR_DATA_TABLE_ENTRY)((PUCHAR)ModuleList-0x020);
                              sFullDllName= data->FullDllName;
                        }
                        data = (PLDR_DATA_TABLE_ENTRY)((PUCHAR)ModuleList-0x020); //此时的data为kernel32.dll对应的LDR_DATA_TABLE_ENTRY结构体
                        sFullDllName= data->FullDllName;
                        
                        dllbase = *(PULONGLONG)((PUCHAR)data+0x030);
                        DbgPrint("dllbase:%llx\n",dllbase);
                        
                        exe_header = dllbase+(*(PULONG)(dllbase+0x3c));//PE header
                        DbgPrint("exe_header:%llx\n",exe_header);
                        
                        MyOptionalHeader=exe_header+0x018;
                        
                        DbgPrint("MyOptionalHeader:%llx\n",MyOptionalHeader);
                        
                        MyVirtualAddressVal = *(PULONG)(MyOptionalHeader+0x070); //VirtualAddressVal的值
                        
                        DbgPrint("MyVirtualAddressVal:%x\n",MyVirtualAddressVal);
                        
                        NumberOfNames = *(PULONG)(MyVirtualAddressVal + dllbase + 0x18); //函数的数量
                        
                        AddrOfFuncsRva = *(PULONG)(MyVirtualAddressVal + dllbase + 0x1c); //AddrOfFuns的rva
                        
                        WinExecAddrRva = *(PULONG)(AddrOfFuncsRva+dllbase+(0x528-0x1)*4); //winexec偏移地址
                        
                        DbgPrint("WinExecAddrRva:%x\n",WinExecAddrRva);
                        
                        WinExecAddr =WinExecAddrRva+dllbase; //winexec地址
                        
                        DbgPrint("WinExecAddr:%llx\n",WinExecAddr);                              
                        
                        //以下是获取第一个函数名字代码
                        /*
                        AddrOfNamesRva=*(PULONG)((ULONGLONG)MyVirtualAddressVal + dllbase + 0x20); //AddrOfNames的偏移地址
                        
                        DbgPrint("AddrOfNamesRva:%x\n",AddrOfNamesRva);
                        
                        myFunRva = *(PULONG)((ULONGLONG)AddrOfNamesRva + dllbase); //函数名字的偏移地址
                        
                        myFun = (PSTR)((ULONGLONG)myFunRva + dllbase ); //函数名字的地址
                        
                        DbgPrint("myFun:%s\n",myFun);
                        */
                              
                        KeUnstackDetachProcess(pKs);
                        
                        
                        
                        
                }
                pTempList = pTempList->Flink;//下一个活动的进程

      } while(pCurrentList != pTempList);
      
      return WinExecAddr;
}

void WPOFFx64()
{
      UINT64 cr0=__readcr0();
      cr0 &= 0xfffffffffffeffff;
      __writecr0(cr0);
      _disable();
}

//打开写保护
void WPONx64()
{
      UINT64 cr0=__readcr0();
      cr0 |= 0x10000;
      _enable();
      __writecr0(cr0);
}

VOID InjectShellCode(PETHREAD pThread,PEPROCESS pProcess)
{
      ULONGLONG i;
      ULONGLONG startaddr;
      PKTRAP_FRAME pTrapFrame;
      ULONG jmpOffset;
      PCLIENT_IDpCid;
      OBJECT_ATTRIBUTES oa;
      HANDLE hProcess;
      NTSTATUS ntstatus;
      PVOID lpTargetPath = NULL;
      ULONGLONG pathAddr;
      ULONGLONG patht;
      ULONG offAddr;
      KIRQL irql;
      int len;
      PUCHAR ShellCode_Const = "\x50\x48\xC7\xC0\x50\x8D\x0C\x77\x48\x8D\x0D\x95\x11\x00\x00\xBA\x05\x00\x00\x00\xFF\xD0\x58\xE9\x78\x56\x34\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
    PUCHAR ShellCode = ExAllocatePool(PagedPool, 72);
      RtlMoveMemory(ShellCode, ShellCode_Const, 72);
      
      DbgBreakPoint();

      DbgPrint("Inject Start\n");
      
      
      __try {
                KeSuspendThread(pThread, NULL);
      }
      __except(1) {
                return;
      }
      
      // PTrapFrame中就是该线程的各个寄存器的值
      pTrapFrame = *(PKTRAP_FRAME*)((ULONGLONG)pThread + 0x1d8);
      //如果
      if (pTrapFrame == 0)
      {
                return;
      }

      DbgPrint("pTrapFrame:%llx\n",pTrapFrame);      
      DbgPrint("ShellCode addr:%llx\n",ShellCode);
      startaddr = (ULONGLONG)ShellCode;

      



WPOFFx64();
RtlCopyMemory((PUCHAR)startaddr + 4, &g_WinExec, 4);    //填写winexec地址

lpTargetPath = (PVOID)((ULONGLONG)startaddr + 32);
memset(lpTargetPath, 0, 40);
DbgPrint("path len:%d\n",strlen(path));
DbgPrint("path addr: %llx\n",path);
pathAddr = ((ULONGLONG)startaddr + 40);
offAddr = (ULONG)(pathAddr-startaddr-15);
RtlCopyMemory((PVOID)((PUCHAR)startaddr + 40), path, 32); //拷贝path字符串到shellcode中
RtlCopyMemory((PUCHAR)startaddr + 11, &offAddr, 4); //拷贝偏移量到shellcode中

WPONx64();



// 下面的代码是分配空间来放置ShellCode
InitializeObjectAttributes(&oa,0,0,0,0);
pCid = (CLIENT_ID*)((ULONGLONG)pThread + 0x3b8);
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);
          //设置jmp 原rip
          DbgPrint("buf addr:%llx\n",pBuff);
          DbgPrint("Rip:%llx]n",(ULONGLONG)pTrapFrame->Rip);
          jmpOffset=(ULONG)(((ULONG)pTrapFrame->Rip)-(ULONG)pBuff-0x1c);
          for( i = startaddr; i <= startaddr + 0x72; ++i ) {
                if( MmIsAddressValid((PVOID)i) && MmIsAddressValid((PVOID)(i+7)) ){
                        if ( *(PULONG)i == 0x12345678 )
                        {
                              DbgPrint("find modify point\n");
                              WPOFFx64();
                              *(PULONG)i = jmpOffset;//修改跳转地址,执行完shellcode跳到原Rip
                              WPONx64();
                              break;
                        }
      }
      }

          RtlCopyMemory(pBuff,ShellCode,72);//拷贝ShellCode过去

      KeUnstackDetachProcess (&kapc);
      // pTrapFrame->Eip指向ShellCode
          DbgPrint("buf addr:%llx\n",pBuff);
      pTrapFrame->Rip = (ULONGLONG)pBuff;
         
      }
      ZwClose(hProcess);
}
KeResumeThread(pThread, NULL);
DbgPrint("Inject End\n");
}

BOOLEAN Inject(char* strProc, int len)
{
      PPEB peb = NULL;
      PUCHAR lpname = NULL;
      PEPROCESS pProcess;
      PETHREAD pThread;
      PLIST_ENTRY pListHead, pNextEntry;
      PLIST_ENTRY pThListHead, pThNextEntry;
      UCHAR SuspendCount;
      ULONG CrossThreadFlags;
      pProcess = PsGetCurrentProcess();
      pListHead = (PLIST_ENTRY)((PUCHAR)pProcess + 0x188);//win7x64下是188 //ActiveProcessLinks
      pNextEntry = pListHead;
      do
      {
                pProcess = (PEPROCESS)((ULONGLONG)pNextEntry - 0x188);
                peb = (PPEB)(*(PULONGLONG)((PUCHAR)pProcess + 0x338));//peb
                lpname = (PUCHAR)pProcess + 0x2e0; // ImageFileName
                DbgPrint("process %s\n", lpname);
               
                //if( !_strnicmp((char*)pProcess + 0x2e0, strProc, len) )
                if( !_strnicmp(lpname, strProc, len) )
                {
                        DbgPrint("find process\n");
                        pThListHead = (PLIST_ENTRY)((ULONGLONG)pProcess + 0x308);
                        pThNextEntry = pThListHead->Flink;
                        while ( pThNextEntry != pThListHead)
                        {
                              //查找符合条件的线程
                              pThread = (PETHREAD)((ULONGLONG)pThNextEntry - 0x428);
                              SuspendCount = *(PUCHAR)((ULONGLONG)pThread + 0x26c);
                              CrossThreadFlags = *(PULONG)((ULONGLONG)pThread + 0x450);
                              if( !SuspendCount && (CrossThreadFlags & PS_CROSS_THREAD_FLAGS_SYSTEM) == 0 )
                              {
                                        //非Suspen,非退出,非内核
                                        DbgPrint("find thread\n");
                                        DbgPrint("pThread addr:%llx\n",pThread);
                                        InjectShellCode(pThread,pProcess);
                                        return TRUE;
                                        break;
                              }
                              pThNextEntry = pThNextEntry->Flink;
                              
                        }
                        break;
                }
                pNextEntry = pNextEntry->Flink;
      } while(pNextEntry != pListHead);
      return FALSE;
}

VOID Ring0Win7X64WinExec()
{
    //得到KeSuspendThreadAddr地址
      GetPsSuspendThreadAddr();
      GetKeSuspendThreadAddr();
      
      //得到KeResumeThread地址
      GetKeResumeThreadAddr();
      
      //获取WinExec地址
      g_WinExec = SearchApiWin7x64();
      
      Inject("explorer.exe",8);

}

页: [1]
查看完整版本: 如何从Windows内核中启动一个R3的程序