黑客编程技术学习之-自动关机

主要使用ExitWindowsEx函数,在NT系统中必须先提权一下

开发环境:Win7+VC6.0

思路 :获得本地进程句柄,新建令牌并赋予较高权限,通过进程句柄为进程赋予新令牌,重启操作

以下是自动重启代码:

#include <windows.h>
int main()
{
    HANDLE hToken;
    TOKEN_PRIVILEGES tkp;

    //取得系统版本
    OSVERSIONINFO osvi;
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if(GetVersionEx(&osvi)== 0)
        return false;

    if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
    {
        if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken))
            return false;

        //获取本地唯一标识用于在特定系统中设置权限
        LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid);
        tkp.PrivilegeCount = 1;
        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

        //提升访问令牌的权限
        AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);
    }

    //强制重启
    ExitWindowsEx(EWX_REBOOT|EWX_FORCE,0);
   
    return 1;
}

以下对用到的一些数据结构以及函数进行详解:

TOKEN_PRIVILEGES:

TOKEN_PRIVILEGES这个结构,其声明如下:

typedef struct _TOKEN_PRIVILEGES {  

 DWORD PrivilegeCount;   

   LUID_AND_ATTRIBUTES Privileges[];  

} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;   

PrivilegeCount指的数组元素的个数,接着是一个LUID_AND_ATTRIBUTES类型的数组,再来看一下LUID_AND_ATTRIBUTES这个结构的内容,声明如下:   

typedef struct _LUID_AND_ATTRIBUTES {   

LUID Luid;   

DWORD Attributes;   

} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES   

第二个参数就指明了我们要进行的操作类型,有三个可选项: SE_PRIVILEGE_ENABLED、SE_PRIVILEGE_ENABLED_BY_DEFAULT、 SE_PRIVILEGE_USED_FOR_ACCESS。要使能一个权限就指定Attributes为SE_PRIVILEGE_ENABLED。第 一个参数就是指权限的类型,是一个LUID的值,LUID就是指locally unique identifier,我想GUID大家是比较熟悉的,和GUID的要求保证全局唯一不同,LUID只要保证局部唯一,就是指在系统的每一次运行期间保证 是唯一的就可以了。

我们要怎么样才能知道一个权限对应的LUID值是多少呢?这就要用到另外一个API函数

LookupPrivilegevalue,其原形如下:

  BOOL LookupPrivilegevalue( LPCTSTR lpSystemName, // system name,为NULL 

                                                LPCTSTR lpName, // privilege name   

                                                 PLUID lpLuid // locally unique identifier,第三个参数就是返回LUID的指针,赋予这个lpLuid一个新的luid   );

在Winnt.h中还定义了一些权限名称的宏,如:

#define SE_BACKUP_NAME TEXT("SeBackupPrivilege")   #define SE_RESTORE_NAME TEXT("SeRestorePrivilege")  

#define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege")   #define SE_DEBUG_NAME TEXT("SeDebugPrivileg")

 

OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessID)还是会遇到“访问拒绝”的错误。什么原因呢?原来在默认的情况下进程的一些访问权限是没有被使能(Enabled)的,所以我们 要做的首先是使能这些权限。与此相关的一些API函数有OpenProcessToken、LookupPrivilegevalue、 AdjustTokenPrivileges。我们要修改一个进程的访问令牌,首先要获得进程访问令牌的句柄,这可以通过

OpenProcessToken 得到,函数的原型如下:

  BOOL OpenProcessToken(   __in HANDLE ProcessHandle, //要修改访问权限的进程句柄,为GetCurrentProcess()即可 

                                                    __in DWORD DesiredAccess, //指定你要进行的操作类型   

                                                    __out PHANDLE TokenHandle //返回的访问令牌指针,即操作目标

                                            );

如果希望获得所有权限,可以为TOKEN_ALL_ACCESS

AdjustTokenPrivileges的原型如下:

  BOOL AdjustTokenPrivileges(   HANDLE TokenHandle, // handle to token   

                                                       BOOL DisableAllPrivileges, // disabling option,一般为FALSE

                                                    PTOKEN_PRIVILEGES NewState, // privilege information,赋予的新令牌状态

                                                     DWORD BufferLength, // size of buffer   

                                                       PTOKEN_PRIVILEGES PreviousState, // original state buffer  

                                                       PDWORD ReturnLength // required buffer size

                                             );


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章