• 1065阅读
  • 1回复

有码无真像,关于内存隐藏,隐藏3层程序的指定区域 [复制链接]

上一主题 下一主题
离线啊冲
 

只看楼主 倒序阅读 使用道具 楼主  发表于: 2016-02-03



有码无真像,关于内存隐藏,隐藏3层程序的指定区域, ITLB 和 DTLB 已经分别被载入,但是代码运行的时候被卡死
在WinDbg 里面看到  在访问和执行的时候 页面分别被换成了我们想要的页面,
目前的问题是读写成功,但是执行的时候,3层程序被卡死了也不蓝

call g_pfnCallIntoHookedPage //通过调用一下那个页面内的代码,装载ITLB  
and dword ptr [ebx], 0xFFFFFFFE  //重新标记为不存在
测试如果把 and dword ptr [ebx], 0xFFFFFFFE   这行去掉  那么程序可以正常运行,但是HOOK 也就失效了~~~~

  求真像~~~~

所引用的头文件在 OllyBonE里面有

达人请指教



#include "ntddk.h"
#include "stdio.h"
#include "stdlib.h"
#include "multicpu.h"

typedef BOOLEAN BOOL;
typedef unsigned long DWORD;
typedef DWORD * PDWORD;
typedef unsigned long ULONG;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef unsigned long* PPTE;
typedef LARGE_INTEGER PHYSICAL_MEMORY;


#define HIGHEST_USER_ADDRESS 0x80000000
                              
#define ERROR_PAGE_NOT_IN_LIST 0

PDEVICE_OBJECT g_PagefaultDevice;
void *g_OldInt0EHandler = NULL;
void *g_Int03Handler = NULL;
void *g_Int01Handler = NULL;
BOOL hooked = FALSE;
DWORD g_pidsaved = 0;
DWORD g_pfnCallIntoHookedPage;
PPTE  g_pReadWritePTE;
PPTE  g_pExePTE;
DWORD g_cr3=0;
DWORD g_pExecutePage=0;
DWORD g_ulHookCodeLen=0;

NTSTATUS PagefaultDispatch(IN PDEVICE_OBJECT, IN PIRP);
NTSTATUS PagefaultUnload(IN PDRIVER_OBJECT);
NTSTATUS PagefaultDeviceControl(IN PFILE_OBJECT, IN BOOLEAN, IN PVOID,
                IN ULONG, OUT PVOID, IN ULONG, IN ULONG,
                OUT PIO_STATUS_BLOCK, IN PDEVICE_OBJECT
                );

#define FILE_DEVICE_IORIPROTECT 0x8000
#define IOCTL_OLLYBONE_SET        CTL_CODE(FILE_DEVICE_IORIPROTECT, 1, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
#define IOCTL_OLLYBONE_RESTORE  CTL_CODE(FILE_DEVICE_IORIPROTECT, 2, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)



#pragma pack(push,1)
typedef struct _ioctlparams
{
    DWORD pid;
    DWORD va;
    DWORD size;
    DWORD ViewPag;
    DWORD va_ret;
} IOCTLPARAMS;

#pragma pack(pop)

#define PROCESS_PAGE_DIR_BASE          0xC0300000
#define PROCESS_PAGE_TABLE_BASE        0xC0000000
#define KERNEL_ADDRESS_START        0x80000000

static DWORD MmSystemPteBase=0xc0000000;
const WCHAR deviceLinkBuffer[]  = L"\\DosDevices\\ollybone";
const WCHAR deviceNameBuffer[]  = L"\\Device\\ollybone";
char buf[100];
const char formatMsg[] = "Handling access fault (pte:%x) at %x for address %x\n";

VOID NTAPI KeAttachProcess( IN PEPROCESS );
VOID NTAPI KeDetachProcess( );
NTSTATUS NTAPI PsLookupProcessByProcessId( DWORD pid, PEPROCESS *eproc );

#define  DebugPrint        DbgPrint

PPTE GetPteAddress( PVOID VirtualAddress );
void HookMemoryPage( PVOID pReadWritePage );
void UnhookMemoryPage( PVOID pReadWritePage );
void MarkPageSupervisorOnly( void *pte );
void MarkPageUserMode( void *pte );
void *SetInterruptHandler(int IntNo, void *HandlerPtr, BYTE flags);
void *GetInterruptHandler(DWORD IntNo, DWORD IdtNum);
void InstallHandler();
void RemoveHandler();



#pragma optimize( "", off )
void __declspec (naked) NewInt0EHandler(void)
{
    __asm                                                
    {                                                    
        pushad                                        
            mov edx, dword ptr [esp+0x20] //PageFault.ErrorCode
        test edx, 1  //不是缺页错误
            jne PassDown

            //通过CR3判断当前进程
            mov eax, cr3
            cmp eax, g_cr3
            jnz PassDown

            mov eax,cr2    //faulting virtual address
            ////////////////////////////////////////
            //判断是否是Hook掉的page
            /////////////////////////////////////////
            mov ebx, g_pExecutePage
            and  ebx, 0xFFFFF000
            and  eax, 0xFFFFF000
            cmp eax, ebx
            mov eax, cr2
            jnz PassDown  //不是,传下去

            ///////////////////////////////////////      
            //下面处理Hook掉的页面了
            /////////////////////////////////////        
            //mov eax, cr2                                                                
            //push eax
            //push eax
            //call GetPteAddress
            //mov ebx, eax  //ebx = pPte
            //pop eax
         mov    eax, cr2
         mov    esi, PROCESS_PAGE_DIR_BASE
        mov    ebx, eax
        shr    ebx, 22
        lea    ebx, [esi + ebx * 4] //ebx = pPTE for large page
        test    [ebx], 0x80    //check if its a large page
        jnz    IsLargePage                        
  
        mov    esi, PROCESS_PAGE_TABLE_BASE
        mov    ebx, eax
        shr    ebx, 12
        lea    ebx, [esi + ebx * 4] //ebx = pPTE

IsLargePage:
                    
            cmp [esp+0x24], eax    //判断是执行出错还是读写时出错?
            je LoadITLB

            //判断是否是Hook的那些字节      
            cmp eax, g_pExecutePage
            jb  LoadDTLB
            sub eax, g_pExecutePage
            cmp eax, g_ulHookCodeLen
            jg  LoadDTLB
            jmp LoadFakeFrame
LoadITLB:
        ////////////////////////////////              
        //是一次执行操作,所以Load ITLB
        ///////////////////////////////
            mov eax, cr2
                mov esi, g_pExePTE
                mov ecx, dword ptr [esi]            //ecx = PTE of the  
            //read / write page
            //把页面替换为真的
            mov edi, [ebx]                                
            and edi, 0x00000FFF //preserve the lower 12 bits of the
                //faulting page's PTE              
                and ecx, 0xFFFFF000 //isolate the physical address in  
                //the "fake" page's PTE            
                or ecx, edi                                  
                mov edx, [ebx]    //save the old PTE so we can replace it
                mov [ebx], ecx    //replace the faulting page's phys frame
                //address w/ the fake one
           cli                    
            or dword ptr [ebx], 0x01        //标志页面为存在
            call g_pfnCallIntoHookedPage //通过调用一下那个页面内的代码,装载ITLB
            and dword ptr [ebx], 0xFFFFFFFE  //重新标记为不存在
            //sti                                          
            jmp ReturnWithoutPassdown                    
            ////////////////////////////////              
            // 这是读写造成的异常,并且不在我们要隐藏的代码范围内,Load DTLB
            ///////////////////////////////                
LoadDTLB:
            cli  
            mov eax,cr2
            or dword ptr [ebx], 0x01          //mark the page present
            mov eax, dword ptr [eax]          //load the DTLB      
            and dword ptr [ebx], 0xFFFFFFFE    //mark page not present
            //sti                                          
            jmp ReturnWithoutPassdown                    

            /////////////////////////////////            
            //需要隐藏这段代码,所以Load伪装的页面
            /////////////////////////////////

LoadFakeFrame:  
            mov eax, cr2
            mov esi, g_pReadWritePTE
            mov ecx, dword ptr [esi]            //ecx = PTE of the  
            //read / write page
            //把页面替换为假的
            mov edi, [ebx]                                
            and edi, 0x00000FFF //preserve the lower 12 bits of the
            //faulting page's PTE              
            and ecx, 0xFFFFF000 //isolate the physical address in  
            //the "fake" page's PTE            
            or ecx, edi                                  
            mov edx, [ebx]    //save the old PTE so we can replace it
            cli    
            mov [ebx], ecx    //replace the faulting page's phys frame
            //address w/ the fake one
            //load DTLB
            or dword ptr [ebx], 0x01  //标志为存在
            mov eax, cr2              //faulting virtual address  
            mov eax, dword ptr[eax]    //访问一次页面的数据,Load DTLB
            and dword ptr [ebx], 0xFFFFFFFE //重新标志为不存在

            //Finally, restore the original PTE
            mov [ebx], edx                                
            //sti                                          

ReturnWithoutPassDown:                                        
        popad                                        
            add esp,4
            sti
            iretd                                        

PassDown:                                                    
        popad                                        
            jmp [g_OldInt0EHandler]

    }//end asm                        
}
#pragma optimize( "", on )

NTSTATUS DriverEntry(
  IN PDRIVER_OBJECT  DriverObject,
  IN PUNICODE_STRING RegistryPath )
{
    NTSTATUS                ntStatus;
    UNICODE_STRING          deviceNameUnicodeString;
    UNICODE_STRING          deviceLinkUnicodeString;      
  
    RtlInitUnicodeString (&deviceNameUnicodeString,
                          deviceNameBuffer );
    RtlInitUnicodeString (&deviceLinkUnicodeString,
                          deviceLinkBuffer );
    ntStatus = IoCreateDevice ( DriverObject,
                                0,
                                &deviceNameUnicodeString,
                                FILE_DEVICE_UNKNOWN,
                                FILE_DEVICE_SECURE_OPEN,
                                FALSE,
                                &g_PagefaultDevice );

    if(! NT_SUCCESS(ntStatus))
    {
        DebugPrint(("Failed to create device!\n"));
        return ntStatus;
    }
      
    ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
                                        &deviceNameUnicodeString );
    if(! NT_SUCCESS(ntStatus))
    {
        IoDeleteDevice(DriverObject->DeviceObject);
        DebugPrint("Failed to create symbolic link!\n");
        return ntStatus;
    }

    DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]        =
    DriverObject->MajorFunction[IRP_MJ_CREATE]          =
    DriverObject->MajorFunction[IRP_MJ_CLOSE]          =
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = PagefaultDispatch;
    DriverObject->DriverUnload                          = PagefaultUnload;

    return STATUS_SUCCESS;
}

NTSTATUS PagefaultUnload(IN PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING          deviceLinkUnicodeString;
    PDEVICE_OBJECT            p_NextObj;

    p_NextObj = DriverObject->DeviceObject;

    if (p_NextObj != NULL)
    {
        RtlInitUnicodeString( &deviceLinkUnicodeString, deviceLinkBuffer );
        IoDeleteSymbolicLink( &deviceLinkUnicodeString );
        IoDeleteDevice( DriverObject->DeviceObject );
        return STATUS_SUCCESS;
    }
    return STATUS_SUCCESS;
}



NTSTATUS
PagefaultDispatch(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    PIO_STACK_LOCATION      irpStack;
    PVOID                  inputBuffer;
    PVOID                  outputBuffer;
    ULONG                  inputBufferLength;
    ULONG                  outputBufferLength;
    ULONG                  ioControlCode;
    NTSTATUS                ntstatus;

    ntstatus = Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    irpStack = IoGetCurrentIrpStackLocation (Irp);
    inputBuffer            = Irp->AssociatedIrp.SystemBuffer;
    inputBufferLength      = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outputBuffer            = Irp->AssociatedIrp.SystemBuffer;
    outputBufferLength      = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
    ioControlCode          = irpStack->Parameters.DeviceIoControl.IoControlCode;

    switch (irpStack->MajorFunction) {
    case IRP_MJ_CREATE:
        break;

    case IRP_MJ_SHUTDOWN:
        break;

    case IRP_MJ_CLOSE:
        break;

    case IRP_MJ_DEVICE_CONTROL:
        ntstatus = PagefaultDeviceControl( irpStack->FileObject, TRUE,
        inputBuffer, inputBufferLength,
        outputBuffer, outputBufferLength,
        ioControlCode, &Irp->IoStatus, DeviceObject );
        break;
    }
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
    return ntstatus;
}


NTSTATUS
PagefaultDeviceControl(
    IN PFILE_OBJECT FileObject,
    IN BOOLEAN Wait,
    IN PVOID InputBuffer,
    IN ULONG InputBufferLength,
    OUT PVOID OutputBuffer,
    IN ULONG OutputBufferLength,
    IN ULONG IoControlCode,
    OUT PIO_STATUS_BLOCK IoStatus,
    IN PDEVICE_OBJECT DeviceObject
    )
{
    NTSTATUS ntStatus;
    DWORD va;
    DWORD i;
    DWORD size;
    DWORD pid;
    PEPROCESS eproc = NULL;
        IOCTLPARAMS     *params;
    char buf[100];
  
    IoStatus->Status = STATUS_SUCCESS;
        IoStatus->Information = 0;

    switch ( IoControlCode )
    {  
    DbgPrint("IOCODE %08x  %08x",IOCTL_OLLYBONE_SET,IoControlCode);
    case IOCTL_OLLYBONE_SET:
            DebugPrint(("IOCTL_OLLYBONE_SET\n"));

            if ((InputBufferLength < sizeof(int) * 3) || (InputBuffer == NULL))
            {
                IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
                break;
            }
            params = (IOCTLPARAMS *)InputBuffer;
            pid =  params->pid;
            va =  params->va & 0xFFFFF000;
            size = params->size;

            if (PsLookupProcessByProcessId(pid, &eproc) == STATUS_SUCCESS)
            {
                KeAttachProcess(eproc);
              
                DbgPrint("PID:%d VA:%08x Size:%08x ViewPag:%08x  va_ret:%08x \n",pid,va,size,params->ViewPag,params->va_ret);
                g_pidsaved = pid;
                g_pExecutePage=va;
                g_ulHookCodeLen=size;
                g_pReadWritePTE=GetPteAddress(params->ViewPag);
                g_pExePTE=GetPteAddress(va);
                g_pfnCallIntoHookedPage=params->va_ret;
                __asm
                {
                    push eax
                    xor eax,eax
                    mov eax,cr3
                    mov g_cr3,eax
                    pop eax
                }
              
                for (i = va; i < va+size; i+=4096)
                    HookMemoryPage((void *)i);
                KeDetachProcess();
              
                if( hooked == FALSE )
                {    
                    InstallHandler();
                    hooked = TRUE;
                }

            }
            else
            {
                IoStatus->Status = STATUS_UNSUCCESSFUL;
            }

    break;

    case IOCTL_OLLYBONE_RESTORE:
            DebugPrint(("**** Got OLLYBONE_RESTORE IOCTL\n"));
          
            if ((InputBufferLength < sizeof(int) * 3) || (InputBuffer == NULL))
            {
                IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
                break;
            }  
            params = (IOCTLPARAMS *)InputBuffer;
            pid =  params->pid;
            va =  params->va;
            size = params->size;
          
            if (PsLookupProcessByProcessId(pid, &eproc) == STATUS_SUCCESS)
            {
                KeAttachProcess(eproc);
                g_pidsaved = 0;

                for (i = va; i < va+size; i+=4096)
                    UnhookMemoryPage((void *)i);

                KeDetachProcess();

            }
            else
            {
                IoStatus->Status = STATUS_UNSUCCESSFUL;
            }
    break;
  
    default:
        IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    return IoStatus->Status;
}

//GetPteAddress
//pte的计算公式
//PAE和非PAE有些差别。目前看不懂
PPTE GetPteAddress( PVOID VirtualAddress )
{
    PPTE pPTE = 0;
    __asm
    {
        cli
            pushad
            mov esi, PROCESS_PAGE_DIR_BASE
            //#define PROCESS_PAGE_DIR_BASE 0xC0300000
            mov edx, VirtualAddress
            mov eax, edx
            shr eax, 22
            lea eax, [esi + eax*4]
        test [eax], 0x80
            jnz Is_Large_Page
            mov esi, PROCESS_PAGE_TABLE_BASE
            //#define PROCESS_PAGE_TABLE_BASE 0xC0000000
            shr edx, 12
            lea eax, [esi + edx*4]
        mov pPTE, eax
            jmp Done
Is_Large_Page:
        mov pPTE, eax
Done:
        popad
            sti
    }
    return pPTE;
}

void MarkPageSupervisorOnly( void *pte )
{
    *(DWORD *)pte &= 0xFFFFFFFE;
}
void MarkPageUserMode( void *pte )
{
    *(DWORD *)pte |= 0x1;
}


void HookMemoryPage( PVOID pPage )
{
    char buf[100];
    void *pReadWritePte;

        pReadWritePte = GetPteAddress( pPage );
        DbgPrint( "Hooking page va:%x  Ppte:%x pte:%x \n",pPage, pReadWritePte, *(DWORD *)pReadWritePte);
    __asm {  
        mov eax, pPage    // access page in case it is paged out
        mov eax, [eax]
        cli
    }

        pReadWritePte = GetPteAddress( pPage );

    __asm {  
            mov eax, pPage
            invlpg [eax]
    }
    // Pages marked Copy-on-Write won't work, change them to normal perms


        //Mark the page supervisor mode only
        MarkPageSupervisorOnly( pReadWritePte );

    __asm {  
            mov eax, pPage
            invlpg [eax]
            sti  //reenable interrupts
    }
    sprintf(buf, "  New pte:%x\n", *(DWORD *)pReadWritePte);
    DebugPrint(buf);
  
}


void UnhookMemoryPage( PVOID pPage )
{
    void *pReadWritePte;

    __asm {  
        mov eax, pPage    // access page in case it is paged out
        mov eax, [eax]
        cli
    }

        pReadWritePte = GetPteAddress( pPage );

    __asm {  
            mov eax, pPage
            invlpg [eax]
    }
        MarkPageUserMode( pReadWritePte );

    __asm {  
            mov eax, pPage
            invlpg [eax]
            sti  //reenable interrupts
        }
}

void InstallHandler()
{
    g_OldInt0EHandler = GetInterruptHandler(0x0e,0);
    g_Int03Handler = GetInterruptHandler(0x03,0);
    g_Int01Handler = GetInterruptHandler(0x01,0);
    SetInterruptHandler(0x0E,&NewInt0EHandler,0x8e);
}

void RemoveHandler()
{
    if (g_OldInt0EHandler != NULL)
        SetInterruptHandler(0x0E, g_OldInt0EHandler, 0x8e);
}

void* GetInterruptHandler(DWORD IntNo, DWORD IdtNum)
{
  DWORD IDTBase=0;
  DWORD OldIntr;
  WORD  *IdtEntry;

  IDTBase = mp_GetIDTBase(IdtNum);

  IdtEntry=(WORD*)(IDTBase+IntNo*8);

  OldIntr=IdtEntry[0]+(IdtEntry[3]<<16);

  return (void*)OldIntr;
}

void* SetInterruptHandler(int IntNo, void *HandlerPtr, BYTE flags)
{

  __asm
  {
          pushad

          mov    eax, IntNo
          mov    dl,  flags
          mov    edi, HandlerPtr
          mov    bx,  cs

          cli                      ; TO DO: StopSecondCPUs()
          call  mp_HookInterrupt
          sti

          popad
  }

  return (void*)mp_OldHandler;
}
善者 慈悲心常在 无怨无恨 以苦为乐
默认压缩密码www.hifyl.com
文件分享密码问题:http://www.hifyl.com/read-htm-tid-4444.html
离线v2680267313

只看该作者 沙发  发表于: 2016-04-30
用户被禁言,该主题自动屏蔽!
快速回复
限100 字节
批量上传需要先选择文件,再选择上传
 
上一个 下一个