Skip to content

Generated profiles do not load on Cobalt Strike 4.13 (stage.rdll_loader and stage.name rejected) #32

Description

@warpedatom

Every profile SourcePoint generates is rejected by c2lint on Cobalt Strike
4.13 (June 2026), so none of them can be loaded by a team server on the current
release. I hit this while testing PR #30 and thought it was worth reporting
separately, since two of the four causes are compatibility questions rather
than bugs and the decision on those is yours.

Reproduction

$ ./SourcePoint -Host acme-email.com -Outfile test.profile -Profile 2 -Injector VirtualAllocEx
$ ./c2lint test.profile
[*] Starting c2lint
[-] Error(s) while compiling test.profile
Error: invalid option for <.stage> at line 53
Error: Unknown statement in <.stage> at line 65
[-] Unable to load the Beacon profile

c2lint reports roughly two errors per run, so the failures surface in waves as
each pair is fixed. There are four in total.

The two in PR #30

These are unambiguous on any version, and are fixed there:

  1. smartinject is set in the stage block. It is a post-ex option.
    SourcePoint already sets it correctly in post-ex (Struct.go), hardcoded
    to "true", so the -SmartInject flag was driving the invalid copy in
    stage and never affected the block it was meant to.
  2. sleep_mask is emitted unquoted (set sleep_mask true;) while every
    other boolean in the block is quoted. c2lint reports this as
    Unknown statement in <.stage>.

The two that are your call

With those fixed, c2lint proceeds further into the block and rejects two more:

Error: invalid option for <.stage> at line 68
       rdll_loader
Error: invalid option for <.stage> at line 77
       name

I isolated every stage option SourcePoint emits, one per minimal profile, to
confirm which ones 4.13 actually rejects:

option 4.13
set rdll_loader "PrependLoader" rejected
set rdll_loader "StompLoader" rejected
set name "test.dll" rejected
set checksum "123" accepted
set rich_header "\x00" accepted
set copy_pe_header "false" accepted
set eaf_bypass "false" accepted
set rdll_use_syscalls "false" accepted
set syscall_method "None" accepted

Two things worth noting from that table. rdll_loader is rejected on both
values, so this is not the stomp loader deprecation warning added in an earlier
release, the option is gone. And checksum and rich_header are still
accepted while name is not, so PE cloning still works in 4.13, it just no
longer takes the cloned module's name.

The 4.13 release notes do not mention either removal.

Why I have not sent a patch for these two

name appears in all 30 Peclone_list entries and is arguably the most
visible part of the PE clone. rdll_loader is a documented flag
(-RdllLoader). Dropping either one silently changes behaviour for anyone on
an older team server, and I do not know which versions you want to support, so
this seemed like the wrong thing to decide on your behalf.

If it is useful, a -CSVersion style flag that omits the two options when
targeting 4.13+ would keep older versions working, and I am happy to send that
as a PR if you want it. Equally happy to just drop them if you would rather
move the minimum supported version forward.

Environment

  • Cobalt Strike 4.13 (June 2026), licensed, c2lint from the team server
    package
  • SourcePoint at current main
  • Go 1.22

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions