Computer Virus - Code Self-decryption 2

Keywords: Windows

Computer Virus - Code Self-decryption 2

problem

Last blog
The last program modified the code area and changed the attributes of the code segment, so the anti-virus program can detect the virus by judging the abnormal attributes of the segment (not the virus or it may report the virus). So we need to replace a segment to store and run encrypted code.

Improvement

In general, we often use the following paragraphs:
Code snippets, readable, executable, and not writable
Data segment, readable, writable, non-executable
Stack segment, readable, writable and executable
So we can choose the stack segment to store and run.

The stack is not easy to operate, and the stack is simple to operate, so we allocate stack space. What the stack needs to pay attention to is that the stack is from high address to low address, contrary to the normal order.

The basic code for this experiment

.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

To write

We mainly get the machine code for the following code

	mov eax,StdOut
	push offset lpMsg1
	call eax

Result

:00401000 B834104000              mov eax, 00401034

* Possible StringData Ref from Data Obj ->"I can decrypt myself!"
                                  |
:00401005 6800304000              push 00403000
:0040100A FFD0                    call eax

The machine code is B8341040006800304000FFD0, but because the address of StdOut and lpMsg1 will change in the next program, the address needs to be acquired at run time.
Encrypted and processed

	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

Address is not handled here
After decrypting the code, add

	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

Complete code

.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

Unfortunately, this program only outputs "Can you?". However, after debugging, the blogger found that the program did enter Std twice and the call location was correct. This problem will be solved next time.

Posted by JCBarry on Thu, 22 Aug 2019 07:04:15 -0700