User-Level Shellcodes
Most computer programs that you encounter run in the “user space”. The term “user space” refers to the
part of computer memory assigned to information and processes that don’t involve deep system issues.
Low-level data and processes run in the computer’s “kernel space” (i.e. the core section of the OS).
Somebody character programs canvas a specialized way of act with the computer’s OS. This
communication method differs from OS to OS. But put, apiece user-level schedule needs to alter a
“grouping call” to ask the OS to deal an computation. If your OS is x86-based, your programs can initiation
system calls through the “sysenter” statement. This order relies on a program-based interruption
performance.
Windows systems (e.g. XP) are unequaled in that they necessary user-level programs to transport usual
run invocations to the deposit functions of Windows. These assemblage functions faculty bare the system
invocations on the user’s behalf. The OS controls nearly all the functions (e.g. web attain, growth
commencement, enter access, etc.) a shellcode requires. Thus, you poverty to bed how to strain those functions if
you essential to be a prospering hacker.
Making a method ring within a Windows machine is whole. For Unix computers, on the additional hand,
sending group calls is as dolabriform as surroundings the suitable values for the mound prior to provision the “int 0x80”
control. Erstwhile you periodical the control, the OS gift strike anxiety of the touch for you. In opposition,
Windows systems are more herculean because they tell you to mention a Windows assemblage use to
act a scheme telephony. You can easily describe Windows functions, but knowing their positioning in the
computer’s storage is extremely arduous. This difficultness arises because Windows functions survive in
DLLs (i.e. impulsive tie libraries), whose locations dissent supported on the Windows OS you are using.
That is the cerebrate why shellcodes for Windows undergo a explore touch to conceptualize the honourable Windows
functions.
Basic Shellcodes
Your main goal is to inject your shellcode into a vulnerable process. Achieving this goal requires proper
selection of shellcodes. It would be great if you will have access to all the capabilities of a shell without
creating one. The hacking process will be a walk in the park if you can just place a shellcode into a
target that already contains a shell. These “ideal situations” gave birth to a popular three-step hacking
process:
1. The hacker will insert shellcodes into the target.
2. The shellcodes trigger a shell inside the infected machine.
3. The resulting shell will send and/or receive information to/from the hacker.
According to many hackers, the first step of this process is the easiest. You can accomplish this step by
invoking “CreateProcess” (a Windows function) or “execve” (a system call in Unix-related operating
systems). The most complex step, meanwhile, is knowing where the resulting shell obtains input and
sends output.
Each computer process starts with three files: “stdout” (the standard output), “stdin” (the standard input),
and “stderr” (standard error). You will encounter these starting files no matter which operating system
you are attacking.
Bind Shellcodes
In many cases, executing shells won’t produce the desired results. If your target terminates the
connection before your shell launches, transmitting data to/from the shell won’t be possible. But real
hackers don’t give up easily. If basic shellcodes don’t work, you must look for another avenue of attack.
For example, you can solve this problem through a shellcode that binds one of the target’s ports. This
kind of shellcode is known as “port binding code”.
Multiple events occur whenever a binding shellcode runs. These events are:
● The shellcode will create one TCP (i.e. transmission control protocol) socket.
● The shellcode will attach the new socket to a port that the hacker specified. You can specify
the port number by including it in the source code of your exploit.
● The hacker will turn his socket into a “listening” one.
● The hacker will receive the connection.
● He will copy the details of the socket onto the three starting files (i.e. stderr, stdin, and
stdout).
● The shellcode will trigger a command shell. This shell allows the hacker to send/receive
information through the socket.
Reverse Shellcodes
Firewalls can block connections between the hacker and the socket. Fortunately, you can solve this
problem by modifying your shellcode. Instead of initiating the communication between your computer
and your listening socket, you can force your target to reach out to you instead. Reverse shellcodes can
help you with this task. With a reverse shellcode, you won’t bind the exploit to a particular port on the
targeted machine. Rather, you will force the target to send outgoing traffic to a particular port of your
own computer. If this process is successful, the socket details will be saved in the three starting files.
This kind of shellcode works well because many firewalls are lenient when it comes to outgoing
transmissions.
During an attack, a reverse shellcode performs the following steps:
1. Generate a transmission control protocol socket.
2. Require the new socket to send outgoing transmissions to the IP address and port number that
the hacker specified. Most hackers include the IP address and port number in the shellcode.
3. Copy the socket-related information to stderr, stdout, and stdin.
4. Trigger a command shell.
Find Socket Codes
This is one of the most popular shellcodes of today. A find socket shellcode lets you utilize a network
connection that you have used before. Because you have accessed a service inside the target, you can use
that service again to transmit your shellcode. Additionally, this kind of shellcode is one of the hardest to
detect. The shellcode will use an existing connection so the transmission will likely go through the
target’s firewall.
Find socket codes do the following:
1. Check all of the existing file descriptors (256 in total).
2. Identify the descriptor that has a legitimate connection.
3. Verify whether the port being used for the connection is the one chosen by the hacker. Hackers
include the port number in the shellcode.
4. Copy the information from the socket onto the stderr, stdin, and stdout files.
5. Launch a shell process.
Command Execution Shellcodes
Sometimes, establishing a network connection with a target is undesirable or impossible. Such
connections require unsafe (i.e. trackable and detectable) telnet sessions. Fortunately, you can just run a
shellcode that sets a legitimate connection between the target and your own computer. There are exploits
that secure future connections by stealing data (e.g. the ssh key), changing the target’s settings, or adding
new network users.
Shellcodes that run commands do the following:
1. Set the identifier of the hacker’s command.
2. Set the arguments of the command.
3. Run the command by invoking “execve”.
Important Note: These shellcodes are often short because they don’t need networking
statements.
How to Encode a Shellcode
When attacking a program, you should know the inputs and structures that you can (or cannot) use. For
example, if a “strcpy” process triggers buffer overflows, you need to make sure that your buffer is free
from null characters. Null characters cause strcpy processes to end immediately (i.e. before the overflow
occurs). Sometimes, failures can occur because of special characters present in the buffer. There are also
some situations where the buffer cannot contain characters except numbers and letters. Identifying the
exact set of inappropriate letters requires reverse-engineering. You should also take note of the
program’s behavior during the debugging process.
You must always consider the “bad characters” when writing shellcodes. If you are using automated
encoders (e.g. the “msfvenom” module of Metasploit), you can set the bad characters as parameters.
Working with the limitations is mostly easy. The process becomes difficult only when the hacker injects
the code to the buffer. For a shellcode to become effective, it must satisfy the following requirements:
● It should adhere to rules concerning format and input types.
● It should be a sequence of characters that the target system can understand.
Some shellcodes violate input and/or format rules. Modifying a faulty shellcode requires programming
skills and access to the code’s language source. Getting complete access and possessing great
programming skills, however, don’t guarantee success. In certain cases, rewriting a shellcode is
impossible. You can solve this problem through shellcode encoding.
Basically, a code encoder converts the contents of an existing payload to make sure that they follow
input and format limitations. But the target machine cannot read the output of shellcode encoders. That
means you need to decrypt the resulting codes within the target machine. Most hackers solve this
problem by placing an encrypted code and a decryption loop inside a single payload.
Important Note: Your decryption loop must also follow the buffer’s restrictions regarding inputs and
formatting.
How to Disassemble a Shellcode
As an inexperienced hacker, you will likely rely on shellcode generators or payloads written by others.
Thus, you will have limited knowledge regarding the actual behavior and/or function of your chosen
payloads. “Dissecting” a payload is quick and easy. You just need to run the “gdb” command. Once you
type “gdb”, the system will dump the contents of its memory as codes. Study the resulting codes in order
to know what your chosen payload really does.
Shellcode Corruption
Shellcodes also need storage space. This space can be variable (just like what typical programs have), or
the consequence of setting parameters on the computer stack before invoking the function. Similar to
other codes, shellcodes have a tendency to rely on the computer stack for its storage requirements. Keep
in mind, however, that shellcodes exist within the stack. That means a shellcode might overwrite itself as
it writes information in the stack. This “self-overwriting” is called “shellcode corruption”.
As a hacker, you need to answer the following questions:
1. How can you identify codes that may overwrite themselves?
2. How can you prevent shellcode corruption?
The first question involves your knowledge regarding the shellcode and where that code came from. In
most cases, a shellcode is a group of characters that you can insert into various exploits. Knowing the
characteristics and limitations of a shellcode is difficult if you’ll rely on automated code generators or
payloads created by other hackers.
You can avoid shell corruption by changing the shellcode’s position. This way, the information that will
be stored on the stack won’t hit the current shellcode. For example, you may place the shellcode at a
higher section of the stack. Move the shellcode to another region if the current one doesn’t have enough
space for a “vertical” relocation. If these solutions don’t solve the problem, you may point the “esp”
away from your shellcode. You can accomplish this by increasing or decreasing the value of “esp”.
Kernel-Level Shellcodes
Vulnerabilities are not limited to user-level programs. You can also find a vulnerability in the kernel of
your operating system. The kernel lies in the deepest parts of a computer. Thus, it is tempting to assume
that kernel-level vulnerabilities are safe from hackers. But nothing could be further from the truth. These
days, hackers have a wide range of tools and techniques for attacking a target’s kernel.
Things to Consider
In general, exploiting the kernel is more difficult than attacking user-level applications. When targeting a
kernel, you should consider the following:
● Consequences of Failure – If a user-level attack fails, your target program will crash. That
means you may attack another program that runs on the victim’s computer. If a kernel-level
attack fails, however, it is likely that the entire system will crash. For Windows computers,
system crashes are characterized by the dreaded “blue screen of death”.
● Post-Exploitation – You also need to consider what you will do after reaching the target’s
kernel. Because you are dealing with the “deepest parts” of a machine, you can’t just run
another process or issue the “execve” command. In addition, you cannot access any library of
useful functions. System calls are no longer relevant since you are already inside the target’s
“system”. If your kernel-level attack succeeds, your choices are limited to the functions
supported by the kernel.
● Stability – This consideration is crucial during the development of a kernel-level exploit.
Keep in mind that a wrong move in a kernel-level attack can disable a whole system. Each
shellcode you will use must keep the exploited thread running, If that thread stops responding,
the whole target might crash
Leave a Reply