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.