/* Injects binary data into a file */
/* */
/* +========[KPS INJECTOR 0.8]===========+*/
/* |:_____: _____ __________ ._________ |*/
/* ||__ |/ /.\______ \./ _______/ |*/
/* | / __/ ___/ . | ▓__/ /\_____ \ |*/
/* | / \ \_ . | \_____/ \ \_| /|*/
/* | \ \ \_ . | : . : \_______/ |*/
/* | \___\____\ .:____| : |*/
/* | K.a.P.i.T.a.L. S i N ' 2022 |*/
/* +-------------------------------------|*/
/* |-KPS- -2022- |*/
/* | # KPS INJECTOR V 0.8 # |*/
/* | # por KAPITAL SIN # |*/
/* | PUBLIC DOMAIN LICENSE |*/
/* +[WIN64/Linux/UTIL]-------B22022022---+*/
/* */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <regex.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define VERSION "0.8"
#define BSIZE 65535
#define STRSIZE 2000
int term_pos = 0;
int term_pos_max = 0;
void print_usage() {
fprintf(stdout, "injector: injects patchfiles (filename_NNNNNNNN_NNNNNNNN.dat) into a file\n");
fprintf(stdout, "Version %s\n", VERSION);
fprintf(stdout, "Usage: injector filename1 filename2 ...\n");
}
void print_up(int nlines) {
fprintf(stdout,"\033[%dA", nlines);
term_pos -= nlines;
}
void print_down(int nlines) {
// fprintf(stdout,"\033[%dB", nlines);
fprintf(stdout,"%.*s", nlines, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
term_pos += nlines;
}
void print_to(int pos) {
if(pos > term_pos) {
print_down(pos-term_pos);
} else if(pos < term_pos) {
print_up(term_pos-pos);
}
}
void print_header() {
fprintf(stdout,
"+--------------------------------------+\n"
"+ KPS INJECTOR 2017 LINUX V" VERSION " +\n"
"+--------------------------------------+\n"
);
term_pos += 3;
}
void print_args_progress(char* fname, int arg_counter, int arg_total) {
unsigned char count_str[20];
print_to(3);
sprintf(count_str, "[%d/%d]", arg_counter, arg_total);
printf("+ %-20.20s %+15s +\n", fname, count_str);
term_pos += 1;
}
#define BAR_SIZE 36
void print_progress(char* fname, int file_counter, int file_count_total) {
int n = BAR_SIZE * file_counter / file_count_total;
unsigned char count_str[20];
print_to(4);
fprintf(stdout,"+ +\n");
sprintf(count_str, "[%d/%d]", file_counter, file_count_total);
fprintf(stdout,"+ %-20.20s %+15s +\n", fname, count_str);
fprintf(stdout,"+ +\n");
fprintf(stdout, "+[%.*s", n, "=====================================");
if(n < BAR_SIZE) {
fprintf(stdout, "%s", ">");
}
if(BAR_SIZE-n-1 > 0){
fprintf(stdout, "%.*s", BAR_SIZE-n-1, " ");
}
fprintf(stdout, "]+\n");
term_pos += 4;
}
void print_footer() {
print_to(8);
fprintf(stdout,"+--------------------------------------+\n");
fprintf(stdout,"+ .--. +\n");
fprintf(stdout,"+ |o_o | +\n");
fprintf(stdout,"+ |:_/ | +\n");
fprintf(stdout,"+ // \\ \\ +\n");
fprintf(stdout,"+ (| | ) +\n");
fprintf(stdout,"+ /'\\_ _/`\\ +\n");
fprintf(stdout,"+ \\___)=(___/ +\n");
fprintf(stdout,"+--------------------------------------+\n");
term_pos += 9;
}
void escape_metachars(char* out, int n, char* in) {
const char metas[] = "\\.^$+*?{[|";
while(*in != 0 && n > 3) {
if(strchr(metas, *in)) {
/* Is metachar */
*out++ = '\\';
n--;
}
*out++ = *in++;
n--;
}
*out = 0;
}
char* split_extension(char* fname) {
char *lastdot = strrchr(fname, '.');
*lastdot = 0;
return lastdot+1;
}
regex_t regex;
int reti;
regmatch_t regmatch[3];
unsigned char inj_offset_str[40];
unsigned char inj_length_str[40];
size_t inj_offset;
size_t inj_length;
void inject(char* fout, char* fin, size_t offset, size_t length) {
int in_h, out_h;
size_t n, bsize;
unsigned char buffer[BSIZE];
in_h = open(fin, O_RDONLY, 0);
out_h = open(fout, O_WRONLY|O_CREAT, 0640);
/* Check file size is correct */
struct stat stat_buf;
fstat(in_h, &stat_buf);
int size = stat_buf.st_size;
/* printf("%s %d %d\n", fin, size, length); */
if (size != length) {
fprintf(stderr, "\nFATAL: Filesize does not match signature for %s\n", fin);
exit(2);
}
if(lseek(out_h, offset, SEEK_SET) < 0) {
/* There was some problem, cancel injection */
close(in_h);
close(out_h);
return;
}
while(length > 0) {
bsize = length > BSIZE? BSIZE:length;
n = read(in_h, buffer, bsize);
if(n==0) {
/* No more input data */
break;
}
n = write(out_h, buffer, n);
length -= n;
}
close(in_h);
close(out_h);
}
int main(int argc,char *argv[]) {
if(argc < 2) {
print_usage();
return 1;
}
const char regex_str[]="_\\([0-9a-fA-F]\\{8\\}\\)_\\([0-9a-fA-F]\\{8\\}\\)\\.";
char file_regex_str[STRSIZE];
DIR *dp;
struct dirent *ep;
print_header();
print_footer();
int arg_counter;
int prev_found=0;
for(arg_counter=1; arg_counter<argc; arg_counter++) {
char *output_fname = argv[arg_counter];
if(arg_counter > 1) {
print_up(1);
if(prev_found) {
print_up(2);
}
}
print_args_progress(output_fname, arg_counter, argc-1);
/* Compile regular expression */
escape_metachars(file_regex_str, STRSIZE, output_fname);
strncat(file_regex_str, regex_str, STRSIZE-strlen(file_regex_str)-1);
reti = regcomp(®ex, file_regex_str, 0);
if (reti) {
perror("Could not compile regex");
}
/* Count files */
prev_found = 0;
int file_count_total = 0;
dp = opendir ("./");
if (dp != NULL)
{
while (ep = readdir (dp)) {
if(ep->d_type == DT_REG) {
/* Is a regular file */
char* fname = ep->d_name;
/* Check filename*/
reti = regexec(®ex, fname, 3, regmatch, 0);
if (!reti) {
/* Matched name format f_NNN_NNN.dat */
file_count_total++;
prev_found = 1;
}
}
}
(void) closedir (dp);
}
/* Walk directory */
int file_counter = 0;
dp = opendir ("./");
if (dp != NULL)
{
while (ep = readdir (dp)) {
if(ep->d_type == DT_REG) {
/* Is a regular file */
char* fname = ep->d_name;
/* Check filename*/
reti = regexec(®ex, fname, 3, regmatch, 0);
if (!reti) {
/* Matched name format f_NNN_NNN.dat */
file_counter++;
strncpy(inj_offset_str, fname+regmatch[1].rm_so, regmatch[1].rm_eo-regmatch[1].rm_so);
strncpy(inj_length_str, fname+regmatch[2].rm_so, regmatch[2].rm_eo-regmatch[2].rm_so);
inj_offset = (size_t)strtol(inj_offset_str, NULL, 16);
inj_length = (size_t)strtol(inj_length_str, NULL, 16);
/* printf("%ld %ld ", inj_offset, inj_length); */
/* puts(fname); */
print_progress(fname, file_counter, file_count_total);
inject(output_fname, fname, inj_offset, inj_length);
}
}
}
(void) closedir (dp);
}
else {
perror ("Couldn't open the directory");
}
regfree(®ex);
}
print_footer();
return 0;
}