Copy Link
Add to Bookmark
Report

29A Issue 03 03 06

eZine's profile picture
Published in 
29A
 · 28 Dec 2019

  

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[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]ÄÄ

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT