/* Binary Instrumentation Tool/Framework for Android
 *  Collin Mulliner <collin[at]mulliner.org>
 *  http://www.mulliner.org/android/
 *
 *  (c) 2012
 *
 *  License: GPL v2
 *
 */
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <string.h>
#include <termios.h>

#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>

#include "libt.h"

#include "uthash.h"

// contains macro of my_init()
// autogenerated
#include "hijacks.h"


char tag[256];

struct mm {
	char name[256];
	unsigned long start, end;
};

int android_version_ID = ANDROID_V_INVALID;
unsigned int mname_offset=0x35;
unsigned int mname_this_offset=0;
unsigned int mClient_thisP_offset=0x14;
unsigned int mPid_mClient_offset=0x10;
unsigned int mStramType_this_offset=0;
unsigned int mState_offset=0x2c;
unsigned int sample_rate_offset=0x30;
unsigned int mCblk_this_offset = 0x1c;
static int log_baseaddress = 0;

// communication socket, a pty :)
int coms;

void __attribute__ ((constructor)) my_init(void);

void my_cacheflush(unsigned int begin, unsigned int end)
{	
	const int syscall = 0xf0002;
	__asm __volatile (
		"mov	 r0, %0\n"			
		"mov	 r1, %1\n"
		"mov	 r7, %2\n"
		//"mov     r2, #0x0\n"
		"mov     r2, #0x0\n"
		"svc     0x00000000\n"
		:
		:	"r" (begin), "r" (end), "r" (syscall)
		:	"r0", "r1", "r7"
		);
}


/*
  
  hook_t holds hook metadata 
  hookf is the hook callback
  
 */
int help(struct hook_t *hook_hash, int pid, char *libname, char *funcname, void *hookf, int by_name, unsigned int raw_address)
{
	unsigned long int addr = 0;
	int i;
	int find_name_result;
	
	struct hook_t *hook = (struct hook_t*) malloc(sizeof(struct hook_t));

	
#ifdef DEBUG_LIBT
	log("hooking - hash table 0x%x\n", help_hash1)
#endif

	if( by_name ) {

	  // 1 - fetch function address and put it into addr
	  find_name_result = find_name(pid, funcname, libname, &addr);
#ifdef DEBUG_LIBT
	  log("find_name_result %d\n", find_name_result);
#endif
	  if ( find_name_result < 0) {
#ifdef DEBUG_LIBT 
	      log("can't find: %s - error code %d\n", funcname, find_name_result)
#endif
	    return 0;
	  }

	} else {


#ifdef DEBUG_LIBT
	  log("specified raw address: %x\n", raw_address)
#endif
	    funcname = "z";//"raw address";



	  /* // find lib where raw address is contained in */

	  struct mm mm[450];
	  struct mm *m;
	  int nmm;
	  int load_memmap_return, mprotect_return;
	  char *slash;


	  load_memmap_return = load_memmap(pid, mm, &nmm);
	  
	  if( load_memmap_return < 0 ) {

#ifdef DEBUG_LIBT 
	    log("failed memmap\n")
#endif
	      exit(1);
	    
	  }


#ifdef DEBUG_LIBT
	  log("[*] searching vaddr for function %s - target relative address 0x%x\n", libname, raw_address)
#endif

	  for( i = 0, m = mm; i < nmm; i++, m++){

	    // awful code, just to print dbg infos

	    slash = strstr(m->name, ".so");
	    if (!slash)
	      continue;
	    
	    //log("[*] %s start: 0x%8x end: 0x%08x\n", m->name, m->start, m->end);
	    
	    if( strstr(m->name, libname) ) {
	      addr = m->start + raw_address;
	      
	      if( !log_baseaddress) {
#ifdef DEBUG_LIBT 
		log("[*] Base address 0x%x - 0x%x\n", m->start, m->end)
#endif
	        log_baseaddress = 1;
		base_address = m->start;
	      }
	      
#ifdef DEBUG_LIBT 
	      log("[*]\tFound address: 0x%8x\n", addr);
#endif

 
	      global_base_address = m->start;

#ifdef DEBUG_LIBT 
	      log("[D] base address: %p\n", global_base_address);
#endif

	      mprotect_return = mprotect((void*)m->start, m->end - m->start, PROT_READ|PROT_WRITE|PROT_EXEC);

	      if( mprotect_return == 0 ) {
#ifdef DEBUG_LIBT 
	    	  log("[*]\t+rwx  memory region ok\n")
#endif
	      }
	      else {
#ifdef DEBUG_LIBT 
		log("[*]\t mprotect failed\n")
#endif
		exit(1);
	      }
	    	
	      break;
	    }
	    
	  }
	  
	}
	
	if( addr == 0) {
#ifdef DEBUG_LIBT 
	  log("[*] Could not find specified library %s\n", libname)
#endif
	    exit(1);
	    }
	
#ifdef DEBUG_LIBT 
	log("[*] Hooking %s = %x  hook = %x  target:", funcname, addr, hookf)
#endif
	
        strncpy(hook->name, funcname, sizeof(hook->name)-1);
		  
	// 2 - hook either ARM or THUMB code
	if (addr % 4 == 0) {
	
	  
#ifdef DEBUG_LIBT 
	  log("ARM\n")
#endif

		hook->thumb = 0;
		hook->patch = (unsigned int)hookf;
		hook->orig = addr;

		hook->jump[0] = 0xe59ff000; // LDR pc, [pc, #0]
		hook->jump[1] = hook->patch;
		hook->jump[2] = hook->patch;


		for (i = 0; i < 3; i++)
			hook->store[i] = ( (int*)hook->orig )[i];

		for (i = 0; i < 3; i++)
			((int*)hook->orig)[i] = hook->jump[i];
	}
	else {
		hook->thumb = 1;
		
		
#ifdef DEBUG_LIBT 
		  log("THUMB\n")
#endif
		  
		  //h->jumpt[13] = 0xdf;
		  //h->jumpt[12] = 0xfe; // bp


		hook->patch = (unsigned int) hookf;
		hook->orig = addr;	

		/* patch without sub address in r12  */

		/* h->jumpt[1] = 0x46; */
		/* h->jumpt[0] = 0xac; */
		
		/* h->jumpt[3] = 0xa5; */
		/* h->jumpt[2] = 0x02; */
		  
		/* h->jumpt[5] = 0x68; */
		/* h->jumpt[4] = 0x2d; */

		/* h->jumpt[7] = 0xb4; */
		/* h->jumpt[6] = 0x20; */
		  
		/* h->jumpt[9] = 0x46; */
		/* h->jumpt[8] = 0x65; */

		/* h->jumpt[11] = 0xbd; */
		/* h->jumpt[10] = 0x00; */


		/* patch with sub address + 0xd  in r12 */
		hook->jumpt[1] = 0x46;
		hook->jumpt[0] = 0xac;
		
		hook->jumpt[3] = 0xa5;
		hook->jumpt[2] = 0x03;
		  
		hook->jumpt[5] = 0x68;
		hook->jumpt[4] = 0x2d;

		hook->jumpt[7] = 0xb4;
		hook->jumpt[6] = 0x20;
		  
		hook->jumpt[9] = 0x46;
		hook->jumpt[8] = 0x65;

		
		hook->jumpt[11] = 0x46;
		hook->jumpt[10] = 0xfc;

		hook->jumpt[13] = 0xbd;
		hook->jumpt[12] = 0x00;
		
		hook->jumpt[15] = 0x46; // nop
		hook->jumpt[14] = 0xe4;
		 
		memcpy(&hook->jumpt[12], (unsigned char*)&hook->patch, sizeof(unsigned int));


		unsigned int orig = addr - 1; 


		//char* cmd_disas_format = "arm-none-eabi-objdump -D --target binary -Mforce-thumb -marm %s";

		//char cmd_disas[256];
		unsigned char dump_buffer[20];

		//remove("tmp_stolen.bin");
		//FILE *stolen_bytes_dump = fopen("tmp_stolen.bin", "w");

		// Save stolen bytes
		
#ifdef DEBUG_LIBT 
		log("[*] Saving stolen bytes\n\t")
#endif

		for (i = 0; i < 20; i++) {
		  //log("%d:", i)
			hook->storet[i] = ((unsigned char*)orig)[i];
			dump_buffer[i] = ((unsigned char*)orig)[i];
			
			
#ifdef DEBUG_LIBT 
			//log("%0.2x ", hook->storet[i])
#endif
			
		}

		
#ifdef DEBUG_LIBT 
		  log("\n")
#endif
		  
	
		  //fprintf(stolen_bytes_dump, dump_buffer);
		  //fflush(stolen_bytes_dump);
		  //fclose(stolen_bytes_dump);
		
		  //remove("tmp_patch.bin");
		  //FILE *patch_bytes_dump = fopen("tmp_patch.bin", "w");


		    // write the patch to mem
#ifdef DEBUG_LIBT 
		    log("[*] Patching target address\n\t")
#endif
		    
		for (i = 0; i < 20; i++) {
		 
		    ( (unsigned char*) orig)[i] = hook->jumpt[i];
		    dump_buffer[i] = hook->jumpt[i];

#ifdef DEBUG_LIBT 
		     // log("%0.2x ", ((unsigned char*)orig)[i])
#endif

		}
		  //fprintf(patch_bytes_dump, dump_buffer);
		  //fflush(patch_bytes_dump);
		  //fclose(patch_bytes_dump);

		  
#ifdef DEBUG_LIBT 
		  log("\n")
#endif



		/* char out_buffer[200]; */
		/* snprintf(cmd_disas, 100, cmd_disas_format, "tmp_stolen.bin"); */
		/* log("[*] Launching command %s\n", cmd_disas) */
		/* FILE *objdump = popen(cmd_disas, "r"); */
		/* while(fgets(out_buffer,200,objdump) != NULL) { */
		/*   log("asdf\n") */
		/*   log(out_buffer) */
		/* } */
		/* pclose(objdump); */




	}

	
#ifdef DEBUG_LIBT 
	  log("[*]Adding 0x%x to hash table 0x%x\n", hook->orig, hook_hash)
#endif
	    
	    HASH_ADD(hh, help_hash1, orig, sizeof(int), hook);


	my_cacheflush((unsigned int)hook->orig, (unsigned int)hook->orig+20);
	
	
#ifdef DEBUG_LIBT
	log("hooking finished\n")
#endif
	return 1;
}


int help_no_hash(struct hook_t *hook, int pid, char *libname, char *funcname, void *hookf, int by_name, unsigned int raw_address)
{
	unsigned long int addr = 0;
	int i;
	int find_name_result;



	if( by_name ) {

	  // 1 - fetch function address and put it into addr
	  find_name_result = find_name(pid, funcname, libname, &addr);
#ifdef DEBUG_LIBT 
	  log("find_name_result %d\n", find_name_result);
#endif
	  if ( find_name_result < 0) {
#ifdef DEBUG_LIBT 
	    log("can't find: %s - error code %d\n", funcname, find_name_result)
#endif
	    return 0;
	  }

	} else {
	  
#ifdef DEBUG_LIBT 
	  log("[*] specified raw address: %x\n", raw_address)
#endif
  
	    funcname = "zz"; //"raw address";



	  /* // find lib where raw address is contained in */

	  struct mm mm[450];
	  struct mm *m;
	  int nmm;
	  int load_memmap_return, mprotect_return;
	  char *slash;


	  load_memmap_return = load_memmap(pid, mm, &nmm);
	  
	  if( load_memmap_return < 0 ) {
#ifdef DEBUG_LIBT 
	    log("failed memmap\n")
#endif
	      exit(1);
	    
	  }
	  
#ifdef DEBUG_LIBT 
	  log("[*] searching vaddr for function %s - target relative address 0x%x\n", libname, raw_address)
#endif

	  for( i = 0, m = mm; i < nmm; i++, m++){

	    // awful code, just to print dbg infos

	    slash = strstr(m->name, ".so");
	    if (!slash)
	      continue;
	    
	    //log("[*] %s start: 0x%8x end: 0x%08x\n", m->name, m->start, m->end);
	    
	    if( strstr(m->name, libname) ) {
	      addr = m->start + raw_address;
	      
	      if( !log_baseaddress) {
#ifdef DEBUG_LIBT 
		log("[*] Base address 0x%x - 0x%x\n", m->start, m->end)
#endif
	        log_baseaddress = 1;
		base_address = m->start;
	      }
	      
#ifdef DEBUG_LIBT 
	      log("[*]\tFound address: 0x%8x\n", addr);
#endif

	      global_base_address = m->start;
#ifdef DEBUG_LIBT 
	      log("[D] base address: %p\n", global_base_address);
#endif
	      
	      mprotect_return = mprotect((void*)m->start, m->end - m->start, PROT_READ|PROT_WRITE|PROT_EXEC);

	      if( mprotect_return == 0 ) {
		
#ifdef DEBUG_LIBT 
		log("[*]\t+rwx  memory region ok\n")
#endif
	      }
	      else {
#ifdef DEBUG_LIBT 
		log("[*]\t mprotect failed\n")
#endif
		exit(1);
	      }
	    	
	      break;
	    }
	    
	  }
	  
	}
	
	if( addr == 0) {
#ifdef DEBUG_LIBT 
	  log("[*] Could not find specified library %s\n", libname)
#endif
	    exit(1);
	}
	
#ifdef DEBUG_LIBT 
	log("[*] Hooking %s = %x  hook = %x  target:", funcname, addr, hookf)
#endif
	
        strncpy(hook->name, funcname, sizeof(hook->name)-1);
		  
	// 2 - hook either ARM or THUMB code
	if (addr % 4 == 0) {
	  

#ifdef DEBUG_LIBT 
	  log("ARM\n")
#endif

		hook->thumb = 0;
		hook->patch = (unsigned int)hookf;
		hook->orig = addr;

		hook->jump[0] = 0xe59ff000; // LDR pc, [pc, #0]
		hook->jump[1] = hook->patch;
		hook->jump[2] = hook->patch;


		for (i = 0; i < 3; i++)
			hook->store[i] = ( (int*)hook->orig )[i];

		for (i = 0; i < 3; i++)
			((int*)hook->orig)[i] = hook->jump[i];
	}
	else {
		hook->thumb = 1;
		
		
#ifdef DEBUG_LIBT 
		  log("THUMB\n")
#endif
		  
		  //h->jumpt[13] = 0xdf;
		  //h->jumpt[12] = 0xfe; // bp


		hook->patch = (unsigned int) hookf;
		hook->orig = addr;	


		hook->jumpt[1] = 0x46;
		hook->jumpt[0] = 0xac;
		
		hook->jumpt[3] = 0x46;
		hook->jumpt[2] = 0x7d;
		  
		hook->jumpt[5] = 0x35;
		hook->jumpt[4] = 0x08;

		hook->jumpt[7] = 0x68;
		hook->jumpt[6] = 0x2d;
		  
		hook->jumpt[9] = 0xb4;
		hook->jumpt[8] = 0x20;

		
		hook->jumpt[11] = 0x46;
		hook->jumpt[10] = 0x65;

		hook->jumpt[13] = 0xbd;
		hook->jumpt[12] = 0x00;
		 
		memcpy(&hook->jumpt[14], (unsigned char*)&hook->patch, sizeof(unsigned int));


		unsigned int orig = addr - 1; 


		//char* cmd_disas_format = "arm-none-eabi-objdump -D --target binary -Mforce-thumb -marm %s";

		//char cmd_disas[256];
		unsigned char dump_buffer[20];

		//remove("tmp_stolen.bin");
		//FILE *stolen_bytes_dump = fopen("tmp_stolen.bin", "w");

		// Save stolen bytes
		
		
#ifdef DEBUG_LIBT 
		log("[*] Saving stolen bytes\n\t")
#endif

		for (i = 0; i < 20; i++) {
		  //log("%d:", i)
			hook->storet[i] = ((unsigned char*)orig)[i];
			dump_buffer[i] = ((unsigned char*)orig)[i];
			
			
#ifdef DEBUG_LIBT 
			//log("%0.2x ", hook->storet[i])
#endif
			
		}

		
#ifdef DEBUG_LIBT 
		log("\n")
#endif
	
		  //fprintf(stolen_bytes_dump, dump_buffer);
		  //fflush(stolen_bytes_dump);
		  //fclose(stolen_bytes_dump);
		
		  //remove("tmp_patch.bin");
		  //FILE *patch_bytes_dump = fopen("tmp_patch.bin", "w");


		  // write the patch to mem
#ifdef DEBUG_LIBT 
		  log("[*] Patching target address\n\t")
#endif
		    
		  for (i = 0; i < 20; i++) {
		    //log("%d - %p: ",i, orig+i);
		    ( (unsigned char*) orig)[i] = hook->jumpt[i];
		    dump_buffer[i] = hook->jumpt[i];
		    
		  
#ifdef DEBUG_LIBT 
		   // log("%0.2x", ((unsigned char*)orig)[i]);
#endif
		    
		  }
		  //fprintf(patch_bytes_dump, dump_buffer);
		  //fflush(patch_bytes_dump);
		  //fclose(patch_bytes_dump);
		
#ifdef DEBUG_LIBT 
		log("\n")
#endif



		/* char out_buffer[200]; */
		/* snprintf(cmd_disas, 100, cmd_disas_format, "tmp_stolen.bin"); */
		/* log("[*] Launching command %s\n", cmd_disas) */
		/* FILE *objdump = popen(cmd_disas, "r"); */
		/* while(fgets(out_buffer,200,objdump) != NULL) { */
		/*   log("asdf\n") */
		/*   log(out_buffer) */
		/* } */
		/* pclose(objdump); */




	}



	my_cacheflush((unsigned int)hook->orig, (unsigned int)hook->orig+20);
	
	
#ifdef DEBUG_LIBT 
	log("hooking finished\n")
#endif
	return 1;
}

void helper_precall(struct hook_t *h)
{
  //  log("[*]\t Precall restoring original code %x\n", h->orig)

	int i;
	
	if (h->thumb) {
		unsigned int orig = h->orig - 1;
		//log("\t\t")
		for (i = 0; i < 20; i++) {
			((unsigned char*)orig)[i] = h->storet[i];
			//	log("%0.2x ", ((unsigned char*)orig)[i] )
		}
		//log("\n")
	}
	else {
		for (i = 0; i < 3; i++)
			( (int*) h->orig)[i] = h->store[i];
	}	
	//	log("[*]\t Precall original code restored %x\n", h->orig);

	
	
	my_cacheflush((unsigned int)h->orig, (unsigned int)h->orig+20);
	
}

void helper_postcall(struct hook_t *h)
{
	int i;

	//log("[*]\t Postcall - restoring hook %x:\n", h->orig)	
	if (h->thumb) {
		unsigned int orig = h->orig - 1;
		//	log("\t\t")
		for (i = 0; i < 20; i++) {
		  ((unsigned char*)orig)[i] = h->jumpt[i];
		  //log("%0.2x ", ((unsigned char*)orig)[i] )
		  }
		//		log("\n")
	}

	else {
		for (i = 0; i < 3; i++)
			((int*)h->orig)[i] = h->jump[i];
	}

	//log("[*]\t Postcall - hook restored %x:\n", h->orig)
	my_cacheflush((unsigned int)h->orig, (unsigned int)h->orig+20);	
	
}

void unhelp(struct hook_t *h)
{
#ifdef DEBUG_LIBT 
	log("unhelping %s = %x  hook = %x ", h->name, h->orig, h->patch)
#endif
	helper_precall(h);
}

/*
 *  workaround for blocked socket API when process does not have network
 *  permissions
 *
 *  this code simply opens a pseudo terminal (pty) which gives us a
 *  file descriptor. the pty then can be used by another process to
 *  communicate with our instrumentation code. an example program
 *  would be a simple socket-to-pty-bridge
 *  
 *  this function just creates and configures the pty
 *  communication (read, write, poll/select) has to be implemented by hand
 *
 */
/* void start_coms() */
/* { */
/* 	// coms is a global */
/* 	coms = open("/dev/ptmx", O_RDWR|O_NOCTTY); */
/* 	if (coms <= 0) */
/* 		log("posix_openpt failed\n") */
/* 	//else */
/* 	//	log("pty created\n") */
/* 	if (unlockpt(coms) < 0) */
/* 		log("unlockpt failed\n") */
/* 	log("pty created, file name: %s\n", ptsname(coms)) */
	
/* 	struct termios  ios; */
/* 	tcgetattr(coms, &ios); */
/* 	ios.c_lflag = 0;  // disable ECHO, ICANON, etc... */
/* 	tcsetattr(coms, TCSANOW, &ios); */
/* } */


void my_init()
{

  
#ifdef DEBUG_LIBT
  log("[*] Start hooking\n");
#endif
    //start_coms();
    
  int v = 0;
  unsigned long int addr = 0;
  unsigned int hook_counter = 0;
  char android_version[10] = "";
  FILE *fp;
  char *command =  "getprop ro.build.version.release";
  
  char *hook_log_filename = malloc( sizeof(char) * 8) ; // 8_8.cnf
  char *full_path_log_filename;
  int full_path_log_filename_length;
  int fd = -1;


  int pid = getpid();
  pid_global = getpid();

  
#ifdef DEBUG_LIBT 
  log("[*] Pid:%d\n", pid);
#endif

  /* determine whether it's running 4.0 compatible or 4.1/4.2 */
  fp = popen(command, "r");

  if( fgets(android_version, sizeof(android_version), fp) != NULL &&  android_version[0] == '4' ) {

    
#ifdef DEBUG_LIBT 
    log("[*] version %s\n", android_version);
#endif


    if( android_version[2] == '0' ) {
   
      
#ifdef DEBUG_LIBT 
      log("[*] 4.0\n");
#endif
      android_version_ID = ANDROID_V_4_0;
      mStramType_this_offset = 0x6c;
      mname_this_offset = 0x70;
      /* 4.0 */
      /* dumpers */
      hook_counter += HOOK_coverage_40_11;  // record
      hook_counter += HOOK_coverage_40_12;  // play

      /* signaling */

      // playback
      hook_counter += HOOK_coverage_40_2;  // new
      hook_counter += HOOK_coverage_40_17; // start
      hook_counter += HOOK_coverage_19;    // stop
      hook_counter += HOOK_coverage_20;    // pause

      // record 
      hook_counter += HOOK_coverage_40_16; // start
      hook_counter += HOOK_coverage_18;    // stop
    } 
    else {

    	if( (android_version[2] == '1' )  ){
#ifdef DEBUG_LIBT
    		log("[*] 4.1\n");
#endif
    		// mStramType_this_offset = 0x6c ,mname_this_offset = 0x70, OFFSET OK,VIBER E SKYPE OK, skype canali leggermente desync
    		android_version_ID = ANDROID_V_4_1;
    		mStramType_this_offset = 0x6c;
    		mname_this_offset = 0x70;
    		//mClient_thisP_offset=0x18;
    		//mCblk_this_offset = 0x20;
    	}else if( (android_version[2] == '2' ) ){
#ifdef DEBUG_LIBT
        log("[*] 4.2\n");
#endif
        android_version_ID = ANDROID_V_4_2;
        mStramType_this_offset = 0x6c;
        mname_this_offset = 0x70;
        mClient_thisP_offset=0x18;
        mCblk_this_offset = 0x20;
      }else if((android_version[2] == '3' )  || (android_version[2] == '4' )){
#ifdef DEBUG_LIBT 
    		log("[*] 4.3/4.4\n");
#endif
    		android_version_ID = ANDROID_V_4_3;
    		mStramType_this_offset = 0x88;
    		mname_this_offset = 0x8c;

    	}else{
    		log("[*] do wee manage %s ?\n",android_version);
    		android_version_ID = ANDROID_V_4_3;
    		mStramType_this_offset = 0x88;
    		mname_this_offset = 0x8c;
    	}

    	/* 4.1/4.2 */
    
      /* dumpers */
      hook_counter += HOOK_coverage_11;  // record
      //if((android_version[2] == '3' )  || (android_version[2] == '4' )){
      //  hook_counter += HOOK_coverage_43_12;  // playbackTrack_threadLoop_write
      //}else{
        hook_counter += HOOK_coverage_12;  // getNextBuffer
      //}
      /* signaling */

      // playback
      v = HOOK_coverage_2;
      hook_counter +=v;
      if ( v== 0){
	log("[*] Trying fallback for Playback new (>4.2?)\n");
	hook_counter += HOOK_coverage_2_fall;  // new
      }
      hook_counter += HOOK_coverage_17; // start
      hook_counter += HOOK_coverage_19; // stop
      hook_counter += HOOK_coverage_20; // pause

      // record 
      hook_counter += HOOK_coverage_16; // start
      hook_counter += HOOK_coverage_18; // stop
    
    }
	
#ifdef DEBUG_LIBT 
    log("[*] Hooking finished\n");
    log("[*] hooked %d/8 functions\n", hook_counter);
    log("[*] dumpPath %s\n", dumpPath);
#endif
    
    // if hook_counter is bigger something happened, do not write cnf file
    if( hook_counter <= 8 ) {
      snprintf(hook_log_filename, 8, "%d_8.cnf", hook_counter);
      
      full_path_log_filename_length = strlen(dumpPath) + 1 + strlen(hook_log_filename) + 1;
      full_path_log_filename = malloc( sizeof(char) * full_path_log_filename_length);
      
      snprintf(full_path_log_filename, full_path_log_filename_length, "%s/%s", dumpPath, hook_log_filename);
 
      fd = open(full_path_log_filename, O_RDWR | O_CREAT , S_IRUSR | S_IRGRP | S_IROTH);

#ifdef DEBUG_LIBT
      log("[*] wrote log file %s fd %d\n", full_path_log_filename, fd);
#endif

      close(fd);
#ifdef DEBUG_LIBT
      snprintf(hook_log_filename, 8, "dbg.cnf", hook_counter);
      full_path_log_filename_length = strlen(dumpPath) + 1 + strlen(hook_log_filename) + 1;
      full_path_log_filename = malloc( sizeof(char) * full_path_log_filename_length);
      snprintf(full_path_log_filename, full_path_log_filename_length, "%s/%s", dumpPath, hook_log_filename);
      fd = open(full_path_log_filename, O_RDWR | O_CREAT , S_IRUSR | S_IRGRP | S_IROTH);
      log("[*] wrote log file %s fd %d\n", full_path_log_filename, fd);
      close(fd);
#endif
      free(hook_log_filename);
      free(full_path_log_filename);


    }
 
  } 
#ifdef DEBUG_LIBT 
  else {
    log("[*] Fail getprop\n");
    
  }
#endif
  pclose(fp);
}
 
















