void scan_base64(const class scanner_params &sp,const recursion_control_block &rcb) { assert(sp.sp_version==scanner_params::CURRENT_SP_VERSION); if(sp.phase==scanner_params::PHASE_STARTUP){ assert(sp.info->si_version==scanner_info::CURRENT_SI_VERSION); sp.info->name = "base64"; sp.info->author = "Simson L. Garfinkel"; sp.info->description = "scans for Base64-encoded data"; sp.info->scanner_version= "1.0"; /* Create the base64 array */ memset(base64array,0,sizeof(base64array)); base64array[(int)'+'] = true; base64array[(int)'/'] = true; for(int ch='a';ch<='z';ch++){ base64array[ch] = true; } for(int ch='A';ch<='Z';ch++){ base64array[ch] = true; } for(int ch='0';ch<='9';ch++){ base64array[ch] = true; } return; /* No feature files created */ } if(sp.phase==scanner_params::PHASE_SHUTDOWN) return; if(sp.phase==scanner_params::PHASE_SCAN){ const sbuf_t &sbuf = sp.sbuf; /* base64 is a newline followed by at least two lines of constant length, * followed by an incomplete line ending with an equal sign. * Lines can be termianted by \n or \r\n. This code simply ignores \r, * which means that you can't have some lines terminated by \n and other * terminated by \n\r. * * Note that this doesn't scan base64-encoded blobs smaller than two lines. * Perhaps we should do that. */ size_t blockstart = 0; bool inblock = false; size_t prevlen = 0; size_t linecount = 0; size_t pos = 0; size_t start = 0; size_t len = 0; bool found_equal = false; while(sbuf_getline(sbuf,pos,start,len)){ //fprintf(stderr,"pos=%zd\n",pos); if(sbuf_line_is_base64(sbuf,start,len,found_equal)){ if(inblock==false){ /* First line of a block! */ if(len >= minlinewidth){ inblock = true; linecount = 1; blockstart = start; prevlen = len; } continue; } if(len!=prevlen){ // whoops! Lines are different lengths if(found_equal && linecount>1){ //fprintf(stderr,"1. linecount=%zd\n",linecount); process(sp,rcb,blockstart,pos-blockstart); } inblock=false; continue; } linecount++; continue; } /* Ran out of the base64 block */ if(linecount>2){ //fprintf(stderr,"2. linecount=%zd\n",linecount); process(sp,rcb,blockstart,pos-blockstart); } inblock = false; } //fprintf(stderr,"done\n"); } }
void scan_base64(const class scanner_params &sp,const recursion_control_block &rcb) { assert(sp.sp_version==scanner_params::CURRENT_SP_VERSION); if(sp.phase==scanner_params::PHASE_STARTUP){ assert(sp.info->si_version==scanner_info::CURRENT_SI_VERSION); sp.info->name = "base64"; sp.info->author = "Simson L. Garfinkel"; sp.info->description = "scans for Base64-encoded data"; sp.info->scanner_version= "1.0"; /* Create the base64 array */ memset(base64array,0,sizeof(base64array)); base64array[(int)'+'] = B64_SYMBOL; base64array[(int)'/'] = B64_SYMBOL; for(int ch='a';ch<='z';ch++){ base64array[ch] = B64_LOWERCASE; } for(int ch='A';ch<='Z';ch++){ base64array[ch] = B64_UPPERCASE; } for(int ch='0';ch<='9';ch++){ base64array[ch] = B64_NUMBER; } return; /* No feature files created */ } if(sp.phase==scanner_params::PHASE_SHUTDOWN) return; if(sp.phase==scanner_params::PHASE_SCAN){ const sbuf_t &sbuf = sp.sbuf; /* base64 is a newline followed by at least two lines of constant length, * followed by an incomplete line ending with an equal sign. * Lines can be termianted by \n or \r\n. This code simply ignores \r, * which means that you can't have some lines terminated by \n and other * terminated by \n\r. * * Note that this doesn't scan base64-encoded blobs smaller than two lines. * Perhaps we should do that. */ bool inblock = false; // are we in a base64 block? size_t blockstart = 0; // where the base64 started size_t prevlen = 0; // length of previous line size_t linecount = 0; // number of lines in region size_t pos = 0; // where we are scanning size_t line_start = 0; // start of the line that was found size_t line_len = 0; // length of the line bool found_equal = false; while(sbuf_getline(sbuf,pos,line_start,line_len)){ //fprintf(stderr,"pos=%zd\n",pos); if(sbuf_line_is_base64(sbuf,line_start,line_len,found_equal)){ if(inblock==false){ /* First line of a block! */ if(line_len >= minlinewidth){ inblock = true; blockstart= line_start; linecount = 1; prevlen = line_len; } continue; } if(line_len!=prevlen){ // whoops! Lines are different lengths if(found_equal && linecount>1){ //fprintf(stderr,"1. linecount=%zd\n",linecount); process(sp,rcb,blockstart,pos-blockstart); } inblock=false; continue; } linecount++; continue; } else { /* Next line is not Base64. If we had more than 2 lines, process them. * Note: hopefully the first line was the beginning of a BASE64 block to address * alignment issues. */ if(linecount>2 && inblock){ //fprintf(stderr,"2. blockstart=%zd line_start=%zd pos=%zd linecount=%zd\n",blockstart,line_start,pos,linecount); process(sp,rcb,blockstart,pos-blockstart); } inblock = false; } } //fprintf(stderr,"done\n"); } }