This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
https://www.pentesteracademy.com/course?id=3
Student ID: PA-7462
All the code from the project is available at my GitHub.
For assignment 2, we are asked to study egghunter shellcode and create an implementation of our own. In case you are unfamiliar with the term egghunting, it is a form of multi-stage shellcode. Multi-stage shellcode can be useful if you find yourself in a situation where you are limited in space for your shellcode. With egghunting, you created a small piece of shellcode that searches memory for the second stage of shellcode that you want to execute. The shellcode is located by looking for a specific set of instructions prepending the shellcode.
One thing that I felt like was not explained too well on some of the other blog posts I found while researching the topic was how do you get the “egg” into memory. While I don’t think that is completely in scope of the assignment, I think it is important to understand what’s going on and how you would ultimately use the shellcode you’ve created. From what I understand, you would likely be performing a buffer overflow of a field and you would use your egg hunter shellcode for this portion. Using another available field, you would deliver your “egg” shellcode. FuzzySecurity has a good blog post that walks through the whole process on Windows which really helped me understand whole process. In their example, they use the UserAgent field for the stage 2 “egg” shellcode.
The actual assembly needed for this assignment was pretty small (which is the point)
Instead of breaking down the individual sections like I have on the previous blogs, I’m just going to talk through the whole piece.
We start with OR’ing the dx register to adjust the PAGE_SIZE, changing the location that we are looking in memory for our “egg”.
Next we incrementing the address (technically, we might want to check the first address, but if our egg was there, it should just be on top of the stack and we would just need to do a jmp esp). Then we load the effective address to ebx for when we make the syscall to access.
When the access syscall is made, eax is set to 0xf2 if there is an EFAULT (an invalid section of memory is accessed), so we check to make sure we are in a valid section, if not we loop back and increment the address. If there is no efault, we move our “egg” to the EAX register. In this case I used 50585058 (pushed in reverse due to endianness). It doesn’t matter too much what you use here, you just want to make sure it’s not going to show up in memory for something legitimate.
The Assembly command SCAS is the scan string command, SCASD specifies the EDI register. Essentially the command searches for a string and then increments the register. If there is no match, we go back to the beginning and move to the next address. If there is a match, we check the next address to see if there is a match. When we add our “egg” to our stage 2, we duplicate the “egg” to ensure that the match is our actual shellcode we found in memory and not the string from out stage 1 shellcode (or some other random string that matched). Once we’ve confirmed the match, we jump to the next address, which is now stored in EDI and our shellcode is executed.
The resulting shellcode is:
"\x31\xc9\x66\x81\xca\xff\x0f\x42\x8d\x5a\x04\x31\xc0\xb0\x21\xcd\x80\x3c\xf2\x74\xed\xb8\x50\x58\x50\x58\x89\xd7\xaf\x75\xe8\xaf\x75\xe5\xff\xe7"
I’ve highlighted the egg that we are searching for, if your shellcode has a different egg, or you’d just like to use something else, it’s easily replaced.
Since creating a buffer overflow and pushing our stage two to memory is kind of out of the scope of this assignment, we will just modify the shellcode.c file that we’ve been using to test our shellcode previously. We will just set out stage 2 shellcode (prepended with out egg) as a variable so it will be loaded into memory and we’ll execute out stage 1 shellcode, which should walk through memory until it finds the egg and executes our stage 2 shellcode.
For this example, I’m using the shellcode I created in Assignment 2
Here is a snippet of the shellcode.c file I used to test the shellcode (keep in mind that some of the shellcode is clipped off in the screenshot, visit my Github for the full code).
I start with defining “egg” with the egg that I’ll be looking for. In addition to the normal “code” variable that I’ve been using, I create an eggCode variable. This variable isn’t directly accessed in our code (other than printing the length of it) as I just want it to be loaded into memory so we can find it with our egghunting shellcode.