还是那个ASM程序,MACH或其他高手请进

iceeagle 2000-06-04 12:44:00

我对这个加密程序的加密算法还是有点糊涂,它是如何用密码的前四位加的密?和什么异或了一下?读了文件头的32个字节干什么用呀?
给文件加密,为什么还要更改源文件?只要求输入密码,密码正确就可继续执行不行吗?

code segment
assume cs:code,ds:code
org 100h
addprog proc far
mov ax,cs
mov ds,ax
mov psp,es
mov es,ax
mov save_ss,ss
mov save_sp,sp
mov sp,cs
mov ss,sp
mov sp,offset stack_ptr
mov ax,psp
add souc_seg,ax
add souc_seg,10h
mov cx,6;为什么是六,是循环次数吗?
;(mach)这个cx是循环次数,表示你一共有6重试的机会
input: mov ah,9
lea dx,dirmsg
int 21h
push cx;为什么要进栈保留起来?
;(mach)要破坏cx了,当然要入栈
mov cx,32
lea di,password
get_input: mov ah,8
int 21h ;(mach)不会显的读一个字符
stosb
cmp al,0dh
jz compare
mov ah,2
mov dl,42;是输出ascii码是42的字符吗?"b"?
;(mach)这里的42是'*',注意分清16进制和10进制
int 21h ;(mach)回显一个'*'
loop get_input
compare: pop cx;用到了刚才保留起来的cx,干什么用?
mov dl,0dh
mov ah,2
int 21h
lea si,password
add si,4;为什么要加四?
;(mach)原来加密时就是这么处理的,前四位用于计算真正的入口地址
mov di,si
load: lodsb
not al;为什么要取反
;(mach)看看底下的程序,当初加密的时候就是取反存放的,所以现在也要取反
stosb
cmp al,0ffh
jz on_comp
cmp al,0f2h
jnz load
on_comp: lea si,keyword
lea di,password
add di,4
comp: cmpsb
jnz wr_input
dec si
lodsb
cmp al,0f2h
jz end_comp
jmp comp
wr_input: mov ah,9
lea dx,wrong
int 21h
loop input
;(mach)前面的cx其实是在这个loop这里用的
jmp cs:reset;跳转到什么地方去,cs是段基址,reset是偏移量是吗?那么reset
现在是什么?赋过值了吗?
;(mach)这里的reset实际是0f000h:0fff0h,知道是干什么的吗?it means reboot,6次输入错
误后重起机器
end_comp: lea dx,right
mov ah,9
int 21h
chain_back: cmp byte ptr isexe,0
je com_back
lea bx,password
mov ax,[bx];以下这几句是在干什么?为什么要相加,bx+2是要干什么?
;(mach)这里的[bx],[bx+2]相当于加密时的key_cs,key_ip
;(mach)当初加密时把程序原来的入口地址用用户输入的口令的前四位加密,这里是逆运算,解
出真正的入口地址
add souc_seg,ax
mov ax,[bx+2]
add souc_off,ax
jmp return
com_back: lea bx,password
mov ax,psp
mov es,ax
lea si,head_save
mov di,100h
mov cx,10h;为什么循环10次?
;(mach)这里是要取回原先加密时保存的32字节的com文件的代码
loadw: lodsw
xor ax,[bx];为什么要异或?
;(mach)这里的异或是解密操作
xor ax,[bx+2]
stosw
loop loadw
return: mov sp,save_sp
push cs:souc_seg
push cs:souc_off
mov dx,psp
mov es,dx
mov ds,dx
xor si,si
xor di,di
retf
save_ss dw ?
save_sp dw ?
souc_off dw ?
souc_seg dw ?
dirmsg db 09h,09h,'Enter your PASSWORD here ... $'
right db 0dh,0ah,09h,09h,' Program continued ... ',0dh,0ah,'$'
wrong db 0dh,0ah,09h,09h,' Wrong password !',0dh,0ah,'$'
reset label dword
reset_off dw 0fff0h
reset_seg dw 0f000h
psp dw ?isexe db 0
head_save db 20h dup(0)
pro_stack dw 20h dup(0)
stack_ptr dw 0
keyword db 16 dup(0)
password db 32 dup(0)
buff db 1024 dup (0)endprog label word
addprog endp
main: mov ax,ds
mov cs:psp_seg,ax ;psp_seg现在是什么内容,是将它的首地址做偏移地址吗
?
;(mach)现在的psp_seg不就是ds的值吗
push cs
pop es
mov al,byte ptr ds:[80h] ;[80]是什么意思,80从何而来?
;(mach)dos程序中命令行参数放在cs:psp_seg+82h处,这里的[80h]中是参数的字符个数
push cs
pop ds
cmp al,0
jz main_help
call get_name
jnc continue
lea dx,dmsg1
mov ah,9
int 21h
lea dx,keybuf
mov ax,0c0ah ;get keyboard buffer ;0a是功能号吧?我没查到0a号功能
是做什么的
;(mach)功能号是0ch,其功能是:清除输入缓冲区,然后将输入的键盘字符存入输入缓冲区key
buf
int 21h
continue: call get_pass ;这段里用了jc,有cf标志位判断是否跳转,可它所调用的子
程序中并没有修改标志位呀?
;(mach)我也没看出来,此处似乎有误
jc main_ret
call find_file
jc main_ret
call add_file
jc main_ret
mov bx,handle
mov ah,3eh
int 21h ;close file
lea dx,msg4
mov ah,9
int 21h
main_ret: mov ax,4c00h
int 21h ;main program end
main_help: mov ah,9
lea dx,help
int 21h
jmp main_ret
get_name proc near
push ds
mov ax,psp_seg
mov ds,ax
mov si,82h ;为什么是82,从何而来?
;(mach)前面说过命令行参数放在psp+82h处(psp=ds:0)
lea di,filename
mov ds,cs:psp_seg
call parsename
mov al,0
stosb
inc si
mov ch,00
mov cl,byte ptr ds:[80h]
add cx,82h
cmp cx,si
jne get_word
stc
pop ds
ret
get_word: lea di,key_cs
call parsename
mov al,0dh
stosb
pop ds
ret
parsename: cld
m01: cmp byte ptr [si],' ';以下这一段是表示,用户敲空格,分号,/,逗号等都可表
示密码输入结束吗?
;(mach)这里是说把不为空格,分号,/,逗号等的字符作为一个命令行参数处理,对于上面的两
次调用,第一次取出路径,第二次取出口令
jne m02
inc si
jmp m01
m02: cmp byte ptr [si],';'
je m03
cmp byte ptr [si],' '
je m03
cmp byte ptr [si],'/'
je m03
cmp byte ptr [si],','
je m03
cmp byte ptr [si],0dh
je m03
cmp byte ptr [si],0ffh
je m03
movsb
jmp m02
m03: ret
get_name endp
get_pass proc near
lea si,chars
lea di,keyword ;get password
get_char: lodsb
not al
;(mach)将口令由第5位开始按位取反后存放在keyword,前四位用于加密入口地址
stosb
cmp al,0ffh
jz get_ret
cmp al,0f2h
jnz get_char
get_ret: ret
get_pass endp
find_file proc near
lea dx,buffer
mov ah,1ah
int 21h
lea dx,filename
mov ah,4eh
int 21h
jnc openfile1
lea dx,msg1
ferr_ret: mov ah,9
int 21h
stc
ret
openfile1: lea dx,filename
mov al,2
mov ah,3dh
int 21h ;open file for read/write
mov handle,ax
lea dx,msg2
jc ferr_ret
ret
find_file endp
add_file proc near
lea dx,buffer ;read file head
mov bx,handle
mov cx,20h
mov ah,3fh
int 21h
or ax,ax
jz point_err
lea di,buffer
cmp [di],5a4dh ;EXE file ;比较文件的头是不是5a4d?为什么?如果是
就是exe文件吗?这是它的特点吗?
;(mach)对呀,dos下的exe文件的开始两个字节一定是"MZ"即4dh和5ah,到了windows下就有些
不同,不只是pe格式的exe文件,dll等一些其他文件也是用MZ开头的
jnz no_exe
mov isexe,1
call head_deal
write: call to_head ;move pointer to head
call write_head
jc point_err
call to_tail ;move pointer to tail
call write_file
jc point_err
ret
point_err: lea dx,msg2
mov ah,9
int 21h
stc
ret
no_exe: mov isexe,0
lea si,buffer
lea di,head_save
mov cx,10h
transfer: lodsw
;为什么要循环10次
;这里是把com文件的开头32字节保存加密后保存到head_save,注意:不是10次,而是16次
xor ax,key_ip,这两句是什么意思?
xor ax,key_cs
;这两句是加密,异或是最简单的加密方法,以后只要用key_ip和key_cs在作一次异或,就可以
解密
stosw
loop transfer
mov souc_off,100h
mov souc_seg,0fff0h
call to_tail
add ax,1fh
and ax,0fff0h
mov cs:file_low,ax
mov cs:file_high,dx
mov cl,4
shr ax,cl
mov cx,20h
lea si,com_head
lea di,buffer
mov [si+1ah],ax
mov [si+18h],0630h
rep movsb
jmp write
com_head: mov dx,cs
mov ax,cs:[11ah]
add ax,dx
push ax
mov ax,100h
push ax
retf
null db 20h dup(0)
sub_ret: ret
add_file endp
head_deal proc near
mov ax,[di+14h]
sub ax,key_ip
mov souc_off,ax ;source code offset
mov ax,[di+16h]
sub ax,key_cs
mov souc_seg,ax ;source code segment
call to_tail
add ax,1fh
adc dx,0
and ax,0fff0h
mov cs:file_low,ax
mov cs:file_high,dx
mov cx,10h
div cx
sub ax,10h
sub ax,[di+08h]
mov word ptr [di+14h],100h ;new cs offset
mov word ptr [di+16h],ax ;new cs segment
mov ax,cs:file_low
mov dx,cs:file_high
lea cx,endprog
sub cx,100h
add ax,cx
adc dx,0
mov cx,200h
div cx
inc ax
mov [di+2],dx
mov [di+4],ax
ret
head_deal endp
to_tail proc near
mov ax,4202h ;move pointer to file tail
mov cx,0
mov dx,0
int 21h
ret
to_tail endp
to_head proc near
mov ax,4200h ;move pointer to file head
mov cx,0
mov dx,0
int 21h
ret
to_head endp
write_head proc near
mov ah,40h ;write file head
lea dx,buffer
mov cx,20h;cx代表写入字节数,这里为什么写入20个字节
;(mach)前面不是读了20h的文件头吗,并且修改了他,当然要写回去了
int 21h
ret
write_head endp
write_file proc near
mov dx,100h
mov cx,cs:file_low ;file_low从何而来?
sub cx,ax ;这几句中的甲减运算是什么意思?
;(mach)计算要写入的代码长度和位置,把endprog开始的代码,也就是addprog写入文件尾
sub dx,cx
mov ax,cx
lea cx,endprog
add cx,ax
sub cx,100h
mov ah,40h
int 21h
ret
write_file endp
help db 'LOCK (R) Version 4.00a Copyright (C) Technique Department 1993-
94.' db 0dh,0ah,'Examples:'
db 0dh,0ah,' LOCK drive:\path\[filename]'
db 0dh,0ah,' LOCK [filename] [password]'
db 24h
dmsg1 db 'Software (R) File Lock Utility (tm) Version 4.00a'
db 0dh,0ah
db 'Copyright (C) Technique Department 1993-94. All rights reserved.
' db 0dh,0ah,0dh,0ah
db 'KEYWORD of source file (at least 5 characters): $'
msg1 db 0dh,0ah,'File can not find.$'
msg2 db 0dh,0ah,'File can not read or disk is full.$'
msg3 db 0dh,0ah,'Not EXE file.$'
msg4 db 0dh,0ah,'File lock successfully.$'psp_seg dw 0
file_low dw 0
file_high dw 0
keybuf db 32h
umchar db 0
key_cs dw 0
key_ip dw 0
chars db 28h dup(0)
handle dw 0
filename db 16h dup(?)
buffer db 20h dup(?)
buff1 db 1024 dup (0)
code ends
end main

...全文
198 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
OldBoy 2000-06-04
  • 打赏
  • 举报
回复
谢了,请先忍耐一两天,如有问题还要麻烦你——我的分所剩不太多了。
mach 2000-06-04
  • 打赏
  • 举报
回复
给可执行文件加密,当然要改动它的执行代码,这个原理和病毒或自解压程序是一样的

这个程序的功能是这样的,假设你有一个要加密的程序src.exe或src.com
当你用这个加密程序对其加密时,它要作如下工作:
如果是src.exe
1.要求你输入密码(如果你没有在命令行参数中指定密码的话),密码最少5位
2.取出密码的第四位以后的部分,把它们取反后存放
3.读出src.exe的文件头(exe文件有一个文件头,其中记录了一些有关的信息,这里用到的就是程序的入口地址,包括段地址和偏移地址)
4.把exe文件头中的入口地址改为指向由加密程序写入到exe文件尾部的addprog代码(解密模块),并把的exe文件头中原来的入口地址用输入的密码的前四位进行处理,方法如下:
seg=oldseg-*(short*)passwd[0];
offset=oldoffset-*(short*)passwd[2];
5.把修改过的文件头写回
6.把解密代码模块addprog写到文件尾部(包括处理过的原入口地址和密码的其他部分)
如果是src.com
1.要求你输入密码(如果你没有在命令行参数中指定密码的话),密码最少5位
2.取出密码的第四位以后的部分,把它们取反后存放
3.因为com文件没有exe文件那样的文件头,其入口地址是固定的(cs:100h处),所以这里处理方法也不一样,这里是这样做的:把com文件开始处的(cs:100h处)32字节的代码用用户输入的密码的前四位进行异或,把标号com_head处的代码写入到cs:100h处
4.把解密模块addprog和异或后的程序原入口代码32字节写入到文件尾

被加密后的程序运行时,首先执行addprog,它会要求用户输密码,它先用密码第四位后的部分取反后于保存的原密码比较,如果不同,则让用户重输,如果6次失败,则机器重起,如果密码正确,则对于exe和com文件根据当初加密时的不同处理进行相应操作,得到程序原来的入口继续执行.

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧