计算机病毒——代码自解密

原理

获取内存中代码段中需解密的片段,并解密。

实现

为了方便,使用xor进行加解密,并使用密钥为8。需要MASMPlus和W32Dasm。

第一个程序代码

这里的代码并没有加密,但却在运行时解密,因此会运行时错误。

.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
	lpMsg		db "I can decrypt myself!",0
	
.data?
	buffer	db MAX_PATH dup(?)
	
.CODE
START:
	mov edi,Virus_start
	mov ecx,Virus_end
	sub ecx,edi
	mov eax,8
Decrypt:
	xor [edi],eax
	inc edi
	loop Decrypt
Virus_start:
	push offset lpMsg
	call StdOut
	;invoke StdOut,offset lpMsg
Virus_end:

	invoke StdOut,offset lpMsg
	invoke StdIn,addr buffer,sizeof buffer
	invoke ExitProcess,0
	
end START

用W32Dasm反编译,需要被加密代码(反汇编略)为

:0040101F 6800304000
:00401024 E828000000

提取机器码:6800304000E828000000

获取加密后的内容

上一个C++写的程序来加密这段代码

#include<bits/stdc++.h>
using namespace std;
typedef unsigned char BYTE;
typedef unsigned int DWORD;
BYTE buff[2];
const BYTE key = 8;
BYTE value;

BYTE scan(BYTE buf[2]);
void print(BYTE x,FILE* f);
int main();

BYTE scan(BYTE buf[2])
{
	BYTE tmp=0;
	if(buf[0]>='0'&&buf[0]<='9') tmp=buf[0]-'0';
	else tmp=buf[0]-'A'+10;
	tmp=tmp*16;
	if(buf[1]>='0'&&buf[1]<='9') tmp+=buf[1]-'0';
	else tmp+=buf[1]-'A'+10;
	return tmp;
}
void print(BYTE x,FILE* f)
{
	fprintf(f,"\tdb ");
	BYTE tmp[2];
	tmp[0]=x/16;
	tmp[1]=x%16;
	if(tmp[0]>=0&&tmp[0]<=9) fprintf(f,"%c",tmp[0]+'0');
	else fprintf(f,"%c",tmp[0]+'A'-10);
	if(tmp[1]>=0&&tmp[1]<=9) fprintf(f,"%c",tmp[1]+'0');
	else fprintf(f,"%c",tmp[1]+'A'-10);
	fprintf(f,"h\n");
}
int main()
{
	FILE* f=fopen("1.code","r");
	FILE* n=fopen("1.decode","w");
	while(fread(buff,1,2,f)!=0)
	{
		value=scan(buff);
		value=value^key;
		print(value,n);
	}
}

把刚才的机器码写入1.code中,运行这个C++程序,在1.decode中得到

	db 60h
	db 08h
	db 38h
	db 48h
	db 08h
	db E0h
	db 20h
	db 08h
	db 08h
	db 08h

这是不符合Masm标准的,修改为

	db 60h
	db 08h
	db 38h
	db 48h
	db 08h
	db 0E0h
	db 20h
	db 08h
	db 08h
	db 08h

接着替换原来的汇编代码

.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
	lpMsg		db "I can decrypt myself!",0
	
.data?
	buffer	db MAX_PATH dup(?)
	
.CODE
START:
	mov edi,Virus_start
	mov ecx,Virus_end
	sub ecx,edi
	mov eax,8
Decrypt:
	xor [edi],eax
	inc edi
	loop Decrypt
Virus_start:
	db 60h
	db 08h
	db 38h
	db 48h
	db 08h
	db 0E0h
	db 20h
	db 08h
	db 08h
	db 08h
	;invoke StdOut,offset lpMsg
Virus_end:

	invoke StdOut,offset lpMsg
	invoke StdIn,addr buffer,sizeof buffer
	invoke ExitProcess,0
	
end START

修改工程属性

然而,Windows下代码段默认不可写,需要修改段属性。在链接参数后补上 /section:.text,rw 即可。

(可选)美化源代码

源代码有很多db,不好看,再次使用W32Dasm反编译,得到

:00401016 60                      pushad
:00401017 0838                    or byte ptr [eax], bh
:00401019 48                      dec eax
:0040101A 08E0                    or al, ah
:0040101C 2008                    and byte ptr [eax], cl
:0040101E 0808                    or byte ptr [eax], cl

用反编译代码替换源代码

.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
	lpMsg		db "I can decrypt myself!",0
	
.data?
	buffer	db MAX_PATH dup(?)
	
.CODE
START:
	mov edi,Virus_start
	mov ecx,Virus_end
	sub ecx,edi
	mov eax,8
Decrypt:
	xor [edi],eax
	inc edi
	loop Decrypt
Virus_start:
	pushad
	or byte ptr [eax], bh
	dec eax
	or al, ah
	and byte ptr [eax], cl
	or byte ptr [eax], cl
	;invoke StdOut,offset lpMsg
Virus_end:

	invoke StdOut,offset lpMsg
	invoke StdIn,addr buffer,sizeof buffer
	invoke ExitProcess,0
	
end START

然而,or al,ah 却编译成了0AC4,因此最终代码如下

.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
	lpMsg		db "I can decrypt myself!",0
	
.data?
	buffer	db MAX_PATH dup(?)
	
.CODE
START:
	mov edi,Virus_start
	mov ecx,Virus_end
	sub ecx,edi
	mov eax,8
Decrypt:
	xor [edi],eax
	inc edi
	loop Decrypt
Virus_start:
	pushad
	or byte ptr [eax], bh
	dec eax
	db 08h
	db 0E0h
	and byte ptr [eax], cl
	or byte ptr [eax], cl
	;invoke StdOut,offset lpMsg
Virus_end:

	invoke StdOut,offset lpMsg
	invoke StdIn,addr buffer,sizeof buffer
	invoke ExitProcess,0
	
end START

运行结果
运行结果

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值