SSDT Hook 还原 (恢复)

 

网上其实有很多介绍ssdt还原的文章,看起来也确实是一个很简单,套用一句网友的话,就是菜B才用的技术。但我着实也费了一番工夫,也可能真是我自己的理解能力太差。一个人搞了两三天才弄出来,其实真的很简单,只是有些文章说得很含糊。

下面我说几个要点:

1. ssdt已存在于原始pe文件中。(具体是ntoskrnl.exe、ntkrnlpa.exe、ntkrnlmp.exe、ntkrpamp.exe 自已想法确定)

操作系统根据是否是多处理器平台和是否支持PAE(Physical Address Extension)来选择合适的系

Picasa Content

统文件。

ntoskrnl.exe

单x86处理器,使用不超过4GB的物理内存。

ntkrnlpa.exe

单x86处理器,支持PAE。

ntkrnlmp.exe

多处理器,使用不超过4GB的物理内存。

ntkrpamp.exe

多处理器,支持PAE。

  
//如何确定系统的内核是ntoskrnl.exe还是ntkrnlpa.exe? 这里没有考虑多核
int nPaeOpen = 0;
WCHAR* kernelName= NULL;
__asm{
    _emit 0x0f
        _emit 0x20
        _emit 0xe0
        mov  edx, 0x1
        shl  edx, 5
        and  eax, edx
        shr  eax, 5
        mov nPaeOpen,eax
}
kernelName = nPaeOpen?L"ntoskrnl.exe":L"ntkrnlpa";

 

 

2. 位置的计算牵涉到几个地址:

    a. ssdt现存地址,可以通过windbg演示一下. (0x80504960 中存放地址表)

    image

   b. 找出当前内核基址 (804d8000)

   image

关于这里为什么是ntkrpamp.exe,我找了点资料:

  c. 有了这两个地址之后就可以算出RVA = 0x80504960 – 0x804d8000 = 0x2C960

  d.我们再去ntkrnlpa.exe中寻找对应的File offset (2BF60)

   image

e. 拿UE找出实际值 (04 C1 4C 00  也就是 0x004CC104)

image

f. 搞定,最后验证一下, 0x004CC104 – ImageBase + 内核基址

  0x004CC104 – 0x00400000 + 0x804d8000 = 805A4104

在windbg中看一下,地址符合,不符的话,肯定就是被 hook掉了。

image

帖点实现代码:

//根据RVA获取原始PE文件中的SSDT表
void GetSSDTFromPE(const SSDT_PARAM& ssdt_param ){
    gvSSDTList.clear();
    const DWORD rva = ssdt_param.ServiceTableBase-ssdt_param.nKernelImageBase;
    HANDLE hMapFile =NULL;
    HANDLE hFile =NULL;
    SIZE_T size = 0;
    int ECode = 0;
    PVOID pLoadBase =NULL;
    __try{
        __try{
            hFile = CreateFile(ssdt_param.kernelpath,
                FILE_ALL_ACCESS,
                FILE_SHARE_READ|FILE_SHARE_WRITE,
                NULL,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                NULL);
            if( hFile ==  INVALID_HANDLE_VALUE){
                DisplayError(_T("CreateFile"),GetLastError());
                RaiseException(1,         // 抛?出?异?常?码?为?的?SEH异?常?
                    0,
                    0, NULL);               // 没?有?参?数?
                __leave;
            }
            DWORD dwBytesInBlock = GetFileSize(hFile,NULL); //文?件?长?度?

            hMapFile = CreateFileMapping(
                hFile,    // use paging file
                NULL,                    // default security 
                PAGE_READWRITE,
                0,                       // max. object size 
                dwBytesInBlock,          // buffer size  
                NULL);                 // name of mapping object

            CloseHandle(hFile);
            if( hMapFile ==  NULL){
                RaiseException(2,
                    0,
                    0, NULL);
                __leave;
            }
            pLoadBase = MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,dwBytesInBlock);
            if(pLoadBase == NULL){
                RaiseException(3,
                    0,
                    0, NULL);
                __leave;
            }
            //_tprintf(_T("ImageBase = 0x%x\n"),pLoadBase);
            PIMAGE_NT_HEADERS pImageNtHeader = ImageNtHeader(pLoadBase);
            if(pImageNtHeader == NULL){
                RaiseException(3,
                    0,
                    0, NULL);
                __leave;
            }
            DWORD ImageBase = pImageNtHeader->OptionalHeader.ImageBase;
            DWORD* VaAddr = (DWORD*)ImageRvaToVa(pImageNtHeader,pLoadBase,rva,NULL);
            if(VaAddr == NULL){
                RaiseException(4,
                    0,
                    0, NULL);
                __leave;
            }
            //_tprintf(_T("Index\tAddress\n"));
            for(DWORD i = 1; i <= ssdt_param.nCount; ++i,++VaAddr){
                //_tprintf(TEXT("0x%x\t[0x%x]\n"),i,*VaAddr-ImageBase+ssdt_param.nKernelImageBase);
                gvSSDTList.push_back(*VaAddr-ImageBase+ssdt_param.nKernelImageBase);
            }
        }
        __except(ECode=GetExceptionCode()) {
            DisplayError(_T(" "),GetLastError());
        }
    }
    __finally{
        if(pLoadBase) UnmapViewOfFile(pLoadBase);
        if(hMapFile) CloseHandle(hMapFile);
        if(hFile) CloseHandle(hFile);
    }
    return ;
}

 

转载于:https://www.cnblogs.com/hhuai/archive/2010/03/01/1675389.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值