阅读:3669回复:9
如何关机,40分(我最多能给这么多)
请问:在KERNEL层,如何关闭系统?
|
|
沙发#
发布于:2005-06-08 18:23
没人理会,只好自己先顶下,不要被淹没了。
难道对高手来说也很难吗 |
|
板凳#
发布于:2005-06-08 20:06
反汇编一下ExitWindowEx,看看调用了什么系统函数。但关机涉及到
csrss,service的很多工作,可能很难从ring0做。为什么必须在ring0 做呢? |
|
地板#
发布于:2005-06-08 21:42
呵呵,我也觉得实现起来有困难,但是有人告诉我说可以直接调用ExitWindowEx,我没有在KERNEL层调用过上层API。如果老大知道怎么实现,请告诉一下
|
|
地下室#
发布于:2005-06-08 22:32
搜索一下Ring0 Call Ring3,以前有过这方面的讨论
|
|
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一下 |
|
|
6楼#
发布于:2005-06-09 12:56
谢谢两位关注我的问题,bmyyyud老兄,你所说的函数我在我的DDK里面找不到说明,我用DDK2003,是不是这些函数是WINDOWS UNDOC的,怎么才能在2K/XP系统上面使用。分数已给,感谢。
|
|
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 中对应这个函数的地址 |
|
|
8楼#
发布于:2005-06-09 18:02
bmyyyud老兄,我按照你的说法查了一些资料,的确发现NtShutdownSystem是在SDT中的,但是RtlAdjustPrivilege呢,怎么办。还有,这样做你是否有实践过?
|
|
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了,就不需要权限提升了,不知大家还有什么想法,请赐教 |
|
|