📌  相关文章
📜  windows 以管理员身份运行 - 汇编(1)

📅  最后修改于: 2023-12-03 15:05:57.478000             🧑  作者: Mango

Windows 以管理员身份运行 - 汇编

在 Windows 上,有一些 Action 和任务需要以管理员身份运行。但如果你的程序没有显式地要求以管理员身份运行,那么用户通过双击或者简单提权的方式运行程序可能会遇到权限不足的问题。

如何使程序以管理员身份运行呢?本文将介绍一种能够检查并获取管理员权限的方法,并且让程序以管理员身份运行。

提权方式
  1. 对于 GUI 应用程序,用户右击程序图标,在弹出的菜单里选择“以管理员身份运行”就行了。
  2. 对于命令行程序,用户可以按下“Win+X”,选择“Windows PowerShell(管理员)”或“命令提示符(管理员)”,然后在控制台中执行程序。
检查并获取管理员权限的方法

我们可以使用 Windows API 来获取当前用户的安全令牌。代码如下所示:

include windows.inc
include user32.inc
include kernel32.inc

.data
    String db 20 dup (0)
    TokenHandle HANDLE ?
    PrivilegeLUID LUID of _TOKEN_PRIVILEGES
    NewStateTOKEN_PRIVILEGES ?
    OldStateTOKEN_PRIVILEGES ?

.data?
    ReturnLength dd ?

.code
start:
    ; 打开当前进程的访问令牌
    invoke GetCurrentProcess
    invoke OpenProcessToken, eax, TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES, addr TokenHandle
    .if eax == false
        invoke MessageBox, 0, addr OpenTokenErrorMsg, addr AppName, MB_ICONERROR or MB_OK
        jmp end
    .endif

    ; 获取管理员权限的 LUID
    invoke LookupPrivilegeValue, 0, SE_DEBUG_NAME, addr PrivilegeLUID
    .if eax == false
        invoke MessageBox, 0, addr LookupPrivilegeErrorMsg, addr AppName, MB_ICONERROR or MB_OK
        jmp close_token_and_end
    .endif

    ; 获取当前进程的安全令牌信息
    invoke GetTokenInformation, TokenHandle, TokenPrivileges, 0, 0, addr ReturnLength
    mov eax, ReturnLength
    invoke GlobalAlloc, GPTR, eax
    mov NewStateTOKEN_PRIVILEGES, eax
    invoke GetTokenInformation, TokenHandle, TokenPrivileges, NewStateTOKEN_PRIVILEGES, eax, addr ReturnLength
    .if eax == false
        invoke MessageBox, 0, addr GetTokenInformationErrorMsg, addr AppName, MB_ICONERROR or MB_OK
        jmp free_mem_close_token_and_end
    .endif

    ; 获取 LUID 所对应的权限的 flag,设置权限
    mov edi, NewStateTOKEN_PRIVILEGES
    mov ecx, dword ptr [edi]
    mov edx, PrivilegeLUID
    mov esi, edi
    sub esi, 4
    mov ebx, dword ptr [esi]
    mov eax, ecx
.process_privileges_loop:
    mov esi, edi
    add esi, eax
    mov eax, dword ptr [esi]
    cmp eax, edx
    .if eax == edx
        invoke RtlCopyMemory, addr ebx, addr eax, 4
        mov dword ptr [ebx + 4], SE_PRIVILEGE_ENABLED
        jmp privileges_processed
    .endif
    add ecx, 4
    cmp ecx, dword ptr [edi-4]
    jb process_privileges_loop

privileges_processed:
    ; 将更改后的权限信息应用到进程
    invoke AdjustTokenPrivileges, TokenHandle, false, NewStateTOKEN_PRIVILEGES, 0, addr OldStateTOKEN_PRIVILEGES, addr ReturnLength
    .if eax == false
        invoke MessageBox, 0, addr AdjustTokenPrivilegesErrorMsg, addr AppName, MB_ICONERROR or MB_OK
    .endif

free_mem_close_token_and_end:
    invoke GlobalFree, NewStateTOKEN_PRIVILEGES

close_token_and_end:
    ; 关闭访问令牌
    invoke CloseHandle, TokenHandle

end:
    invoke ExitProcess, 0
让程序以管理员身份运行

接下来,我们将使用该方法来启动一个新的进程,该进程也会以管理员身份运行。代码如下所示:

include windows.inc
include user32.inc
include kernel32.inc

.data
    AppName db 'My Application',0
    CommandLine db 'notepad.exe',0

.code
start:
    ; 检查并获取管理员权限
    ; ...

    ; 启动新进程以获取管理员权限
    invoke CreateProcessAsUser, 0, addr CommandLine, 0, 0, 0, 0, 0, 0, 0, addr StartupInfo, addr ProcessInfo
    .if eax == false
        invoke MessageBox, 0, addr CreateProcessErrorMsg, addr AppName, MB_ICONERROR or MB_OK
        jmp end
    .endif

    invoke CloseHandle, ProcessInfo.hProcess
    invoke CloseHandle, ProcessInfo.hThread

end:
    invoke ExitProcess, 0

现在你的程序已经以管理员身份成功运行了!