Skip to content

Tk bof#2

Merged
TGJLS merged 72 commits into
mainfrom
tk-bof
May 26, 2026
Merged

Tk bof#2
TGJLS merged 72 commits into
mainfrom
tk-bof

Conversation

@TGJLS

@TGJLS TGJLS commented May 26, 2026

Copy link
Copy Markdown
Owner

Add bofs to manage tokens

TGJLS and others added 30 commits May 23, 2026 12:48
… bofdefs.h

- Create TK-BOF/bofdefs.h with 7 ADVAPI32$ + 1 NTDLL$ token API declarations
- Add KERNEL32$OpenProcess to _include/bofdefs.h in new process-management section
- Signatures verified against MinGW 16.1.0 windows.h + winternl.h

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- steal.c: DWORD pid + BOOL no_apply via BeaconDataInt x2
- use.c: DWORD token_handle via BeaconDataInt x1
- make.c: username/password/domain via BeaconDataExtract x3 + BOOL no_apply via BeaconDataInt x1
- rm.c: DWORD token_handle via BeaconDataInt x1
- revert.c + privget.c: no args, empty body
- All 12 targets compile cleanly under x64 and x32 MinGW

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TK-BOF/Makefile: 12 x64+x32 targets, CFLAGS -I . for local bofdefs.h
- Root Makefile SUBDIRS: FS-BOF Exit-BOF TK-BOF
- make -C TK-BOF/ produces 12 stripped .o files with zero [!] lines
- make clean && make at repo root succeeds end-to-end

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add 29-01-SUMMARY.md for phase 29 plan 01

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Swap CFLAGS from -I ../_include -I . to -I . -I ../_include so
TK-BOF/bofdefs.h shadows the shared header for all TK-BOF sources.
Add chain-include of ../_include/bofdefs.h in TK-BOF/bofdefs.h so
both KERNEL32/MSVCRT and ADVAPI32/NTDLL symbol sets are visible.
…se.c

Use HANDLE token_handle = NULL and the triple cast
(HANDLE)(ULONG_PTR)(DWORD) to correctly widen the 32-bit parser value
to a pointer-sized HANDLE without silent truncation on x64.
intZeroMemory macro expands to MSVCRT$memset but the function was not
declared in the MSVCRT block. Add the missing declaration so callers
compile without implicit-declaration errors.
Set status: fixed and fixed timestamp after CR-01, WR-01, and WR-02
were applied and build verified (12 [+], 0 [!]).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Static inline TkErrorMessage wrapping KERNEL32$FormatMessageA (flags 0x1300)
- On success: copies FormatMessage text, strips trailing CR/LF/space, frees sysBuf
- On failure: fallback via MSVCRT$_snprintf with 'error %lu' format
- Header guard _TKERROR_H_, includes bofdefs.h (relative to TK-BOF/)
- No FsErrorMessage/FsNormalizeSlashes/base.c references
- Static inline TkErrorMessage wrapping KERNEL32$FormatMessageA (flags 0x1300)
- On success: copies FormatMessage text, strips trailing CR/LF/space, frees sysBuf
- On failure: fallback via MSVCRT$_snprintf with 'error %lu' format
- Header guard _TKERROR_H_, includes bofdefs.h (relative to TK-BOF/)
- No FsErrorMessage/FsNormalizeSlashes/base.c references
- OpenProcess(PROCESS_QUERY_INFORMATION) -> OpenProcessToken(TOKEN_DUPLICATE)
- DuplicateTokenEx(TOKEN_ALL_ACCESS, SecurityImpersonation, TokenImpersonation)
- Intermediate handles closed immediately after DuplicateTokenEx success
- no_apply=FALSE: ImpersonateLoggedOnUser + print '[+] Handle: 0x%lx'
- no_apply=TRUE: skip impersonation, print '[+] Handle: 0x%lx (impersonation not applied)'
- All four failure paths use TkErrorMessage + BeaconPrintf(CALLBACK_ERROR)
- Handle cleanup on every failure path; no handle leaks
- Builds steal x64 and steal x32 cleanly
- tkerror.h created: TkErrorMessage static inline helper wrapping KERNEL32$FormatMessageA
- steal.c implemented: full 4-step token chain with handle cleanup on all failure paths
- Build clean: steal x64 and steal x32 pass, no [!] lines
- TK-01 requirement satisfied
…handle

- Add #include "../tkerror.h" after bofdefs.h
- Call ADVAPI32$ImpersonateLoggedOnUser(token_handle)
- On failure: capture GetLastError, format via TkErrorMessage, emit CALLBACK_ERROR
- On success: emit "[+] Impersonating handle 0x%lx" via CALLBACK_OUTPUT
- Builds clean for use x64 and use x32
… on failure

- Call NTDLL$NtClose(token_handle) and store NTSTATUS result
- Failure test is status < 0 (NT_SUCCESS literal, no macro)
- On failure: emit "[-] rm: NtClose failed: 0x%lx" with (ULONG) status cast
- On success: emit "[+] Handle 0x%lx closed." with (ULONG_PTR) token_handle
- No tkerror.h — NtClose does not return Win32 error; FormatMessage not used
- Builds clean for rm x64 and rm x32
…error branch

- Call ADVAPI32$RevertToSelf() — return value discarded per D-07
- Emit "[+] Reverted to process token." via CALLBACK_OUTPUT
- No error branch, no BeaconDataParse, no tkerror.h — minimal per CLAUDE.md
- Builds clean for revert x64 and revert x32
- SUMMARY.md records ImpersonateLoggedOnUser chain (use.c), NtClose+NTSTATUS chain (rm.c), RevertToSelf minimal body (revert.c)
- Six successful build lines: use x64/x32, rm x64/x32, revert x64/x32
- All three files compile cleanly with zero [!] lines
…GW LLP64

%lx with ULONG_PTR silently drops the upper 32 bits on x64 MinGW (LLP64
data model: long is 32-bit). Fixes steal.c (×2), use.c, and rm.c.
NTSTATUS error in rm.c left as %lx/(ULONG) — NTSTATUS is always 32-bit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… to bofdefs.h

- Added ADVAPI32$OpenThreadToken declaration (required by privget in Plan 02)
- Added KERNEL32$GetCurrentThread declaration (required by privget in Plan 02)
- Added KERNEL32$GetCurrentProcess declaration (required by privget in Plan 02)
- Parse 5 args: username, password, domain, no_apply, logon_type
- Sentinel: logon_type defaults to 9 (LOGON32_LOGON_NEW_CREDENTIALS)
- Sentinel: domain defaults to "." when empty/null
- Call LogonUserA; on failure print error and return (no handle leak)
- On ImpersonateLoggedOnUser failure: NtClose hToken before return (D-07)
- Print handle as 0x%llx; no_apply path notes impersonation not applied
…implementation

- bofdefs.h: added OpenThreadToken, GetCurrentThread, GetCurrentProcess
- make.c: LogonUserA credential token creation BOF with optional impersonation
- All 12 TK-BOF targets compile cleanly (x64+x32)
TGJLS and others added 28 commits May 24, 2026 21:45
…n-only

- Registers steal, use, make, rm, revert, privget under parent `tk` command
- steal: addArgInt(pid) + addArgBool(--no-apply); packs int,int
- use/rm: addArgInt(token_handle); packs int
- make: addArgString(username/password) + addArgFlagString(--domain) + addArgBool(--no-apply) + addArgFlagInt(--logon-type); packs wstr,wstr,wstr,int,int
- revert/privget: no args; execute_alias without bof_params
- Registers beacon-only: ["beacon"], ["windows"], []
- Appends ax.script_load(path + "TK-BOF/tk.axs") after PS-BOF line
- bof-collection.axs now loads all 4 category scripts: FS-BOF, Exit-BOF, PS-BOF, TK-BOF
…mmand sections

- H1 title, one-line intro listing all 6 subcommands
- ## Handle Lifecycle section (before command sections, per D-12)
- One ## section per command (steal, use, make, rm, revert, privget)
- Each section has description paragraph and fenced usage code block
- Usage variants per D-11: steal (2 lines), make (4 lines), others (1 line)
- No table (table goes in root README only, per FS-BOF/README.md precedent)
…redit

- Insert ## TK-BOF section between ## PS-BOF and ## Credits
- 6-row command table (steal, use, make, rm, revert, privget) with Commands/Usage/Notes columns
- More details link pointing to TK-BOF/README.md
- Update Kharon credit from "PS-BOF command implementations" to "PS-BOF and TK-BOF command implementations" (D-14)
- TK-BOF/README.md: per-command docs with handle lifecycle note (TK-09)
- README.md: TK-BOF section table + extended Kharon credit (TK-10)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…K-BOF/README.md)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Close TK-09 gaps found during verification: ROADMAP SC-2 requires a
command table and Kharon attribution in TK-BOF/README.md. Plan 03 had
followed FS-BOF/README.md conventions (table in root only) which
conflicted with the roadmap contract.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The code-fixer changed ADVAPI32 declarations from WINBASEAPI to WINADVAPI
to match _include/bofdefs.h convention, but MinGW treats both identically
in this toolchain and WINBASEAPI is the established pattern across every
other BOF file in the project. Revert to WINBASEAPI for consistency.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Insert idempotent step after Create CI user and before Start OpenSSH Server
- Creates local Windows user tk_test with password Tk_Test_Pass1!
- Uses Get-LocalUser SilentlyContinue guard pattern from existing CI user step
- tk_test is for tk make LogonUser testing only; not added to Administrators
- TK-BOF deploy block from Phase 32 (TK-12) remains untouched
…-11)

- 9 entries in D-11 order: spawn fixture, steal immediate, revert,
  steal --no-apply, use, rm, make, revert, privget
- tk_pid captured from ps run fixture (distinct from PS-BOF pid)
- tk_handle captured from steal --no-apply for use/rm chaining
- tk make uses tk_test/Tk_Test_Pass1! credentials from CI setup step
- tk privget uses not_expected: error (partial success acceptable per D-10)
- No cleanup task per D-02; ping fixture dies on beacon exit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GitHub-hosted Windows runners reject New-LocalUser with
InvalidPasswordException for Tk_Test_Pass1! due to runner-applied
password complexity/length policy. Export the local security policy
via secedit, disable complexity and zero the minimum length, then
apply before creating the test user. Runner is ephemeral so the
policy change has no lasting effect.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Only registered for beacon; CI agent is kharon. Match the pattern
used by fs.axs, ps.axs, and exit.axs: ["beacon", "gopher", "kharon"].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tk use / tk rm used addArgInt which rejects hex strings like "0xad8".
Change both to addArgString and parse with parseInt(val, 16) in the
PreHook — handles both "0x"-prefixed and bare hex inputs.

Update tk-steal-noapply capture regex from Handle: 0x(...) to
Handle: (0x...) so {{tk_handle}} carries the 0x prefix that parseInt
and the expected_regex patterns already expect.

Move TK-BOF block to the top of tasks.yaml so token tests run first.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tput

Windows copy output includes a trailing space on the "C:\...\*.xyz" line
when no files match; stripping it broke the substring match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Planning artifacts are local-only; not intended for the public branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@TGJLS TGJLS merged commit 1478eeb into main May 26, 2026
12 checks passed
@TGJLS TGJLS deleted the tk-bof branch May 26, 2026 05:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant