一些关于SSDT的东西

先转载下某个博客园网友的文章,这里表示下感谢。http://www.cnblogs.com/hhuai/archive/2010/03/01/1675389.html

网上其实有很多介绍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 中存放地址表)
    b. 找出当前内核基址 (804d8000)
    c. 有了这两个地址之后就可以算出RVA = 0x80504960 – 0x804d8000 = 0x2C960
    d.我们再去ntkrnlpa.exe中寻找对应的File offset (2BF60)
    e. 拿UE找出实际值 (04 C1 4C 00  也就是 0x004CC104)
    f. 搞定,最后验证一下, 0x004CC104 – ImageBase + 内核基址
  0x004CC104 – 0x00400000 + 0x804d8000 = 805A4104
在windbg中看一下,地址符合,不符的话,肯定就是被 hook掉了。
//根据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 ;
}

/

我系统里面的内核文件是ntkrnlpa.exe,首先要明白的是ntkrnlpa.exe这个文件导出了SSDT表,即SSDT本来表就存在于ntkrnlpa.exe的某处,并不是凭空产生的。只是ntkrnlpa.exe这个PE文件的IMAGEBASE是00400000,所以SSDT表的地址也是0040XXXX的某地址处,那么这个XXXX就是SSDT表的RVA了,RVA是什么意思呢?就是说不管你ntkrnlpa.exe加载地址是哪里,只要用加载地址加上这个RVA就能得到SSDT表的实际地址了。

这就是比较通用的一种获得SSDT表地址的方法了。

ntkrnlpa.exe的加载地址+SSDT表的RVA=SSDT表的实际地址

 

ntkrnlpa.exe的加载地址获取方法网上貌似有4种吧,而获取SSDT表的RVA的方法是通过MapViewOfFile(或者LoadLibraryEx也可以) ntkrnlpa到进程空间,然后解析重定位表(重定位表包括至少一个重定位块)。

待续。。。

转载于:https://www.cnblogs.com/shremie/archive/2012/07/12/2587523.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值