ciomhan
驱动牛犊
驱动牛犊
  • 注册日期2004-04-26
  • 最后登录2010-07-27
  • 粉丝0
  • 关注0
  • 积分244分
  • 威望75点
  • 贡献值0点
  • 好评度23点
  • 原创分0分
  • 专家分0分
阅读:3558回复:9

如何关机,40分(我最多能给这么多)

楼主#
更多 发布于:2005-06-08 14:23
请问:在KERNEL层,如何关闭系统?
ciomhan
驱动牛犊
驱动牛犊
  • 注册日期2004-04-26
  • 最后登录2010-07-27
  • 粉丝0
  • 关注0
  • 积分244分
  • 威望75点
  • 贡献值0点
  • 好评度23点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2005-06-08 18:23
没人理会,只好自己先顶下,不要被淹没了。
难道对高手来说也很难吗
zhaock
驱动太牛
驱动太牛
  • 注册日期2002-01-26
  • 最后登录2018-06-02
  • 粉丝3
  • 关注2
  • 积分73328分
  • 威望362317点
  • 贡献值1点
  • 好评度226点
  • 原创分0分
  • 专家分0分
  • 社区居民
板凳#
发布于:2005-06-08 20:06
反汇编一下ExitWindowEx,看看调用了什么系统函数。但关机涉及到
csrss,service的很多工作,可能很难从ring0做。为什么必须在ring0 做呢?
ciomhan
驱动牛犊
驱动牛犊
  • 注册日期2004-04-26
  • 最后登录2010-07-27
  • 粉丝0
  • 关注0
  • 积分244分
  • 威望75点
  • 贡献值0点
  • 好评度23点
  • 原创分0分
  • 专家分0分
地板#
发布于:2005-06-08 21:42
呵呵,我也觉得实现起来有困难,但是有人告诉我说可以直接调用ExitWindowEx,我没有在KERNEL层调用过上层API。如果老大知道怎么实现,请告诉一下
zhaock
驱动太牛
驱动太牛
  • 注册日期2002-01-26
  • 最后登录2018-06-02
  • 粉丝3
  • 关注2
  • 积分73328分
  • 威望362317点
  • 贡献值1点
  • 好评度226点
  • 原创分0分
  • 专家分0分
  • 社区居民
地下室#
发布于:2005-06-08 22:32
搜索一下Ring0 Call Ring3,以前有过这方面的讨论
bmyyyud
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2010-01-21
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望130点
  • 贡献值0点
  • 好评度106点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2005-06-09 09:02
用这个,ZwShutdownSystem在ntdll.dll中
nRet=RtlAdjustPrivilege(0x13,1,1,&en);
if(nRet==0x0C000007C)
    nRet = RtlAdjustPrivilege(0x13,1,0,&en);
nRet=ZwShutdownSystem(2);
如果要用ZwShutdownSystem对应于ntoskrnl中的NtShutdownSystem,虽然NtShutdownSystem没有在ntoskrnl中输出,但在SDT中,我的是windows 2003 sp1服务号为102,你的OS不同,可能需要自己locate一下
滚滚长江东逝水 浪花淘尽英雄 是非成败转头空 青山依旧在 几度夕阳红 白发渔樵江渚上 惯看秋月春风 一壶浊酒喜相逢 古今多少事 尽付笑谈中
ciomhan
驱动牛犊
驱动牛犊
  • 注册日期2004-04-26
  • 最后登录2010-07-27
  • 粉丝0
  • 关注0
  • 积分244分
  • 威望75点
  • 贡献值0点
  • 好评度23点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2005-06-09 12:56
谢谢两位关注我的问题,bmyyyud老兄,你所说的函数我在我的DDK里面找不到说明,我用DDK2003,是不是这些函数是WINDOWS UNDOC的,怎么才能在2K/XP系统上面使用。分数已给,感谢。
bmyyyud
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2010-01-21
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望130点
  • 贡献值0点
  • 好评度106点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2005-06-09 15:24
谢谢两位关注我的问题,bmyyyud老兄,你所说的函数我在我的DDK里面找不到说明,我用DDK2003,是不是这些函数是WINDOWS UNDOC的,怎么才能在2K/XP系统上面使用。分数已给,感谢。

我上面已说过
虽然NtShutdownSystem没有在ntoskrnl中输出,但在SDT中,我的是windows 2003 sp1服务号为102,你的OS不同,可能需要自己locate一下
没有输出,肯定在DDK中找不到,但是在KeServiceDescriptorTable指向的结构中的系统Dispatch Table 中对应这个函数的地址
滚滚长江东逝水 浪花淘尽英雄 是非成败转头空 青山依旧在 几度夕阳红 白发渔樵江渚上 惯看秋月春风 一壶浊酒喜相逢 古今多少事 尽付笑谈中
ciomhan
驱动牛犊
驱动牛犊
  • 注册日期2004-04-26
  • 最后登录2010-07-27
  • 粉丝0
  • 关注0
  • 积分244分
  • 威望75点
  • 贡献值0点
  • 好评度23点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2005-06-09 18:02
bmyyyud老兄,我按照你的说法查了一些资料,的确发现NtShutdownSystem是在SDT中的,但是RtlAdjustPrivilege呢,怎么办。还有,这样做你是否有实践过?
bmyyyud
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2010-01-21
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望130点
  • 贡献值0点
  • 好评度106点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2005-06-10 10:01
bmyyyud老兄,我按照你的说法查了一些资料,的确发现NtShutdownSystem是在SDT中的,但是RtlAdjustPrivilege呢,怎么办。还有,这样做你是否有实践过?

RtlAdjustPrivilege,ZwShutdownSystem 这两个函数最初在ntdll.dll中输出
我在ring3下试过,其实很多病毒都采用这种关机办法
在ring 0下,我个人认为既然已经是ring 0了,就不在乎RtlAdjustPrivilege,不需要了,而且NtShutdownSystem一般是通过权限校验后才调用的,具体看
https://www.xfocus.org/bbs/index.php?act=SE&f=3&t=37808&p=139854
一条一条的看
这里贴一部分

--------------------------------------------------------------------------------
 
发帖者:hzzh 讨论区:编程讨论推荐区
标 题:关于2000的关机函数问题
发信站:安全焦点(2004年6月20日17时58分59秒)
在win2000下,从用户进程中调用ExitWindowsEx(),关机一切正常
但是在系统进程中(winlogon.exe)调用ExitWindowsEx()能退出系统,却不能关闭电源!?
试过EWX_SHUTDOWN ,EWX_POWEROFF  , EWX_FORCE  ,EWX_FORCEIFHUNG  的各种组合,也试过 InitiateSystemShutdownEx(),都出现“现在可以安全地关机了”,不能关闭电源,郁闷中

那位高人能给与指点,万分感谢~~~~~

--

--------------------------------------------------------------------------------
发帖者:flyleaf 讨论区:编程讨论推荐区
标 题:用我的代码试:
发信站:安全焦点(2004年7月2日9时45分51秒)
HANDLE hToken;
            TOKEN_PRIVILEGES tkp;
            // Get a token for this process.
            if (!OpenProcessToken(GetCurrentProcess(),
                TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
                MessageBox(\"error\",\"error\",0);
            
            // Get the LUID for the shutdown privilege.
            
            LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
                &tkp.Privileges[0].Luid);
            
            tkp.PrivilegeCount = 1;  // one privilege to set    
            tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
            
            // Get the shutdown privilege for this process.
            
            AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
                (PTOKEN_PRIVILEGES)NULL, 0);
            
            if (GetLastError() != ERROR_SUCCESS)
                MessageBox(\"error\",\"error\",0);
            
            // Shut down the system and force all applications to close.
            InitiateSystemShutdown(
                NULL,
                \"马上自动关机!请保存您的文件\",
                20,
                FALSE,
                FALSE
                );
            
            
            if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF, 0))
                MessageBox(\"error\",\"error\",0);

另发现个问题:这个坛子中的人都不喜欢把代码帖出来,问问题的也不帖出来让大家看那里错了
:(

--
/**********************************************************
*  谁教我如何注释掉自己的方法?
***********************************************************/
--------------------------------------------------------------------------------
发帖者:hzzh 讨论区:编程讨论推荐区
标 题:Re: 关于2000的关机函数问题
发信站:安全焦点(2004年7月3日21时05分21秒)
flyleaf 说的极是“这个坛子中的人都不喜欢把代码帖出来,问问题的也不帖出来让大家看那里错了”
谢谢flyleaf 回答。

我的程序如下:
==================================================
int  ExitComputer(int ExitCode )
{
    int iRet=0;
    HANDLE hToken;
    TOKEN_PRIVILEGES NewState;
    DWORD  ReturnLength = 0;
    LUID luidPrivilegeLUID;
    OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken);
    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &luidPrivilegeLUID);
    NewState.PrivilegeCount = 1;
    NewState.Privileges[0].Luid = luidPrivilegeLUID;
    NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(hToken, FALSE, &NewState, NULL, NULL, NULL);
//        InitiateSystemShutdown(NULL,NULL,0,TRUE,FALSE);
//        InitiateSystemShutdownEx(NULL, NULL, 0, 1,0,-1 );
//        iRet=RunUserProcess( m_DefUser, m_DefPass,\"c:\\\\shutdown.exe\", \"-s -f -t 5\");
    iRet = ExitWindowsEx(ExitCode,-1);
    if(iRet==0)
    {
        CString err;
        DisplayErrorText(GetLastError(),err);
        _SandMessage(err);
    }
    return iRet;
}

//以lpszUsername 身份运行lpApplicationName
int RunUserProcess(LPCTSTR lpszUsername,LPCTSTR lpszPassword, LPCTSTR lpApplicationName, LPTSTR lpCommandLine)
{
    HANDLE hToken;
    HANDLE hTokenNew;
    STARTUPINFO startinfo;
    PROCESS_INFORMATION procinfo;
    if(! LogonUser(lpszUsername,NULL,lpszPassword,LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,&hToken))
        return 1;
    if(! DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,NULL,SecurityImpersonation ,TokenPrimary,&hTokenNew))
        return 2;
    GetStartupInfo(&startinfo);
    if(! CreateProcessAsUser(hTokenNew,lpApplicationName,lpCommandLine,NULL,NULL,TRUE,0,NULL,NULL,&startinfo,&procinfo))
        return 3;
    return 0;
}
============================================================

问题描述:
用ExitComputer(int ExitCode ) 退出系统和关闭电源
在系统进程中(winlogon.exe)调用ExitComputer(),能够正常LOGOFF、REBOOT,但是SHUTDOWN或POWEROFF时,出现“现在可以安全地关机了”,不能关闭电源。
但是把相同的代码用DLL远程注入到用户进程,如explorer.exe中,一切都正常,能够正常关闭电源了。
试过EWX_SHUTDOWN ,EWX_POWEROFF  , EWX_FORCE  ,EWX_FORCEIFHUNG  的各种组合,也试过 InitiateSystemShutdown(),InitiateSystemShutdownEx(),
RunUserProcess(\"administrator\", password,\"c:\\\\shutdown.exe\", \"-s -f -t 5\");,shutdown.exe为XP中的关机程序,
也试过flyleaf 介绍的InitiateSystemShutdown与ExitWindowsEx的组合,结果完全一样:能够退出系统,但是不能关闭电源!
我这个程序是用于机器不使用时,自动关闭电源的,杭州用电紧张啊,呵呵
请大家帮帮忙。

--

--------------------------------------------------------------------------------
发帖者:hzzh 讨论区:编程讨论推荐区
标 题:Re: 关于2000的关机函数问题
发信站:安全焦点(2004年7月4日15时46分32秒)
终于搞定了
试了N多方法,都不行,难道比尔盖茨还有秘密武器?
用IDA对winlogon.exe和msgina.dll进行了分析,NND,比尔盖茨果然藏了秘密武器ZwShutdownSystem!

ZwShutdownSystem是用于驱动程序关闭系统的一个未公开函数,位于NTDLL.DLL中。按理winlogon.exe并非驱动程序,也没有运行在内核级,应该用不到驱动函数的,但是盖茨大叔用了,我也可以用吧,仿照winlogon.exe的用法,代码如下:
======================================
nRet=RtlAdjustPrivilege(0x13,1,1,&en);
if(nRet==0x0C000007C)
    nRet = RtlAdjustPrivilege(0x13,1,0,&en);
nRet=ZwShutdownSystem(2);
================================

嘿嘿,这下系统干净利索地,没有任何脾气地快速关闭了
就这样解决了,害得我绞了几天的脑汁 ^^)。



--

--------------------------------------------------------------------------------
发帖者:hzzh 讨论区:编程讨论推荐区
标 题:Re: 关于2000的关机函数问题
发信站:安全焦点(2004年7月7日22时54分19秒)
被加为推荐了~~,呵呵,对大家有用就好;-)

我再狗尾续貂,把关闭电源问题总结一下:
在windows2000/xp中,先获得SE_SHUTDOWN_NAME权限,可以退出系统的函数有:

1、ExitWindowsEx(EWX_POWEROFF,0);
    标准方法,
2、InitiateSystemShutdown(NULL,NULL,0,TRUE,FALSE);
    标准方法,
3、CreateProcessAsUser(hTokenNew,\"c:\\\\shutdown.exe\", \"-s -f -t 5\",NULL,NULL,TRUE,0,NULL,NULL,&startinfo,&procinfo);
    调用shutdown.exe进程来关闭系统,  当然也可以CreateProcess来创建shutdown.exe进程。

4、    BYTE buffer[64]={0};
    *((DWORD *)buffer+11)=EWX_POWEROFF;        
    i=CsrClientCallServer(buffer,0,0x00030a00;,0x10);
    发送关闭电源消息给子系统。

5、    nRet=RtlAdjustPrivilege(0x13,1,1,&en);
    if(nRet==0x0C000007C)
            nRet = RtlAdjustPrivilege(0x13,1,0,&en);
    nRet=ZwShutdownSystem(2);
    利用ZwShutdownSystem(2)关闭电源,这个函数要求有 SE_SHUTDOWN_PRIVILEGE权限,因此要先用RtlAdjustPrivilege函数来设置 SE_SHUTDOWN_PRIVILEGE,SE_SHUTDOWN_PRIVILEGE的值为0x13,我前面的程序中13错了,应该为0x13。 ZwShutdownSystem函数不通知应用程序和服务程序,就直接关闭系统了,关机速度非常快,但是如果有程序没有保存数据的话,是不会有任何提示的。


    以上5种方法,在应用程序中,都可以正常关闭电源,不会有任何问题。(估计flyleaf 是在用户模式程序中试验的,所以没有问题)。
    但是在winlogon.exe进程中(我的关机代码是放在GINA.DLL中的),用上述5中方法,都能够退出系统,但是前面4中都会出现出现“现在可以安全地关机了”提示,不能关闭电源。

    当然第5种方法,也不是太理想,关机太快了,就像突然拔除电源一样,不过原来的目的达到了,也就将就着用了。要像windows那样能够优雅地关闭电源,其实还有许多问题没有弄懂,以后有兴趣再分析吧。



至于用IDA怎样对winlogon.exe和msgina.dll进行了分析,过程不复杂,(高手就别看了,呵呵)

1、用IDA对winlogon.exe进行反汇编
2、用serch 找ShutdownSystem,就可以找到以下内容:
.idata:010015CC                 extrn NtShutdownSystem:dword ; DATA XREF: sub_10117E3+3C
.idata:010015CC                                         ; sub_101182F+3C
.idata:010015CC                                         ; sub_101187B+8C
.idata:010015CC                                         ; sub_101187B+123
.idata:010015CC                                         ; sub_101187B+16A
.idata:010015CC                                         ; sub_101187B+1A9
.idata:010015CC                                         ; sub_10153BF+184
.idata:010015CC                                         ; .text:01017880
.idata:010015CC                                         ; .text:01018DFE
.idata:010015CC                                         ; .text:01018F11
.idata:010015D0                 extrn RtlEnterCriticalSection:dword

3、根据NtShutdownSystem的引用,可以看到以下内容
.text:010119D5                 push    1
.text:010119D7                 push    13h
.text:010119D9                 call    sub_1013C8A
.text:010119DE                 cmp     edi, 0Ah
.text:010119E1                 jnz     short loc_10119F4
.text:010119E3                 push    2
.text:010119E5
.text:010119E5 loc_10119E5:                            ; CODE XREF: sub_101187B+180
.text:010119E5                                         ; sub_101187B+183
.text:010119E5                 call    ebp ; NtShutdownSystem

    其中
.text:010119E3                 push    2
.text:010119E5                 call    ebp ; NtShutdownSystem
    表示调用NtShutdownSystem(2)函数。

.text:010119D5                 push    1
.text:010119D7                 push    13h
.text:010119D9                 call    sub_1013C8A
    
表示调用sub_1013C8A(0X13,1)函数:

.text:01013C8A sub_1013C8A     proc near               ; CODE XREF: ShutDown_101173D+4Cp
.text:01013C8A var_2           = byte ptr -2
.text:01013C8A var_1           = byte ptr -1
.text:01013C8A arg_0           = dword ptr  8
.text:01013C8A arg_4           = dword ptr  0Ch
.text:01013C8A
.text:01013C8A                 push    ebp
.text:01013C8B                 mov     ebp, esp
.text:01013C8D                 push    ecx
.text:01013C8E                 lea     eax, [ebp+var_1]
.text:01013C91                 push    esi
.text:01013C92                 mov     esi, ds:RtlAdjustPrivilege
.text:01013C98                 push    eax
.text:01013C99                 push    1
.text:01013C9B                 push    [ebp+arg_4]
.text:01013C9E                 push    [ebp+arg_0]
.text:01013CA1                 call    esi ; RtlAdjustPrivilege
.text:01013CA3                 cmp     eax, 0C000007Ch
.text:01013CA8                 jnz     short loc_1013CB8
.text:01013CAA                 lea     eax, [ebp+var_1]
.text:01013CAD                 push    eax
.text:01013CAE                 push    0
.text:01013CB0                 push    [ebp+arg_4]
.text:01013CB3                 push    [ebp+arg_0]
.text:01013CB6                 call    esi ; RtlAdjustPrivilege
.text:01013CB8
.text:01013CB8 loc_1013CB8:                            ; CODE XREF: sub_1013C8A+1Ej
.text:01013CB8                 xor     ecx, ecx
.text:01013CBA                 pop     esi
.text:01013CBB                 test    eax, eax
.text:01013CBD                 setnl   cl
.text:01013CC0                 mov     eax, ecx
.text:01013CC2                 leave
.text:01013CC3                 retn    8
.text:01013CC3 sub_1013C8A     endp

改用c来表示的话:
int sub_1013C8A(int Privilege ,BOOL flag)
{
    int en;
    int nRet=RtlAdjustPrivilege(Privilege ,flag,TRUE,&en);
    if(nRet==0x0C000007C)
            nRet = RtlAdjustPrivilege((Privilege ,flag,FALSE,&en);
    return nRet;
}

因此就得到了如下快速关机代码
=====================================
    #define SE_SHUTDOWN_PRIVILEGE             0x13
    nRet=RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,TRUE,TRUE,&en);
    if(nRet==0x0C000007C)
        nRet = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,TRUE,FALSE,&en);    
    nRet=ZwShutdownSystem(2);
======================================

    大家可能注意到:在IDA中得到的是NtShutdownSystem,而C语言实际用的是ZwShutdownSystem。
    实际上在NTDLL.DLL中,Nt*****和Zw*****开头的函数,对于用户模式程序,是等价的,只是NTDLL.dll中相同入口点的两个不同符号而已,用GetProcAddress(hMsDll,\"ZwShutdownSystem\")和 GetProcAddress(hMsDll,\"NtShutdownSystem\")就可以发现他们完全相同,而且实际运行结果也没有差异。
    但是通过查阅资料,好像说Zw*****的入口会有运行特权的权限检查,会把程序的运行模式更新为内核模式,而Nt*****的入口就没有这个检查。因此感觉上,使用ZwShutdownSystem会安全一些,我想可能原因是内核模式程序是依靠 ntoskrnl.exe而不是依靠ntdll.dll来连接的,这时Nt*****和Zw*****可能有差别。(吓猜的,可能会误人子弟,还是让高手来点评吧,闪)



--

--------------------------------------------------------------------------------
发帖者:sinister 讨论区:编程讨论推荐区
标 题:Re: 关于2000的关机函数问题
发信站:安全焦点(2004年7月7日23时38分47秒)
我个人觉得最后一段说的正确。NATIVE API 有两套。一个是 ring 3 NTDLL 导出的,一个是由 ring 0 NTOSKRNL 导出的。ring 3 的 NTDLL 导出了全部 NATIVE API。NTOSKRNL 则没有。两套 NATIVE API 都分别有各自的 Nt/Zw 开头的函数,正如你分析的当在 ring 3 调用 NTDLL 的 Zw/Nt 时实际指向的是同一函数,由 int 2e / sysentry 切换到 ring 0。 KiSystemService / KiFastCallEntry 派发。当在内核调用 NTOSKRNL 的 ZwXXX 时,是通过 int 2e 重入内核 (NT/2K),内核中的 NtXXX 函数一开始就是函数实现没有额外的东西。你看资料上说的应该是指内核模式的
NATIVE API 调用区别。(不是高手,更谈不上点评)

--
学而后知不足
--------------------------------------------------------------------------------
注意最后sinister的理解,我也觉得既然已经ring 0了,就不需要权限提升了,不知大家还有什么想法,请赐教
 
 
 
滚滚长江东逝水 浪花淘尽英雄 是非成败转头空 青山依旧在 几度夕阳红 白发渔樵江渚上 惯看秋月春风 一壶浊酒喜相逢 古今多少事 尽付笑谈中
游客

返回顶部