SRL Archive - C/C++ Help and Tutorials

Mutating executable


Yakman

2010-04-20 15:18:07

this is an executable which modified itself.

It has an encrypted block and the key.
When its run, it decrypts the block with the key. Then it randomly generates a new key, encrypts the block with this new key and edits the executable file to contain the new block and key.

It also prints out the key, newkey and decrypted block. If you run it multiple times, you should notice the newkey of the first run is equal to the key of the second run.


Here is the code of the main file, but you need other files to compile it too, all attached to this post along with a win32 executable if you want to try it without much effort.


#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>

#ifdef __WIN32__
#include <windows.h>
#else
#include <unistd.h>
#endif

#ifndef min
#define min(x, y) (x < y ? x : y)
#endif


#include "isaac.h"

//0x643d98ad + 0xbe5e42cc + 0x6bc5d1a2 + 0x1d6c2f9f = 0xabcddcba
//0x9dbbc374 + 0x52bfdfaf + 0xe1596189 + 0xb5903e75 = 0x87654321

char resource_block[] =
"\xad\x98\x3d\x64\xcc\x42\x5e\xbe\xa2\xd1\xc5\x6b\x9f\x2f\x6c\x1d"

"\x3f\xb7\xde\x28\x58\xe0\x38\x04\xce\x07\x8a\x5f\xe4\x84\xb1\x85"
"\x23\x12\x49\xc3\xea\xf7\xfc\x2c\xef\x24\x19\x6b\x2b\xc7\x02\x77"
"\x05\xdb\x89\xe8\xd2\x72\xd4\xf0\x74\x90\x1e\x4a\x27\xaf\x9d\x08"
"\x20\x98\xf9\x9e\x1a\x95\xe7\xac\xa6\xdb\x04\x5c\xef\xb0\x0e\xbc"
"\x50\xfe\x3a\x98\xaf\x5a\x8a\x4e\x51\x7a\x98\xf4\xe2\x60\x2b\xf0"
"\x19\x86\x06\x76\x5e\x8c\xc6\x1f\x95\x9f\x53\xfb\x5e\x48\x3f\x8d"
"\xef\x2e\xbd\x9a\x18\x47\xc6\x3f\x2a\x5d\x01\x57\xce\xbf\x3a\x97"
"\xc2\x3d\x42\xed\xee\x98\xb1\x3b\xfd\xf8\x12\xa8\xdb\xb1\xc2\x0a"
"\x41\x5d\xca\x50\xcb\xb3\x93\xa5\x3d\xb0\x27\x46\xcf\x28\x38\xbd"
"\xfc\x47\xb1\x08\x29\x7b\x61\xd6\x47\xa6\x1c\x7b\x8f\x2e\xaa\x7b"
"\x1a\x2a\x06\xc2\xae\x04\x86\xbe\xb6\x03\xb5\xe4\xaa\x77\x6a\x70"
"\x8a\x85\x94\x0a\x27\xcd\x72\xa6\x6a\x15\x75\xae\x9c\x12\x39\xea"
"\xd3\x43\x6f\x86\x9d\x40\xea\x77\xe4\xfa\x47\xcc\x3d\x0b\x17\x76"
"\xed\x7f\x51\x87\xb2\x05\xd0\xbe\x78\xeb\x3a\x13\xc1\x24\xf1\xf5"
"\x18\xf7\xac\xee\x35\x94\xc7\xd3\x9a\xa0\x73\xd7\xc7\x3a\x48\x48"
"\xab\xd6\xc6\x7a\xa6\xa3\xc4\xf7\xdc\x52\x96\x87\x69\xb0\xf4\x86"
"\x6c\xc9\x71\x8e\x4a\x1a\x49\x69\xec\x4f\xd3\xa2\x86\x5e\x5c\xcf"
"\x69\x50\x87\xaf\x13\xb0\xd9\xc3\x02\xd0\x31\x0e\x6c\xe7\xb4\x23"
"\x62\xbe\xf4\x02\xc6\x87\x2c\xd3\xca\xde\x0a\x32\x4f\xc7\xd2\x64"
"\x7d\x4f\x96\x07\x2d\x4f\x8c\xf3\xcc\xb5\xb9\xfe\xad\xf7\xb7\x04"
"\x4a\x41\xe9\xdc\xe0\x02\x55\x82\xb2\x16\x5b\x00\xc7\x65\x5b\x8b"
"\xf1\x1d\x35\x6c\x3c\x7b\x35\xe6\x36\xc4\x30\xf7\x31\xb7\x25\x98"
"\x8e\x2b\x02\x77\x52\x86\x53\xb3\xe9\xd2\x57\x70\x48\x53\x92\xeb"
"\x8f\x85\x86\x8a\xdf\x18\x0e\x6b\x86\x51\x04\x39\x0c\x4a\xe7\xd3"
"\x68\xb2\xc3\x31\xbb\xbd\xd5\x35\x5b\x73\x60\xce\x73\xb6\x17\x63"
"\xa6\x84\x98\x94\x4f\x0e\x14\x43\x02\x84\xdf\x92\x15\x0e\x7c\x6a"
"\x96\x72\x59\x33\xc5\xf7\x00\x97\x9c\x0f\x44\x06\x17\xad\x11\xab"
"\xab\x84\x50\x1d\x8a\x30\xfd\x97\xe4\x68\x9d\x8b\x3f\x1d\x60\xef"
"\xcd\xd9\xe9\x7b\xfc\xb1\x90\xce\x05\xe7\x50\x06\x79\x14\x1e\x56"
"\x49\x10\x87\xe4\x71\xec\xb7\x58\xe4\x19\x73\x4d\x66\x77\x17\x4f"
"\x69\x1a\xe8\x13\xea\x9f\x4e\xc1\x54\x82\x11\xff\x00\x84\x7d\x49"
"\x41\x5d\x58\xa1\x16\x91\x60\x9c\xb7\x5f\x0e\x6f\x4f\x16\x2c\x1b"
"\x3c\xec\x65\x74\xd6\x68\x73\x1f\xd6\xf0\xd2\x3e\x82\xba\x12\x4d"
"\xc1\xfe\x25\x7c\xbf\x8a\xda\xcf\xfe\x4b\x35\x99\xc0\xf0\x4f\x32"
"\x85\x0c\x2b\x27\x3a\x09\x6a\x43\x20\xeb\x31\xed\xad\xd7\xd0\xe4"
"\x18\xff\x5b\x49\x7b\xca\xa1\x0e\x2d\x6b\x23\x89\x28\x7a\xe5\xd5"
"\xb9\x8a\xea\x87\xab\xf2\x11\x18\xd7\x2e\x66\x29\x07\x21\x75\x93"
"\x53\x36\xb4\x56\xb4\x4c\xc1\x0d\xff\xc7\x5e\x4d\xb5\x81\xb1\xa0"
"\xdf\x89\x4b\xb8\xfe\x6e\x1c\x68\x44\x73\x55\x20\x88\xae\x33\x84"
"\x77\x95\x37\x58\xab\x8c\x4e\x79\xee\x74\x28\xf9\x56\xe0\x17\x88"
"\x81\xec\x33\x48\x50\xa7\xf3\x63\xb4\x71\xf5\xf0\x0e\x43\x9c\x12"
"\x98\xca\xdd\x57\x51\xf4\x66\x92\x40\x5c\x8c\xeb\x4e\x77\x99\x60"
"\x01\xb3\xe9\x49\x5e\x2f\x82\x59\x5c\x36\xbd\x1c\x79\x23\xbf\x67"
"\xdb\xdb\x86\x95\xc7\x1b\x1b\x72\x5e\xfc\x95\xf8\xa7\x44\xc4\x8e"
"\x18\x56\x84\x4b\xef\xe0\xc8\x51\xad\xdc\x36\xb8\xed\xfa\xc1\x77"
"\x33\x60\x73\x4b\x99\x8b\x0f\x73\x08\xb1\x66\x1f\x71\xa8\x7b\xeb"
"\xca\xf8\x40\x4c\x06\xce\xf9\xad\xaf\x11\xa0\x67\x95\x1d\x26\x99"
"\xfa\x41\xf3\x7e\xff\x66\x9f\x12\xe5\x2b\xf3\xe0\x60\xd0\xf7\x73"
"\x35\x80\xf7\x77\x5d\x25\x7d\x25\xb4\x87\x2e\x46\xe3\x01\x78\x79"
"\xf2\x56\x62\x8c\x18\x9c\x48\xcc\x39\x7c\xe0\x7a\xa8\xe3\xb7\x3a"
"\x9e\x87\xdb\x36\xb9\xcf\xc1\x10\xec\x37\xf6\x4e\xd3\xd1\x03\x85"
"\x7c\xd7\xb9\xa4\x27\x11\x00\x2d\x96\x4b\x63\xa7\xea\x7d\xe3\x77"
"\x60\x59\x86\x53\x95\x5d\x42\x11\x0b\xde\xf6\x5c\x4a\xea\xa4\x34"
"\x41\x52\xea\xe3\xab\x16\x22\x0d\xfd\x8f\x3f\xc7\xcb\xb3\x6a\xd5"
"\x09\x1f\xb8\x91\x2e\x0c\xab\x92\x4f\xc2\xbe\x59\x85\x7d\x0e\x42"
"\xf3\xa9\xc8\x1c\xfa\xc9\x87\xad\xd5\x78\xc8\x05\x13\xcb\x4d\xa7"
"\x3e\x87\x38\xce\x3d\xf2\x7c\x65\xf7\xac\xbe\x23\x48\x15\x54\xb7"
"\xd6\x28\x69\x9c\x98\x03\x14\xb9\x9b\xd5\x49\xee\x97\x44\x35\x6b"
"\xb5\xf2\x66\xf9\x81\xb0\xa5\x05\x87\x43\xa9\x42\x51\x8f\x1f\xd6"
"\xb0\xe3\xad\x05\x63\xd0\xef\xe6\xcd\x31\xba\xba\x99\x90\xe1\x85"
"\xe7\x9c\x5e\x4c\x3d\x3b\x64\xe2\x66\x69\xa3\x4c\x46\x7e\x94\x41"
"\x43\x93\xbb\x13\xe4\xea\x17\x44\xd0\x05\x5b\x07\x2c\xeb\x7e\x3b"
"\x59\x5c\x30\x7b\xc1\x2e\x68\xe6\x60\xad\xba\x22\x41\xa3\x91\x10"
"\x91\x9d\xcc\x6d\x4c\x81\xda\x14\x5c\xc7\x51\x2d\x7a\xf3\xd8\x05"
"\x01\xd9\x15\xac\xf4\x20\x70\x19\xcd\x3e\xf1\x43\x8c\x1b\x77\x9a"
"\x2a\xc2\xbf\xe8\xcf\x65\x40\xe8\xd7\x47\x05\x0d\x5d\x67\x79\x21"
"\x0f\x7a\xa8\x15\x5d\xdb\xf7\xa2\xbe\x01\xf4\x85\x63\x14\x8a\x84"
"\xea\xc9\x63\x09\x20\xc1\x2e\x99\xdd\x1b\x39\xec\xea\x1c\x5f\xae"
"\x3d\x1f\xb8\xec\xa7\x0c\x26\x7a\x5e\x4c\x02\x5c\x63\x9d\x79\xe0"
"\x25\xf4\x2f\x3a\x2c\x31\x6f\x16\x5a\xa4\x72\x25\x89\x34\x2b\x0e"
"\xad\xff\x2c\xd0\x47\x72\x3a\x83\x55\x13\x00\xde\x7b\x86\x48\x81"
"\xe7\xee\x66\x51\x09\x5f\xaf\x02\xec\x53\x35\xcb\x04\xc1\xd8\xfc"
"\xd1\xa3\xc9\xde\x14\x60\xa9\x1b\x9a\x8d\x8c\x18\x2f\x98\xb6\x7c"
"\x05\x21\x66\x4e\x30\xcc\x61\xd0\x40\x46\xf1\x05\x95\x7e\xe3\x25"
"\xd9\x47\xe1\x99\x97\xc0\x5c\x2e\x74\x73\x22\xdc\x49\xa5\x37\x98"
"\x14\x36\x5a\x12\xdf\x0d\x52\x5c\x0d\xc6\x7a\x16\x26\x0e\xc0\x02"
"\x9a\x92\xe0\x05\x4c\x09\xce\x35\xf0\xae\xdc\xe2\x56\xc2\x2b\xfc"
"\x9a\xfa\x59\xc7\x59\xd4\x08\x04\xf1\xfb\xa0\x6b\xcd\xdc\xe8\xbc"
"\x0b\x9e";


char key_block[] =
"\x74\xc3\xbb\x9d\xaf\xdf\xbf\x52\x89\x61\x59\xe1\x75\x3e\x90\xb5"

"\x36\x2a\x0d\x5d\x96\x9b\xfb\xd4\xeb\xf5\x16\xf0\xb2\xb0\x80\xbb";

char* find_id_sequence(char* buf, int len, int target) {

int k;
for(k = 0; k < len - 4*sizeof(int); k++)
if( *(int*)(buf + k) + *(int*)(buf + k + sizeof(int)) +
*(int*)(buf + k + 2*sizeof(int)) + *(int*)(buf + k + 3*sizeof(int))
== target)
break;
if(k == len - 4*sizeof(int))
return NULL;
return buf + k + 4*sizeof(int);
}

bool read_file(char* name, char** buf, int* len) {
FILE* message_fd = fopen(name, "rb");
if(!message_fd) {
perror("fopen()");
return false;
}
fseek(message_fd, 0, SEEK_END);
*len = ftell(message_fd);
fseek(message_fd, 0, SEEK_SET);

*buf = malloc(*len);
fread(*buf, 1, *len, message_fd);
fclose(message_fd);

return true;
}

void isaac_apply(isaacctx* ctx, bool add, void* buf, unsigned int len) {
unsigned int l = len;
int p = 0; //buffer pointer
char* buffer = buf;
int op = -1;
if(add)
op = 1;

while(l > 0) {
if(!ctx->randcnt) {
isaac(ctx);
ctx->randcnt = RANDSIZ;
}

int el = min(l, ctx->randcnt); //effective length
l -= el;
int f;
for(f = 0; f < el; f++) {
buffer[p++] += op*ctx->randrsl[RANDSIZ - ctx->randcnt]; //implicit AND 0xff
ctx->randcnt--;
}
}
}

void fprintc(char* p, FILE* fd, unsigned char* buf, int size) {
if(p)
fprintf(fd, p);

fprintf(fd, "\n\t\"");
int f;
for(f = 0; f < size; f++) {
fprintf(fd, "\\x%02x", buf[f]);
if((f+1) % 16 == 0)
fprintf(fd, "\"\n\t\"");
}
fprintf(fd, "\"\n\n");
}

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


//uncomment this bit if you want to generate another ciphertext
/*
char text[] =
"";
printf("--- cleartext ---\n%s--- end clear ---\n\n", text);

//generate and output the key
isaacctx randctx;
memset(&randctx, 0, sizeof(randctx));
randctx.randrsl[0] = time(NULL);
randinit(&randctx);

unsigned char kkey[16];
memcpy(kkey, randctx.randrsl, 16);

printf("key =\n\"");
int z;
for(z = 0; z < sizeof(kkey); z++)
printf("\\x%02x", kkey[z]);
printf("\"\n");

//encrypt and output text
isaacctx encrypt_ctx;
memset(&encrypt_ctx, 0, sizeof(encrypt_ctx));
memcpy(encrypt_ctx.randrsl, kkey, sizeof(kkey));
randinit(&encrypt_ctx);

char ciphertext[sizeof(text)];
memcpy(ciphertext, text, sizeof(text));
isaac_apply(&encrypt_ctx, true, ciphertext, sizeof(text)-1);
fprintc("resource =", stdout, ciphertext, sizeof(text)-1);

return EXIT_SUCCESS;
*/


//print out resource

char* resource = resource_block + 16; //skip id seq
char* key = key_block + 16;
unsigned int resource_len = sizeof(resource_block) - 17;
unsigned int key_len = sizeof(key_block) - 17;

isaacctx crypt_ctx;
memset(&crypt_ctx, 0, sizeof(crypt_ctx));
memcpy(crypt_ctx.randrsl, key, key_len);
randinit(&crypt_ctx);

char* cleartext = malloc(resource_len + 1);
cleartext[resource_len] = 0;
memcpy(cleartext, resource, resource_len);

isaac_apply(&crypt_ctx, false, cleartext, resource_len);
printf("--- cleartext ---\n%s--- end clear ---\n\n", cleartext);

printf(" key = ");
int q;
for(q = 0; q < key_len; q++)
printf("%02x ", key[q] & 0xff);
printf("\n");

/* load exe file and edit it */
char exepath[FILENAME_MAX+1];
#ifdef __WIN32__
GetModuleFileName(NULL, exepath, sizeof(exepath)-1);
#else
readlink("/proc/self/exe", exepath, sizeof(exepath)-1); //almost all linuxes have /proc/self/
#endif

int len;
char* buf;
if(!read_file(exepath, &buf, &len))
return printf("fopen(): %s\n", strerror(errno));

/* generate new key, identifier sequences and ciphertext */
isaacctx rndctx;
memset(&rndctx, 0, sizeof(rndctx));
rndctx.randrsl[0] = time(NULL);
randinit(&rndctx);

//0xabcddcba resource
int r_field[4];
memset(r_field, 0, sizeof(r_field));
memcpy(r_field, rndctx.randrsl, 12); //3 ints
r_field[3] = 0xabcddcba - r_field[0] - r_field[1] - r_field[2];
printf("res_id = 0x%08x + 0x%08x + 0x%08x + 0x%08x = 0x%08x\n",
r_field[0], r_field[1], r_field[2], r_field[3], r_field[0]+r_field[1]+r_field[2]+r_field[3]);

//0x87654321 key
int k_field[4];
memset(k_field, 0, sizeof(k_field));
memcpy(k_field, rndctx.randrsl + 12, 12); //3 ints
k_field[3] = 0x87654321 - k_field[0] - k_field[1] - k_field[2];
printf("key_id = 0x%08x + 0x%08x + 0x%08x + 0x%08x = 0x%08x\n",
k_field[0], k_field[1], k_field[2], k_field[3], k_field[0]+k_field[1]+k_field[2]+k_field[3]);


/* find resource and key location in exe file buffer */
char* bufresource = find_id_sequence(buf, len, 0xabcddcba);
char* bufkey = find_id_sequence(buf, len, 0x87654321);
if(!bufresource || !bufkey)
return printf("no bufresource or bufkey\n");

memcpy(bufkey, rndctx.randrsl + 24, 16);

printf("newkey = ");
for(q = 0; q < key_len; q++)
printf("%02x ", bufkey[q] & 0xff);
printf("\n");

/* encrypt with new key */
memset(&crypt_ctx, 0, sizeof(crypt_ctx));
memcpy(crypt_ctx.randrsl, bufkey, key_len);
randinit(&crypt_ctx);
isaac_apply(&crypt_ctx, true, cleartext, resource_len);

memcpy(bufresource, cleartext, resource_len);


#ifdef __WIN32__
/* rename this exe and output file in its place */
char renamedexepath[FILENAME_MAX+1];
strcpy(renamedexepath, exepath);
strcat(renamedexepath, ".txt");
DeleteFile(renamedexepath); //could use remove() and rename() here
MoveFile(exepath, renamedexepath);
#else
remove(exepath); //on linux you gotta delete then write
#endif

FILE* fd = fopen(exepath, "wb");
if(!fd)
return printf("fopen(): %s\n", strerror(errno));
fwrite(buf, 1, len, fd);
fclose(fd);

#ifdef __WIN32__
system("pause");
#endif

return EXIT_SUCCESS;
}

Frement

2010-04-20 15:20:18

Wow, and i thought i knew C++ :D

senrath

2010-04-20 15:21:01

Pretty neat. Although I'm not sure if the ASCII art was necessary.

Diddy Kong

2010-04-20 23:16:02

This should not be allowed.

Smartzkid

2010-04-20 23:18:03

From: Diddy Kong
This should not be allowed.


What?

Sex

2010-04-20 23:28:15

The Goatse.

Nava2

2010-04-21 08:30:34

Cool concept! :)

trecool999

2010-04-23 15:51:08

Dude… wut…?

Bionicle

2010-04-23 15:52:23

From: Diddy Kong
This should not be allowed.


..why?

Nava2

2010-04-23 17:34:06

the goatse was not necessary, man.

Yakman

2010-04-24 18:38:58

Given that the ASCII art is of such poor quality, I do think you are slightly overreacting.

The meaning is only obvious if you've already seen the real photograph version, or to paraphrase. It takes one to know one. ;)

itSchRis917

2010-04-27 15:11:41

Hahaha i opened it in class.. Thanks for that. Still found it funny. Great work. This is very cool!

Here

2010-05-12 17:40:45

People really interested in self-mutating code can go to vx.netlux and check out the poly/metamorph engines. Most are in asm, some are in VB - they are mostly written for batch scripts and really old computers. Some modern C++ Win32 jewels can be found though.

I know poly/metamorphing is not an anti-ban protection in RS, but it is in many other applications.

Just if you're interested.

EDIT: OP's program is still a nice simple one, though. Filling blocks of NOPs with junk code using rand() is another way to make very simple self-modifying code. And the goatse was NOT obligatory.

fronty

2010-05-13 04:05:59

With operating system which has good security this isn't possible.

Here

2010-06-01 14:32:09

From: fronty
With operating system which has good security this isn't possible.


Eh? What isn't possible? If you can read/write memory and files, polymorphing/metamorphing can be done in ring3, which OSes don't care about (such as PatchGuard). There are also semi-legitimate uses for morphing code sections, although AVs might scream.

ShowerThoughts

2010-06-01 16:59:35

From: Here
Eh? What isn't possible? If you can read/write memory and files, polymorphing/metamorphing can be done in ring3, which OSes don't care about (such as PatchGuard). There are also semi-legitimate uses for morphing code sections, although AVs might scream.


He was talking about the AVs.

fronty

2010-06-01 19:36:57

Sorry, I didn't look at this very well. I thought it was some type of self-modifying code which fails to data execution prevention if you don't play around with fancy file mappings. Still not very fancy, I think.

I don't know about any ring3 or PatchGuard, PC architecture isn't my cup of tea.

R0b0t1

2010-06-05 05:48:20

The file mapping aren't necessarily fancy, and most operating systems do not restrict you in marking pages as executable.

fronty

2010-06-06 10:37:45

mmaping is easy (manual 185 pages on my system) and using it to bypass W^X doesn't add many lines. Didn't quite get your another point.

R0b0t1

2010-06-09 19:29:53

The "execution prevention" having to do with the mappings was what I meant. On Linux, the memory needs to be aligned on a page boundary (with posix_memalign()), and then you call mprotect(). Not sure about Windows, but I think it is even simpler/you don't need to do anything.