首页
社区
课程
招聘
[求助]有码无真像,关于内存隐藏,隐藏3层程序的指定区域, ITLB 和 DTLB 已经分别被载入,但是代码运行的时候被卡死
发表于: 2010-8-28 11:00 9050

[求助]有码无真像,关于内存隐藏,隐藏3层程序的指定区域, ITLB 和 DTLB 已经分别被载入,但是代码运行的时候被卡死

2010-8-28 11:00
9050
有码无真像,关于内存隐藏,隐藏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;
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 389
活跃值: (967)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
2
厄  自顶一下
2010-8-30 19:56
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
你好,我也在研究内存隐藏,我编译你的代码不成功,能指教下吗,谢谢,我的QQ:493236294
2011-1-6 14:16
0
游客
登录 | 注册 方可回帖
返回
//