ring0 暴力枚举进程

Posted HsinTsao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ring0 暴力枚举进程相关的知识,希望对你有一定的参考价值。

原理:遍历进程ID,然后openprocess,能打开的都枚举出来

ring0 :

#include "EnumProcessByForce.h"


extern
char* PsGetProcessImageFileName(PEPROCESS EProcess);
extern
POBJECT_TYPE* PsProcessType;

NTSTATUS
DriverEntry(PDRIVER_OBJECT  DriverObject, PUNICODE_STRING  RegisterPath)
{
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status;
    int i = 0;
    UNICODE_STRING  DeviceName;
    UNICODE_STRING  LinkName;

    RtlInitUnicodeString(&DeviceName, DEVICE_NAME);
    RtlInitUnicodeString(&LinkName, LINK_NAME);

    Status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    Status = IoCreateSymbolicLink(&LinkName, &DeviceName);
    
    if (!NT_SUCCESS(Status))
    {
        //销毁设备对象
        IoDeleteDevice(DeviceObject);
        DeviceObject = NULL;

        return Status;
    }

    DriverObject->DriverUnload = UnloadDriver;


    //设置派遣函数  
    for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
        DriverObject->MajorFunction[i] = DefaultPassThrough;
    }

    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControlDispatch;   //DeviceIoControl(DeviceObject)

}

NTSTATUS DefaultPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{

    Irp->iostatus.Information = 0;
    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);   //将Irp返回给IO管理器,IO_NO_INCREMENT不增加优先级
    return STATUS_SUCCESS;

}


void UnloadDriver(PDRIVER_OBJECT DriverObject)
{
    PDEVICE_OBJECT DeviceObject = NULL;
    PDEVICE_OBJECT v1 = NULL;
    UNICODE_STRING LinkName;

    RtlInitUnicodeString(&LinkName, LINK_NAME);
    IoDeleteSymbolicLink(&LinkName);
    DeviceObject = DriverObject->DeviceObject;
    v1 = DeviceObject;
    while (DeviceObject != NULL)
    {
        v1 = DeviceObject->NextDevice;
        IoDeleteDevice(DeviceObject);
        DeviceObject = v1;
    }

}

NTSTATUS DeviceControlDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    NTSTATUS Status = STATUS_SUCCESS;
    ULONG IoControlCode = 0;
    PVOID    InputBuffer = NULL;
    PVOID    OutputBuffer = NULL;
    ULONG32  InputLength = 0;
    ULONG32  OutputLength = 0;
    char     BufferData[MAX_PATH] = { 0 };
    ULONG    BufferLength = MAX_PATH;

    PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

    IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;

    switch (IoControlCode)   //IO控制码
    {
        case CTL_GET_PROCESS_IMAGE_NAME_BY_PROCESSID:
        {
            
            InputBuffer = OutputBuffer = Irp->AssociatedIrp.SystemBuffer;  //CopyBuffer   
            InputLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
            OutputLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;

            //功能
            if (InputLength == sizeof(ULONG) && InputBuffer != NULL&&OutputLength == MAX_PATH)
            {
                Status = EnumProcessByForce(*((PULONG)InputBuffer), BufferData, &BufferLength);

                if (NT_SUCCESS(Status))
                {
                    memcpy((char*)OutputBuffer, BufferData, BufferLength);
                }

                else
                {
                    BufferLength = 0;
                }

            }

        }
        default:
        {

            break;
        }

    }

    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = BufferLength;                 //指示有多少内存向Ring3拷贝

                                                              //最后派遣函数将IRP请求结束,通过IoCompleteRequest

    IoCompleteRequest(Irp, IO_NO_INCREMENT);       //将Irp返回给IO管理器
    return STATUS_SUCCESS;



}

NTSTATUS  EnumProcessByForce(ULONG ProcessID, char* BufferData, ULONG* BufferLength)
{
    //进程的名称存储在进程的EProcess当前

    NTSTATUS  Status = STATUS_UNSUCCESSFUL;
    PEPROCESS EProcess = NULL;
    Status = PsLookupProcessByProcessId((HANDLE)ProcessID, &EProcess);

    if (!NT_SUCCESS(Status))
    {
        return Status;
    }
    //判断是否有效
    if (IsRealProcess(EProcess) == TRUE)
    {
        ObDereferenceObject(EProcess);

        if (strlen(PsGetProcessImageFileName(EProcess)) < *BufferLength)
        {
            *BufferLength = strlen(PsGetProcessImageFileName(EProcess));
        }
        else
        {
            *BufferLength = *BufferLength - 1;
        }

        memcpy(BufferData, PsGetProcessImageFileName(EProcess), *BufferLength);
        return STATUS_SUCCESS;
    }

    return Status;
}

BOOLEAN IsRealProcess(PEPROCESS EProcess)
{
    ULONG_PTR    ObjectType;
    ULONG_PTR    ObjectTypeAddress;
    ULONG_PTR    ProcessType = ((ULONG_PTR)*PsProcessType);   //系统导出的全局变量

    if (ProcessType && EProcess && MmIsAddressValid((PVOID)(EProcess)))
    {
        ObjectType = KeGetObjectType((PVOID)EProcess);  //通过EProcess 获得进程对象特征码
        if (ObjectType &&
            ProcessType == ObjectType)
        {
            return TRUE;
        }
    }
    return FALSE;
}
ULONG_PTR KeGetObjectType(PVOID ObjectBody)
{
    ULONG_PTR ObjectType = NULL;

    pfnObGetObjectType        ObGetObjectType = NULL;
    /*
    kd> u ObGetObjectType
    nt!ObGetObjectType:
    840a8b68 8bff            mov     edi,edi
    840a8b6a 55              push    ebp
    840a8b6b 8bec            mov     ebp,esp
    840a8b6d 8b4508          mov     eax,dword ptr [ebp+8]
    840a8b70 0fb640f4        movzx   eax,byte ptr [eax-0Ch]
    840a8b74 8b04858035f983  mov     eax,dword ptr nt!ObTypeIndexTable (83f93580)[eax*4]
    840a8b7b 5d              pop     ebp
    840a8b7c c20400          ret     4
    */
    if (!MmIsAddressValid || !ObjectBody || !MmIsAddressValid(ObjectBody))
    {
        return NULL;
    }
    ObGetObjectType = (pfnObGetObjectType)GetFunctionAddressByName(L"ObGetObjectType");
    if (ObGetObjectType)
    {
        ObjectType = ObGetObjectType(ObjectBody);
    }

    return ObjectType;
}

PVOID GetFunctionAddressByName(WCHAR *FunctionName)
{
    UNICODE_STRING v1;
    PVOID FunctionAddress = NULL;

    if (FunctionName && wcslen(FunctionName) > 0)
    {
        RtlInitUnicodeString(&v1, FunctionName);
        FunctionAddress = MmGetSystemRoutineAddress(&v1);   //在系统第一个模块ntoskrnl.exe 导出表中搜索
    }
    return FunctionAddress;
}
//对派遣函数的简单处理
//大部分的IRP都源于文件I / O处理的API,如CreateFile、ReadFile等。处理这些IRP最简单的方法是在相应的派遣函数中,
//将IRP的状态设置成功,然后结束IRP的请求(使用IoCompleteRequest),并让派遣函数返回成功。

ring3 :

#include "stdafx.h"
#include "EnumProcessForceRing3.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 唯一的应用程序对象
#include <windows.h>
#include <WinIoCtl.h>
#include <map>
CWinApp theApp;

using namespace std;

#define LINK_NAME    L"\\\\.\\LinkName"    //rdata

#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) )
#define CTL_GET_PROCESS_IMAGE_NAME_BY_PROCESSID \
    CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_ANY_ACCESS)  

void EnumProcessForce(HANDLE DeviceHandle, map<ULONG, CString>& ProcessInfo);
BOOL GrantPriviledge(IN const WCHAR*  PriviledgeName);
map<ULONG, CString> __ProcessInfo;
int main()
{

    GrantPriviledge(L"SeDebugPrivilege");
    HANDLE DeviceHandle = NULL;
    DeviceHandle = CreateFile(LINK_NAME,   //设备名称 不是\\Device\\ 是要使用设备对象的LinkName
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (DeviceHandle == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }
    printf("已连接");
    __ProcessInfo[4] = "System.exe";
    EnumProcessForce(DeviceHandle, __ProcessInfo);  //模块
    if (DeviceHandle != NULL)
    {
        CloseHandle(DeviceHandle);

        DeviceHandle = NULL;
    }

    map<ULONG, CString>::iterator Travel;

    for (Travel = __ProcessInfo.begin(); Travel != __ProcessInfo.end(); Travel++)
    {
        printf("%4d   %S\r\n", Travel->first, Travel->second);
    }


    printf("Input AnyKey To Exit\r\n");
    getchar();
    return 0;
}

void EnumProcessForce(HANDLE DeviceHandle, map<ULONG, CString>& ProcessInfo)
{
    DWORD ReturnLength = 0;
    char  ProcessImageName[MAX_PATH] = { 0 };
    size_t i = 4;
    while (i < 100000)
    {
        HANDLE ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, i);
        if (ProcessHandle == NULL)
        {
            i += 4;
            continue;
        }
        BOOL IsOk = DeviceIoControl(DeviceHandle, CTL_GET_PROCESS_IMAGE_NAME_BY_PROCESSID,    //消息码
            &i,                           //InputData
            sizeof(ULONG),               //InputDataSize
            ProcessImageName,          //OutputData
            MAX_PATH,                  //OutputDataSize
            &ReturnLength,
            NULL);
        if (IsOk == TRUE&&ReturnLength != 0)
        {
            ProcessImageName[ReturnLength] = \0;
        }
        ProcessInfo[i] = ProcessImageName;
        i += 4;
    }
}
BOOL GrantPriviledge(IN const WCHAR*  PriviledgeName)
{
    // 打开权限令牌
    HANDLE  ProcessHandle = GetCurrentProcess();
    HANDLE  TokenHandle = NULL;
    LUID             uID;
    if (!OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
    {
        return FALSE;
    }
    if (!LookupPrivilegeValue(NULL, PriviledgeName, &uID))        // 通过权限名称查找uID
    {
        CloseHandle(TokenHandle);
        TokenHandle = NULL;
        return FALSE;
    }
    TOKEN_PRIVILEGES TokenPrivileges;
    TokenPrivileges.PrivilegeCount = 1;        // 要提升的权限个数
    TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;    // 动态数组,数组大小根据Count的数目
    TokenPrivileges.Privileges[0].Luid = uID;
    if (!AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges,
        sizeof(TOKEN_PRIVILEGES), NULL, NULL))
    {
        printf("%d\r\n", GetLastError());
        CloseHandle(TokenHandle);
        TokenHandle = NULL;
        return FALSE;
    }
    CloseHandle(TokenHandle);
    TokenHandle = NULL;
    return TRUE;
}

 

以上是关于ring0 暴力枚举进程的主要内容,如果未能解决你的问题,请参考以下文章

暴力枚举进程

PsLookupProcessByProcessId分析

结束进程的N种方法(RING0 AND RING3)

结束进程的N种方法(RING0 AND RING3)

ring0 进程隐藏实现

蓝桥系列212道「暴力枚举」真题,夯实你的刷题基本功(暴力枚举模板)