Recursive Binary String Search
This program is similar to the other one I made a while back, except this one searches for matches against a binary (string) value instead. For ease of use, the binary string is specified using a hexadecimal string.
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <limits.h> #include <unistd.h> #include <dirent.h> static int hex_value(int c) { if (c >= 0x30 && c <= 0x39) /* '0' - '9' */ return c - 0x30; else if (c >= 0x41 && c <= 0x46) /* 'A' - 'F' */ return (c - 0x41) + 10; else if (c >= 0x61 && c <= 0x66) /* 'a' - 'f' */ return (c - 0x61) + 10; else return -1; } static int convert_from_hex(char *hex_string, unsigned char *bin_string, int bin_string_len) { int n1, n2, high; high = -1; n1 = n2 = 0; while (hex_string[n1] != '\0') { if (hex_value(hex_string[n1]) >= 0) { if (high == -1) { high = hex_string[n1]; } else { bin_string[n2] = hex_value(high) * 16 + hex_value(hex_string[n1]); if (n2 >= bin_string_len) break; n2++; high = -1; } } n1++; } return n2; } static void search(char *path, unsigned char *bin_string, int len) { int c, match, name_shown, address, match_address; FILE *fh; fh = fopen(path, "rb"); if (fh == NULL) { fprintf(stderr, "Warning: Unable to open file: %s\n", path); return; } match = address = name_shown = match_address = 0; while ((c = fgetc(fh)) != EOF) { if (c == bin_string[match]) { if (match_address == 0) match_address = address; match++; if (match >= len) { if (! name_shown) { printf("%s\n", path); name_shown = 1; } printf("0x%x\n", match_address); match = 0; match_address = 0; } } else { match = 0; match_address = 0; } address++; } fclose(fh); } static void recurse(char *path, unsigned char *bin_string, int len) { char full_path[PATH_MAX]; struct dirent *entry; struct stat st; DIR *dh; dh = opendir(path); if (dh == NULL) { fprintf(stderr, "Warning: Unable to open directory: %s\n", path); return; } while ((entry = readdir(dh))) { if (entry->d_name[0] == '.') continue; /* Ignore files with leading dot. */ #ifdef WINNT snprintf(full_path, PATH_MAX, "%s\\%s", path, entry->d_name); #else snprintf(full_path, PATH_MAX, "%s/%s", path, entry->d_name); #endif stat(full_path, &st); if (S_ISDIR(st.st_mode)) { recurse(full_path, bin_string, len); } else if (S_ISREG(st.st_mode)) { search(full_path, bin_string, len); } } closedir(dh); return; } int main(int argc, char *argv[]) { int len; unsigned char *bin_string; struct stat st; if (argc != 3) { fprintf(stderr, "Usage: %s <directory or file> <hex string>\n", argv[0]); return 1; } len = strlen(argv[2]) / 2; bin_string = malloc(sizeof(unsigned char) * len); if (bin_string == NULL) { fprintf(stderr, "Error: Unable to malloc().\n"); return 1; } len = convert_from_hex(argv[2], bin_string, len); if (len == 0) { fprintf(stderr, "Error: Invalid input hex string.\n"); return 1; } stat(argv[1], &st); if (S_ISDIR(st.st_mode)) { recurse(argv[1], bin_string, len); } else if (S_ISREG(st.st_mode)) { search(argv[1], bin_string, len); } else { fprintf(stderr, "Error: Not a directory or regular file.\n"); free(bin_string); return 1; } free(bin_string); return 0; }