计算机病毒——代码自解密2
问题
上一篇博客
上次的程序修改了代码区,因此改变了代码段属性,那么反病毒程序可以通过判断段属性异常来查毒(不是病毒也可能会报毒)。因此我们需要换一个段来存储并运行被加密的代码。
改进
.一般,我们常用的段有:
代码段,可读可执行不可写
数据段,可读可写不可执行
堆栈段,可读可写可执行
因此我们可以选择堆栈段来存储运行。
堆不好操作,而栈操作简单,所以我们分配栈空间。栈需要注意的地方就是栈是从高地址到低地址,与正常顺序正好相反。
这一次实验的基本代码
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
include gdi32.inc
includelib gdi32.lib
includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
include macro.asm
.data
lpMsg1 db "I can decrypt myself!",0
lpMsg2 db "Can you?",0
.data?
buffer db MAX_PATH dup(?)
.CODE
START:
mov eax,StdOut
push offset lpMsg1
call eax
invoke StdOut,offset lpMsg2
invoke StdIn,addr buffer,sizeof buffer
invoke ExitProcess,0
end START
编写
我们主要是获取下面代码的机器码
mov eax,StdOut
push offset lpMsg1
call eax
结果
:00401000 B834104000 mov eax, 00401034
* Possible StringData Ref from Data Obj ->"I can decrypt myself!"
|
:00401005 6800304000 push 00403000
:0040100A FFD0 call eax
机器码是B8341040006800304000FFD0,但是由于StdOut、lpMsg1在接下来的程序中地址会发生改变,因此地址还需运行时获取。
加密并处理得到
mov ebp,esp
sub esp,18
mov BYTE ptr [esp],0B0h
;mov eax,StdOut
mov BYTE ptr [esp+5],60h
;push offset lpMsg1
mov BYTE ptr [esp+10],0F7h
mov BYTE ptr [esp+11],0D8h
;call eax
mov BYTE ptr [esp+12],60h
;push Ending
mov BYTE ptr [esp+17],0C3h
;ret
这里地址不处理
解密代码后加上
mov [esp+1],StdOut
mov DWORD ptr [esp+6],offset lpMsg1
mov [esp+13],Ending
jmp esp
Ending:
add esp,18
invoke StdOut,offset lpMsg2
invoke StdIn,addr buffer,sizeof buffer
invoke ExitProcess,0
完整代码
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
include gdi32.inc
includelib gdi32.lib
includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
include macro.asm
.data
lpMsg1 db "I can decrypt myself!",0
lpMsg2 db "Can you?",0
.data?
buffer db MAX_PATH dup(?)
.CODE
START:
mov ebp,esp
sub esp,18
mov BYTE ptr [esp],0B0h
;mov eax,StdOut
mov BYTE ptr [esp+5],60h
;push offset lpMsg1
mov BYTE ptr [esp+10],0F7h
mov BYTE ptr [esp+11],0D8h
;call eax
mov BYTE ptr [esp+12],60h
;push Ending
mov BYTE ptr [esp+17],0C3h
;ret
mov edi,esp
mov ecx,ebp
sub ecx,1
sub ecx,edi
mov eax,8
Decrypt:
xor [edi],eax
inc edi
loop Decrypt
mov [esp+1],StdOut
mov DWORD ptr [esp+6],offset lpMsg1
mov [esp+13],Ending
jmp esp
Ending:
add esp,18
invoke StdOut,offset lpMsg2
invoke StdIn,addr buffer,sizeof buffer
invoke ExitProcess,0
end START
不过遗憾的是,这个程序只输出了"Can you?"。然而博主在调试后发现程序的确两次进入了Std,且call位置正确,这个问题下次解决。