I am doing experiments on encrypting PE code segment by XORing each byte with some key value. So far I managed to XOR this segment and inject at the end of code segment binary code that is decoding by XORing again with the same value. Of course I also updated AddressOfEntryPoint to be equal of decoder's address.
But when I calculate address of first byte to be XORed (it is equal to the first byte before decoder - because I will be going up) and I try to do this I receive access violation.
Now the details:
1) as a test PE I use some super easy console "hello world" app in plain C++
2) injected decoder code is written in NASM assembler, then assembled to binary and then injected at the end of .text section of test PE. Its code is below:
call get_proc ; push return address
get_proc:
pop esi ; pop current address
sub esi, 0x5 ; esi = address of injected code, 0x5 = size of call instruction
xor ebx, ebx ; clear registers
xor ecx, ecx ;
mov bl, <DECODER_KEY> ; decoder key
mov ecx, <CODE_SIZE> ; encoded code size
sub esi, ecx ; esi = address of encoded code
decoder_loop:
mov edx, esi ; construct encoded byte address
add edx, ecx ;
dec edx ;
xor byte [cs:edx], bl ; decode
loop decoder_loop ; loop back
jmp esi ; jump back to decoded code
3) <DECODER_KEY>
and <CODE_SIZE>
are replaced (before assembling) with proper values by my another app that is doing injection
4) when first loop iteration is passing, final EDX value is equal to the address of byte just before call get_proc
, checked with Immunity Debugger
5) here I post a screenshot presenting situation when I have access violation when attempting to do XOR on first byte (with red line I marked my injected code that is executed at the beginning)
6) I am aware of the fact, that by default code segment is only readable and executable, but my injecting app also adds write permission.
7) I am using Windows 8.1 64-bit
And finally questions:
A) Is presented code doing what I want it to do?
B) Is adding write permission to code segment enough to perform this operation (I know that there are some "write protection" mechanisms, but I don't know any details)?
Exploits are often using this technique (or at least they used to), so I wonder why isn't this working. In addition I have to tell, that when I remove only XOR operations, then program works fine (so calculated addresses are correct).
EDIT: Here is link to PEdump result: PEdump
I found solution to my problem. In general: there was a mistake in assembler code - referencing [cs:edx]
in xor operation is wrong, should be just [edx]
. Why?
It seems that now segment registers are not doing what we (or at least I) think. I heard that previously they were used as base address for each segment and instruction [cs:addr]
was an offset within code segment.
But when you look closer at the values of segment registers in the photo I provided in question, you will see that those registers are in fact some descriptors that reference mainly 0xFFFFFFFF address! When I removed cs
from instruction it worked! But then I loaded binary into debugger and suprisingly it was translated into ds:[edx]
! Again, why DS (data segment)? That one I don't know. But lesson from this issue should be to not to use those registers.
If you don't agree or you have any clarification please comment this answer.