Quantcast
Channel: 看雪安全论坛
Viewing all articles
Browse latest Browse all 9556

【原创】SSDT Hook 详细过程

$
0
0
一。目标程序***********

//target.exe
代码:

int x=5;
int main() 

        while(1)
        {
                printf("%p %d",&x,x);
                Sleep(20000);
        }
}

//test.exe
代码:

int main() 

        int pid=0;
        PROCESSENTRY32 pe32;
        pe32.dwSize = sizeof(pe32);
        HANDLE hProcessSnap = 
      ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
        if (hProcessSnap == INVALID_HANDLE_VALUE)
        {
                printf("CreateToolhelp32Snapshot 调用失败.\n");
                return -1;
        }
        BOOL bMore = ::Process32First(hProcessSnap,&pe32);
        while (bMore)
        {
                if(strcmp(pe32.szExeFile,"target.exe")==0)
                {
                        pid=pe32.th32ProcessID;
                        break;
                }
                bMore = ::Process32Next(hProcessSnap,&pe32);
        }
        ::CloseHandle(hProcessSnap);
        HANDLE hOpen=OpenProcess(PROCESS_VM_READ, 0, pid);
        PVOID pbaseaddr=(PVOID)0x40bdc0;
        DWORD data=0;
        DWORD readlen=0;
        printf("%x",hOpen);
        ReadProcessMemory(hOpen,pbaseaddr,&data,4,&readlen);
        printf("%d",data);
        system("pause");
        return 0; 
}

程序预览
附件 85882

本文通过ssdt hook 使test.exe读取内存的值为77

二。验证思路***********
用od打开test.exe看ReadProcessMemory
附件 85883

附件 85884

附件 85885
调用SSDT表中函数的编号为0xBA

windbg中加上断点
kd> bp nt!NtReadVirtualMemory
发现会停很多次
查看堆栈
kd> dd esp
附件 85886

其中esp+8为读内存起始地址
加上条件断点
kd> bc 0
kd> bp nt!NtReadVirtualMemory "j(poi(esp+8)==0x40bdc0)'!process;dd esp';'g'"
附件 85887

发现就是test.exe进程,接收缓冲区地址为0x0012fe48
运行至NtReadVirtualMemory的ret处
kd> ed 0012fe48 0x4d
运行结果
附件 85888

验证成功!

三。编程实现***********
这里说主要内容,附件有代码

这个是挂钩后调用的函数
获取进程名字用的地址是
kd> dt _EProcess获取的
附件 85889

代码:

NTSTATUS MyNtReadVirtualMemory (
        IN HANDLE ProcessHandle,
        IN PVOID BaseAddress,
        OUT PVOID Buffer,
        IN ULONG BufferSize,
        OUT PULONG NumberOfBytesRead
        )
{
        NTSTATUS ret=((NTREADVIRTUALMEMORY)g_pReadVirtualMemory)(ProcessHandle,BaseAddress,Buffer,BufferSize,NumberOfBytesRead);
        if(ret==STATUS_SUCCESS)
        {
                PEPROCESS Process;
                ret=ObReferenceObjectByHandle(ProcessHandle,EVENT_MODIFY_STATE,*PsProcessType,KernelMode,(PVOID*)&Process,NULL);
                if(ret==STATUS_SUCCESS && Process!=NULL)
                {
                        PEPROCESS curProcess=IoGetCurrentProcess();
                        if (_stricmp((char*)((char*)Process+0x174), "target.exe") == 0 )
                        {
                                if(_stricmp((char*)((char*)curProcess+0x174), "test.exe") == 0 )
                                {
                                        *((CHAR*)Buffer)=77;
                                }
                        }
                        ObDereferenceObject(Process);
                }
               
        }
       
        return ret;
}


这里是驱动入口
由于ssdt是只读内存,修改只读内存有2种常规方法,这里用的是修改cr0的WP位(问题:这样修改会不会在多CPU下出问题?????有什么好办法),另外一种是用Mdl

Hook的办法也有2种,这里用直接Hook SSDT,另外一种是inline Hook
代码:

extern "C"
NTSTATUS    DriverEntry(void* pModudleBase,int nNothing) {
        g_pNtKernelBaseAddr = FindKernelBaseAddr(&g_nNtKernelSizeOfImage);
        if (NULL == g_pNtKernelBaseAddr) {
                return -1;
        }

        ULONG  nNetIoSizeOfImage = 0;
        DWORD nServicesTableRVA=FindAPIRVAByName((PVOID)g_pNtKernelBaseAddr,"KeServiceDescriptorTable");
        if (NULL == nServicesTableRVA) {
                return FALSE;
        }
        PSERVICE_DESCRIPTOR_TABLE pServicesTable=(PSERVICE_DESCRIPTOR_TABLE)((PUCHAR)g_pNtKernelBaseAddr + nServicesTableRVA);
        PUCHAR pnSSDTVA = (PUCHAR)(pServicesTable->ServiceTableBase);


        //
        //SSDT Hook
        //
        PVOID* pReadVirtualMemory=(PVOID*)(pnSSDTVA+(0xba*4));
        __asm{
                cli
                        mov  eax,cr0
                        and  eax,not 10000h
                        mov  cr0,eax
        }
        g_pReadVirtualMemory=*pReadVirtualMemory;
        *pReadVirtualMemory=(PVOID*)(DWORD)MyNtReadVirtualMemory;
        __asm{ 
                mov  eax,cr0
                        or  eax,10000h
                        mov  cr0,eax
                        sti
        }

    return STATUS_SUCCESS;
}

四。验证***********
附件 85891

第一次发帖
不知道截图附件有没有问题

上传的图像
文件类型: jpg QQ截图20131229135241.jpg (26.0 KB)
文件类型: jpg QQ截图20131228154456.jpg (21.6 KB)
文件类型: jpg QQ截图20131228154534.jpg (11.2 KB)
文件类型: jpg QQ截图20131228154738.jpg (14.9 KB)
文件类型: jpg dd esp.jpg (29.9 KB)
文件类型: jpg bp j.jpg (93.3 KB)
文件类型: jpg result.jpg (31.7 KB)
文件类型: jpg dt.jpg (64.9 KB)
文件类型: jpg SSdt.jpg (120.9 KB)
上传的附件
文件类型: zip SSDT.zip (2.5 KB)

Viewing all articles
Browse latest Browse all 9556

Trending Articles