首页
社区
课程
招聘
ssdt 未导出函数问题
发表于: 2011-5-24 15:34 5817

ssdt 未导出函数问题

2011-5-24 15:34
5817
大大们小弟刚接触ssdt~

通过硬编码取出未导出函数地址,如何取出当前函数服务地址~

谢谢大大们

[课程]Linux pwn 探索篇!

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 83
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
自己顶下别沉了
2011-5-24 17:27
0
雪    币: 42
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
SSDT索引号的获取
对于这个问题,困惑了许久,也许是应为很久没弄这个方面的东西了,曾经看过关于Native API 和 SSDT都忘得差不多了。吸取教训,今天把知识记录下来,并时常温故而知新。

系统服务描述符表,System Service Dispatch Table,SSDT

KeServiceDescriptorTable是由内核导出的表。该表拥有一个指针(其实仅有ntoskrnel一项,没有包含win32k),指向SSDT中包含由Ntoskrnl.exe实现的核心系统服务的相应部分,它是内核的主要组成部分。

typedef struct _SystemServiceDescriptorTable
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}SystemServiceDescriptorTable,*PSystemServiceDescriptorTable;

其中SSDT包含了所有内核导出函数的地址。每个地址长度为4个字节。所以要获得某个函数在SSDT中的偏移量,可以用:KeServiceDescriptorTable->ServiceTableBase + 函数ID* 4获取。

那么怎么获取函数ID呢?

其实很简单,ntoskrnl.exe导出的Zw*函数和Nt*函数,大家肯定都注意到了很多函数都是同名的,只是前缀不同。其实是这样的,Nt*函数是私有函数,其地址列于SSDT中。Zw*函数是由内核为使用设备驱动程序和其他内核组件而导出的函数,目的就在于同过Zw*函数去调用内核的Nt函数。(SSDT中的每一项和每个Zw*函数之间不存在一对一的对应关系)

内核中的所有Zw*函数都以操作码mov eax, ULONG起始,其中ULONG是系统调用在SSDT中的索引号。

说的具体点,就是每个Zw*号函数的第一行中的 ULONG值 就是其所对应的Nt*函数在SSDT中的索引号。

举个例子,如果我现在想获取 NtOpenProcess的ID号,那么就可以在Windbg中运行 u ZwOpenProcess

u ZwOpenProcess
nt!ZwOpenProcess:
805016c4 b87a000000      mov     eax,7Ah
805016c9 8d542404        lea     edx,[esp+4]
805016cd 9c              pushfd
805016ce 6a08            push    8
805016d0 e88c0d0400      call    nt!KiSystemService (80542461)
805016d5 c21000          ret     10h

获取到的0x7A就是NtOpenProcess在SSDT中的ID号了。

代码1: (需要自己获取索引号)
#include<ntddk.h>

typedef struct _SystemServiceDescriptorTable
{
      PVOID      ServiceTableBase;
      PULONG      ServiceCounterTableBase;
      ULONG      NumberOfService;
      ULONG      ParamTableBase;
}SystemServiceDescriptorTable,*PSystemServiceDescriptorTable;

// KeServiceDescriptorTable为ntoskrnl.exe导出
extern      PSystemServiceDescriptorTable      KeServiceDescriptorTable;

// 定义一下NtOpenProcess的原型,下面如果用汇编调用就不用定义了,但是我想尽量不用汇编
typedef      NTSTATUS      (__stdcall *NTOPENPROCESS)( OUT PHANDLE ProcessHandle,
                                                

IN ACCESS_MASK AccessMask,
                                                

IN POBJECT_ATTRIBUTES ObjectAttributes,
                                                

IN PCLIENT_ID ClientId
                                                

);

NTOPENPROCESS      RealNtOpenProcess;

// 定义函数原型
VOID Hook();
VOID Unhook();
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);

// 真实的函数地址,我们会在自定义的函数中调用
ULONG      RealServiceAddress;

// 需要被驱动保护的进程ID
HANDLE      MyPID;

// 自定义的NtOpenProcess函数
NTSTATUS __stdcall MyNtOpenProcess( OUT      PHANDLE ProcessHandle,
                      IN      ACCESS_MASK DesiredAccess,
                      IN      POBJECT_ATTRIBUTES ObjectAttributes,
                      IN      PCLIENT_ID ClientId )
{
      NTSTATUS      rc;
      ULONG          PID;
   
    //DbgPrint( "NtOpenProcess() called.\n" );
   
      rc = (NTSTATUS)(NTOPENPROCESS)RealNtOpenProcess( ProcessHandle, DesiredAccess,

ObjectAttributes, ClientId );
   
    if( (ClientId != NULL) )
      {
          PID = (ULONG)ClientId->UniqueProcess;
        //DbgPrint( "%d was opened,Handle is %d.\n", PID, (ULONG)ProcessHandle );
        
        // 如果进程PID是1520,直接返回权限不足,并将句柄设置为空
        if( PID == 1520 )
          {
              DbgPrint( "Some want to open pid 1520!\n" );
            
              ProcessHandle = NULL;
                        
              rc = STATUS_ACCESS_DENIED;
          }
      }
   
    return rc;
}

// 驱动入口
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath )
{
      DriverObject->DriverUnload = OnUnload;

      Hook();
   
    return STATUS_SUCCESS;
}

// 驱动卸载
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
      Unhook( );
}

//    此处修改SSDT中的NtOpenProcess服务地址
VOID Hook()
{
      ULONG              Address;
   
    // 0x7A为Winxp+SP2下NtOpenProcess服务ID号
    // Adress是个地址A,这个地址的数据还是一个地址B,这个地址B就是NtOpenProcess的地址了
    // (ULONG)KeServiceDescriptorTable->ServiceTableBase就是温家堡的第一个房间
    // Address是第7A个房间。
      Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;

    // 取得地址A的值,也就是NtOpenProcess服务的地址了,保存原来NtOpenProcess的地址以后恢复用
      RealServiceAddress = *(ULONG*)Address;
   
      RealNtOpenProcess = (NTOPENPROCESS)RealServiceAddress;
   
      DbgPrint( "Address of Real NtOpenProcess: 0x%08X\n", RealServiceAddress );

      DbgPrint(" Address of MyNtOpenProcess: 0x%08X\n", MyNtOpenProcess );

    // 去掉内存保护
      __asm
      {
          cli
          mov      eax, cr0
          and      eax, not 10000h
          mov      cr0, eax
      }
   
    // 修改SSDT中NtOpenProcess服务的地址
   *((ULONG*)Address) = (ULONG)MyNtOpenProcess;

    // 恢复内存保护
      __asm
      {
          mov      eax, cr0
          or      eax, 10000h
          mov      cr0, eax
          sti
      }
}

//////////////////////////////////////////////////////
VOID Unhook()
{
     ULONG     Address;
     Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;

      __asm
      {
          cli
          mov      eax, cr0
          and      eax, not 10000h
          mov      cr0, eax
      }

    // 还原SSDT
    *((ULONG*)Address) = (ULONG)RealServiceAddress;
   
      __asm
      {
          mov      eax, cr0
          or      eax, 10000h
          mov      cr0, eax
          sti
      }

      DbgPrint("Unhook");
}

代码2:(不需要自己获取索引号,程序自动获取)
#include <ntddk.h>
#pragma pack(1)
typedef struct _SYSTEM_SERVICES_DESCRIPTOR_TABLE
{
        PULONG                        *ServiceTableBase;
        PULONG                        *ServiceCounterTableBase;        //Used in check builds only
        unsigned int        NumberOfServices;
        PULONG                        *ParamTableBase;
}SSDT, *PSSDT;
#pragma pack()

typedef struct _DEVICE_EXTENSION
{
        PDEVICE_OBJECT        pDevObj;
        UNICODE_STRING        uniSymLink;
        PMDL                        pMdl;
        PULONG                        pulSSDTMapped;
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;

typedef NTSTATUS (*ZWTERMINATEPROCESS)(
    IN HANDLE  ProcessHandle,
    IN NTSTATUS  ExitStatus
    );
        
/*Getting system service function address, the index of function locates 1 bytes offset*/
#define        SYSTEM_SERVICE(_Func)        KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_Func + 1)]
#define        SYSTEM_INDEX(_Func)                (*(PULONG)((PUCHAR)_Func + 1))
#define        IOCTL_START_PROTECTION        CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define        C_MAXPROCNUMS                        12

//Global variable
__declspec(dllimport) SSDT        KeServiceDescriptorTable;
ZWTERMINATEPROCESS        ZwTerminateProcessReal;
ULONG        ulPIDs[C_MAXPROCNUMS];

DRIVER_UNLOAD        DriverUnload;
DRIVER_DISPATCH        DispatchDevOpen, DispatchDevCtl;
NTSTATUS ZwTerminateProcessHook(IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus);

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryPath)
{
        PDEVICE_OBJECT                pDevObj;
        PDEVICE_EXTENSION        pDevExt;
        UNICODE_STRING                uniSymLink, uniDevName;
        NTSTATUS                        ntStatus;
        PMDL                                pMdl;
        PULONG                                pulSSDTMapped;
        
        RtlInitUnicodeString(&uniSymLink, L"\\DosDevices\\ProcessesGuard_KernoneSoft");
        RtlInitUnicodeString(&uniDevName, L"\\Device\\ProcessesGuard");
        pDriverObj->DriverUnload = DriverUnload;
        pDriverObj->MajorFunction[IRP_MJ_CREATE] =
        pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchDevOpen;
        pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDevCtl;
        
        ntStatus = IoCreateDevice(pDriverObj, sizeof (DEVICE_EXTENSION), &uniDevName, FILE_DEVICE_UNKNOWN,
                0, FALSE, &pDevObj);
        if (!NT_SUCCESS(ntStatus))
                return(ntStatus);
               
        IoCreateSymbolicLink(&uniSymLink, &uniDevName);
        pDevObj->Flags |= DO_BUFFERED_IO;
        pDevExt = pDevObj->DeviceExtension;
        pDevExt->pDevObj = pDevObj;
        pDevExt->uniSymLink = uniSymLink;
        
        pMdl = IoAllocateMdl(KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices * 4,
                FALSE, FALSE, NULL);
        if (pMdl == NULL)
        {
                IoDeleteSymbolicLink(&uniSymLink);
                IoDeleteDevice(pDevObj);
                return(STATUS_INSUFFICIENT_RESOURCES);
        }
        
        MmBuildMdlForNonPagedPool(pMdl);
        pMdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;        //Write SSDT
        
        pulSSDTMapped = (PULONG)MmMapLockedPagesSpecifyCache(pMdl, KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority);
        if (pulSSDTMapped == NULL)
        {
                IoDeleteSymbolicLink(&uniSymLink);
                IoDeleteDevice(pDevObj);
                IoFreeMdl(pMdl);
                return(STATUS_UNSUCCESSFUL);
        }
        
        pDevExt->pMdl = pMdl;
        pDevExt->pulSSDTMapped = pulSSDTMapped;
        
        ZwTerminateProcessReal = (ZWTERMINATEPROCESS)SYSTEM_SERVICE(ZwTerminateProcess);
        pulSSDTMapped[SYSTEM_INDEX(ZwTerminateProcess)] = (PULONG)ZwTerminateProcessHook;
        
        return(ntStatus);
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{
        PDEVICE_OBJECT                pDevObj = pDriverObj->DeviceObject;
        PDEVICE_EXTENSION        pDevExt = pDevObj->DeviceExtension;
        PULONG                                pulSSDTMapped = pDevExt->pulSSDTMapped;
        PMDL                                pMdl = pDevExt->pMdl;
        
        pulSSDTMapped[SYSTEM_INDEX(ZwTerminateProcess)] = (PULONG)ZwTerminateProcessReal;
        MmUnmapLockedPages(pulSSDTMapped, pMdl);
        IoFreeMdl(pMdl);
        while (pDevObj)
        {
                pDevExt = pDevObj->DeviceExtension;
                pDevObj = pDevObj->NextDevice;
               
                IoDeleteSymbolicLink(&pDevExt->uniSymLink);
                IoDeleteDevice(pDevExt->pDevObj);
        }
}

NTSTATUS DispatchDevOpen(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
        NTSTATUS        ntStatus = STATUS_SUCCESS;
        
        pIrp->IoStatus.Status = ntStatus;
        pIrp->IoStatus.Information = 0;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        return(ntStatus);
}

NTSTATUS DispatchDevCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
        PIO_STACK_LOCATION        pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
        ULONG                                ulIoCode, ulBufLength, ulRtn, ulCounts = 0, ulIndex;
        PVOID                                pvBuf;
        NTSTATUS                        ntStatus;
        
        ulIoCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
        switch (ulIoCode)
        {
        case IOCTL_START_PROTECTION:
                ulBufLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
                pvBuf = pIrp->AssociatedIrp.SystemBuffer;
                ulCounts = ulBufLength / sizeof (ULONG);
                KdPrint(("Protection Numbers: %d\n"), ulCounts);
                for (ulIndex = 0; ulIndex < ulCounts && ulIndex < C_MAXPROCNUMS; ulIndex++)
                {
                        ulPIDs[ulIndex] = ((PULONG)pvBuf)[ulIndex];
                        KdPrint(("Index %d -- PID %d\n"), ulIndex, ulPIDs[ulIndex]);
                }
                ntStatus = STATUS_SUCCESS;
                ulRtn = ulBufLength;
                break;
        default:
                ntStatus = STATUS_INVALID_PARAMETER;
                ulRtn = 0;
                break;
        }
        
        pIrp->IoStatus.Status = ntStatus;
        pIrp->IoStatus.Information = ulRtn;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        return(ntStatus);
}

NTSTATUS ZwTerminateProcessHook(IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus)
{
        PEPROCESS        pEProcessTarget = NULL;
        int                        i;
        HANDLE                hID;
        BOOLEAN                bKillSelf = FALSE, bKillProtection = FALSE;
        
        if (NT_SUCCESS(ObReferenceObjectByHandle(ProcessHandle, STANDARD_RIGHTS_READ, *PsProcessType, KernelMode, &pEProcessTarget, NULL)))
        {
                hID = PsGetProcessId(pEProcessTarget);
                for (i = 0; i < C_MAXPROCNUMS; i++)
                {
                        if((ULONG)hID == ulPIDs[ i ])
                        {
                                bKillProtection = TRUE;
                                if ((ULONG)PsGetCurrentProcessId() == ulPIDs[ i ])
                                        bKillSelf = TRUE;
                                else
                                        bKillSelf = FALSE;
                                break;
                        }
                }
                ObDereferenceObject(pEProcessTarget);
        }
        
        if (bKillProtection)
        {
                if (bKillSelf)
                        return(ZwTerminateProcessReal(ProcessHandle, ExitStatus));
                else
                        return(STATUS_ACCESS_DENIED);
        }
        else
                return(ZwTerminateProcessReal(ProcessHandle, ExitStatus));
}
2011-5-25 09:47
0
游客
登录 | 注册 方可回帖
返回
//