黑客編程技術學習之-自動關機

主要使用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

                                             );


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