The Self-Erasing Code Example (x64)
2022-03-15 Dawid Farbaniec

/* Dawid is digging in his archives. */
It is possible that in some program one will need to erase certain data or even code. Although the technique of wiping code from memory may seem suspicious to some readers (Viral behavior! o_O).
Let's get the idea without complaining about whether the technique will be used to erase the shellcode in the penetration test or for other purpose. Wiping code from memory is a bit more complex than wiping data (a variable).
An example in MASM x64 Assembly is shown below. Filling the procedure's body with
Stay tuned for more cybersecurity content! 🦠☣️💉🧪🛡️
It is possible that in some program one will need to erase certain data or even code. Although the technique of wiping code from memory may seem suspicious to some readers (Viral behavior! o_O).
Let's get the idea without complaining about whether the technique will be used to erase the shellcode in the penetration test or for other purpose. Wiping code from memory is a bit more complex than wiping data (a variable).
An example in MASM x64 Assembly is shown below. Filling the procedure's body with
NOP
(no operation) instructions is possible by getting the start and end of the code block using labels and the size of the code in bytes. Write access to the code section is obtained through VirtualProtect
.
;+---------------------------------------+
;| Erase procedure body code in MASM x64 |
;| Code example by Dawid Farbaniec |
;+---------------------------------------+
extrn MessageBoxA : proc
extrn VirtualProtect : proc
.const
PAGE_EXECUTE_READWRITE equ 040h
ProcInfo struct
bodyStart dq 0
bodyEnd dq 0
bodySize dq 0
ProcInfo ends
.data
szCaption db "ethical.blue", 0
szText db "This is sample procedure call.", 0
oldProtect dd 0
procInfo1 ProcInfo <0,0,0>
.code
MyProc1 proc
mov rax, offset _ERASE_START
mov [procInfo1.bodyStart], rax
push rbp
mov rbp, rsp
_ERASE_START:
sub rsp, 30h
xor r9, r9
lea r8, szCaption
lea rdx, szText
xor rcx, rcx
call MessageBoxA
add rsp, 30h
_ERASE_END:
leave
mov rcx, offset _ERASE_END
dec rcx
mov [procInfo1.bodyEnd], rcx
sub rcx, qword ptr [procInfo1.bodyStart]
mov [procInfo1.bodySize], rcx
ret
MyProc1 endp
Main proc
;sample procedure call
sub rsp, 28h
call MyProc1
add rsp, 28h
;get write access to code block
sub rsp, 28h
mov r9, offset oldProtect
mov r8, PAGE_EXECUTE_READWRITE
mov rdx, [procInfo1.bodySize]
mov rcx, qword ptr [procInfo1.bodyStart]
call VirtualProtect
add rsp, 28h
;erase procedure body (fill with NOPs)
mov rdx, [procInfo1.bodyStart]
xor rcx, rcx
_loop1:
mov byte ptr [rdx + rcx * sizeof byte], 90h
inc rcx
cmp rcx, [procInfo1.bodySize]
jle _loop1
;sample procedure call (after erasing)
sub rsp, 28h
call MyProc1
add rsp, 28h
ret
Main endp
end
Stay tuned for more cybersecurity content! 🦠☣️💉🧪🛡️