看流星社区

 找回密码
 注册账号
查看: 6003|回复: 16

x86与x64下内核APC注入源码

[复制链接]

该用户从未签到

发表于 2018-2-27 12:41:24 | 显示全部楼层 |阅读模式
关于内核插入用户apc,简单整理了一下思路和代码,参考《windows内核情景分析》中apc的介绍。
先简单总结一下APC的一些常用知识点吧:
APC,即异步过程调用,是针对具体线程、要求由具体线程在某一时刻加以执行的函数信息集合。
所以每一个线程都有自己的APC队列,APC队列相关信息保存在KTHREAD中
dt _kthread
nt!_KTHREAD
   +0x000 Header           : _DISPATCHER_HEADER
        ……
   +0x040 ApcState         : _KAPC_STATE
   +0x040 ApcStateFill     : [23] UChar
   +0x057 Priority         : Char
   +0x058 NextProcessor    : Uint4B
   +0x05c DeferredProcessor : Uint4B
   +0x060 ApcQueueLock     : Uint4B
         ……
+0x130 CallbackDepth    : Uint4B
   +0x134 ApcStateIndex    : UChar
       ……
   +0x168 ApcStatePointer  : [2] Ptr32 _KAPC_STATE
   +0x170 SavedApcState    : _KAPC_STATE
   +0x170 SavedApcStateFill : [23] UChar
   +0x187 WaitReason       : UChar
         ……
   +0x194 SuspendApc       : _KAPC
         ……
APC队列存放于结构体_KAPC_STATE中
kd> dt _KAPC_STATE
nt!_KAPC_STATE
   +0x000 ApcListHead      : [2] _LIST_ENTRY
   +0x010 Process          : Ptr32 _KPROCESS
   +0x014 KernelApcInProgress : UChar
   +0x015 KernelApcPending : UChar
   +0x016 UserApcPending   : UChar
在ApcListHead就是APC的队列头,由此结构可以看出,该队列有两条,分别为内核APC队列和用户层APC队列,两个队列中的函数分别只在内核或用户空间执行。在KTHREAD中还有ApcStatePointer , SavedApcState, ApcStateIndex 这些结构,当一个进程挂靠到另一个进程时这些结构用于保存当前的APC信息ApcStateIndex代表当前前程是出于挂靠状态还是原始状态。不管是插入内核apc还是用户apc,系统都需要将一个KAPC结构挂入相应队列中
kd> dt _kapc
nt!_KAPC
   +0x000 Type             : UChar
   +0x001 SpareByte0       : UChar
   +0x002 Size             : UChar
   +0x003 SpareByte1       : UChar
   +0x004 SpareLong0       : Uint4B
   +0x008 Thread           : Ptr32 _KTHREAD
   +0x00c ApcListEntry     : _LIST_ENTRY
   +0x014 KernelRoutine    : Ptr32     void
   +0x018 RundownRoutine   : Ptr32     void
   +0x01c NormalRoutine    : Ptr32     void
   +0x020 NormalContext    : Ptr32 Void
   +0x024 SystemArgument1  : Ptr32 Void
   +0x028 SystemArgument2  : Ptr32 Void
   +0x02c ApcStateIndex    : Char
   +0x02d ApcMode          : Char
   +0x02e Inserted         : UChar
这里的NormalRoutine就是需要执行的APC函数,KernelRoutine需要用来释放apc结构,而且KernelRoutine总是会得到执行的,而且无论是内核apc还是用户apc,KernelRoutine的执行时机总是在NormalRoutine之前。
内核APC总是在用户APC之前执行,而且内核apc是在线程降低运行级别,或者进程切换时执行的,而用户APC是在线程由内核返回到用户层时得到执行的。
内核apc kernelRoutine -> 内核apc normalRoutine -> 用户apc kernelRoutine -> 用户apc normalRoutine
内核apc是一次执行队列中所有的内核apc函数(一个while循环依次执行),而用户apc则一次只执行第一项apc请求。而且用户APC的执行流程相对来说比较复杂,毛老师的书里面说的很详细。

APC注入流程:

注入的流程中,在目标进程中分配内存不要使用MDL,mdl在win7上注入系统进程崩溃,mdl没有执行权限,在xp上还行,网上有很多代码都是在这里用mdl来分配内存,那都是在xp上跑可以,win7上总是崩,记得当时刚开始玩的时候一直堵在这,知道有问题也不知道咋改-,-,就是想找个能在win7上好好跑起来的内核注入真的超级难。

shellcode:
APC注入的基本流程就是这样,另外一个重要的地方就是shellcode吧,一开始也是坑的不行。
首先,我们需要被注入的程序执行LoadLibraryA来加载我们的dll,所以,我们要先定位 LoadLibraryA的地址,正常且比较好的方法应该是找进程PEB,通过PEB找kernel32.dll的地址,然后遍历他的导出表找到 LoadLibraryA。或者你也可以找到kernel32后,用 kernel32 基址加大小直接搜 LoadLibraryA,但是这样会有死掉的风险,搜也不能整个 kernel32 大小的搜,因为有些地方是无法访问的,根据PE文件结构来看,可能是有些地址并没有映射,或者被换出之类的(猜的-,-),这里有知道的老师帮忙解答一下吧~~。代码里我用的是比较稳妥的遍历导出表的方法,网上找了一个x86的稍作修改就可以

  1. BOOLEAN get_loadlibrarya_from_kernel32_eat(char* dllPath, void* unused1, void* unused2)
  2. {
  3.     PVOID ulModuleBase;
  4.     PCHAR functionName;
  5.     WORD* arrayOfFunctionOrdinals;
  6.     ULONG functionOrdinal;
  7.     ULONG* arrayOfFunctionAddresses;
  8.     ULONG* arrayOfFunctionNames;
  9.     ULONG_PTR Base, x, functionAddress;
  10.     PIMAGE_DOS_HEADER pDosHeader;
  11.     PIMAGE_NT_HEADERS NtDllHeader;
  12.     IMAGE_OPTIONAL_HEADER opthdr;
  13.     IMAGE_EXPORT_DIRECTORY *pExportTable;

  14.      __asm
  15.      {
  16.          pushad
  17.          pushfd

  18.          lea ecx, ulModuleBase
  19.          mov ebx, fs:[0x30]
  20.          mov ebx, [ebx + 0x0c]//_PEB_LDR_DATA
  21.          mov ebx, [ebx + 0x0c]//InLoadOrderModuleList
  22.          mov ebx, [ebx]
  23.          mov ebx, [ebx]
  24.          mov eax, [ebx + 0x18]//kernel32 address
  25.          mov[ecx], eax

  26.          popfd
  27.          popad
  28.      }

  29.     pDosHeader = (PIMAGE_DOS_HEADER)ulModuleBase;//dos头
  30.     NtDllHeader = (PIMAGE_NT_HEADERS)(ULONG_PTR)((ULONG_PTR)pDosHeader + pDosHeader->e_lfanew);//nt头
  31.     opthdr = NtDllHeader->OptionalHeader;//pe可选镜像头
  32.     pExportTable = (IMAGE_EXPORT_DIRECTORY*)((ULONG_PTR)ulModuleBase +
  33.                                 opthdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
  34.     arrayOfFunctionNames = (ULONG_PTR*)((BYTE*)ulModuleBase + pExportTable->AddressOfNames);//函数名表
  35.     arrayOfFunctionOrdinals = (WORD*)((BYTE*)ulModuleBase + pExportTable->AddressOfNameOrdinals);// 函数索引号RVA
  36.     arrayOfFunctionAddresses = (ULONG_PTR*)((ULONG_PTR)ulModuleBase + pExportTable->AddressOfFunctions);//地址表
  37.     Base = pExportTable->Base;
  38.     for (x = 0; x < pExportTable->NumberOfFunctions; x++) //在整个导出表里扫描
  39.     {
  40.         functionName = (char*)((BYTE*)ulModuleBase + arrayOfFunctionNames[x]);//函数名字
  41.         if ('L' == *functionName && 'o' == *(functionName + 1) && 'a' == *(functionName + 2) &&
  42.             'd' == *(functionName + 3) && 'L' == *(functionName + 4) &&
  43.             'i' == *(functionName + 5)&& 'b' == *(functionName + 6) && 'r' == *(functionName + 7) &&
  44.             'a' == *(functionName + 8) && 'r' == *(functionName + 9) &&
  45.             'y' == *  (functionName + 10) && 'A' == *(functionName + 11))
  46.         {
  47.             functionOrdinal = arrayOfFunctionOrdinals[x] + Base - 1; //函数索引号RVA[x]
  48.             functionAddress = (ULONG_PTR)((BYTE*)ulModuleBase + arrayOfFunctionAddresses[functionOrdinal]);//函数地址
  49.             ((LOADLIBRARYA)functionAddress)(dllPath);
  50.             return TRUE;
  51.         }
  52.     }
  53.     return FALSE;
  54. }
复制代码



在x64上获取peb是在gs:[60h],kernel32同样也是在第二个dll加载(exe -> ntdll ->kernel32),上面的代码在vs里面提取shellcode就好,注意提取的时候把什么vs自带的检查都去掉(GS什么的),提取出最纯净的代码!

以上,在x86上注入和在x64上注入64位都没有问题。但是!在64位上注入32位的时候,还是出了点问题,以注入目标进程就崩了(可以用来杀进程了= =),一试一个准。
问题出在哪里呢?
这个也是好在已经有前辈们踩过坑了一个APC引起的折腾

wow64!whNtQueueApcThread:
00000000`7477af68 4883ec38 sub rsp,38h
00000000`7477af6c 8b5104 mov edx,dword ptr [rcx+4]
00000000`7477af6f 8b4108 mov eax,dword ptr [rcx+8]
00000000`7477af72 448b490c mov r9d,dword ptr [rcx+0Ch]
00000000`7477af76 448b5110 mov r10d,dword ptr [rcx+10h]
00000000`7477af7a 486309 movsxd rcx,dword ptr [rcx]
00000000`7477af7d 4c8bc0 mov r8,rax
00000000`7477af80 48f7da neg rdx
00000000`7477af83 48c1e202 shl rdx,2
00000000`7477af87 4c89542420 mov qword ptr [rsp+20h],r10
00000000`7477af8c ff156e6cfeff call qword ptr [wow64!_imp_NtQueueApcThread (00000000`74761c00)]
00000000`7477af92 90 nop
00000000`7477af93 4883c438 add rsp,38h
00000000`7477af97 c3 ret

我对这篇文章的理解是
这个 wow64!whNtQueueApcThread应该是用户层32位程序调用 QueueUserAPC的时候会进入这个函数,在这里 whNtQueueApcThread把APC函数的地址进行了求补且左移两位,而我们在内核插入用户apc的时候,可能操作系统就默认你插入的都是64位的apc所以就不做这个地址的转换操作。So,我们在内核插入32位进程apc的时候需要我们自己来手动对apc函数地址进行求补后左移2位!

好了,上代码
apc_inject_test.c
  1. #include "apc_inject_test.h"
  2. #include "asm_export.h"

  3. #ifdef ALLOC_PRAGMA
  4. #pragma alloc_text(INIT,DriverEntry)
  5. #pragma alloc_text(PAGE,DriverUnload)
  6. #pragma alloc_text(PAGE,ntLoadLibraryA)
  7. #pragma alloc_text(PAGE,WorkThreAd_Exec)
  8. #pragma alloc_text(PAGE,uSetTheApc_Exec)
  9. #pragma alloc_text(PAGE,KernelApcCAllBAck_Exec)
  10. #pragma alloc_text(PAGE,find_threAd_Exec)
  11. #endif

  12. BOOLEAN
  13. ntLoadLibraryA(
  14.     PCHAR dllPath
  15.     )
  16. {
  17.     NTSTATUS            status;
  18.     HANDLE              hThreAd = NULL;

  19.     if (strlen(dllPath) > 50)
  20.     {
  21.         KdPrint(("dllpath overflow\n"));
  22.         return FALSE;
  23.     }
  24.     status = PsCreateSystemThread(&hThreAd,
  25.         (ACCESS_MASK)0,
  26.         NULL,
  27.         (HANDLE)0,
  28.         NULL,
  29.         WorkThreAd_Exec,
  30.         dllPath
  31.         );
  32.     if (!NT_SUCCESS(status))
  33.     {
  34.         KdPrint(("PsCreateSystemThread err\n"));
  35.         return FALSE;
  36.     }
  37.     return TRUE;
  38. }

  39. VOID
  40. WorkThreAd_Exec(
  41.     IN PVOID pContext
  42.     )
  43. {
  44.     POINTER         process = 0;
  45.     POINTER         threAd = 0;
  46.     POINTER         func_size = 0;
  47.     POINTER         param_size = 0;
  48.     HANDLE          hProcess = NULL;
  49.     PKEVENT         pEvent = NULL;
  50.     PVOID           func_address = NULL;
  51.     PVOID           param_address = NULL;
  52.     KAPC_STATE      ApcStAte = { 0 };
  53.     PCHAR           dllPath = NULL;
  54.     NTSTATUS        status = 0;

  55.     dllPath = (PCHAR)pContext;
  56.     //寻找一个进程的eprocess,和可以插入apc的线程的线程对象
  57.     if (!find_threAd_Exec(&process, &threAd))
  58.     {
  59.         KdPrint(("cAnnot find the right threAd\n"));
  60.         PsTerminateSystemThread(STATUS_SUCCESS);
  61.     }
  62.     //申请一个event,用来提供通知
  63.     pEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  64.     if (!pEvent)
  65.     {
  66.         KdPrint(("ExAllocatePool(pEvent) fAiled\n"));
  67.         PsTerminateSystemThread(STATUS_SUCCESS);
  68.     }

  69. #ifdef _WIN64
  70. #ifdef INJECT_WOW64
  71.     func_size = sizeof(shellcode);
  72. #else
  73.     func_size = (UCHAR*)call_loadlibrary_end - (UCHAR*)call_loadlibrary;
  74. #endif
  75. #else
  76.     func_size = (UCHAR*)UserExec_end - (UCHAR*)UserExec;
  77. #endif

  78.     KdPrint(("size: %d\n", func_size));
  79.     param_size = 50;
  80.     status = ObOpenObjectByPointer((PVOID)process,
  81.         OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
  82.         NULL,
  83.         GENERIC_ALL,
  84.         *PsProcessType,
  85.         KernelMode,
  86.         &hProcess
  87.         );
  88.     if (!NT_SUCCESS(status))
  89.     {
  90.         KdPrint(("ObOpenObjectByPointer false :%x\n", status));
  91.         PsTerminateSystemThread(STATUS_SUCCESS);
  92.     }
  93.     //使用mdl在win7上注入系统进程崩溃  mdl没有执行权限
  94.     //看雪:MDL在NT5上还是可执行的,但是到了NT6上就不可执行了
  95.     //ZwAllocateVirtualMemory内部有attach和detach进程操作
  96.     //这里的内存释放的时机根据具体业务在判断吧
  97.     status = ZwAllocateVirtualMemory(hProcess, &func_address, 0, &func_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  98.     if (!NT_SUCCESS(status))
  99.     {
  100.         KdPrint(("ZwAllocateVirtualMemory false :%x\n", status));
  101.         PsTerminateSystemThread(STATUS_SUCCESS);
  102.     }
  103.     status = ZwAllocateVirtualMemory(hProcess, &param_address, 0, &param_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  104.     if (!NT_SUCCESS(status))
  105.     {
  106.         KdPrint(("ZwAllocateVirtualMemory false :%x\n", status));
  107.         PsTerminateSystemThread(STATUS_SUCCESS);
  108.     }
  109.     //拷贝apc函数体和参数到用户地址空间
  110.     KeStackAttachProcess((PEPROCESS)process, &ApcStAte);
  111.     RtlZeroMemory(func_address, func_size);

  112. #ifdef _WIN64
  113. #ifdef INJECT_WOW64
  114.     RtlCopyMemory(func_address, shellcode, func_size);
  115. #else
  116.     RtlCopyMemory(func_address, call_loadlibrary, func_size);
  117. #endif
  118. #else
  119.     RtlCopyMemory(func_address, UserExec, func_size);
  120. #endif

  121.     RtlZeroMemory(param_address, param_size);
  122.     RtlCopyMemory(param_address, dllPath, param_size);
  123.     KeUnstackDetachProcess(&ApcStAte);

  124.     KeInitializeEvent(pEvent, NotificationEvent, FALSE);
  125.     //插入apc
  126.     status = uSetTheApc_Exec(process, threAd, (POINTER)func_address, pEvent, param_address);
  127.     if (NT_SUCCESS(status))
  128.     {
  129.         KeWaitForSingleObject(pEvent, Executive, KernelMode, FALSE, NULL);
  130.         KdPrint(("apc inject success!\n"));
  131.     }
  132.     else
  133.     {
  134.         KdPrint(("apc inject failed!\n"));
  135.     }
  136.     ExFreePool(pEvent);
  137.     PsTerminateSystemThread(STATUS_SUCCESS);
  138.     KdPrint(("Never be here \n"));
  139. }

  140. NTSTATUS
  141. uSetTheApc_Exec(
  142.     POINTER         process,
  143.     POINTER         threAd,
  144.     POINTER         MAppedAddress,
  145.     PKEVENT         pEvent,
  146.     PCHAR           dllPath
  147.     )
  148. {
  149.     PKAPC           pkApc;
  150.     BOOLEAN         ret;
  151.     NTSTATUS        dwStAtus = STATUS_SUCCESS;

  152.     *((CHAR*)threAd + USERAPCPENDING_OFFSET) = 1;
  153.     pkApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
  154.     if (pkApc == NULL)
  155.     {
  156.         KdPrint(("error:ExAllocAtePool\n"));
  157.         return STATUS_INSUFFICIENT_RESOURCES;
  158.     }

  159. #if defined(_WIN64) && defined(INJECT_WOW64)
  160.     //在64位系统中插入32位用户apc时apc函数地址需要求补后左移两位
  161.     MAppedAddress = (~MAppedAddress + 1) << 2;
  162. #endif

  163.     //初始化一个APC
  164.     KeInitializeApc(
  165.         pkApc,
  166.         (PKTHREAD)threAd,
  167.         OriginalApcEnvironment,
  168.         (PKKERNEL_ROUTINE)KernelApcCAllBAck_Exec,
  169.         NULL,
  170.         (PKNORMAL_ROUTINE)MAppedAddress,//UserApcCAllBAck,
  171.         UserMode,   //用户模式
  172.         (PVOID)dllPath
  173.         );

  174.     //插入apc
  175.     ret = KeInsertQueueApc(pkApc, pEvent, 0, 0);
  176.     if (!ret){
  177.         KdPrint(("KeInsertQueueApc err\n"));
  178.         return STATUS_UNSUCCESSFUL;
  179.     }
  180.     return STATUS_SUCCESS;
  181. }

  182. VOID
  183. KernelApcCAllBAck_Exec(
  184.     PKAPC Apc,
  185.     PKNORMAL_ROUTINE *NormAlRoutine,
  186.     IN OUT PVOID *NormAlContext,
  187.     IN OUT PVOID *SystemArgument1,
  188.     IN OUT PVOID *SystemArgument2
  189.     )
  190. {
  191.     PKEVENT     pEvent;
  192.     //回调得到执行的时候应该是在KiDeliverApc内部用户apc的KernelRoutine得到执行的时候,而且其实他在normalRoutine之前也就是我们的apc函数之前执行的
  193.     KdPrint(("NormAlContext: 0x%x\n", (POINTER)*NormAlContext));
  194.     pEvent = (PKEVENT)*SystemArgument1;
  195.     if (pEvent)
  196.     {
  197.         KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
  198.     }
  199.     if (Apc)
  200.     {
  201.         ExFreePool(Apc);
  202.     }
  203. }

  204. //找到合适的插入目标
  205. BOOLEAN
  206. find_threAd_Exec(
  207.     OUT POINTER *process,
  208.     OUT POINTER *threAd
  209.     )
  210. {
  211.     POINTER         eproc;
  212.     POINTER         begin_proc;
  213.     POINTER         ethreAd;
  214.     POINTER         begin_threAd;
  215.     PLIST_ENTRY     plist_Active_procs;
  216.     PLIST_ENTRY     plist_threAd;

  217.     //遍历进程
  218.     eproc = (POINTER)PsGetCurrentProcess();
  219.     if (!eproc)
  220.     {
  221.         return FALSE;
  222.     }
  223.     begin_proc = eproc;
  224.     while (1)
  225.     {
  226.         //OBJECT_TABLE_OFFSET 没有句柄表就是死的进程
  227.         if (0 == _stricmp((CHAR*)(eproc + IMAGEFILENAME_OFFSET), "explorer.exe") && (PVOID)(*(POINTER*)((char*)eproc + OBJECT_TABLE_OFFSET)) != NULL)
  228.         {
  229.             break;
  230.         }
  231.         else
  232.         {
  233.             plist_Active_procs = (LIST_ENTRY*)(eproc + ACTIVEPROCESSLINKS_OFFSET);
  234.             eproc = (POINTER)plist_Active_procs->Flink;
  235.             eproc = eproc - ACTIVEPROCESSLINKS_OFFSET;
  236.             if (eproc == begin_proc)
  237.             {
  238.                 return FALSE;
  239.             }
  240.         }
  241.     }
  242.     plist_threAd = (LIST_ENTRY*)(eproc + THREADLISTHEAD_OFFSET);
  243.     ethreAd = (POINTER)plist_threAd->Flink;
  244.     ethreAd = ethreAd - THREADLISTENTRY_OFFSET;
  245.     KdPrint(("threAd: 0x%x\n", ethreAd));

  246.     //遍历线程
  247.     begin_threAd = ethreAd;
  248.     while (1){
  249.         KdPrint(("(*(POINTER*)((POINTER)ethreAd+TCB_TEB_OFFSET): 0x%x\n", *(POINTER*)((CHAR*)ethreAd + TCB_TEB_OFFSET)));
  250.         if ((*(POINTER*)((POINTER)ethreAd + TCB_TEB_OFFSET) != 0))
  251.         {
  252.             break;
  253.         }
  254.         else{
  255.             plist_threAd = (LIST_ENTRY*)(ethreAd + THREADLISTENTRY_OFFSET);
  256.             ethreAd = (POINTER)plist_threAd->Flink;
  257.             ethreAd = ethreAd - THREADLISTENTRY_OFFSET;
  258.             KdPrint(("ethreAd: 0x%x\n", ethreAd));
  259.             if (ethreAd == begin_threAd)
  260.             {
  261.                 return FALSE;
  262.             }
  263.         }
  264.     }
  265.     *process = eproc;
  266.     *threAd = ethreAd;
  267.     return TRUE;
  268. }

  269. VOID
  270. DriverUnload(
  271.     IN PDRIVER_OBJECT DriverObject
  272.     )
  273. {
  274.     if (dllPath)
  275.     {
  276.         ExFreePoolWithTag(dllPath, 'HTAP');
  277.     }
  278.     KdPrint(("DriverUnload\r\n"));
  279. }

  280. NTSTATUS
  281. DriverEntry(
  282.     IN PDRIVER_OBJECT DriverObject,
  283.     IN PUNICODE_STRING pRegistryString
  284.     )
  285. {
  286.     DriverObject->DriverUnload = DriverUnload;
  287.     dllPath = ExAllocatePoolWithTag(PagedPool, 50, 'HTAP');
  288.     if (dllPath)
  289.     {
  290.         RtlCopyMemory(dllPath, "C:\\dlltest32.dll", 50);
  291.         if (ntLoadLibraryA(dllPath))
  292.         {
  293.             return STATUS_SUCCESS;
  294.         }
  295.     }
  296.     return STATUS_UNSUCCESSFUL;
  297. }

  298. #ifndef _WIN64
  299. __declspec(naked)
  300. UserExec(
  301.     PCHAR   dllPath,
  302.     PVOID   unused1,
  303.     PVOID   unused2
  304.     )
  305. {
  306.     __asm
  307.     {
  308.         push        ebp
  309.         mov         ebp, esp
  310.         sub         esp, 150h
  311.         push        ebx
  312.         push        esi
  313.         push        edi
  314.         pushad
  315.         pushfd
  316.         lea         ecx, [ebp - 4]
  317.         mov         ebx, dword ptr fs : [0x00000030]
  318.         mov         ebx, dword ptr[ebx + 0x0C]
  319.         mov         ebx, dword ptr[ebx + 0x0C]
  320.         mov         ebx, dword ptr[ebx]
  321.         mov         ebx, dword ptr[ebx]
  322.         mov         eax, dword ptr[ebx + 18h]
  323.         mov         dword ptr[ecx], eax
  324.         popfd
  325.         popad
  326.         mov         eax, dword ptr[ebp - 4]
  327.         mov         dword ptr[ebp - 28h], eax
  328.         mov         eax, dword ptr[ebp - 28h]
  329.         mov         ecx, dword ptr[ebp - 28h]
  330.         add         ecx, dword ptr[eax + 3Ch]
  331.         mov         dword ptr[ebp - 2Ch], ecx
  332.         mov         esi, dword ptr[ebp - 2Ch]
  333.         add         esi, 18h
  334.         mov         ecx, 38h
  335.         lea         edi, [ebp + 0xFFFFFEF4]
  336.         rep movs    dword ptr es : [edi], dword ptr[esi]
  337.         mov         eax, 8
  338.         imul        ecx, eax, 0
  339.         mov         edx, dword ptr[ebp - 4]
  340.         add         edx, dword ptr[ebp + ecx + 0xFFFFFF54]
  341.         mov         dword ptr[ebp + 0xFFFFFEF0], edx
  342.         mov         eax, dword ptr[ebp + 0xFFFFFEF0]
  343.         mov         ecx, dword ptr[ebp - 4]
  344.         add         ecx, dword ptr[eax + 20h]
  345.         mov         dword ptr[ebp - 18h], ecx
  346.         mov         eax, dword ptr[ebp + 0xFFFFFEF0]
  347.         mov         ecx, dword ptr[ebp - 4]
  348.         add         ecx, dword ptr[eax + 24h]
  349.         mov         dword ptr[ebp - 0Ch], ecx
  350.         mov         eax, dword ptr[ebp + 0xFFFFFEF0]
  351.         mov         ecx, dword ptr[ebp - 4]
  352.         add         ecx, dword ptr[eax + 1Ch]
  353.         mov         dword ptr[ebp - 14h], ecx
  354.         mov         eax, dword ptr[ebp + 0xFFFFFEF0]
  355.         mov         ecx, dword ptr[eax + 10h]
  356.         mov         dword ptr[ebp - 1Ch], ecx
  357.         mov         dword ptr[ebp - 20h], 0
  358.         jmp         s1
  359.     s5 :
  360.         mov         eax, dword ptr[ebp - 20h]
  361.         add         eax, 1
  362.         mov         dword ptr[ebp - 20h], eax
  363.     s1 :
  364.         mov         eax, dword ptr[ebp + 0xFFFFFEF0]
  365.         mov         ecx, dword ptr[ebp - 20h]
  366.         cmp         ecx, dword ptr[eax + 14h]
  367.         jae         s2
  368.         mov         eax, dword ptr[ebp - 20h]
  369.         mov         ecx, dword ptr[ebp - 18h]
  370.         mov         edx, dword ptr[ebp - 4]
  371.         add         edx, dword ptr[ecx + eax * 4]
  372.         mov         dword ptr[ebp - 8], edx
  373.         mov         eax, dword ptr[ebp - 8]
  374.         movsx       ecx, byte ptr[eax]
  375.         cmp         ecx, 4Ch
  376.         jne         s3
  377.         mov         eax, dword ptr[ebp - 8]
  378.         movsx       ecx, byte ptr[eax + 1]
  379.         cmp         ecx, 6Fh
  380.         jne         s3
  381.         mov         eax, dword ptr[ebp - 8]
  382.         movsx       ecx, byte ptr[eax + 2]
  383.         cmp         ecx, 61h
  384.         jne         s3
  385.         mov         eax, dword ptr[ebp - 8]
  386.         movsx       ecx, byte ptr[eax + 3]
  387.         cmp         ecx, 64h
  388.         jne         s3
  389.         mov         eax, dword ptr[ebp - 8]
  390.         movsx       ecx, byte ptr[eax + 4]
  391.         cmp         ecx, 4Ch
  392.         jne         s3
  393.         mov         eax, dword ptr[ebp - 8]
  394.         movsx       ecx, byte ptr[eax + 5]
  395.         cmp         ecx, 69h
  396.         jne         s3
  397.         mov         eax, dword ptr[ebp - 8]
  398.         movsx       ecx, byte ptr[eax + 6]
  399.         cmp         ecx, 62h
  400.         jne         s3
  401.         mov         eax, dword ptr[ebp - 8]
  402.         movsx       ecx, byte ptr[eax + 7]
  403.         cmp         ecx, 72h
  404.         jne         s3
  405.         mov         eax, dword ptr[ebp - 8]
  406.         movsx       ecx, byte ptr[eax + 8]
  407.         cmp         ecx, 61h
  408.         jne         s3
  409.         mov         eax, dword ptr[ebp - 8]
  410.         movsx       ecx, byte ptr[eax + 9]
  411.         cmp         ecx, 72h
  412.         jne         s3
  413.         mov         eax, dword ptr[ebp - 8]
  414.         movsx       ecx, byte ptr[eax + 0Ah]
  415.         cmp         ecx, 79h
  416.         jne         s3
  417.         mov         eax, dword ptr[ebp - 8]
  418.         movsx       ecx, byte ptr[eax + 0Bh]
  419.         cmp         ecx, 41h
  420.         jne         s3
  421.         mov         eax, dword ptr[ebp - 20h]
  422.         mov         ecx, dword ptr[ebp - 0Ch]
  423.         movzx       edx, word ptr[ecx + eax * 2]
  424.         mov         eax, dword ptr[ebp - 1Ch]
  425.         lea         ecx, [edx + eax - 1]
  426.         mov         dword ptr[ebp - 10h], ecx
  427.         mov         eax, dword ptr[ebp - 10h]
  428.         mov         ecx, dword ptr[ebp - 14h]
  429.         mov         edx, dword ptr[ebp - 4]
  430.         add         edx, dword ptr[ecx + eax * 4]
  431.         mov         dword ptr[ebp - 24h], edx
  432.         mov         eax, dword ptr[ebp + 8]
  433.         push        eax
  434.         call        dword ptr[ebp - 24h]
  435.         mov         al, 1
  436.         jmp         s4
  437.     s3 :
  438.         jmp         s5
  439.     s2 :
  440.         xor         al, al
  441.     s4 :
  442.         pop         edi
  443.         pop         esi
  444.         pop         ebx
  445.         mov         esp, ebp
  446.         pop         ebp
  447.         ret
  448.     }
  449. }
  450. __declspec(naked)
  451. UserExec_end(VOID)
  452. {

  453. }
  454. #endif
复制代码


附件里的项目是在vs2013+wdk7600下开发,在xp,win7 32和64上自测注入explorer没有问题。
思路和方法上应该还有很多可以改进的地方,但是就目前我这点水平来说也看不出来什么花了,也希望大家多多指教。。

x86与x64下内核APC注入.zip (12.66 KB, 下载次数: 176, 售价: 5 流星币)

该用户从未签到

发表于 2019-11-18 16:51:33 | 显示全部楼层
看看 64能用不

该用户从未签到

发表于 2019-11-18 16:57:24 | 显示全部楼层
看看 64能用不

该用户从未签到

发表于 2019-11-18 17:00:46 | 显示全部楼层
看看 64能用不

该用户从未签到

发表于 2019-11-18 17:16:59 | 显示全部楼层
看看 64能用不

该用户从未签到

发表于 2019-11-18 17:17:53 | 显示全部楼层
我日 下载购买5个逼 下载1个逼 够黑

该用户从未签到

发表于 2020-3-24 11:06:35 | 显示全部楼层
感谢楼主分享,下载看看

该用户从未签到

发表于 2020-6-13 19:51:07 | 显示全部楼层
楼主分享,下载看看

该用户从未签到

发表于 2020-6-13 19:51:53 | 显示全部楼层
楼主分享,下载看看

该用户从未签到

发表于 2020-6-13 19:52:32 | 显示全部楼层
楼主分享,下载看看
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-4-26 19:33

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表