├── bin └── delete_it ├── .gitignore ├── src ├── thanos_common.c ├── thanos_mem.h ├── thanos_mem.c ├── thanos_str.h ├── thanos_io.h ├── thanos.h ├── thanos_io.c ├── thanos_scan.h ├── thanos_db.h ├── thanos_common.h ├── thanos_scan.c ├── thanos_str.c ├── thanos_db.c └── thanos.c ├── Makefile └── README.md /bin/delete_it: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | thanos 2 | *.o 3 | -------------------------------------------------------------------------------- /src/thanos_common.c: -------------------------------------------------------------------------------- 1 | #include "thanos_common.h" 2 | 3 | FILE *output; 4 | -------------------------------------------------------------------------------- /src/thanos_mem.h: -------------------------------------------------------------------------------- 1 | #ifndef THANOS_MEM 2 | #define THANOS_MEM 3 | 4 | #include 5 | #include 6 | 7 | #include "thanos_common.h" 8 | 9 | #define xfree(x) _xfree((void **)&x); 10 | 11 | void *xmalloc(size_t size); 12 | void _xfree(void **ptr); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/thanos_mem.c: -------------------------------------------------------------------------------- 1 | #include "thanos_mem.h" 2 | 3 | void *xmalloc(size_t size){ 4 | void *ptr = malloc(size); 5 | 6 | if(ptr == NULL){ 7 | err("malloc() failed\n"); 8 | } 9 | 10 | return ptr; 11 | } 12 | 13 | void _xfree(void **ptr){ 14 | assert(ptr); 15 | if(ptr != NULL){ 16 | free(*ptr); 17 | *ptr = NULL; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/thanos_str.h: -------------------------------------------------------------------------------- 1 | #ifndef THANOS_STR 2 | #define THANOS_STR 3 | 4 | #include 5 | #include 6 | 7 | #include "thanos_common.h" 8 | 9 | int th4n0s_inet_addr(const char *str, uint32_t *ret); 10 | void th4n0s_hex(const char *x, int size); 11 | void hexencode(const char *input, char *output, size_t len); 12 | void hexdecode(const unsigned char *input, char *output); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -Wall -Wextra -O3 3 | LDFLAGS = -lpthread -lsqlite3 4 | 5 | SRC_DIR = ./src 6 | OBJ_DIR = ./bin 7 | OBJECTS = $(OBJ_DIR)/thanos_common.o \ 8 | $(OBJ_DIR)/thanos_io.o \ 9 | $(OBJ_DIR)/thanos_mem.o \ 10 | $(OBJ_DIR)/thanos_str.o \ 11 | $(OBJ_DIR)/thanos_db.o \ 12 | $(OBJ_DIR)/thanos_scan.o \ 13 | $(OBJ_DIR)/thanos.o 14 | 15 | 16 | thanos: $(OBJECTS) 17 | $(CC) -o thanos $(OBJECTS) $(CFLAGS) $(LDFLAGS) 18 | 19 | $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c 20 | $(CC) $(CFLAGS) -c -o $@ $< 21 | 22 | clean: 23 | rm $(OBJECTS) thanos 24 | -------------------------------------------------------------------------------- /src/thanos_io.h: -------------------------------------------------------------------------------- 1 | #ifndef THANOS_IO 2 | #define THANOS_IO 3 | 4 | //#ifndef MAX_SIZE // when i make a configure file, it will be set using ./configure --set-max-size xxxxx ??? 5 | #define MAX_SIZE 1024 6 | //#endif 7 | 8 | #define HEX_SIZE MAX_SIZE*2 +1 9 | 10 | 11 | #include "thanos_common.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | int xopen(const char *filename, int mode); 19 | size_t filesize(int fd); 20 | void overwrite_file(const char *filename); 21 | FILE *xfopen(const char *filename, const char *mode); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/thanos.h: -------------------------------------------------------------------------------- 1 | #ifndef THANOS_H 2 | #define THANOS_H 3 | 4 | #define THANOS_VERSION "1.0.0 beta" 5 | #define THANOS_AUTHOR "MMxM" // 6 | 7 | #define OPTS "ht:o:ns:e:D" 8 | 9 | #define MIN_TIMEOUT 1 10 | #define MAX_TIMEOUT 100 11 | 12 | #define DEFAULT_TIMEOUT 10 13 | #define DEFAULT_LIMIT_BYTES 300 14 | 15 | typedef struct { 16 | unsigned int threads; 17 | char *config; 18 | char *output_filename; 19 | char *data_file; 20 | uint32_t start; 21 | uint32_t end; 22 | bool list; 23 | int limit_bytes; 24 | int port; 25 | int timeout; 26 | int delete_id; 27 | int update_id; 28 | } THANOS_OPTIONS; 29 | 30 | enum { 31 | CHECK_START, 32 | CHECK_END, 33 | CHECK_PORT, 34 | CHECK_TIMEOUT, 35 | CHECK_LIMIT, 36 | CHECK_LEN 37 | }; 38 | 39 | #endif 40 | 41 | -------------------------------------------------------------------------------- /src/thanos_io.c: -------------------------------------------------------------------------------- 1 | #include "thanos_io.h" 2 | 3 | int xopen(const char *filename, int mode){ 4 | int fd = open(filename, mode); 5 | 6 | if(fd < 0){ 7 | err("open(%s, %d) failed: ",filename, mode); 8 | } 9 | 10 | return fd; 11 | } 12 | 13 | size_t filesize(int fd){ 14 | struct stat buf; 15 | 16 | if( fstat(fd, &buf) == -1 ){ 17 | err("fstat(%d, &buf) failed: ", fd); 18 | } 19 | 20 | return (size_t) buf.st_size; 21 | } 22 | 23 | void overwrite_file(const char *filename){ 24 | FILE *x; 25 | x = fopen(filename, "w+"); 26 | fclose(x); 27 | } 28 | 29 | FILE *xfopen(const char *filename, const char *mode){ 30 | FILE *ret = fopen(filename, mode); 31 | if(ret == NULL){ 32 | err("fopen(%s, %s) failed: ", filename, mode); 33 | } 34 | 35 | return ret; 36 | } -------------------------------------------------------------------------------- /src/thanos_scan.h: -------------------------------------------------------------------------------- 1 | #ifndef THANOS_SCAN_H 2 | #define THANOS_SCAN_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "thanos_common.h" 16 | #include "thanos_mem.h" 17 | #include "thanos_str.h" 18 | 19 | typedef struct { 20 | int timeout; 21 | char *send_data; 22 | 23 | size_t data_size; 24 | size_t max_len; 25 | 26 | unsigned short port; 27 | } THANOS_SCAN; 28 | 29 | typedef struct { 30 | int len; 31 | THANOS_SCAN *scanner; 32 | } THANOS; 33 | 34 | extern THANOS thanos_scan; 35 | extern bool nowide; 36 | extern bool hexdump; 37 | extern pthread_mutex_t mutexsum; 38 | 39 | void *th4n0s_scanner(void *ptr); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/thanos_db.h: -------------------------------------------------------------------------------- 1 | #ifndef _THANOS_DB 2 | #define _THANOS_DB 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "thanos_common.h" 9 | #include "thanos_mem.h" 10 | #include "thanos_io.h" 11 | #include "thanos_str.h" 12 | #include "thanos_scan.h" 13 | 14 | #include 15 | 16 | void open_db(const char *filename, int flags, sqlite3 **db); 17 | void overwrite_file(const char *filename); 18 | void create_db(const char *filename); 19 | int check_thanos_struct(sqlite3 *db); 20 | void insert_data(sqlite3 *db, const char *file_data, int port, int timeout, int limit); 21 | void delete_data(sqlite3 *db, int id); 22 | void list_data(sqlite3 *db); 23 | 24 | void update_int(sqlite3 *db, const char *query, int update_id, int new_value); 25 | void update_data_file(sqlite3 *db, int update_id, char *filename); 26 | 27 | void load_struct(sqlite3 *db); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/thanos_common.h: -------------------------------------------------------------------------------- 1 | #ifndef THANOS_COMMON_ 2 | #define THANOS_COMMON_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | extern FILE *output; 10 | 11 | #define CYAN "\e[0;36m" 12 | #define RED "\e[0;31m" 13 | #define RESET "\e[0m" 14 | 15 | #define GOOD_M "%s[+]%s " 16 | #define BAD_M "%s[!]%s " 17 | 18 | #define say(x...) fprintf(stdout, x); 19 | #define warn(x...) fprintf(stderr, x); 20 | 21 | #define file_print(x...) \ 22 | if(output){\ 23 | fprintf(output, x); \ 24 | } 25 | 26 | #define err(x...) \ 27 | do { \ 28 | warn(x); \ 29 | perror(NULL); \ 30 | exit(1); \ 31 | } while(0); 32 | 33 | #define good(x...) \ 34 | say(GOOD_M, CYAN, RESET); \ 35 | say(x); 36 | 37 | #define bad(x...) \ 38 | say(BAD_M, RED, RESET); \ 39 | say(x); 40 | 41 | #define die(x...) \ 42 | do { \ 43 | warn(x); \ 44 | exit(1); \ 45 | } while(0); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/thanos_scan.c: -------------------------------------------------------------------------------- 1 | #include "thanos_scan.h" 2 | 3 | THANOS thanos_scan; 4 | bool nowide; 5 | bool hexdump; 6 | pthread_mutex_t mutexsum; 7 | 8 | void *th4n0s_scanner(void *ptr){ 9 | uint32_t ip_addr = (uint32_t) (uintptr_t)ptr; 10 | 11 | int sockfd = 0, i = 0, recv_ret = 0, j = 0; 12 | struct sockaddr_in target; 13 | char *recv_buffer; 14 | 15 | struct timeval timeout; 16 | timeout.tv_usec = 0; 17 | 18 | target.sin_addr.s_addr = ip_addr; 19 | target.sin_family = PF_INET; 20 | 21 | for(i=0; i < thanos_scan.len; i++){ 22 | target.sin_port = thanos_scan.scanner[i].port; 23 | 24 | 25 | if((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP)) == -1){ 26 | err("socket creation failed\n"); 27 | } 28 | 29 | if(connect(sockfd, (struct sockaddr * ) &target, sizeof(target)) == -1){ 30 | pthread_mutex_lock(&mutexsum); 31 | bad("%d.%d.%d.%d:%d closed\n", (ip_addr & 0xff), (ip_addr >> 8 & 0xff), 32 | (ip_addr >> 16 & 0xff), (ip_addr >> 24 & 0xff), ntohs(thanos_scan.scanner[i].port)); 33 | pthread_mutex_unlock(&mutexsum); 34 | close(sockfd); 35 | continue; 36 | } 37 | 38 | 39 | recv_buffer = xmalloc(thanos_scan.scanner[i].max_len); 40 | 41 | timeout.tv_sec = thanos_scan.scanner[i].timeout; 42 | 43 | if(setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0){ 44 | err("setsockopt failed\n"); 45 | } 46 | 47 | if(thanos_scan.scanner[i].data_size){ 48 | send(sockfd, thanos_scan.scanner[i].send_data, thanos_scan.scanner[i].data_size, 0); 49 | } 50 | 51 | recv_ret = recv(sockfd, recv_buffer, thanos_scan.scanner[i].max_len, MSG_WAITALL); 52 | 53 | pthread_mutex_lock(&mutexsum); 54 | good("%d.%d.%d.%d:%d open\n\n", (ip_addr & 0xff), (ip_addr >> 8 & 0xff), 55 | (ip_addr >> 16 & 0xff), (ip_addr >> 24 & 0xff), ntohs(thanos_scan.scanner[i].port)); 56 | 57 | if(recv_ret > 0){ 58 | if(hexdump){ 59 | th4n0s_hex(recv_buffer, recv_ret); 60 | } else { 61 | for(j=0; j '9'){ 22 | return 0; 23 | } 24 | 25 | else { 26 | if(ipv4[pos] * 10 > 0xff){ 27 | return 0; 28 | } else { 29 | ipv4[pos] *= 10; 30 | } 31 | 32 | if(ipv4[pos] + *str-'0' > 0xff){ 33 | return 0; 34 | } else { 35 | ipv4[pos] += *str-'0'; 36 | } 37 | 38 | i++; 39 | } 40 | 41 | str++; 42 | 43 | } 44 | 45 | if(!i){ 46 | return 0; 47 | } 48 | 49 | *ret = (ipv4[0] << 24 | ipv4[1] << 16 | ipv4[2] << 8 | ipv4[3]); 50 | 51 | return 1; 52 | } 53 | 54 | void th4n0s_hex(const char *x, int size){ 55 | 56 | int tot = 0, i = 0, aux = 0, pf = 0, count = 0; 57 | 58 | while(1){ 59 | printf("\t0x%03d0: ",count); 60 | 61 | (tot+16 > size) ? (tot = size) : (tot += 16); 62 | 63 | for(i=aux;i 32 && x[i] < 127) ? x[i] : '.'); 75 | } 76 | 77 | count++; 78 | 79 | printf("\n"); 80 | pf = 0; 81 | 82 | if(i >= size) 83 | break; 84 | 85 | aux += 16; 86 | } 87 | 88 | } 89 | 90 | void hexencode(const char *input, char *output, size_t len){ 91 | const char ht[]="0123456789abcdef"; // hextable 92 | 93 | size_t i = 0, j = 0; 94 | 95 | for(i=0; i /tmp/ftp_scan 53 | $ ./thanos --cfg-db banner_grabber.db \ 54 | --cfg-port 21 \ 55 | --cfg-file /tmp/ftp_scan \ 56 | --cfg-timeout 10 57 | --cfg-limit 300 58 | 59 | [...] 60 | 61 | [+] Inserting new options to database file 62 | [+] Ok 63 | ``` 64 | 65 | A new type of scan was insert on database, will scan the port 21, if it is open, will 66 | send the data of file /tmp/ftp_scan for the port, and wait for 10 seconds, or until 67 | the cfg-limit be reached, or when the server close the connection. 68 | 69 | We can list the scanners in database using the option --list: 70 | 71 | ``` 72 | $ ./thanos --cfg-db banner_grabber.db --list 73 | 74 | [...] 75 | 76 | [+] Starting listing rows in database file 77 | 78 | [+] ID: 1 79 | [+] Port: 21 80 | [+] Data: 515549540a0a 81 | [+] Timeout: 10 82 | [+] Limit Download: 300 83 | 84 | [+] Finish 85 | ``` 86 | 87 | ID = Scanner ID 88 | 89 | Port = Port to check 90 | 91 | Data = Content to send 92 | 93 | Timeout = Max time of seconds to wait 94 | 95 | Limit Download = Max size of bytes to reached 96 | 97 | if you want insert a new scanner, the option --cfg-port is required, 98 | if --cfg-file not be set so the value will be NULL, if --cfg-timeout not be set 99 | the value used will be the macro DEFAULT_TIMEOUT, if --cfg-limit not be set 100 | the value used will be the macro DEFAULT_LIMIT_BYTES. 101 | 102 | Doing the Scan: 103 | 104 | ``` 105 | $ ./thanos --cfg-db banner_grabber.db -s 0 -e 0 106 | 107 | [...] 108 | 109 | Number of scans load: 1 110 | Total IP's to scan: 1 111 | 112 | [+] 0.0.0.0:21 open 113 | 114 | CHEWB FTP SERVER 115 | 116 | ``` 117 | 118 | -s | --start = IP address to start 119 | 120 | -e | --end = IP address to end 121 | 122 | IP address samples: 123 | 124 | 1 = 1.0.0.0 125 | 126 | 1.2 = 1.2.0.0 127 | 128 | 1.2.3 = 1.2.3.0 129 | 130 | you can configure the banner output, using -n (--no-wide) or -D (--hex-dump). 131 | 132 | 133 | ### Changing the configuration file: 134 | 135 | You can edit the parameters of the configuration file , setting the option --update-id, example: 136 | 137 | ``` 138 | $ ./thanos --cfg-db banner_grabber.db --update-id 1 --cfg-data /dev/null 139 | ``` 140 | 141 | Change the Data value. 142 | 143 | You can also delete scanners configurations, using --delete-id, example: 144 | 145 | ``` 146 | $ ./thanos --cfg-db banner_grabber.db --delete-id 1 147 | ``` 148 | -------------------------------------------------------------------------------- /src/thanos_db.c: -------------------------------------------------------------------------------- 1 | #include "thanos_db.h" 2 | 3 | void create_db(const char *filename){ 4 | 5 | sqlite3 *db; 6 | 7 | const char query[]= "create table thanos_scan (\n" 8 | " id INTEGER PRIMARY KEY,\n" 9 | " port INTEGER NOT NULL,\n" 10 | " data TEXT,\n" 11 | " timeout INTEGER,\n" 12 | " limit_download INTEGER\n" 13 | ");"; 14 | 15 | char x = 0; 16 | int ret = 0; 17 | 18 | printf("\n"); 19 | good("Creating new database file: %s\n", filename); 20 | 21 | if( access(filename, F_OK) != -1 ){ 22 | bad("file %s already exists\n", filename); 23 | 24 | do { 25 | printf("\nDo You want overwrite this file ? [y/n] "); 26 | x = getchar(); 27 | while(getchar() != '\n'); 28 | } while(x != 'y' && x != 'Y' && x != 'n' && x != 'N'); 29 | printf("\n"); 30 | if(x == 'y' || x == 'Y'){ 31 | overwrite_file(filename); 32 | } else { 33 | bad("no database create\n"); 34 | good("exiting database file creation\n\n"); 35 | return; 36 | } 37 | } 38 | 39 | open_db(filename, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, &db); 40 | good("Ok\n"); 41 | 42 | good("Creating table\n"); 43 | good("Executing query:\n\n%s\n\n", query); 44 | 45 | if( (ret = sqlite3_exec(db, query, 0, NULL, NULL)) != SQLITE_OK ){ 46 | fprintf(stderr, "sqlite3_exec() error: %s\n", sqlite3_errstr(ret)); 47 | exit(1); 48 | } 49 | 50 | good("Ok\n\n"); 51 | 52 | sqlite3_close_v2(db); 53 | } 54 | 55 | int check_thanos_struct(sqlite3 *db){ 56 | struct x { 57 | int id; 58 | char *name; 59 | char *type; 60 | int notnull; 61 | int pk; 62 | }; 63 | 64 | const struct x table_struct[]= 65 | { 66 | {0,"id","INTEGER",0,1}, 67 | {1,"port","INTEGER",1,0}, 68 | {2,"data","TEXT",0,0}, 69 | {3,"timeout","INTEGER",0,0}, 70 | {4,"limit_download","INTEGER",0,0}, 71 | }; 72 | 73 | int i, len = 0, ret = 0; 74 | 75 | sqlite3_stmt *stmt; 76 | 77 | if( sqlite3_prepare_v2(db, "PRAGMA table_info(thanos_scan);", -1, &stmt, NULL) != SQLITE_OK){ 78 | return 0; 79 | } 80 | 81 | len = sizeof(table_struct) / sizeof(struct x); 82 | 83 | for(i=0; i 88 | 89 | if(table_struct[i].id != sqlite3_column_int(stmt, 0) 90 | || strcmp(table_struct[i].name, (char *)sqlite3_column_text(stmt, 1)) 91 | || strcmp(table_struct[i].type, (char *)sqlite3_column_text(stmt, 2)) 92 | || table_struct[i].notnull != sqlite3_column_int(stmt, 3) 93 | || table_struct[i].pk != sqlite3_column_int(stmt, 5) 94 | ){ 95 | break; 96 | } 97 | } 98 | 99 | if(i == len && sqlite3_step(stmt) != SQLITE_ROW) 100 | ret = 1; 101 | 102 | sqlite3_finalize(stmt); 103 | 104 | return ret; 105 | } 106 | 107 | void open_db(const char *filename, int flags, sqlite3 **db){ 108 | int err = 0; 109 | if( (err = sqlite3_open_v2(filename, db, flags, NULL)) != SQLITE_OK){ 110 | die("sqlite3_open_v2() error: %s\n", sqlite3_errstr(err)); 111 | } 112 | } 113 | 114 | void delete_data(sqlite3 *db, int id){ 115 | sqlite3_stmt *stmt; 116 | int rc; 117 | 118 | 119 | sqlite3_prepare_v2(db, "delete from thanos_scan where id = ?1;", -1, &stmt, NULL); 120 | sqlite3_bind_int(stmt, 1, id); 121 | 122 | rc = sqlite3_step(stmt); 123 | 124 | if (rc != SQLITE_DONE){ 125 | die("error: %s\n", sqlite3_errmsg(db)); 126 | } 127 | 128 | sqlite3_finalize(stmt); 129 | 130 | } 131 | 132 | void insert_data(sqlite3 *db, const char *file_data, int port, int timeout, int limit){ 133 | sqlite3_stmt *stmt; 134 | 135 | char *data = NULL; 136 | char encode_data[HEX_SIZE]; 137 | 138 | size_t size_file = 0; 139 | int fd = 0, rc = 0; 140 | 141 | 142 | if(file_data){ 143 | fd = xopen(file_data, O_RDONLY); 144 | size_file = filesize(fd); 145 | if(size_file > MAX_SIZE){ 146 | die("error: file is big than %d\n",MAX_SIZE); 147 | } 148 | 149 | data = mmap(0, size_file, PROT_READ, MAP_PRIVATE, fd, 0); 150 | hexencode(data, encode_data, size_file); 151 | munmap(data, size_file); 152 | close(fd); 153 | } else { 154 | encode_data[0] = 0; 155 | } 156 | 157 | sqlite3_prepare_v2(db, "insert into thanos_scan values(null, ?1, ?2, ?3, ?4);", -1, &stmt, NULL); 158 | sqlite3_bind_int(stmt, 1, port); 159 | sqlite3_bind_text(stmt, 2, encode_data, -1, SQLITE_STATIC); 160 | sqlite3_bind_int(stmt, 3, timeout); 161 | sqlite3_bind_int(stmt, 4, limit); 162 | 163 | rc = sqlite3_step(stmt); 164 | if (rc != SQLITE_DONE){ 165 | die("error: %s\n", sqlite3_errmsg(db)); 166 | } 167 | 168 | sqlite3_finalize(stmt); 169 | 170 | } 171 | 172 | void list_data(sqlite3 *db){ 173 | sqlite3_stmt *stmt; 174 | int rc; 175 | 176 | sqlite3_prepare_v2(db, "select * from thanos_scan;", -1, &stmt, NULL); 177 | 178 | while ( (rc = sqlite3_step(stmt)) == SQLITE_ROW) { 179 | good("ID: %d\n", sqlite3_column_int(stmt, 0)); 180 | good("Port: %d\n", sqlite3_column_int(stmt, 1)); 181 | good("Data: %s\n", sqlite3_column_text(stmt, 2)); 182 | good("Timeout: %d\n", sqlite3_column_int(stmt, 3)); 183 | good("Limit Download: %d\n\n", sqlite3_column_int(stmt, 4)); 184 | } 185 | 186 | sqlite3_finalize(stmt); 187 | } 188 | 189 | 190 | void update_int(sqlite3 *db, const char *query, int update_id, int new_value){ 191 | sqlite3_stmt *stmt; 192 | int rc; 193 | 194 | sqlite3_prepare_v2(db, query, -1, &stmt, NULL); 195 | sqlite3_bind_int(stmt, 1, new_value); 196 | sqlite3_bind_int(stmt, 2, update_id); 197 | rc = sqlite3_step(stmt); 198 | 199 | if(rc!=SQLITE_DONE){ 200 | die("error: %s\n", sqlite3_errmsg(db)); 201 | } 202 | sqlite3_finalize(stmt); 203 | } 204 | 205 | void update_data_file(sqlite3 *db, int update_id, char *filename){ 206 | sqlite3_stmt *stmt; 207 | 208 | char *data = NULL; 209 | char encode_data[HEX_SIZE]; 210 | 211 | size_t size_file = 0; 212 | int fd = 0, rc = 0; 213 | 214 | 215 | if(filename){ 216 | fd = xopen(filename, O_RDONLY); 217 | size_file = filesize(fd); 218 | 219 | if(size_file > MAX_SIZE){ 220 | die("error: file is big than %d\n",MAX_SIZE); 221 | } 222 | 223 | data = mmap(0, size_file, PROT_READ, MAP_PRIVATE, fd, 0); 224 | hexencode(data, encode_data, size_file); 225 | munmap(data, size_file); 226 | close(fd); 227 | 228 | } else { 229 | encode_data[0] = 0; 230 | } 231 | 232 | sqlite3_prepare_v2(db, "update thanos_scan set data = ?1 where id = ?2;", -1, &stmt, NULL); 233 | sqlite3_bind_int(stmt, 2, update_id); 234 | sqlite3_bind_text(stmt, 1, encode_data, -1, SQLITE_STATIC); 235 | rc = sqlite3_step(stmt); 236 | 237 | if(rc!=SQLITE_DONE){ 238 | die("error: %s\n", sqlite3_errmsg(db)); 239 | } 240 | 241 | sqlite3_finalize(stmt); 242 | 243 | } 244 | 245 | void load_struct(sqlite3 *db){ 246 | sqlite3_stmt *stmt; 247 | int count = 0, rc = 0, id = 0, bytes; 248 | 249 | sqlite3_prepare_v2(db, "select count(*) from thanos_scan;", -1, &stmt, NULL); 250 | rc = sqlite3_step(stmt); 251 | 252 | if(rc!=SQLITE_ROW){ 253 | die("error: %s\n", sqlite3_errmsg(db)); 254 | } 255 | 256 | count = sqlite3_column_int(stmt, 0); 257 | sqlite3_finalize(stmt); 258 | 259 | if(!count){ 260 | die("error: the database are blank\n"); 261 | } 262 | 263 | thanos_scan.len = count; 264 | thanos_scan.scanner = xmalloc(count*sizeof(THANOS_SCAN)); 265 | 266 | sqlite3_prepare_v2(db, "select * from thanos_scan;", -1, &stmt, NULL); 267 | 268 | 269 | 270 | while ( (rc = sqlite3_step(stmt)) == SQLITE_ROW){ 271 | thanos_scan.scanner[id].timeout = sqlite3_column_int(stmt, 3); 272 | thanos_scan.scanner[id].max_len = sqlite3_column_int(stmt, 4); 273 | thanos_scan.scanner[id].port = (unsigned short) htons(sqlite3_column_int(stmt, 1)); 274 | 275 | bytes = sqlite3_column_bytes(stmt, 2); 276 | 277 | if(bytes%2){ 278 | die("error: invalida data at row id: %d\n",id+1); 279 | } 280 | 281 | bytes /= 2; 282 | thanos_scan.scanner[id].data_size = bytes; 283 | 284 | if(bytes){ 285 | thanos_scan.scanner[id].send_data = xmalloc(bytes); 286 | hexdecode(sqlite3_column_text(stmt, 2), thanos_scan.scanner[id].send_data); 287 | } else { 288 | thanos_scan.scanner[id].send_data = NULL; 289 | } 290 | 291 | id++; 292 | } 293 | 294 | sqlite3_finalize(stmt); 295 | } 296 | -------------------------------------------------------------------------------- /src/thanos.c: -------------------------------------------------------------------------------- 1 | /* 2 | -- Thanos Banner Grabber -- 3 | 4 | Author: MMxM 5 | Github: https://github.com/hc0d3r 6 | 7 | Greetz: Mh4x0f, Joridos, n4sss, kwrnel, Dennis, Cooler, Kodo no kami, 8 | cyclone, susp31t0virtual, xstpl, m0nad, Sir.Rafiki, clandestine, 9 | Janissaries Team 10 | 11 | P0cl4bs Team 2015 - ~ 12 | 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "thanos.h" 23 | #include "thanos_db.h" 24 | #include "thanos_str.h" 25 | #include "thanos_common.h" 26 | #include "thanos_scan.h" 27 | 28 | void banner(void){ 29 | printf("\n"); 30 | printf("_____ _ __ _ ___ __ \n"); 31 | printf(" | | | |_| / /\\ | |\\ | / / \\ ( (` \n"); 32 | printf(" |_| |_| | /_/--\\ |_| \\| \\_\\_/ _)_) \n"); 33 | printf("\n"); 34 | printf(" Banner Grabber v%s\n\n",THANOS_VERSION); 35 | } 36 | 37 | void help(void){ 38 | printf("\n"); 39 | printf(" -h, --help Display this help menu\n\n"); 40 | printf(" DB Options:\n\n"); 41 | 42 | printf(" --new-db STRING Create new database file\n"); 43 | printf(" --cfg-db STRING Set db configuration file\n"); 44 | printf(" --cfg-port NUMBER Insert new port on cfg-db\n"); 45 | printf(" --cfg-file STRING File contains the data that will be send on cfg-port. Default=NULL\n"); 46 | printf(" --cfg-timeout NUMBER Define timeout for connection. Default=%d\n",DEFAULT_TIMEOUT); 47 | printf(" --cfg-limit NUMBER Max size of bytes to reached. Default=%d\n",DEFAULT_LIMIT_BYTES); 48 | printf(" --delete-id NUMBER Delete a row in database\n"); 49 | printf(" --update-id NUMBER Update a row in database\n"); 50 | printf(" --list List rows in database\n\n"); 51 | 52 | 53 | printf(" Scan Options:\n\n"); 54 | printf(" -s, --start-ip STRING IP number to start scan\n"); 55 | printf(" -e, --end-ip STRING IP number to end scan\n"); 56 | //printf(" -o, --output STRING Output file\n"); depois eu faco isso 57 | printf(" -t, --threads NUMBER Simultaneous connections number\n"); 58 | printf(" -n, --no-wide No print wide chars\n"); 59 | printf(" -D, --hex-dump Print output in hexdump format\n"); 60 | 61 | printf("\n"); 62 | exit(0); 63 | } 64 | 65 | void parser_opts(int argc, char **argv, THANOS_OPTIONS *opts){ 66 | static struct option long_options[] = 67 | { 68 | {"help", no_argument, 0, 'h'}, //ok 69 | {"threads", required_argument, 0, 't'}, //ok 70 | 71 | {"output", required_argument, 0, 'o'}, //ok 72 | {"start-ip", required_argument, 0, 's'}, //ok 73 | {"end-ip", required_argument, 0, 'e'}, //ok 74 | {"no-wide", no_argument, 0, 'n'}, //ok 75 | {"hex-dump", no_argument, 0, 'D'}, //ok 76 | 77 | {"new-db", required_argument, 0, 0}, //ok 78 | {"cfg-db", required_argument, 0, 0}, //ok 79 | {"cfg-port", required_argument, 0, 0}, //ok 80 | {"cfg-file", required_argument, 0, 0}, //ok 81 | {"cfg-timeout", required_argument, 0, 0}, //ok 82 | {"cfg-limit", required_argument, 0, 0}, //ok 83 | 84 | {"delete-id", required_argument, 0, 0}, //ok 85 | {"update-id", required_argument, 0, 0}, //ok 86 | 87 | {"list", no_argument, 0, 0}, //ok 88 | {0, 0, 0, 0} 89 | }; 90 | 91 | int Getopts, tmp, option_index = 0; 92 | static bool check[CHECK_LEN]; 93 | 94 | char *opt_ptr; 95 | 96 | while(1){ 97 | Getopts = getopt_long(argc, argv, OPTS, long_options, &option_index); 98 | 99 | if(Getopts == -1){ 100 | break; 101 | } 102 | 103 | opt_ptr = (char *) long_options[option_index].name; 104 | 105 | switch(Getopts){ 106 | case 0: 107 | if(!strcmp("new-db", opt_ptr)){ 108 | create_db(optarg); 109 | } 110 | 111 | else if(!strcmp("cfg-db", opt_ptr)){ 112 | opts->config = optarg; 113 | } 114 | 115 | else if(!strcmp("cfg-port", opt_ptr)){ 116 | tmp = (int) strtol(optarg, NULL, 10); 117 | if(tmp < 0 || tmp > 0xffff){ 118 | die("error: --cfg-port %s not is a valid port !!!\n", optarg); 119 | } else { 120 | opts->port = tmp; 121 | check[CHECK_PORT] = true; 122 | } 123 | } 124 | 125 | else if(!strcmp("cfg-timeout", opt_ptr)){ 126 | tmp = (int) strtol(optarg, NULL, 10); 127 | if(tmp < MIN_TIMEOUT || tmp > MAX_TIMEOUT){ 128 | die("error: --cfg-timeout %s not is a valid value\n", optarg); 129 | } else { 130 | opts->timeout = tmp; 131 | check[CHECK_TIMEOUT] = true; 132 | } 133 | } 134 | 135 | else if(!strcmp("cfg-limit", opt_ptr)){ 136 | tmp = (int) strtol(optarg, NULL, 10); 137 | if(tmp < 0){ 138 | die("error: --cfg-limit %s not is a valide value\n", optarg); 139 | } else { 140 | opts->limit_bytes = tmp; 141 | check[CHECK_LIMIT] = true; 142 | } 143 | } 144 | 145 | else if(!strcmp("cfg-file", opt_ptr)){ 146 | opts->data_file = optarg; 147 | } 148 | 149 | else if(!strcmp("delete-id", opt_ptr)){ 150 | tmp = (int) strtol(optarg, NULL, 10); 151 | if(tmp < 1){ 152 | die("error: --delete-id %s not is a valide value\n", optarg); 153 | } else { 154 | opts->delete_id = tmp; 155 | } 156 | } 157 | 158 | else if(!strcmp("update-id", opt_ptr)){ 159 | tmp = (int) strtol(optarg, NULL, 10); 160 | if(tmp < 1){ 161 | die("error: --update-id %s not is a valide value\n", optarg); 162 | } else { 163 | opts->update_id = tmp; 164 | } 165 | } 166 | 167 | else if(!strcmp("list", opt_ptr)){ 168 | opts->list = true; 169 | } 170 | 171 | break; 172 | 173 | case 'h': 174 | help(); 175 | break; 176 | 177 | case 't': 178 | tmp = (int) strtol(optarg, NULL, 10); 179 | if(tmp < 0){ 180 | die("-t, --threads error: %s not is a valide value\n", optarg); 181 | } else { 182 | opts->threads = (unsigned int)tmp; 183 | } 184 | break; 185 | 186 | case 'c': 187 | opts->config = optarg; 188 | break; 189 | 190 | case 'o': 191 | opts->output_filename = optarg; 192 | break; 193 | 194 | case 's': 195 | if( !th4n0s_inet_addr( optarg, &(opts->start) ) ){ 196 | die("-s, --start error: %s not is a valide IP address\n", optarg); 197 | } 198 | check[CHECK_START] = true; 199 | break; 200 | 201 | case 'e': 202 | if( !th4n0s_inet_addr( optarg, &(opts->end) ) ){ 203 | die("-e, --end error: %s not is a valide IP address\n", optarg); 204 | } 205 | check[CHECK_END] = true; 206 | break; 207 | 208 | case 'n': 209 | nowide = true; 210 | break; 211 | 212 | case 'D': 213 | hexdump = true; 214 | break; 215 | default: 216 | abort(); 217 | } 218 | 219 | 220 | } 221 | 222 | sqlite3 *db; 223 | 224 | if(opts->config){ 225 | open_db(opts->config, SQLITE_OPEN_READWRITE, &db); 226 | 227 | if(!check_thanos_struct(db)){ 228 | die("%s not is a valide database\n", opts->config); 229 | } 230 | 231 | if(opts->delete_id){ 232 | good("Deleting row, id: %d\n",opts->delete_id); 233 | delete_data( db, opts->delete_id ); 234 | good("Deleted !!!\n\n"); 235 | } 236 | 237 | if(opts->update_id){ 238 | good("Updating row id: %d\n",opts->update_id); 239 | 240 | if(check[CHECK_PORT]){ 241 | update_int(db, "update thanos_scan set port = ?1 where id = ?2;", opts->update_id, opts->port); 242 | } 243 | 244 | if(check[CHECK_TIMEOUT]){ 245 | update_int(db, "update thanos_scan set timeout = ?1 where id = ?2;", opts->update_id, opts->timeout); 246 | } 247 | 248 | if(check[CHECK_LIMIT]){ 249 | update_int(db, "update thanos_scan set limit_download = ?1 where id = ?2;", opts->update_id, opts->limit_bytes); 250 | } 251 | 252 | if(opts->data_file){ 253 | update_data_file(db, opts->update_id, opts->data_file); 254 | } 255 | 256 | good("Update finish\n\n"); 257 | } else { 258 | 259 | if(check[CHECK_PORT]){ 260 | good("Inserting new options to database file\n"); 261 | insert_data( db, opts->data_file, opts->port, opts->timeout, opts->limit_bytes ); //ok 262 | good("Ok\n\n"); 263 | } 264 | } 265 | 266 | if(opts->list){ 267 | good("Starting listing rows in database file\n\n"); 268 | list_data(db); 269 | good("Finish\n\n"); 270 | } 271 | } else { 272 | if(check[CHECK_PORT] || check[CHECK_START] || 273 | check[CHECK_END] || opts->delete_id || opts->list || 274 | opts->update_id){ 275 | die("error: cfg-db not set\n"); 276 | } 277 | 278 | } 279 | 280 | if(!check[CHECK_START] || !check[CHECK_END]){ 281 | if(opts->config){ 282 | sqlite3_close_v2(db); 283 | } 284 | 285 | exit(0); 286 | } 287 | 288 | if(opts->end < opts->start){ 289 | if(opts->config){ 290 | sqlite3_close_v2(db); 291 | } 292 | 293 | die("error: start address must be minor than end address\n"); 294 | } else { 295 | load_struct(db); 296 | sqlite3_close_v2(db); 297 | } 298 | } 299 | 300 | void init_values(THANOS_OPTIONS *x){ 301 | x->threads = 0; 302 | x->config = NULL; 303 | x->timeout = DEFAULT_TIMEOUT; 304 | x->output_filename = NULL; 305 | x->start = 0; 306 | x->end = 0; 307 | x->limit_bytes = DEFAULT_LIMIT_BYTES; 308 | hexdump = false; 309 | nowide = false; 310 | x->data_file = NULL; 311 | x->port = 0; 312 | x->delete_id = 0; 313 | x->list = false; 314 | x->update_id = 0; 315 | } 316 | 317 | int main(int argc, char *argv[]){ 318 | THANOS_OPTIONS options; 319 | 320 | pthread_t *threads = NULL; 321 | uint32_t i_addr; 322 | unsigned int tid = 0, count = 0; 323 | int i; 324 | 325 | if(argc == 1){ 326 | warn("thanos: try 'thanos -h' or 'thanos --help'\n"); 327 | return 0; 328 | } 329 | 330 | banner(); 331 | init_values(&options); 332 | parser_opts(argc, argv, &options); 333 | 334 | printf("Number of scans load: %d\n",thanos_scan.len); 335 | printf("Total IP's to scan: %u\n\n", options.end - options.start + 1); 336 | 337 | 338 | if(!options.threads){ 339 | for(i_addr=options.start; i_addr<= options.end; i_addr++){ 340 | th4n0s_scanner((void *) (uintptr_t) htonl(i_addr)); 341 | } 342 | } else { 343 | threads = xmalloc(options.threads * sizeof(pthread_t)); 344 | 345 | for(i_addr=options.start; i_addr <= options.end; i_addr++){ 346 | if (pthread_create(&threads[tid], NULL, th4n0s_scanner, (void *) (uintptr_t) (htonl(i_addr))) != 0){ 347 | err("error: pthread_create failed\n"); 348 | } 349 | tid++; 350 | 351 | if(tid == options.threads){ 352 | for(count=0; count < tid; count++){ 353 | pthread_join(threads[count], NULL); 354 | } 355 | tid = 0; 356 | } 357 | } 358 | 359 | 360 | for(count=0; count < tid; count++){ 361 | pthread_join(threads[count], NULL); 362 | } 363 | 364 | xfree(threads); 365 | } 366 | 367 | for(i=0; i < thanos_scan.len; i++){ 368 | xfree(thanos_scan.scanner[i].send_data); 369 | } 370 | 371 | xfree(thanos_scan.scanner); 372 | 373 | return 0; 374 | } 375 | 376 | --------------------------------------------------------------------------------