John Vn
John Vn

Reputation: 91

Store a program inside another program

I made a program which copies all contents of another c prog (binary file), writes them to another file and then executes it (execve()) after adding execution permission to it (chmod()).

Now I want to store all the contents of the file in an array inside the prog (I use hex representation) and then execute it. For this purpose I created another program in C which converts a file to hex representation here is the source code of these two programs:

#include <stdio.h> //program used for execution
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>

unsigned char prog []= {}// thats the string i am planning to use so i can store the program 

void FileCreate(const char *in) {

  FILE *fp2 = fopen(in,"wb"); // create afile in binary form with write permission
  if (fp2==NULL) {  //error checking
    fclose(in);
    printf("file '%s' isn't here...\n", in);
    exit(1);
  }

  int ch;  
  int i = 0;
  for (i=0; i<sizeof(prog);++i) { 
    ch = prog[i];
    fputc(ch, fp2);
  }

  fclose(fp2);
}

int main (int argc,char *argv[]){
  if (argc != 2) {
     fprintf(stderr, "Usage: %s [file_name]\n", argv[0]);
     exit(1);
  }
  FileCreate(argv[1]);
  char *cmd[] = {argv[1], NULL};
  int err = chmod (argv[1], S_IXUSR);
  if (err==-1){
     perror ("Change mode");
     exit(1);
  }
  err = execve (cmd[0], cmd,NULL);
  if (err==-1){
    perror ("Execute file");
    exit(1);
  }
  return 0;
}

converter.c: program that converts file to hex reprentation

#include <stdio.h>
int main (void) {
  unsigned char data[1024];
  size_t numread, i;

  while ((numread = read(0, data, 1024)) > 0) {
    for (i = 0; i < numread; i++) {
       if(data[i] != 0){ //remove null bytes
       printf("0x%02x,", data[i]);
    }
  }
}

  return 0;
}

As you can see in my converter program i remove the null bytes from the executable file. Is that correct or will the program fail to executes? My main issue is that I cant fit the whole program content inside an array. So how can I implement a program that stores the contents of another and then executes them?

Upvotes: 0

Views: 183

Answers (2)

kundrata
kundrata

Reputation: 679

You can embed the exe to your program like specified here: http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967

Just remember when writing the file to disk to use fopen with binary mode: fopen("myexe.exe", wb");

Upvotes: 0

j2ko
j2ko

Reputation: 2539

If you have binary file like following [A prog, B prog] and you know where B prog starts in your executable you could use mmap like in this thread.

UPDATE (only for linux) from this :

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

unsigned char mya[] =   {
              0x50,0x57,0x56,0x52,0xe8,
              0x00,0x00,0x00,0x00,0x5e,
              0x48,0x81,0xc6,0x24,0x00,
              0x00,0x00,0x48,0xc7,0xc0,
              0x01,0x00,0x00,0x00,0x48,
              0xc7,0xc7,0x01,0x00,0x00,
              0x00,0x48,0xc7,0xc2,0x0e,
              0x00,0x00,0x00,0x0f,0x05,
              0x5a,0x5e,0x5f,0x5a,0xc3,
              0x48,0x65,0x6c,0x6c,0x6f,
              0x2c,0x20,0x57,0x6f,0x72,
              0x6c,0x64,0x21,0x0a,0x00
            };

int main(int argc, char**argv)
{
  void *addr = (void*)((unsigned long)mya & ((0UL - 1UL) ^ 0xfff));/*get memory page*/
  int ans = mprotect(addr, 1, PROT_READ|PROT_WRITE|PROT_EXEC);/*set page attributes*/
  if (ans)
  {
    perror("mprotect");
    exit(EXIT_FAILURE);
  }

  ((void(*)(void))mya)();/*execute array*/

  return 0;
}

This will output "Hello, world!"

To manage big executable files you can make converter that will generate c header file like following:

//data.h
static unsigned char executable[] =
{
0x50, 0x36, 0x0A, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 
0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4D, 0x50, 0x0A, 0x32, 0x37, 
0x37, 0x20, 0x31, 0x36, 0x32, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
....

and then include it in your main program and use as in example above.

Upvotes: 1

Related Questions