Copy Link
Add to Bookmark
Report
29A Issue 03 03 06
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[1.c]ÄÄ
// Advanced ZCME
// Permutating Engine Research
// Copyright (C) 1997, 1998 Z0MBiE/29A
//
// *** NOT FOR [RE]PUBLISHING/DISASM IN VX-ZINES, EXCEPT 29A ***
// Internal version: 0.04
// Last modified: 18-07-98
#include "params.h"
char ZERO_FILL_ARRAY[max_size-0x1300] = {0};
#include "system.h"
#include "crt.h"
#include "fileio.h"
#include "random.h"
#include "disasm.h"
#include "engine.h"
void main(void)
{
pchar p;
#ifdef SKIP_PRINTF
asm
__1: lea di, printf
mov al, 0xC3
stosb
lea di, __1
mov cx, __2 - __1
mov al, 0x90
rep stosb
end;
#endif
clrscr(3);
asm
__2:end;
printf("Startup code executed\n");
run_engine();
printf("Terminating\n");
exit(0);
}
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[1.c]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[params.h]ÄÄ
/* DEBUG parameters */
#define SKIP_PRINTF
#define SKIP_DEBUGFILES
/* ENGINE parameters */
#define SKIP_JMPS
//#define SKIP_JMPS_BUT_ADD_NOPS
#define RANDOM_JCC
//#define INVERSE_JCC
#define SKIP_NOP
//#define SKIP_INT3
#define SKIP_RANDOM
#define ADD_RANDOM 30
#define CHANGE_CMD
//#define FILL_UNUSED_CC
#define FILL_UNUSED_RANDOM
#define USE_RANDOM_IP 20
#define min_left 20
#define min_right 40
#define min_right_left 20
#define KILL_J2J
#define MAKE_SHORT_JMPS
#define max_size 0x3000+0x0100
#define max_cmd 3000
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[params.h]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[system.h]ÄÄ
#define make_ptr( seg,ofs ) ( (void _seg * )( seg ) +( void near * )( ofs ))
#define ptr_seg( fp ) ( (unsigned )( void _seg * )( void far * )( fp ))
#define ptr_ofs( fp ) ( (unsigned )( fp ))
typedef unsigned char byte;
typedef unsigned int word;
typedef unsigned long dword;
#define short signed char
#define pchar const far char *
#define MAX(a,b) a > b ? a : b
#define MIN(a,b) a < b ? a : b
#define asm asm {
#define end }
void exit(byte exitcode);
void fillchar(pchar buf, word bufsize, char filler);
void move(pchar src, pchar dest, word size);
word len(pchar str);
void beep(void)
{
asm
mov al, 7
int 29h
end;
}
void exit(byte exitcode)
{
asm
mov al, exitcode
add al, '0'
int 29h
mov ah, 4Ch
mov al, exitcode
int 21h
end;
}
void fillchar(pchar buf, word bufsize, char filler)
{
asm
mov cx, bufsize
or cx, cx
jz __1
les di, buf
mov al, filler
cld
rep stosb
__1:
end;
}
void move(pchar src, pchar dest, word size)
{
asm
mov cx, size
or cx, cx
jz __1
push ds
lds si, src
les di, dest
cld
rep movsb
pop ds
__1:
end;
}
word len(pchar str)
{
asm
les di, str
mov cx, 0ffffh
xor al, al
repnz scasb
neg cx
dec cx
dec cx
xchg cx, ax
end;
}
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[system.h]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[crt.h]ÄÄ
void clrscr(byte mode);
void pascal printf_char(char c);
void pascal printf_dword(dword d);
void printf_word(word w);
void printf_byte(byte b);
void pascal printf_long(long l);
void printf_int(int i);
void printf_short(short s);
void pascal printf_hexchar(byte b);
void pascal printf_hexbyte(byte b);
void pascal printf_hexword(word w);
void pascal printf_hexdword(dword d);
void pascal printf_crlf(void);
void printf(pchar format, ...);
void clrscr(byte mode)
{
asm
xor ax, ax
mov al, mode
int 10h
end;
}
void pascal printf_char(char c)
{
asm
mov ah, 2
mov dl, c
int 21h
end;
}
void pascal printf_crlf(void)
{
printf_char(13);
printf_char(10);
}
void pascal printf_dword(dword d)
{
asm
mov eax, d
call __1
jmp __3
__1: xor edx, edx
mov ebx, 10
div ebx
push dx
or eax, eax
jz __2
call __1
__2: pop ax
add al, '0'
push ax
call printf_char
ret
__3:
end;
}
void printf_word(word w)
{
printf_dword(w);
}
void printf_byte(byte b)
{
printf_dword(b);
}
void pascal printf_long(long l)
{
if (l < 0)
{
printf_char('-');
l = -l;
}
printf_dword(l);
}
void printf_int(int i)
{
printf_long(i);
}
void printf_short(short s)
{
printf_long(s);
}
void pascal printf_hexchar(byte b)
{
if (b <= 9)
printf_char('0'+b);
else
printf_char('A'+b-10);
}
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 printf(pchar format, ...)
{
int stack_ptr = 0;
asm
push ds
lds si, format
cld
__nextchar:
lodsb
or al, al
jz __exit
cmp al, '%'
je __percent
cmp al, 10
je __crlf
__putchar:
push ax
call printf_char
jmp __nextchar
__crlf: call printf_crlf
jmp __nextchar
__percent:
lodsb
or al, al
jz __exit
cmp al, 'c'
je __c
cmp al, 'i'
je __i
cmp al, 'l'
je __l
cmp al, 'b'
je __b
cmp al, 'w'
je __w
cmp al, 'd'
je __d
cmp al, 'B'
je __B_
cmp al, 'W'
je __W_
cmp al, 'D'
je __D_
jmp __putchar
__pop_ax:
mov di, stack_ptr
add word ptr stack_ptr, 2
mov ax, [bp+8+di]
ret
__pop_eax:
mov di, stack_ptr
add word ptr stack_ptr, 4
mov eax, [bp+8+di]
ret
__c: call __pop_ax
push ax
call printf_char
jmp __nextchar
__s: call __pop_ax
push ax
call printf_short
jmp __nextchar
__i: call __pop_ax
push ax
call printf_int
jmp __nextchar
__l: call __pop_eax
push eax
call printf_long
jmp __nextchar
__b: call __pop_ax
push ax
call printf_byte
jmp __nextchar
__w: call __pop_ax
push ax
call printf_word
jmp __nextchar
__d: call __pop_eax
push eax
call printf_dword
jmp __nextchar
__B_: call __pop_ax
push ax
call printf_hexbyte
jmp __nextchar
__W_: call __pop_ax
push ax
call printf_hexword
jmp __nextchar
__D_: call __pop_eax
push eax
call printf_hexdword
jmp __nextchar
__exit:
pop ds
end;
}
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[crt.h]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fileio.h]ÄÄ
#define handle word
handle openfile(pchar fname);
handle createfile(pchar fname);
void closefile(handle h);
word readfile(handle h, pchar buf, word bufsize);
word writefile(handle h, pchar buf, word bufsize);
dword filepos(handle h);
dword seekfile(handle h, dword newpos);
dword seekeof(handle h);
dword filesize(handle h);
handle openfile(pchar fname)
{
asm
push ds
mov ax, 3d02h
lds dx, fname
int 21h
pop ds
end;
}
handle createfile(pchar fname)
{
asm
push ds
mov ah, 3Ch
xor cx, cx
lds dx, fname
int 21h
pop ds
end;
}
void closefile(handle h)
{
asm
mov ah, 3Eh
mov bx, h
int 21h
end;
}
word readfile(handle h, pchar buf, word bufsize)
{
asm
push ds
mov ah, 3Fh
mov bx, h
mov cx, bufsize
lds dx, buf
int 21h
pop ds
end;
}
word writefile(handle h, pchar buf, word bufsize)
{
asm
push ds
mov ah, 40h
mov bx, h
mov cx, bufsize
lds dx, buf
int 21h
pop ds
end;
}
dword filepos(handle h)
{
asm
mov ax, 4201h
mov bx, h
int 21h
end;
}
dword seekfile(handle h, dword newpos)
{
asm
mov ax, 4200h
mov bx, h
mov cx, word ptr newpos + 2
mov dx, word ptr newpos + 0
int 21h
end;
}
dword seekeof(handle h)
{
asm
mov ax, 4202h
mov bx, h
xor cx, cx
cwd
int 21h
end;
}
dword filesize(handle h)
{
dword savepos, retvalue;
savepos = filepos(h);
retvalue = seekeof(h);
seekfile(h, savepos);
return(retvalue);
}
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fileio.h]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[random.h]ÄÄ
int rndword;
word random_word(void);
word rnd_word(word range);
word rnd_word_minmax(word min, word max);
word random_word(void)
{
asm
mov bx, rndword
in al, 40h
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;
}
word rnd_word(word range)
{
if (range == 0)
return(0);
else
return(random_word() % range);
}
word rnd_word_minmax(word min, word max)
{
return(rnd_word(max-min+1) + min);
}
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[random.h]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[disasm.h]ÄÄ
#define cf_is66 0x0001
#define cf_is67 0x0002
#define cf_isSEG 0x0004
#define cf_isREP 0x0008
#define cf_isLOCK 0x0010
#define cf_is0F 0x0020
#define cf_isMODRM 0x0040
#define cf_isSIB 0x0080
#define cf_isMEM 0x0100
#define cf_isDATA 0x0200
#define cf_isDATAREL 0x0400
#define ct_UNKNOWN 0
#define ct_JMP 1
#define ct_JCC 2
#define ct_CALL 3
#define ct_RET 4
typedef union datauion
{
word w[3];
byte b[6];
} dataunion;
typedef struct tcmdrec
{
word flags; // cf_xxxx
word type; // ct_xxxx
word size; // total cmd. size
word base; // instruction offset (16-bit)
byte px_SEG; // prefix: segment prefix
byte px_REP; // prefix: repz/repnz
byte opcode;
byte modrm;
byte mod;
byte reg;
byte rm;
byte sib;
word memsize;
byte mem[4];
word datasize;
dataunion data;
word jmpptr; // jmp/call ABSOLUTE pointer (+base), 16-bit
} tcmdrec;
void dump(pchar cmd, word size)
{
printf("%W ",(word) cmd);
for (; size>0; size--, cmd++)
printf(" %B", (byte) (*cmd));
printf("\n");
}
#define getbyte(x) { x = (byte) (*cmd_ptr++); };
#define getword(x) { x = (word) (*cmd_ptr+=1); };
#define getdword(x) { x = (dword) (*cmd_ptr+=2); };
#define getnextbyte(x) { x = ((byte) (*cmd_ptr)); }
tcmdrec r;
pchar cmd_ptr;
word disasm_base;
void modrm_proc(void)
{
getbyte(r.modrm);
r.mod = r.modrm >> 6;
r.reg = (r.modrm >> 3) & 7;
r.rm = r.modrm & 7;
if ((r.flags & cf_is67) == 0)
{
// 16-bit MODR/M
if (((r.mod == 0) && (r.rm == 6)) || (r.mod == 2)) r.memsize = 2;
if (r.mod == 1) r.memsize = 1;
}
else
{
// 32-bit MODR/M
if (((r.mod == 0) && (r.rm == 5)) || (r.mod == 2)) r.memsize = 4;
if (r.mod == 1) r.memsize = 1;
if (r.rm == 4)
{
r.flags |= cf_isSIB;
getbyte(r.sib);
};
};
}
void disasm(pchar cmd, tcmdrec far *rec)
{
byte b,nextbyte;
int i;
fillchar(&r, sizeof(tcmdrec), 0x00);
r.base = (word) cmd;
r.jmpptr = -1;
cmd += disasm_base;
cmd_ptr = cmd;
// begin disasm
prefix:
getbyte(b);
if ((b==0x2E) ||
(b==0x26) ||
(b==0x3E) ||
(b==0x36) ||
(b==0x64) ||
(b==0x65))
{
r.flags |= cf_isSEG;
r.px_SEG = b;
goto prefix;
}
if ((b==0xF2) ||
(b==0xF3))
{
r.flags |= cf_isREP;
r.px_REP = b;
goto prefix;
}
switch(b)
{
case 0x66: r.flags |= cf_is66;
goto prefix;
case 0x67: r.flags |= cf_is67;
goto prefix;
case 0xF0: r.flags |= cf_isLOCK;
goto prefix;
};
// prefix analyzed
r.opcode = b;
if (b == 0x0F) goto prefix_0F;
getnextbyte(nextbyte);
if (b == 0xE9)
{
r.type = ct_JMP;
goto data_offs_rel;
}
if (b == 0xE8)
{
r.type = ct_CALL;
goto data_offs_rel;
}
if ((b & 0xF0) == 0x70)
{
r.type = ct_JCC;
goto data_byte_rel;
}
if (b == 0xEB)
{
r.type = ct_JMP;
goto data_byte_rel;
}
if ((b == 0xC3) || (b == 0xCF))
{
r.type = ct_RET;
goto okey;
}
if (b == 0xC2)
{
r.type = ct_RET;
goto data_word;
}
if (b == 0xC8)
goto data_3xbyte;
if (
(b == 0xC9) ||
(b == 0xFC) ||
(b == 0xAA) ||
(b == 0xA4) ||
(b == 0xAE) ||
(b == 0x98) ||
(b == 0x99) ||
(b == 0xAC) ||
(b == 0xCC) // int 3
)
goto okey;
if ((b & 0xFC) == 0x88)
goto modrm;
if ((b & 0xFE) == 0xC6)
goto modrm_data_w_66;
if ((b & 0xF0) == 0xB0)
goto data_w3_66;
if ((b & 0xFC) == 0xA0)
goto data_offs;
if (
(b == 0xCD) ||
(b == 0xE4)
)
goto data_byte;
if ((b & 0xF0) == 0x50)
goto okey;
if ((b == 0xFF) &&
(
(((nextbyte >> 3) & 7) == 0) || (((nextbyte >> 3) & 7) == 6)
))
goto modrm;
if ((b & 0xFE) == 0xC4) // gluk !
goto modrm;
if ((b & 0xE6) == 0x06)
goto okey;
if ((b & 0xC4) == 0x00)
goto modrm;
if ((b & 0xFC) == 0x80)
goto modrm_data_sw_66;
if ((b & 0xC6) == 0x04)
goto data_w_66;
if ( ((b & 0xFE) == 0xF6) && (((nextbyte >> 3) & 6) == 2) )
goto modrm;
if ((b & 0xF0) == 0x40)
goto okey;
if ( ((b & 0xFE) == 0xFE) && (((nextbyte >> 3) & 6) == 0) )
goto modrm;
if ((b & 0xF8) == 0x90)
goto okey;
if (b == 0x6A)
goto data_byte;
if (b == 0x68)
goto data_66;
if ( ((b & 0xFE) == 0xF6) && (((nextbyte >> 3) & 6) == 6) )
goto modrm;
if ((b & 0xFC) == 0xD0)
goto modrm;
if ((b & 0xFE) == 0xC0)
goto modrm_data_byte;
if ((b & 0xFE) == 0x84)
goto modrm;
if ( ((b & 0xF6) == 0xF6) && (((nextbyte >> 3) & 7) == 0) )
goto modrm_data_w_66;
if ((b & 0xFE) == 0xA8)
goto data_w_66;
if ((b & 0xFD) == 0x8C)
goto modrm;
if (b == 0x8D)
goto modrm;
if ( ((b & 0xFE) == 0xF6) && (((nextbyte >> 3) & 7) == 4) )
goto modrm;
if ((b & 0xFE) == 0x86)
goto modrm;
error:
dump(cmd, 10);
printf("<- unknown command\n");
exit(1);
prefix_0F:
r.flags |= cf_is0F;
getbyte(b);
r.opcode = b;
getnextbyte(nextbyte);
if ((b & 0xF0) == 0x80)
{
r.type = ct_JCC;
goto data_offs_rel;
}
if ((b & 0xF6) == 0xB6)
goto modrm;
goto error;
modrm_data_byte:
modrm_proc();
goto data_byte;
modrm_data_w_66:
modrm_proc();
goto data_w_66;
modrm_data_sw_66:
modrm_proc();
goto data_sw_66;
modrm:
modrm_proc();
goto okey;
data_w3_66:
if ((r.opcode & 0x08) != 0)
goto data_66;
else
goto data_byte;
data_sw_66:
if ((r.opcode & 0x02) != 0)
goto data_byte;
goto data_w_66;
data_w_66:
if ((r.opcode & 0x01) != 0)
goto data_66;
else
goto data_byte;
data_byte:
r.datasize = 1;
goto data;
data_66:
if ((r.flags & cf_is66) == 0)
goto data_word;
else
goto data_dword;
data_dword:
r.datasize = 4;
goto data;
data_word:
r.datasize = 2;
goto data;
data_3xbyte:
r.datasize = 3;
goto data;
data_offs:
if ((r.flags & cf_is67) == 0)
r.datasize = 2;
else
r.datasize = 4;
goto data;
data_offs_rel:
if ((r.flags & cf_is66) == 0)
r.datasize = 2;
else
r.datasize = 4;
goto data_rel;
data_byte_rel:
r.datasize = 1;
goto data_rel;
data_rel:
r.flags |= cf_isDATAREL;
goto data;
data:
r.flags |= cf_isDATA;
goto okey;
okey:
if (r.datasize != 0)
for (i=0; i<r.datasize; i++)
getbyte(r.data.b[i]);
if (r.memsize != 0)
for (i=0; i<r.memsize; i++)
getbyte(r.mem[i]);
// end disasm
r.size = cmd_ptr - cmd;
if ((r.flags & cf_isDATAREL) != 0)
{
r.jmpptr = r.base + r.size;
if (r.datasize == 1)
r.jmpptr += (short) r.data.b[0];
else
if (r.datasize == 2)
r.jmpptr += (int) r.data.w[0];
else
{
printf("Disasm error calculating r.jmpptr: r.datasize=%w", r.datasize);
exit(0);
}
}
// dump(cmd, r.size);
move(&r, rec, sizeof(tcmdrec));
}
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[disasm.h]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[engine.h]ÄÄ
#define OUTPUT_FILLER 0xCC
#define UNUSED '-'
#define MARKED 'x'
#define FORNEXTPASS 'N'
byte output[max_size];
byte buf_mark[max_size];
word link_2[max_cmd];
word link_1[max_cmd];
word link_max;
word out_ip;
void mark_cmd(word ofs, word size, byte marker)
{
if (buf_mark[ofs] == MARKED)
{
printf("Alredy MARKED\n");
return;
}
for (; size > 0; size--)
buf_mark[ofs++] = marker;
}
void store_byte(byte b)
{
output[out_ip++] = b;
}
void store_word(word w)
{
store_byte(w & 255);
store_byte(w >> 8);
}
void store_link(word old_ip,
word new_ip)
{
if (link_max >= max_cmd)
{
printf("Too many links(commands)\n");
exit(1);
}
link_1[link_max] = old_ip;
link_2[link_max] = new_ip;
link_max++;
printf("link #%w: %W <--> %W\n", link_max,old_ip,new_ip);
}
void store_jmp(word to_ip)
{
printf("*** STORE_JMP: offs=%W\n", to_ip);
store_link(0xFFFE, out_ip);
store_byte(0xE9);
store_word(to_ip);
}
void store_jmp_output(word to_ip)
{
word w;
printf("*** STORE_JMP_OUTPUT: offs=%W\n", to_ip);
store_link(0xFFFF, out_ip);
//store_byte(0x90);
store_byte(0xE9);
store_word(to_ip - (out_ip+2));
}
word free_space(word start)
{
int i;
for (i=0; (start+i)<max_size, output[start+i] == OUTPUT_FILLER ; i++) ;
return(i);
}
void make_new_ip(void)
{
word i;
word c;
printf("Executing NEW_IP, searching for IP...\n");
for (c=0; c<1000; c++)
{
i = rnd_word_minmax(0x100+min_left, max_size-min_right);
if ( free_space(i) > (min_left+min_right) )
goto found;
};
printf("***WARNING***: No free space in output buffer\n");
return;
found:
i += min_left;
printf("New IP found at %W\n", i);
store_jmp_output(i);
out_ip = i;
}
void random_new_ip(void)
{
#ifdef USE_RANDOM_IP
printf("Executing RANDOM_NEW_IP\n");
if (rnd_word(USE_RANDOM_IP) == 0)
{
make_new_ip();
};
#endif
}
byte store_inversed_jmp;
void store_cmd(word ip, word size)
{
pchar p;
tcmdrec r;
word i;
if (free_space(out_ip) < min_right_left)
make_new_ip();
else
random_new_ip();
printf("*** STORE_CMD: offs=%W size=%W\n", ip, size);
store_link(ip, out_ip);
disasm(make_ptr(_CS,ip), &r);
if ((r.type == ct_JMP) || (r.type == ct_JCC) || (r.type == ct_CALL))
{
if ( (store_inversed_jmp == 1) && (r.type == ct_JCC) )
{
r.jmpptr = ip-disasm_base + r.size;
r.opcode ^= 1;
}
if ((r.opcode & 0xF0) == 0x80)
{
store_byte(0x0F);
store_byte(r.opcode);
store_word(r.jmpptr);
return;
}
if ((r.opcode & 0xF0) == 0x70)
{
store_byte(0x0F);
store_byte(r.opcode - 0x70 + 0x80);
store_word(r.jmpptr);
return;
}
if (r.opcode == 0xEB)
{
store_byte(0xE9);
store_word(r.jmpptr);
return;
}
if ( (r.opcode == 0xE8) || (r.opcode == 0xE9) )
{
store_byte(r.opcode);
store_word(r.jmpptr);
return;
}
printf("ERROR 1, X=%B\n", r.opcode);
exit(2);
}
#ifdef SKIP_NOP
if (r.opcode == 0x90)
return;
#endif
#ifdef SKIP_INT3
if (r.opcode == 0xCC)
return;
#endif
#ifdef SKIP_RANDOM
if (r.size == 2)
if (
(
((r.opcode & 0xFE) == 0x86) ||
((r.opcode & 0xFE) == 0x88)
)
&&
(r.mod == 3)
)
return;
#endif
#ifdef CHANGE_CMD
i = r.opcode & 0xFE;
if (r.size == 2)
if (r.mod == 3)
if ( (i == 0x08) ||
(i == 0x0A) ||
(i == 0x20) ||
(i == 0x22) ||
(i == 0x84) )
{
i = rnd_word(5);
if (i == 0) i = 0x08;
if (i == 1) i = 0x0A;
if (i == 2) i = 0x20;
if (i == 3) i = 0x22;
if (i == 4) i = 0x84;
store_byte(((r.opcode & 0x01) + i));
store_byte(r.modrm);
return;
};
#endif
for (; size>0; size--)
{
p = make_ptr(_CS,ip++);
store_byte( (byte) *p );
}
#ifdef ADD_RANDOM
if (rnd_word(ADD_RANDOM) == 0)
{
word f;
store_byte(0x86 + rnd_word(4));
f = (random_word() & 7);
store_byte(0xC0 + (f << 3) + f);
};
#endif
}
byte pass_action;
void process_1(word ip)
{
tcmdrec rec;
nextcmd:
if ((ip < 0x0100) ||
(ip >= max_size))
{
printf("IP range check error, exiting\n");
return;
}
disasm(make_ptr(_CS,ip), &rec);
printf("Marking: ");
dump(make_ptr(_CS,ip+disasm_base), rec.size);
if (pass_action == 2)
{
printf("PASS 2: Saving offset %W to LINK_2[%w]\n", ip, link_max);
if (link_max > max_cmd*2) // *2 becoz using 2 arrays: ..._2 & 1
{
printf("Too many links!!!");
exit(3);
};
link_2[link_max] = ip;
link_max++;
}
if (buf_mark[ip] == MARKED)
{
printf("Alredy marked, exiting\n");
if (pass_action == 1)
store_jmp(ip+disasm_base);
return;
};
mark_cmd(rec.base, rec.size, MARKED);
if (rec.type == ct_UNKNOWN)
{
if (pass_action == 1)
store_cmd(ip+disasm_base, rec.size);
ip += rec.size;
};
if (rec.type == ct_RET)
{
if (pass_action == 1)
store_cmd(ip+disasm_base, rec.size);
printf("[RET] Exiting\n");
return;
};
if (rec.type == ct_JMP)
{
if (pass_action == 1)
{
#ifndef SKIP_JMPS
store_cmd(ip+disasm_base, rec.size);
#else
store_link(ip+disasm_base, out_ip);
#ifdef SKIP_JMPS_BUT_ADD_NOPS
store_byte(0x90);
#endif
#endif
}
printf("[JMP] Changing IP to %W\n", rec.jmpptr);
ip = rec.jmpptr;
};
if (rec.type == ct_CALL)
{
if (pass_action == 1)
store_cmd(ip+disasm_base, rec.size);
ip+=rec.size;
printf("[CALL] Marking for next pass: %W\n", rec.jmpptr);
mark_cmd(rec.jmpptr, 1, FORNEXTPASS);
};
if (rec.type == ct_JCC)
{
#ifdef RANDOM_JCC
word rnd = rnd_word(2);
#else
#ifdef INVERSE_JCC
word rnd = 1;
#else
word rnd = 0;
#endif
#endif
if (rnd == 0)
{
store_inversed_jmp = 0;
if (pass_action == 1)
store_cmd(ip+disasm_base, rec.size);
ip+=rec.size;
printf("[Jcc] Marking for next pass: %W\n", rec.jmpptr);
mark_cmd(rec.jmpptr, 1, FORNEXTPASS);
};
if (rnd == 1)
{
store_inversed_jmp = 1;
if (pass_action == 1)
store_cmd(ip+disasm_base, rec.size);
ip+=rec.size;
printf("[Jcc] ***INVERSED*** Marking for next pass: %W\n", ip);
mark_cmd(ip, 1, FORNEXTPASS);
printf("Changing IP to %W\n", rec.jmpptr);
ip = rec.jmpptr;
};
};
goto nextcmd;
}
void mark_unused(void)
{
int i;
fillchar(buf_mark, max_size, UNUSED);
link_max = 0;
printf("Marking entry point(s)\n");
process_1(0x0100);
cycle:
printf("Searching for FORNEXTPASS mark(s)\n");
for (i = 0; i < max_size; i++)
if (buf_mark[i] == FORNEXTPASS)
{
printf("Found at %W\n", i);
process_1(i);
goto cycle;
}
printf("No FORNEXTPASS-mark(s) found\n");
}
void run_engine(void)
{
handle h;
word i;
word j;
word k;
word w;
word q;
word e;
pchar p;
tcmdrec r1;
tcmdrec r2;
tcmdrec r3;
printf("Engine!\n {\n");
fillchar(output, max_size, OUTPUT_FILLER);
out_ip = 0x100;
disasm_base = 0;
pass_action = 1;
printf("Marking UNUSED commands (1)\n");
mark_unused();
#ifndef SKIP_DEBUGFILES
printf("Writing file(s)\n");
h = createfile("buf_mark.1");
writefile(h, buf_mark, max_size);
closefile(h);
h = createfile("link_1.1");
writefile(h, link_1, link_max * 2);
closefile(h);
h = createfile("link_2.1");
writefile(h, link_2, link_max * 2);
closefile(h);
h = createfile("output.1");
writefile(h, &output[0x100], max_size-0x100);
closefile(h);
#endif
printf("Updating JMPs...\n");
fillchar(buf_mark, max_size, UNUSED);
for (i=0; i<link_max; i++)
if (link_1[i] != 0xFFFF)
{
for (j=0; j<link_max; j++)
if (i != j)
if (link_2[i] == link_2[j])
if (link_1[j] == 0xFFFF)
goto skip_cycle;
printf("DEBUG: &out[...]=%W, ...=%W i=%w link_1[i]=%W \n", (word) &output[link_2[i]], link_2[i], i, link_1[i]);
p = &output[link_2[i]];
disasm(p, &r);
if (
(r.type == ct_JMP) ||
(r.type == ct_JCC) ||
(r.type == ct_CALL)
)
{
printf("Command to update found at %W\n", link_2[i]);
if (buf_mark[link_2[i]] == MARKED)
printf("Alredy updated");
else
{
buf_mark[link_2[i]] = MARKED;
if ( (r.opcode == 0xE9) || (r.opcode == 0xE8) )
k=1;
else
k=2;
printf("k=%w\n",k);
w = r.data.w[0];
printf("Points to %W\n",w);
q = 0;
for (j=0; j<link_max; j++)
if (link_1[j] == w)
{
printf("Link to (replacing with) %W, j=%w, patch at %W+, link_1[j]=%W\n", link_2[j], j, link_2[i], link_1[j]);
e = (int) link_2[j] - (link_2[i] + r.size);
output[link_2[i]+k ] = e & 255;
output[link_2[i]+k+1] = ((word) e) >> 8;
q++;
}
if (q != 1)
{
printf("ERROR 2, q=%w\n",q);
exit(4);
}
};
};
skip_cycle:
};
disasm_base = ((word) &output[0x0100]) - 0x100;
pass_action = 2;
printf("Marking UNUSED commands (2)\n");
mark_unused();
#ifndef SKIP_DEBUGFILES
printf("Writing file(s)\n");
h = createfile("buf_mark.2");
writefile(h, buf_mark, max_size);
closefile(h);
h = createfile("link_1.2");
writefile(h, link_1, link_max * 2);
closefile(h);
h = createfile("link_2.2");
writefile(h, link_2, link_max * 2);
closefile(h);
#endif
#ifdef KILL_J2J
printf("Searching for Jxx-JMP, CALL-JMP, CALL-RET situations\n");
for (i=0; i<link_max; i++)
{
disasm(make_ptr(_CS,link_2[i]), &r1);
if ( (r1.type == ct_CALL) && (r1.opcode == 0xE8) )
{
disasm(make_ptr(_CS, r1.jmpptr), &r2);
if (r2.opcode == 0xC3)
{
printf("CALL-RET found at %W, points to %W\n", r1.base, r1.jmpptr);
j=r1.base;
output[j ] = 0x87; // xchg ax, ax
output[j+1] = 0xC0;
output[j+2] = 0x90; // nop
};
};
if (
(r1.type == ct_JCC ) ||
(r1.type == ct_CALL) ||
(r1.type == ct_JMP)
)
{
printf("Jxx-JMP or CALL-JMP found at %W, points to %W\n", r1.base, r1.jmpptr);
disasm(make_ptr(_CS, r1.jmpptr), &r2);
if (r2.type != ct_JMP)
printf("Suxx...\n");
else
{
cycle: printf("Points to %W\n", r2.jmpptr);
disasm(make_ptr(_CS, r2.jmpptr), &r3);
if (r3.type == ct_JMP)
{
move(&r3, &r2, sizeof(tcmdrec));
goto cycle;
};
printf("Updating: cmd at %W, jmpptr=%W -> %W \n", r1.base, r1.jmpptr, r2.jmpptr );
j=r1.base;
if ((r1.flags & cf_is0F) != 0) j++; // 0F
j++; // opcode
w = r2.jmpptr - (j+2);
output[j ] = w & 255;
output[j+1] = w >> 8;
};
};
};
printf("Marking UNUSED commands (3)\n");
mark_unused();
#endif
#ifdef MAKE_SHORT_JMPS
printf("Searching for Jxx/JMPs\n");
for (i=0; i<link_max; i++)
{
disasm(make_ptr(_CS,link_2[i]), &r1);
if (r1.type == ct_JCC)
{
w = r1.jmpptr - (r1.base+2);
if ( ((short) (w & 255)) == w)
{
printf("Changing JCC at %W, r1.data.w[0]=%W\n", r1.base, r1.data.w[0]);
output[r1.base+0] = r1.opcode - 0x10;
output[r1.base+1] = w & 255;
output[r1.base+2] = 0x87; // xchg ax, ax
output[r1.base+3] = 0xC0; //
};
};
if (r1.type == ct_JMP)
{
w = r1.jmpptr - (r1.base+2);
if ( ((short) (w & 255)) == w)
{
printf("Changing JMP at %W, r1.data.w[0]=%W\n", r1.base, r1.data.w[0]);
output[r1.base+0] = 0xEB;
output[r1.base+1] = w & 255;
buf_mark[r1.base+2] = UNUSED;
};
};
};
#endif
#ifdef FILL_UNUSED_CC
printf("Filling UNUSED space with 0xCC\n");
for (i=0; i<max_size; i++)
if (buf_mark[i] == UNUSED)
output[i] = 0xCC;
#endif
#ifdef FILL_UNUSED_RANDOM
printf("Filling UNUSED space with RANDOM bytes\n");
for (i=0; i<max_size; i++)
if (buf_mark[i] == UNUSED)
output[i] = random_word();
#endif
printf("Writing 1.COM\n");
h = openfile("1.com");
writefile(h, &output[0x100], max_size-0x100);
closefile(h);
printf(" }\nEngine terminated.\n");
}
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[engine.h]ÄÄ