驱动DLL注入,APC注入,驱动回调注入等实现详细流程及代码!

DLL注入有很多方法,远线程,钩子,输入法,劫持,APC等等。
现在的好多进程都有保护,特别是一些游戏有各种保护如TP TS HS NP CD GPK BE SG3等等保护,这样常规的注入方法就没效果了。

现在流行且稳定的注入方法一般都要用驱动来实现了,驱动注入,APC,回调等都可以用驱动注入。

下载地址:https://download.csdn.net/download/qq1289671197/11869225

驱动部分代码:

#include "apc_inject_test.h"
#include "asm_export.h"

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,DriverEntry)
#pragma alloc_text(PAGE,DriverUnload)
#pragma alloc_text(PAGE,ntLoadLibraryA)
#pragma alloc_text(PAGE,WorkThreAd_Exec)
#pragma alloc_text(PAGE,uSetTheApc_Exec)
#pragma alloc_text(PAGE,KernelApcCAllBAck_Exec)
#pragma alloc_text(PAGE,find_threAd_Exec)
#endif

BOOLEAN 
ntLoadLibraryA(
    PCHAR dllPath
    )
{
    NTSTATUS			status;
    HANDLE				hThreAd = NULL;

    if (strlen(dllPath) > 50)
    {
        KdPrint(("dllpath overflow\n"));
        return FALSE;
    }
    status = PsCreateSystemThread(&hThreAd,
        (ACCESS_MASK)0,
        NULL,
        (HANDLE)0,
        NULL,
        WorkThreAd_Exec,
        dllPath
        );
    if (!NT_SUCCESS(status))
    {
        KdPrint(("PsCreateSystemThread err\n"));
        return FALSE;
    }
    return TRUE;
}

VOID
WorkThreAd_Exec(
    IN PVOID pContext
    )
{
    POINTER			process = 0;
    POINTER         threAd = 0;
    POINTER			func_size = 0;
    POINTER			param_size = 0;
    HANDLE          hProcess = NULL;
    PKEVENT			pEvent = NULL;
    PVOID			func_address = NULL;
    PVOID			param_address = NULL;
    KAPC_STATE		ApcStAte = { 0 };
    PCHAR			dllPath = NULL;
    NTSTATUS        status = 0;

    dllPath = (PCHAR)pContext;
    //寻找一个进程的eprocess,和可以插入apc的线程的线程对象 
    if (!find_threAd_Exec(&process, &threAd))
    {
        KdPrint(("cAnnot find the right threAd\n"));
        PsTerminateSystemThread(STATUS_SUCCESS);
    }
    //申请一个event,用来提供通知
    pEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
    if (!pEvent)
    {
        KdPrint(("ExAllocatePool(pEvent) fAiled\n"));
        PsTerminateSystemThread(STATUS_SUCCESS);
    }

#ifdef _WIN64
#ifdef INJECT_WOW64
    func_size = sizeof(shellcode);
#else
    func_size = (UCHAR*)call_loadlibrary_end - (UCHAR*)call_loadlibrary;
#endif
#else
    func_size = (UCHAR*)UserExec_end - (UCHAR*)UserExec;
#endif

    KdPrint(("size: %d\n", func_size));
    param_size = 50;
    status = ObOpenObjectByPointer((PVOID)process,
        OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
        NULL,
        GENERIC_ALL,
        *PsProcessType,
        KernelMode,
        &hProcess
        );
    if (!NT_SUCCESS(status))
    {
        KdPrint(("ObOpenObjectByPointer false :%x\n", status));
        PsTerminateSystemThread(STATUS_SUCCESS);
    }
    //使用mdl在win7上注入系统进程崩溃  mdl没有执行权限  
    //看雪:MDL在NT5上还是可执行的,但是到了NT6上就不可执行了
    //ZwAllocateVirtualMemory内部有attach和detach进程操作
    //这里的内存释放的时机根据具体业务在判断吧
    status = ZwAllocateVirtualMemory(hProcess, &func_address, 0, &func_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (!NT_SUCCESS(status))
    {
        KdPrint(("ZwAllocateVirtualMemory false :%x\n", status));
        PsTerminateSystemThread(STATUS_SUCCESS);
    }
    status = ZwAllocateVirtualMemory(hProcess, &param_address, 0, &param_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (!NT_SUCCESS(status))
    {
        KdPrint(("ZwAllocateVirtualMemory false :%x\n", status));
        PsTerminateSystemThread(STATUS_SUCCESS);
    }
    //拷贝apc函数体和参数到用户地址空间
    KeStackAttachProcess((PEPROCESS)process, &ApcStAte);
    RtlZeroMemory(func_address, func_size);

#ifdef _WIN64
#ifdef INJECT_WOW64
    RtlCopyMemory(func_address, shellcode, func_size);
#else
    RtlCopyMemory(func_address, call_loadlibrary, func_size);
#endif
#else
    RtlCopyMemory(func_address, UserExec, func_size);
#endif

    RtlZeroMemory(param_address, param_size);
    RtlCopyMemory(param_address, dllPath, param_size);
    KeUnstackDetachProcess(&ApcStAte);

    KeInitializeEvent(pEvent, NotificationEvent, FALSE);
    //插入apc
    status = uSetTheApc_Exec(process, threAd, (POINTER)func_address, pEvent, param_address);
    if (NT_SUCCESS(status))
    {
        KeWaitForSingleObject(pEvent, Executive, KernelMode, FALSE, NULL);
        KdPrint(("apc inject success!\n"));
    }
    else
    {
        KdPrint(("apc inject failed!\n"));
    }
    ExFreePool(pEvent);
    PsTerminateSystemThread(STATUS_SUCCESS);
    KdPrint(("Never be here \n"));
}

NTSTATUS 
uSetTheApc_Exec(
    POINTER			process,
    POINTER			threAd,
    POINTER			MAppedAddress,
    PKEVENT			pEvent,
    PCHAR			dllPath
    )
{
    PKAPC			pkApc;
    BOOLEAN			ret;
    NTSTATUS		dwStAtus = STATUS_SUCCESS;

    *((CHAR*)threAd + USERAPCPENDING_OFFSET) = 1;
    pkApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
    if (pkApc == NULL)
    {
        KdPrint(("error:ExAllocAtePool\n"));
        return STATUS_INSUFFICIENT_RESOURCES;
    }

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

    //初始化一个APC
    KeInitializeApc(
        pkApc,
        (PKTHREAD)threAd,
        OriginalApcEnvironment,
        (PKKERNEL_ROUTINE)KernelApcCAllBAck_Exec,
        NULL,
        (PKNORMAL_ROUTINE)MAppedAddress,//UserApcCAllBAck,
        UserMode,	//用户模式
        (PVOID)dllPath
        );

    //插入apc
    ret = KeInsertQueueApc(pkApc, pEvent, 0, 0);
    if (!ret){
        KdPrint(("KeInsertQueueApc err\n"));
        return STATUS_UNSUCCESSFUL;
    }
    return STATUS_SUCCESS;
}

VOID
KernelApcCAllBAck_Exec(
    PKAPC Apc,
    PKNORMAL_ROUTINE *NormAlRoutine,
    IN OUT PVOID *NormAlContext,
    IN OUT PVOID *SystemArgument1,
    IN OUT PVOID *SystemArgument2
    )
{
    PKEVENT		pEvent;
    //回调得到执行的时候应该是在KiDeliverApc内部用户apc的KernelRoutine得到执行的时候,而且其实他在normalRoutine之前也就是我们的apc函数之前执行的
    KdPrint(("NormAlContext: 0x%x\n", (POINTER)*NormAlContext));
    pEvent = (PKEVENT)*SystemArgument1;
    if (pEvent)
    {
        KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
    }
    if (Apc)
    {
        ExFreePool(Apc);
    }
}

//找到合适的插入目标
BOOLEAN
find_threAd_Exec(
    OUT	POINTER	*process,
    OUT	POINTER	*threAd
    )
{
    POINTER			eproc;
    POINTER			begin_proc;
    POINTER			ethreAd;
    POINTER			begin_threAd;
    PLIST_ENTRY		plist_Active_procs;
    PLIST_ENTRY		plist_threAd;

    //遍历进程
    eproc = (POINTER)PsGetCurrentProcess();
    if (!eproc)
    {
        return FALSE;
    }
    begin_proc = eproc;
    while (1)
    {
        //OBJECT_TABLE_OFFSET 没有句柄表就是死的进程
        if (0 == _stricmp((CHAR*)(eproc + IMAGEFILENAME_OFFSET), "mir.exe") && (PVOID)(*(POINTER*)((char*)eproc + OBJECT_TABLE_OFFSET)) != NULL)
        {
            break;
        }
        else
        {
            plist_Active_procs = (LIST_ENTRY*)(eproc + ACTIVEPROCESSLINKS_OFFSET);
            eproc = (POINTER)plist_Active_procs->Flink;
            eproc = eproc - ACTIVEPROCESSLINKS_OFFSET;
            if (eproc == begin_proc)
            {
                return FALSE;
            }
        }
    }
    plist_threAd = (LIST_ENTRY*)(eproc + THREADLISTHEAD_OFFSET);
    ethreAd = (POINTER)plist_threAd->Flink;
    ethreAd = ethreAd - THREADLISTENTRY_OFFSET;
    KdPrint(("threAd: 0x%x\n", ethreAd));

    //遍历线程
    begin_threAd = ethreAd;
    while (1){
        KdPrint(("(*(POINTER*)((POINTER)ethreAd+TCB_TEB_OFFSET): 0x%x\n", *(POINTER*)((CHAR*)ethreAd + TCB_TEB_OFFSET)));
        if ((*(POINTER*)((POINTER)ethreAd + TCB_TEB_OFFSET) != 0))
        {
            break;
        }
        else{
            plist_threAd = (LIST_ENTRY*)(ethreAd + THREADLISTENTRY_OFFSET);
            ethreAd = (POINTER)plist_threAd->Flink;
            ethreAd = ethreAd - THREADLISTENTRY_OFFSET;
            KdPrint(("ethreAd: 0x%x\n", ethreAd));
            if (ethreAd == begin_threAd)
            {
                return FALSE;
            }
        }
    }
    *process = eproc;
    *threAd = ethreAd;
    return TRUE;
}

VOID 
DriverUnload(
    IN PDRIVER_OBJECT DriverObject
    )
{
    if (dllPath)
    {
        ExFreePoolWithTag(dllPath, 'HTAP');
    }
    KdPrint(("DriverUnload\r\n"));
}

NTSTATUS 
DriverEntry(
    IN PDRIVER_OBJECT DriverObject, 
    IN PUNICODE_STRING pRegistryString
    )
{
    DriverObject->DriverUnload = DriverUnload;
    dllPath = ExAllocatePoolWithTag(PagedPool, 50, 'HTAP');
    if (dllPath)
    {
        RtlCopyMemory(dllPath, "C:\\MyHook.dll", 50);
        if (ntLoadLibraryA(dllPath))
        {
            return STATUS_SUCCESS;
        }
    }
    return STATUS_UNSUCCESSFUL;
}

#ifndef _WIN64
__declspec(naked)
UserExec(
    PCHAR	dllPath,
    PVOID	unused1,
    PVOID	unused2
    )
{
    __asm
    {
        push        ebp
        mov         ebp, esp
        sub         esp, 150h
        push        ebx
        push        esi
        push        edi
        pushad
        pushfd
        lea         ecx, [ebp - 4]
        mov         ebx, dword ptr fs : [0x00000030]
        mov         ebx, dword ptr[ebx + 0x0C]
        mov         ebx, dword ptr[ebx + 0x0C]
        mov         ebx, dword ptr[ebx]
        mov         ebx, dword ptr[ebx]
        mov         eax, dword ptr[ebx + 18h]
        mov         dword ptr[ecx], eax
        popfd
        popad
        mov         eax, dword ptr[ebp - 4]
        mov         dword ptr[ebp - 28h], eax
        mov         eax, dword ptr[ebp - 28h]
        mov         ecx, dword ptr[ebp - 28h]
        add         ecx, dword ptr[eax + 3Ch]
        mov         dword ptr[ebp - 2Ch], ecx
        mov         esi, dword ptr[ebp - 2Ch]
        add         esi, 18h
        mov         ecx, 38h
        lea         edi, [ebp + 0xFFFFFEF4]
        rep movs    dword ptr es : [edi], dword ptr[esi]
        mov         eax, 8
        imul        ecx, eax, 0
        mov         edx, dword ptr[ebp - 4]
        add         edx, dword ptr[ebp + ecx + 0xFFFFFF54]
        mov         dword ptr[ebp + 0xFFFFFEF0], edx
        mov         eax, dword ptr[ebp + 0xFFFFFEF0]
        mov         ecx, dword ptr[ebp - 4]
        add         ecx, dword ptr[eax + 20h]
        mov         dword ptr[ebp - 18h], ecx
        mov         eax, dword ptr[ebp + 0xFFFFFEF0]
        mov         ecx, dword ptr[ebp - 4]
        add         ecx, dword ptr[eax + 24h]
        mov         dword ptr[ebp - 0Ch], ecx
        mov         eax, dword ptr[ebp + 0xFFFFFEF0]
        mov         ecx, dword ptr[ebp - 4]
        add         ecx, dword ptr[eax + 1Ch]
        mov         dword ptr[ebp - 14h], ecx
        mov         eax, dword ptr[ebp + 0xFFFFFEF0]
        mov         ecx, dword ptr[eax + 10h]
        mov         dword ptr[ebp - 1Ch], ecx
        mov         dword ptr[ebp - 20h], 0
        jmp         s1
    s5 :
        mov         eax, dword ptr[ebp - 20h]
        add         eax, 1
        mov         dword ptr[ebp - 20h], eax
    s1 :
        mov         eax, dword ptr[ebp + 0xFFFFFEF0]
        mov         ecx, dword ptr[ebp - 20h]
        cmp         ecx, dword ptr[eax + 14h]
        jae         s2
        mov         eax, dword ptr[ebp - 20h]
        mov         ecx, dword ptr[ebp - 18h]
        mov         edx, dword ptr[ebp - 4]
        add         edx, dword ptr[ecx + eax * 4]
        mov         dword ptr[ebp - 8], edx
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax]
        cmp         ecx, 4Ch
        jne         s3
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax + 1]
        cmp         ecx, 6Fh
        jne         s3
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax + 2]
        cmp         ecx, 61h
        jne         s3
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax + 3]
        cmp         ecx, 64h
        jne         s3
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax + 4]
        cmp         ecx, 4Ch
        jne         s3
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax + 5]
        cmp         ecx, 69h
        jne         s3
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax + 6]
        cmp         ecx, 62h
        jne         s3
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax + 7]
        cmp         ecx, 72h
        jne         s3
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax + 8]
        cmp         ecx, 61h
        jne         s3
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax + 9]
        cmp         ecx, 72h
        jne         s3
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax + 0Ah]
        cmp         ecx, 79h
        jne         s3
        mov         eax, dword ptr[ebp - 8]
        movsx       ecx, byte ptr[eax + 0Bh]
        cmp         ecx, 41h
        jne         s3
        mov         eax, dword ptr[ebp - 20h]
        mov         ecx, dword ptr[ebp - 0Ch]
        movzx       edx, word ptr[ecx + eax * 2]
        mov         eax, dword ptr[ebp - 1Ch]
        lea         ecx, [edx + eax - 1]
        mov         dword ptr[ebp - 10h], ecx
        mov         eax, dword ptr[ebp - 10h]
        mov         ecx, dword ptr[ebp - 14h]
        mov         edx, dword ptr[ebp - 4]
        add         edx, dword ptr[ecx + eax * 4]
        mov         dword ptr[ebp - 24h], edx
        mov         eax, dword ptr[ebp + 8]
        push        eax
        call        dword ptr[ebp - 24h]
        mov         al, 1
        jmp         s4
    s3 :
        jmp         s5
    s2 :
        xor         al, al
    s4 :
        pop         edi
        pop         esi
        pop         ebx
        mov         esp, ebp
        pop         ebp
        ret
    }
}
__declspec(naked)
UserExec_end(VOID)
{

}
#endif

  • 3
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值