what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

cryptelf.c

cryptelf.c
Posted Mar 11, 2003
Authored by Slacko

A simple ELF binary encryption tool for Linux that encrypts the .text part of an ELF file with the password being given as an argument.

tags | encryption
systems | linux
SHA-256 | 1777c3839840816aef4069dcfdb183463ba353c5bb7c384b9bbfea62bcde1611

cryptelf.c

Change Mirror Download
/* cryptelf is a simple ELF binary encryption tool for linux */
/* encrypts the .text part of an ELF file with the password given as argument and adds the decryption opcode to the target file */
/* Usage : ./cryptelf <binary> <password> */

/* by SLACKo slacko@mail.ru */


#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <linux/elf.h>

#define ADDRESS 0x06000000

/* PASS_WRITE_ADDR offset to patch address "password:" in opcode[] */

#define PASS_WRITE_ADDR 31

/* offset to patch address of the read password in opcode[] */

#define PASS_READ_ADDR 53

/* bytes to skip when setting new entry point */

#define STORAGE_BYTES 19

/* offset of "password:\n" in opcode[] */

#define PASS_SRC_ADDR 0

/* offset to save the read password */

#define PASS_DST_ADDR 10

#define ENTRY_PATCH_ADDR 87

#define MPROTECT_SIZE_OF_TEXT_PATCH_ADDR 75

#define LOW_PASS_WORD_PATCH_ADDR 92

#define HIGH_PASS_WORD_PATCH_ADDR 97

#define SIZE_OF_TEXT_PATCH_ADDR 102



void __checkarg(int _num,char **_arg) {
if(_num < 3) {
fprintf(stderr,"Usage : ./cryptelf <binary> <password>\n");
exit(1);
}
if(strlen(_arg[2]) > 8) {
fprintf(stderr,"Error : Max password length 8 characters\n");
exit(1);
}
}

int __getsize(int fd) {
struct stat _info;
fstat(fd,&_info);
return _info.st_size;
}

void __keyerror(char *_key,char *_arg) {
bzero(_key,8);
strcpy(_key,_arg);
_key[strlen(_arg)] = 0xA;
}

/* A function to check if the ELF binary is already encrypted */
void __checkifencrypted(char *_arg,long _offset,int _opcodesize) {
int fd;
int _size;
unsigned long _mapped;
fd = open(_arg,O_RDWR,0);
_size = __getsize(fd);
(void *)_mapped = mmap(0,_size,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);
if(!strncmp( (unsigned long *)( (_mapped + _size) - 7),"XEgypT",6)) {
fprintf(stderr,"File seems to be already encrypted with cryptelf\n");
munmap(0,_size);
close(fd);
exit(1);
}

munmap(0,_size);
close(fd);
}



/* A function to get the entry point of the target file */
unsigned long __getentry(char *_arg) {
Elf32_Ehdr _ehdr;
int fd;
fd = open(_arg,O_RDWR,0);
read(fd,(void *)&_ehdr,sizeof(Elf32_Ehdr));
close(fd);
return _ehdr.e_entry;
}

/* A function to get the offset of the section header string table */
unsigned long __getstrtaboff(unsigned long _mapped) {
Elf32_Ehdr _ehdr;
Elf32_Shdr _shdr;
unsigned long _shstrtab;
_ehdr = *(Elf32_Ehdr *)_mapped;
_shdr = *(Elf32_Shdr *)(_mapped + _ehdr.e_shoff + (_ehdr.e_shstrndx * sizeof(Elf32_Shdr)) );
return _shdr.sh_offset;
}

/* A function that gets the .note-ABI-tag section offset also replace ".note-ABI-tag" with x3gpt sign ;) */
unsigned long __getnoteoff(unsigned long _mapped,int _size,int _opcodesize) {
Elf32_Ehdr _ehdr;
Elf32_Shdr _shdr;
unsigned long _strtaboff;
int i = 0;
unsigned long _extra = 0;
_ehdr = *(Elf32_Ehdr *)_mapped;
/* this section reads the section string table into _shdr and save it's offset */
_strtaboff = __getstrtaboff(_mapped);
while(i++<_ehdr.e_shnum) {
_shdr = *(Elf32_Shdr *)(_mapped + _ehdr.e_shoff + _extra);
if( !strncmp((char *)(_mapped+_strtaboff+_shdr.sh_name),".note.ABI-tag\0",14) ) {

/* next line changes ".note-ABI-tag" to "XEgypt" */
strncpy((_mapped+_strtaboff+_shdr.sh_name),".XEgypT\0\0\0\0\0\0\0",14);
/* next line the rest of the changes to .note section header struct are handled*/
__changenote(_mapped,_ehdr.e_shoff,_extra,_size,_opcodesize);

return _shdr.sh_offset; //returns offset of .note
}
_extra += sizeof(Elf32_Shdr);

}
}

/* A function to change NOTE segment to LOAD */
void __changenoteseg(unsigned long _mapped,int _size,int _opcodesize) {
Elf32_Ehdr _ehdr;
Elf32_Phdr *_phdr;
int i=0;
int _extra = 0;
_ehdr = *(Elf32_Ehdr *)_mapped;
while(i++<_ehdr.e_phnum) {
_phdr = (Elf32_Phdr *)(_mapped + _ehdr.e_phoff + _extra);
_extra += sizeof(Elf32_Phdr);
if (_phdr->p_type == 0x4) {
/* change NOTE segment info */
_phdr->p_type = 0x1;
_phdr->p_flags = 0x7; // 0x5;
_phdr->p_offset = _size - _opcodesize;
_phdr->p_vaddr = ADDRESS + _phdr->p_offset;
_phdr->p_paddr = ADDRESS + _phdr->p_offset;
_phdr->p_filesz = _opcodesize;
_phdr->p_memsz = _opcodesize;
_phdr->p_align = 0x1000;
}
}
}


/* A function to update .note with the new info */
int __changenote(unsigned long _mapped,unsigned long _shoff, unsigned long _noteoff,int
_targetsize,int _opcodesize) {

Elf32_Shdr *_shdr;
_shdr = (Elf32_Shdr *)(_mapped + _shoff + _noteoff);
_shdr->sh_type = 0x1;
_shdr->sh_flags = 0x6; // AX
_shdr->sh_addr = ADDRESS + (_targetsize - _opcodesize);
_shdr->sh_offset = _targetsize - _opcodesize;
_shdr->sh_size = _opcodesize;
_shdr->sh_addralign = 16;
}

/* A function to append opcodes to the ELF binary */
void __appendopcodes(char *_arg,unsigned char *opcode,int _opcodesize) {
int fd = open(_arg,O_APPEND|O_RDWR,0);
write(fd,opcode,_opcodesize);
close(fd);
}

/* A function to change the entry point to the address of note*/
void __changentry(unsigned long _mapped,long _offset) {
Elf32_Ehdr *_ehdr;
_ehdr = (Elf32_Ehdr *)_mapped;
_ehdr->e_entry = ADDRESS + _offset + STORAGE_BYTES ;
}


/* A function to patch the opcodes at runtime */
void __patchopcode(unsigned long _mapped,int _size,int _opcodesize,unsigned long _entry) {
/* (_size - _opcodesize) = offset of .XegypT section in the file */
*(unsigned long *)(_mapped + _size - 13) = _entry;
*(unsigned long *)(_mapped + (_size - _opcodesize ) + PASS_WRITE_ADDR) = ADDRESS + (_size - _opcodesize) + PASS_SRC_ADDR;
*(unsigned long *)(_mapped + (_size - _opcodesize ) + PASS_READ_ADDR) = ADDRESS + (_size - _opcodesize ) + PASS_DST_ADDR;
*(unsigned long *)(_mapped + (_size - _opcodesize ) + ENTRY_PATCH_ADDR) = _entry;
*(unsigned long *)(_mapped + (_size - _opcodesize ) + LOW_PASS_WORD_PATCH_ADDR ) = (ADDRESS + (_size - _opcodesize) + PASS_DST_ADDR);
*(unsigned long *)(_mapped + (_size - _opcodesize ) + HIGH_PASS_WORD_PATCH_ADDR ) = (ADDRESS + (_size -_opcodesize) +PASS_DST_ADDR + 4);
*(unsigned long *)(_mapped + (_size - _opcodesize ) + SIZE_OF_TEXT_PATCH_ADDR ) = (unsigned long)__gettextsize(_mapped);
*(unsigned long *)(_mapped + (_size - _opcodesize ) + MPROTECT_SIZE_OF_TEXT_PATCH_ADDR ) = _size; // well it can't be bigger
}

/* A function to return .text section address */
unsigned long __gettextaddr(unsigned long _mapped) {
Elf32_Ehdr _ehdr;
Elf32_Shdr _shdr;
unsigned long _strtaboff;
int i = 0;
int _extra = 0;
_strtaboff = __getstrtaboff(_mapped);
_ehdr = *(Elf32_Ehdr *)_mapped;
/* search for .text section */
while(i++<_ehdr.e_shnum) {
_shdr = *(Elf32_Shdr *)(_mapped + _ehdr.e_shoff + _extra);
if( !strncmp((char *)(_mapped+_strtaboff+_shdr.sh_name),".text\0",6)) {
return _shdr.sh_addr;
}
_extra += sizeof(Elf32_Shdr);
}
}


/* A function to return .text offset */
unsigned long __gettextoffset(unsigned long _mapped) {
Elf32_Ehdr _ehdr;
Elf32_Shdr _shdr;
unsigned long _strtaboff;
int i = 0;
int _extra = 0;
_strtaboff = __getstrtaboff(_mapped);
_ehdr = *(Elf32_Ehdr *)_mapped;
/* search for .text section */
while(i++<_ehdr.e_shnum) {
_shdr = *(Elf32_Shdr *)(_mapped + _ehdr.e_shoff + _extra);
if( !strncmp((char *)(_mapped+_strtaboff+_shdr.sh_name),".text\0",6)) {
return _shdr.sh_offset;
}
_extra += sizeof(Elf32_Shdr);
}
}

/* A function to return .text size */
int __gettextsize(unsigned long _mapped) {
Elf32_Ehdr _ehdr;
Elf32_Shdr _shdr;
int _textoffset;
unsigned long _strtaboff;
int i = 0;
int _extra = 0;
_strtaboff = __getstrtaboff(_mapped);
_ehdr = *(Elf32_Ehdr *)_mapped;
/* search for .text section */
while(i++<_ehdr.e_shnum) {
_shdr = *(Elf32_Shdr *)(_mapped + _ehdr.e_shoff + _extra);
if( !strncmp((char *)(_mapped+_strtaboff+_shdr.sh_name),".text\0",6)) {
_textoffset = _shdr.sh_size;
if((_textoffset % 8) != 0) {
_textoffset += 4;
}
return _textoffset;
}
_extra += sizeof(Elf32_Shdr);
}
}


/* A function to encrypt the ELF .text bytes */
void __crypttext(unsigned long _mapped,char * _key) {
unsigned long _text;
int _textsize;
unsigned long _textaddr;
int i;
_textsize = __gettextsize(_mapped);
_textaddr = (_mapped + __gettextoffset(_mapped));
for(i=0;i<_textsize;i+=8) {
/* xor it with the key */
*(long long *)(_textaddr + i) ^= *(long long *)(_key);
}

}


int main(int argc,char **argv) {

unsigned char opcode[] = {
/* Start storage part */
"\x70\x61\x73\x73\x77\x6f\x72\x64\x3a\x20" /* 10 bytes for "password: " [STORAGE_BYTES] */
"\x0\x0\x0\x0\x0\x0\x0\x0\x0" /* 8 bytes storage for the password {STORAGE_BYTES] + 1*/
/* End storage part */

/* Saving registers (new entry point starts here) */
"\x60" /* pusha */
/* End of Saving registers */

/* Start write code part */
"\xb8\x4\x0\x0\x0" /* movl $4,%eax */
"\xbb\x1\x0\x0\x0" /* movl $1,%ebx */
/* PATCHED */ "\xb9\x00\x00\x00\x00" /* movl $first_9_bytes_adr,%ecx (patched at runtime) at opcode + PASS_WRITE_ADDR */
"\xba\xa\x0\x0\x0" /* movl $0xa,%edx */
"\xcd\x80" /* write(1,"password:\n",10) */
/* End write code part */


/* Start read code part */
"\xb8\x3\x0\x0\x0" /* movl $3,%eax */
"\xbb\x0\x0\x0\x0" /* movl $0,%ebx */
/* PATCHED */ "\xb9\x00\x00\x00\x00" /* movl $read_pass_addr,%ecx (patched at runtime) at opcode + PASS_READ_ADDR*/
"\xba\x9\x0\x0\x0" /* movl $0x8,%edx */
"\xcd\x80" /* read(0,PASS_DST_ADDR,8) */
/* End read code part */

/* Start of mprotect() part */
"\xb8\x7d\x00\x00\x00" /* movl $0x7d,%eax */
"\xbb\x00\x80\x04\x08" /* movl $0x8048000,%ebx */
/* PATCHED */ "\xb9\x00\x00\x00\x00" /* movl $size_of_text,%ecx */
"\xba\x07\x00\x00\x00" /* movl $0x7,%edx */
"\xcd\x80" /* mprotect(0x08048000,_size,PROT_READ|PROT_WRITE|PROT_EXEC) */
/* End of mprotect() part */


/* Start register setting part */
/* PATCHED */ "\xb8\x00\x00\x00\x00" /* movl $original_entry,%eax*/
/* PATCHED */ "\xb9\x00\x00\x00\x00" /* movl $low_pass_word_addr ,%ecx */
/* PATCHED */ "\xba\x00\x00\x00\x00" /* movl $high_pass_word_addr,%edx */
/* PATCHED */ "\xbb\x00\x00\x00\x00" /* movl $size_of_text,%ebx */
/* End register setting part */


/* Start of decryption code */
"\x8b\x39" /* movl (%ecx),%edi */ // %ecx = Lower password word address
"\x33\x38" /* xorl (%eax),%edi */ // %eax = Orginal entry point
"\x89\x38" /* movl %edi,(%eax) */
"\x83\xc0\x04" /* addl $0x4,%eax */
"\x8b\x3a" /* movl (%edx),%edi */ // %edx = Higher password word address
"\x33\x38" /* xorl (%eax),%edi */
"\x89\x38" /* movl %edi,(%eax) */
"\x83\xc0\x04" /* addl $0x4,%eax */
"\x83\xeb\x08" /* subl $0x8,%ebx */
"\x75\xe9" /* jne start of encryption part (0xffffffe9 is the number of bytes back to the start of the loop) */
/* End of decryption code */


/* Start restore registers/jump to original code part */
"\x61" /* popa */
/* PATCHED */ "\xb8\x00\x00\x00\x00" /* movl $original_entry,%eax */
"\xff\xe0" /* jmp *%eax */
"\x58\x45\x67\x79\x70\x54" /* XEgypT sign in hex */
/* End restore registers/jump to original code part */
};

unsigned long _entry,_mapped,_note;
int fd,_size;
int _opcodesize;
char _key[8];

__checkarg(argc,argv);
__keyerror(_key,argv[2]);

_entry = __getentry(argv[1]);
_opcodesize = sizeof(opcode);


/* check if ELF binary already encrypted */
__checkifencrypted(argv[1],(_size - _opcodesize),_opcodesize);

/* append opcodes to ELF binary */
__appendopcodes(argv[1],opcode,_opcodesize);

fd = open(argv[1],O_RDWR,0);
_size = __getsize(fd);
(void *)_mapped = mmap(0,_size,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);

/* patch opcodes with runtime info */
__patchopcode(_mapped,_size,_opcodesize,_entry);

_note = __getnoteoff(_mapped,_size,_opcodesize);

/* change NOTE to LOAD */
__changenoteseg(_mapped,_size,_opcodesize);

/* change the entry point to 0x06000000 */
__changentry(_mapped,(_size - _opcodesize));

/* encrypt the text part */
__crypttext(_mapped,_key);

munmap(0,_size);

}

Login or Register to add favorites

File Archive:

August 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Aug 1st
    15 Files
  • 2
    Aug 2nd
    22 Files
  • 3
    Aug 3rd
    0 Files
  • 4
    Aug 4th
    0 Files
  • 5
    Aug 5th
    15 Files
  • 6
    Aug 6th
    11 Files
  • 7
    Aug 7th
    43 Files
  • 8
    Aug 8th
    42 Files
  • 9
    Aug 9th
    36 Files
  • 10
    Aug 10th
    0 Files
  • 11
    Aug 11th
    0 Files
  • 12
    Aug 12th
    27 Files
  • 13
    Aug 13th
    0 Files
  • 14
    Aug 14th
    0 Files
  • 15
    Aug 15th
    0 Files
  • 16
    Aug 16th
    0 Files
  • 17
    Aug 17th
    0 Files
  • 18
    Aug 18th
    0 Files
  • 19
    Aug 19th
    0 Files
  • 20
    Aug 20th
    0 Files
  • 21
    Aug 21st
    0 Files
  • 22
    Aug 22nd
    0 Files
  • 23
    Aug 23rd
    0 Files
  • 24
    Aug 24th
    0 Files
  • 25
    Aug 25th
    0 Files
  • 26
    Aug 26th
    0 Files
  • 27
    Aug 27th
    0 Files
  • 28
    Aug 28th
    0 Files
  • 29
    Aug 29th
    0 Files
  • 30
    Aug 30th
    0 Files
  • 31
    Aug 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close