This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
Student ID: PA-7462
All the code from the project is available at my GitHub.
For the sixth assignment, we are asked to find three pieces of shellcode on the Shell Storm website and modify the shellcode so that it still performs the same function, but has been modified to avoid potential detection or fingerprinting. We are restricted to keeping the shellcode no larger that 150% the original size of the shellcode (if the original shellcode was 30 bytes, the largest it may be is 45 bytes)
IPTables Flush Shellcode
The first piece of shellcode I decided to study and modify was a piece of shellcode that was to perform an IPTables “Flush” command using the sysexecve system call. If you are unfamiliar with the flush command for IPTables, this will simply remove all the firewall rules in IPTables, this could be handy if you have successfully exploited a service running on root of a box, but the firewall is preventing you from accessing the box further.
The original shellcode was 43 bytes, allowing or polymorphic shellcode to be up to 64 bytes. To start, we’ll take a look at the original code for the shellcode. It’s pretty straightforward as it just calls execve with the argument /sbin/iptables -F
I originally made more changes to the shellcode, but I had to revert a few of them due to the overall length. The first thing I changed was instead of pushing the arguments to the stack, I am moving them manually and also accounting for the address change of the stack manually. To do this, I move the hex value to ESP-4, placing it just on top of the stack. Later, I will need to move ESP to the appropriate location. Additionally, I wanted to obfuscate the string a little bit more, so move the hex value for the string minus one and I then increment the value to get the string I’m looking for. For the second string, I move the value minus 0x11 (to partially obfuscate the string). For this value, I move it to ESP-8 to put it above last string. The next and final change I made was instead of moving 0xb to AL, I did this to partially obfuscate the execve system call. Finally I increment AL to 0xb and make the execve system call.
The newly modified shellcode comes to a total of 63 bytes, 1 byte under our requirement. If we look at the strings that are in the two pieces of shellcode, you can see there is definitely a difference. The obfuscation may have been a little unnecessary since the string isn’t overly obvious in the first piece of shellcode, nevertheless, it is more obfuscated in the new version.
System Beep shellcode
The second shellcode I modified performed a system beep. Obviously this piece of shellcode isn’t terrible useful, other than maybe annoying someone, but I thought it would be something different to look at. The original shellcode was 45 bytes, but when I ran it I would get a segmentation fault following the system beep, so I decided to add a system call for exit to prevent the segmentation fault. The new length of the “original” shellcode was 49 bytes with this change.
The original shellcode opens /dev/tty10 using the open system call. Then uses the ioctl system call and issues the KDMKTONE command to generate the beep.
For this piece of shellcode, I kept the modifications fairly simple as I was shooting for having the shellcode being shorter than the original.
Instead of using the push pop technique, I cleared eax and moved the value to the al register. I originally was going to replace the CDQ with clearing the EDX register, but that pushed me over the original length of the shellcode, so I reverted it. I could have replaced pushing the strings to the stack with the technique used earlier (moving them to ESP-4, ESP-8, etc.) but again, I was looking to make a few changes to the shellcode, but make it smaller. Additionally, I could have used the technique i used previously where I set EAX to one value, but increment it later.
Again, I replaced the push pop with a clear of EAX and setting the value in AL. The original author placed a value into ecx and then performed a NOT on it, i decided to just move the final value. If you were interested in obfuscating this, you could do an XOR, add/sub, etc.
The final length of the shellcode was 48 bytes, 1 byte shorter than the original. It’s not much of a reduction, but it’s something.
The final piece of shellcode I decided to take a look at was a piece of shellcode that performs a chmod system call and sets /etc/shadow to 0666, giving everyone read and write to the file.
Since there is a chmod system call, this piece of code is pretty straight forward. The system call id is set, the string for /etc/shadow is set to EBX, the permission value of 0666 is set to ECX and the system call is made.
The original length of this shellcode is 36 bytes, allowing us up to 54 bytes for our morphed version.
To change it up a little, I converted the push pop to a mov eax, edx since EDX has already been cleared, then I set AL to 0x01, which is a system call of sys exit (i will add to it later to make it the CHMOD system call). Next I wanted to obfuscate the string /etc/shadow a little bit more than the original author had, due to the author pushing the word then the byte for the last segment, it doesn’t show up perfectly in Strings, but I figured it was worth obfuscating a little more. Do to this, for the first dword that is pushed to the stack, I place a the original value subtracted by 0x01010101 to the EDI register, then I add that value back to EDI, making EDI the actual value we wanted and then push that to the stack. I could have went with the same technique I used in the first piece of shellcode where I make the modifications to it on the stack, but I just wanted to change it up a little. For the next dword, I decided to subtract 0x10101010 from the original value, and same as before I add that back to EDI and push it to the stack. finally, I add 14 to AL (which I set to 0x01 earlier) to now make it 0x0f (15) which is the value for a chmod system call. Finally the system call is made.
The final shellcode length count is 53 bytes, 1 byte under what our allowed size was.
As with the first example, if we look at Strings for the two pieces of shellcode, you can see part of /etc/shadow in the original, albeit already broken up a little. For the final shellcode, you can see that there isn’t much left that is intelligible in strings.