翰文个人计算机学习网
  • 翰文快讯
  • 翰文PC快讯
  • 综合软件区
  • 操作系统
  • 注册表解析
  • Windows系列
  • Unix/Linux
  • 其他系统
  • 应用软件
  • 微软MS Office
  • WPS Office
  • 多媒体软件
  • 图像处理
  • Photoshop
  • Painter
  • Illustrator
  • CorelDRAW
  • 三维空间
  • AutoCAD
  • 3DMAX
  • 3DMAYA
  • 硬件资源
  • 攒机指南
  • 硬件超频
  • 维修指南
  • 网络资源
  • 在线通讯
  • 网上冲浪
  • 浏览器中心
  • 网络故障解析
  • 病毒资料
  • 病毒通报
  • 病毒防治
  • 病毒常识
  • 黑客技巧
  • SQL/MySQL
  • Oracle
  • Delphi
  • 编程资源
  •  C/C#/C++/VC++/VC.NET
  •  Basic/VB/VB.NET/VBScript
  •  FoxBasic/FoxPro/VF/VF.NET
  •  Java/JavaScript
  • PowerBuilder
  • 热门词:
  • 翰文计算机学习网首页
  • >
  • Basic/VB/VB.NET/VBScript
  • >
  • 使用VB获取系统服务描述表入口地址方法
  • 使用VB获取系统服务描述表入口地址方法

  • 资源来源:
  • HW-PCS.ORG
  • 资源作者:
  • 翰文计算机学习网
  • 人气指数:
  • [4544]
  •   在《自动获取 NT 系统服务描述表与函数名映射表》一文中我使用MS提供的DbgHelp库,从符号库文件中查找KeServiceDescriptorTable和KeServiceDescriptorTableShadow符号,以获取系统服务描述表入口地址。这种方法逻辑简单,但是对不同操作系统版本的调试符号文件有依赖性,不适用于作为工具被散发出去的程序。因此这儿给出另外一种从线程本身的特性着手获取系统服务描述表入口地址的方法。

      我们所说的线程,实际上分为核心态和用户态两部分。Win32下这两者基本上是1对1的关系,其他平台如Solaris或Linux 2.6以前的版本则使用不同的映射模型。而Win32系统中核心态的线程,实际上也分为两类:工作线程和GUI线程。前者是建立核心线程的缺省类型,后者在线程第一次使用Win32k.sys系统服务时自动转换,或者使用PsConvertToGuiThread函数(ntospspsquery.c:3247)显式转换。两者之间的区别主要在于使用的资源缺省大小不同,以及使用的系统服务描述表不同。

      这也是为什么系统服务描述表要分为KeServiceDescriptorTable和KeServiceDescriptorTableShadow的原因之一,后者包括前者没有的对GDI服务的入口函数地址,一般在Win32k.sys中实现。核心线程对象的ETHREAD::KTHREAD::ServiceTable字段保存了此线程适用的系统调用服务表地址,此字段也被PsConvertToGuiThread函数用于判断线程类型。功能与Windows XP/2003提供的IsGUIThread函数类型。
    使用上我们可以创建一个线程,此线程不做任何实际工作,只是根据我们要取哪个系统服务描述表来决定是否调用GDI函数,如

      以下为引用:

    class TGuiThread : public TThread
    {
    public:
    TGuiThread(void) : TThread(false)
    {
    FreeOnTerminate = false;
    }

    void __fastcall Execute(void)
    {
    ::GetDesktopWindow();
    }
    };

      在需要获取地址时,我们可以创建一个此线程的实例,然后通过其句柄获取内核对象地址。

      以下为引用:

    //---------------------------------------------------------------------------
    DWORD TServiceTableApplication::GetpKeServiceDescriptorTableAddress(void) const

    {
    std::auto_ptr GuiThread(new TGuiThread());

    GuiThread-WaitFor();

    ::THandleTable tblHandles;

    PVOID pObj = NULL;
    TSystemHandleList handles = tblHandles.HandleByProcessID[::GetCurrentProcessId()];

    for(TSystemHandleCPtr itHandle = handles.begin();
    itHandle != handles.end(); itHandle++)
    {
    if((HANDLE)itHandle-Handle == (HANDLE)GuiThread-Handle)
    {
    pObj = itHandle-Object;
    break;
    }
    }

    assert(pObj);

    LPVOID lpAddr;

    TPhysicalMemoryManager::Default().ReadVirtualMemory((LPCVOID)((DWORD)pObj + 0x124), lpAddr, sizeof(lpAddr));

    return lpAddr;
    }

      然后读取ETHREAD内核对象偏移0x124(win2003为0x124,win2000sp4为0xDC,其他版本可能有区别)的ServiceTable字段,即可 :D

    以下为引用:

    0:001 dt nt!_KTHREAD
    +0x000 Header : _DISPATCHER_HEADER
    ...
    +0x120 Affinity : Uint4B
    +0x124 ServiceTable : Ptr32 Void
    +0x128 ApcStatePointer : [2] Ptr32 _KAPC_STATE
    ...

    /*
      作为该flier程序的第一个小白鼠,我在2000上运行的时候就蹦出了非法访问的框子,bug提交Flier后,发现是ServiceTable的偏移在各系统上不同导致的。
      作为小白鼠,我有义务找个通用的办法。

      ServiceTable在ETHREAD中的偏移,每个各不相同,但是在NTOSKRNL.EXE的系统调用入口部分用到了这个偏移,所以我们可以用搜索代码的方式将这个偏移找出来。
    tombkeeper#nsfocus.com
    */

    #include
    #include
    #include

    char * get_func(char str[],char moduleName[])
    {
    char *ret = 0;
    char *b = (char*)LoadLibrary(moduleName);
    int i;
    __try
    {
    for (i=0; i0x100000; i++, b++)
    {
    if (memcmp(b, str, 12) == 0)
    {
    printf("ServiceTable offset: 0x%.8x ",*(DWORD *)(b+12));
    }
    }
    }
    __except(1){}

    return ret;
    }

    void main()
    {
    int i = 0;
    char * funcAddr = 0;
    static char moduleName[]="NTOSKRNL.EXE";
    static char str[] = {
    0x8B,0xF8,0xC1,0xEF,0x08,0x83,
    0xE7,0x30,0x8B,0xCF,0x03,0xBE,
    0xDC,0x00,0x00,0x00
    };
    get_func(str,moduleName);
    }

    感谢您对翰文计算机学习网的支持

  • 关于我们
  • 联系方式
  • 成功案例
  • 技术报价
  • RSS索引
  • 网站地图
  • 翰文电脑学习网
  • MSN:LNDDYGYC9@HOTMAIL.COM Powered by 翰文个人计算机学习网 版权所有,未经允许不得转载
    ICP备案号码:[沪ICP备12020678号] Copyright 2008-2020 HW-PCS.ORG, All Rights Reserved.