Maj CI/CD

This commit is contained in:
maxdcb
2026-04-21 13:48:26 +02:00
parent a99f8806c5
commit af70d988ba
6 changed files with 251 additions and 59 deletions
+165 -48
View File
@@ -1,69 +1,186 @@
name: Release
name: CI CD
on:
on:
workflow_dispatch:
pull_request:
push:
branches:
- "**"
tags:
- '*'
- "*"
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_DIR: build-conan
BUILD_TYPE: Release
RELEASE_TARBALL: Release.tar.gz
RELEASE_ARTIFACT: C2LinuxImplant-Linux-Release
permissions:
contents: write
contents: read
jobs:
buildAndRelease:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
# You can convert this to a matrix build if you need cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
# compile for old libc to cover more linux versions
build-test:
name: Build and test Linux deliverables
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Samba client dev headers
run: |
sudo apt-get update
sudo apt-get install -y libsmbclient-dev
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
# Update references
- name: Git Sumbodule Update
run: |
git submodule update --init
- name: Get Conan
# You may pin to the exact commit or the version.
# uses: turtlebrowser/get-conan@c171f295f3f507360ee018736a6608731aa2109d
uses: turtlebrowser/get-conan@v1.2
- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y libsmbclient-dev
- name: Create default profile
run: conan profile detect
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=${{github.workspace}}/conan_provider.cmake
- name: Install Conan
run: |
python -m pip install --upgrade pip
python -m pip install "conan>=2,<3"
conan profile detect --force
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 18
- name: Cache Conan packages
uses: actions/cache@v4
with:
path: ~/.conan2
key: conan-${{ runner.os }}-${{ hashFiles('conanfile.txt') }}
restore-keys: |
conan-${{ runner.os }}-
- name: Prep release
shell: bash
run: |
rm ./Release/Beacons/.gitignore
mv ./Release/Beacons ./Release/LinuxBeacons
rm ./Release/Modules/.gitignore
mv ./Release/Modules ./Release/LinuxModules
tar -zcvf Release.tar.gz Release
- name: Configure
run: |
cmake \
-S . \
-B "$BUILD_DIR" \
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
-DC2CORE_BUILD_TESTS=ON \
-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES="$GITHUB_WORKSPACE/conan_provider.cmake"
- name: Upload release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: Release.tar.gz
asset_name: Release.tar.gz
tag: ${{ github.ref }}
overwrite: true
body: "Linux beacons and modules"
- name: Build
run: cmake --build "$BUILD_DIR" --config "$BUILD_TYPE" --parallel "$(nproc)"
- name: Test
run: ctest --test-dir "$BUILD_DIR" --output-on-failure --timeout 60
- name: Validate deliverables
run: |
set -euo pipefail
expected_beacons=(
BeaconDns
BeaconGithub
BeaconHttp
BeaconSmb
BeaconTcp
)
expected_modules=(
libAssemblyExec.so
libCat.so
libChangeDirectory.so
libChisel.so
libCimExec.so
libCoff.so
libDcomExec.so
libDotnetExec.so
libDownload.so
libEnumerateRdpSessions.so
libEnumerateShares.so
libEvasion.so
libGetEnv.so
libInject.so
libIpConfig.so
libKerberosUseTicket.so
libKeyLogger.so
libKillProcess.so
libListDirectory.so
libListProcesses.so
libMakeToken.so
libMiniDump.so
libMkDir.so
libNetstat.so
libPowershell.so
libPrintWorkingDirectory.so
libPsExec.so
libPwSh.so
libRegistry.so
libRemove.so
libRev2self.so
libRun.so
libScreenShot.so
libScript.so
libShell.so
libSpawnAs.so
libSshExec.so
libStealToken.so
libTaskScheduler.so
libTree.so
libUpload.so
libWhoami.so
libWinRM.so
libWmiExec.so
)
for file in "${expected_beacons[@]}"; do
test -s "Release/Beacons/$file" || {
echo "Missing or empty beacon deliverable: $file" >&2
exit 1
}
done
for file in "${expected_modules[@]}"; do
test -s "Release/Modules/$file" || {
echo "Missing or empty module deliverable: $file" >&2
exit 1
}
done
- name: Stage release archive
run: |
set -euo pipefail
stage="artifacts/Release"
rm -rf artifacts "$RELEASE_TARBALL"
mkdir -p "$stage/LinuxBeacons" "$stage/LinuxModules"
find Release/Beacons -maxdepth 1 -type f ! -name ".gitignore" -exec cp -t "$stage/LinuxBeacons" {} +
find Release/Modules -maxdepth 1 -type f ! -name ".gitignore" -exec cp -t "$stage/LinuxModules" {} +
tar -C artifacts -czf "$RELEASE_TARBALL" Release
- name: Upload CI artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.RELEASE_ARTIFACT }}
path: ${{ env.RELEASE_TARBALL }}
if-no-files-found: error
release:
name: Publish GitHub release
runs-on: ubuntu-22.04
needs: build-test
if: startsWith(github.ref, 'refs/tags/')
permissions:
contents: write
steps:
- name: Download release archive
uses: actions/download-artifact@v4
with:
name: ${{ env.RELEASE_ARTIFACT }}
- name: Upload release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ env.RELEASE_TARBALL }}
asset_name: ${{ env.RELEASE_TARBALL }}
tag: ${{ github.ref }}
overwrite: true
body: "Linux beacons and modules"
+33
View File
@@ -0,0 +1,33 @@
# AGENT.md - C2LinuxImplant
## CI/CD Contract
- CI runs on `pull_request` and every branch push, including tag pushes before release publication.
- CD publishes only from tag builds after the CI build, tests, deliverable validation, and archive staging have succeeded.
- GitHub Actions permissions stay read-only by default. Only the release publication job may request `contents: write`.
## Build and Test Contract
- Linux CI builds with Conan through `conan_provider.cmake`.
- The CI configure step must pass `-DC2CORE_BUILD_TESTS=ON`.
- Tests must be visible from the top-level build directory and run with `ctest --test-dir <build-dir> --output-on-failure --timeout 60`.
- Do not silently skip unstable tests. Fix them when reasonable, or isolate them explicitly with a documented reason.
- `libs/libDns/tests/fonctionalTest` is intentionally not registered in CI because it is a manual server/client harness and exits with usage information unless runtime arguments are provided.
## Release Layout
C2TeamServer consumes Linux release payloads from the archive layout below:
```text
Release/
LinuxBeacons/
BeaconDns
BeaconGithub
BeaconHttp
BeaconSmb
BeaconTcp
LinuxModules/
lib*.so
```
The CMake build may copy intermediate deliverables into `Release/Beacons` and `Release/Modules`, but packaging must not rename, delete, or mutate those source output directories. Stage archives from a clean `artifacts/Release` tree instead.
+30 -9
View File
@@ -8,6 +8,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
option(C2CORE_BUILD_TESTS "Enable C2Core tests from the parent project" OFF)
if(C2CORE_BUILD_TESTS)
enable_testing()
endif()
set(C2_RUNTIME_MODULE_OUTPUT_DIR "${CMAKE_SOURCE_DIR}/Release/Modules" CACHE PATH
"Directory where C2Core runtime modules are copied after build")
@@ -28,9 +31,12 @@ add_definitions(-DBUILD_IMPLANT)
set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
find_package(OpenSSL REQUIRED)
find_package(httplib REQUIRED)
find_package(Libssh2 REQUIRED)
find_package(httplib REQUIRED)
find_package(Libssh2 REQUIRED)
find_package(nlohmann_json REQUIRED CONFIG)
if(C2CORE_BUILD_TESTS)
find_package(Catch2 REQUIRED CONFIG)
endif()
include_directories(${CMAKE_INCLUDE_PATH})
@@ -46,9 +52,20 @@ endif()
include_directories(thirdParty)
add_subdirectory(libs)
add_subdirectory(thirdParty)
add_subdirectory(libs)
if(C2CORE_BUILD_TESTS)
add_test(NAME dnsTest COMMAND dnsTest)
add_test(NAME utilsTest COMMAND utilsTest)
# fonctionalTest is a manual server/client harness that requires runtime args.
# Keep it built, but do not register it in CI ctest without explicit parameters.
add_test(NAME responseDecodeTest COMMAND responseDecodeTest)
add_test(NAME messageTest COMMAND messageTest)
add_test(NAME interleavedTest COMMAND interleavedTest)
add_test(NAME TestsSockerHandler COMMAND TestsSockerHandler)
add_test(NAME TestsSocksServer COMMAND TestsSocksServer)
endif()
add_subdirectory(thirdParty)
include_directories(thirdParty/base64)
include_directories(thirdParty/donut/include)
@@ -58,10 +75,14 @@ set_target_properties(Donut PROPERTIES
IMPORTED_LOCATION "${DONUT_BUILD_DIR}/lib/libdonut.a"
)
add_subdirectory(core/modules)
add_subdirectory(core/beacon)
include_directories(core/listener)
add_subdirectory(core/modules)
add_subdirectory(core/beacon)
if(C2CORE_BUILD_TESTS)
add_subdirectory(core/beacon/tests)
add_subdirectory(core/listener/tests)
endif()
include_directories(core/listener)
include_directories(core/beacon)
include_directories(core/modules/ModuleCmd)
add_subdirectory(beacon/beacon)
+20
View File
@@ -87,3 +87,23 @@ make -j4
* Compiled Beacons: `Release/Beacons`
* Compiled Modules: `Release/Modules`
### CI/CD Release Contract
CI runs on pull requests and branch pushes. It installs Conan, configures a Release Linux build with `C2CORE_BUILD_TESTS=ON`, builds all Linux beacons/modules, runs `ctest --output-on-failure --timeout 60`, and validates every expected deliverable before archiving.
Release publication runs only from tag builds after CI succeeds. The archive is staged from a clean `artifacts/Release` tree and uses the C2TeamServer-facing layout:
```text
Release/
LinuxBeacons/
BeaconDns
BeaconGithub
BeaconHttp
BeaconSmb
BeaconTcp
LinuxModules/
lib*.so
```
Packaging must not rename, delete, or mutate the CMake output directories `Release/Beacons` and `Release/Modules`; it only copies their non-`.gitignore` contents into staging.
+2 -1
View File
@@ -3,6 +3,7 @@ openssl/3.6.2
cpp-httplib/0.39.0
libssh2/1.11.1
nlohmann_json/3.12.0
catch2/3.14.0
[options]
libssh2/*:shared=False
@@ -11,4 +12,4 @@ libssh2/*:shared=False
cmake_layout
[generators]
CMakeDeps
CMakeDeps
+1 -1
Submodule core updated: 04fc881a07...35fe79d442