0% found this document useful (0 votes)
11 views58 pages

Code Injection and Hooking 2

The document discusses code injection techniques used by attackers to inject malicious code into legitimate processes, allowing them to perform harmful actions such as data theft. It explains the concepts of virtual memory, user mode, and kernel mode, detailing how processes and threads interact with the operating system. Additionally, it covers different types of HTML injection attacks and the methods attackers use to execute injected code within the context of a target process.

Uploaded by

Amrita Yadav
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views58 pages

Code Injection and Hooking 2

The document discusses code injection techniques used by attackers to inject malicious code into legitimate processes, allowing them to perform harmful actions such as data theft. It explains the concepts of virtual memory, user mode, and kernel mode, detailing how processes and threads interact with the operating system. Additionally, it covers different types of HTML injection attacks and the methods attackers use to execute injected code within the context of a target process.

Uploaded by

Amrita Yadav
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 58

Code Injection

and Hooking
Code Injection
and Hooking
• In this chapter, you will learn how
malicious programs inject code into
another process (called target process
or remote process) to perform
malicious actions. The technique of
injecting malicious code into a target
process's memory and executing the
malicious code within the context of
the target process is called code
injection (or process injection).
An attacker typically chooses a legitimate process (such as
explorer.exe or svchost.exe) as the target process.

Once the malicious code is injected into the target process, it can
then perform malicious actions, such as logging keystrokes, stealing
passwords, and exfiltrating data, within the context of the target
process.

After injecting the code into the memory of the target process, the
malware component responsible for injecting code can either
continue to persist on the system, thereby injecting code into the
target process every time the system reboots, or it can delete itself
from the filesystem, keeping the malicious code in memory only.
Virtual Memory
• Virtual memory is a memory management technique
used by modern operating systems to provide each
process with the illusion of a large, contiguous address
space, even if physical memory (RAM) is limited. It
allows multiple processes to run concurrently while
efficiently utilizing available memory resources.
• Windows memory manager, with the help of hardware,
translates the virtual address into the physical address
(in RAM) where the actual data resides; to manage the
memory, it pages some of the memory to the disk.
• Virtual memory is segregated into process memory
(process space or user space) and kernel memory
(kernel space or system space).
• The size of the virtual memory address space
depends on the hardware platform.
• For example, on a 32-bit architecture, by default,
the total virtual address space (for both process and
kernel memory) is a maximum of 4 GB.
• On a 32-bit system, out of the 4 GB virtual address
space, each process thinks that it has 2 GB of process
memory, ranging from 0x00000000 - 0x7FFFFFFF.
• Since each process thinks that it has its own private
virtual address space (which ultimately gets mapped
to physical memory), the total virtual address gets
much larger than the available physical memory
(RAM).
• The Windows memory manager addresses this by
paging some of the memory to the disk; this frees the
physical memory, which can be used for other
processes, or for the operating system itself.
• Even though each Windows process has its own private
memory space, the kernel memory is, for the most part,
common, and is shared by all the processes.
The following diagram shows the memory layout of 32-bit
architecture. You may notice a 64 KB gap between the
user and kernel space; this region is not accessible and
ensures that the kernel does not accidentally cross the
boundary and corrupt the user-space.
Even though the virtual address range is the same for
each process (x00000000 - 0x7FFFFFFF), both the
hardware and Windows make sure that the physical
addresses mapped to this range are different for each
process.

For instance, when two processes access the same


virtual address, each process will end up accessing a
different address in the physical memory.

By providing private address space for each process, the


operating system ensures that processes do not
overwrite each other's data.
The virtual memory space need not always be
divided into 2 GB halves; that is just the default
setup.

For example, you can enable a 3 GB boot


switch, which increases the process memory to
3 GB, ranging from 0x00000000 - 0xBFFFFFFF;
the kernel memory gets the remaining 1 GB,
from 0xC0000000 - 0xFFFFFFFF:
User Mode And Kernel Mode
• The user-space contains code (such as executable and DLL) that runs with
restricted access, known as the user mode.
• In other words, the executable or DLL code that runs in the user space
cannot access anything in the kernel space or directly interact with the
hardware.
• The kernel space contains the kernel itself (ntoskrnl.exe) and the device
drivers. The code running in the kernel space executes with a high
privilege, known as kernel mode, and it can access both the user-space
and the kernel space.
• By providing the kernel with a high privilege level, the operating system
ensures that a user-mode application cannot cause system instability by
accessing protected memory or I/O ports.
• Third-party drivers can get their code to run in kernel mode by
implementing and installing signed drivers.
The difference between the space (user space/kernel
space) and the mode (user mode/kernel mode) is that
space specifies the location where the contents
(data/code) are stored, and mode refers to the
execution mode, which specifies how an application's
instructions are allowed to execute.
• If the user-mode applications cannot directly interact
with the hardware, then the question is, how can a
malware binary running in user-mode write content to a
file on the disk by calling the WriteFile API?.
• In fact, most of the APIs called by user-mode
applications, end up calling the system service routines
(functions) implemented in the kernel executive
(ntoskrnl.exe), which in turn interacts with the hardware
(such as, for writing to a file on the disk). I
• In the same manner, any user-mode application that
calls a GUI-related API ends up calling the functions
exposed by win32k.sys in the kernel space.
The ntdll.dll (residing in the user-space) acts as the
gateway between the user-space and the kernel space. In
the same way, user32.dll acts as a gateway for the GUI
applications.
Windows API
Call Flow
• When a process is invoked by double-clicking a program,
the process executable image and all its associated DLLs
are loaded into the process memory by the Windows
loader.
• When a process starts, the main thread gets created,
which reads the executable code from the memory and
starts executing it.

• An important point to remember is that it is not the process that


executes the code, it is the thread that executes the code (a
process is merely a container for the threads).
• The thread that is created starts executing in the user-mode
(with restricted access). A process may explicitly create
additional threads, as required.
• Let's suppose that an application needs to call the
WriteFile() API, which is exported by kernel32.dll.
• To transfer the execution control to WriteFile(), the
thread has to know the address of WriteFile() in the
memory.
• If the application imports WriteFile(), then it can
determine its address by looking in a table of function
pointers called the Import Address Table (IAT), as shown
in the preceding diagram.
• This table is located in an application's executable
image in the memory, and it is populated by the
windows loader with the function addresses when the
DLLs are loaded.
An application can also load a DLL during runtime by
calling the LoadLibrary() API, and it can determine the
address of a function within the loaded DLL by using the
GetProcessAddress() API. If an application loads a DLL
during runtime, then the IAT does not get populated.
• Once the thread determines the address of WriteFile()
from the IAT or during runtime, it calls WriteFile(),
implemented in kernel32.dll. The code in the WriteFile()
function ends up calling a function, NtWriteFile(),
exported by the gateway DLL, ntdll.dll.
• The NtWriteFile() function in ntdll.dll is not a real
implementation of NtWriteFile(). The actual function,
with the same name, NtWriteFile() (system service
routine), resides in ntoskrnl.exe (executive), which
contains the real implementation. T
• he NtWriteFile() in ntdll.dll is just a stub routine that
executes either SYSENTER (x86) or SYSCALL (x64)
instructions. These instructions transition the code to
the kernel mode
• Now, the thread running in kernel mode (with unrestricted
access) needs to find the address of the actual function,
NtWriteFile(), implemented in ntoskrnl.exe.
• To do that, it consults a table in the kernel space called the
System Service Descriptor Table (SSDT) and determines
the address of NtWriteFile().
• It then calls the actual NtWriteFile() (system service
routine) in the Windows executive (in ntoskrnl.exe), which
directs the request to the I/O functions in the I/O manager.
• The I/O manager then directs the request to the
appropriate kernel-mode device driver.
Code Injection
Techniques
As mentioned earlier, the
objective of a code injection
technique is to inject code into
the remote process memory and
execute the injected code within
the context of a remote process.
The injected code could be a
module such as an executable,
DLL, or even shellcode. Code
injection techniques provide
many benefits for attackers
HTML Injection
HTML injection is a type of attack where malicious HTML
code is inserted into a website. This can lead to a variety
of issues, from minor website defacement to serious
data breaches. Unlike other web vulnerabilities, HTML
injection targets the markup language that forms the
backbone of most websites.
Types
Stored HTML Injection

Stored HTML injection, also known as persistent injection, is a type of attack


where the malicious code is permanently stored on the target server.As an
example, a forum post where an attacker might embed a malicious script that
unsuspecting users read, and then click, which initiates execution of the script,
leading to potential data theft or other malicious outcomes.

Reflected HTML Injection

Unlike stored injections, reflected attacks are not permanently housed on the
server. Instead, they trick users into executing malicious code via a URL. This
is often achieved through phishing emails or messages that lure users into
clicking on a compromised link.For instance, an attacker might send an email
posing as a trusted entity, urging the recipient to click on a link. This link
contains the malicious payload, which gets executed once clicked, leading to
the desired malicious outcome.
DOM-based HTML Injection

The attack targets the Document Object Model (DOM) of


a webpage, which represents the page’s structure. By
manipulating the DOM, attackers can introduce malicious
scripts that get executed client-side.

Understanding the DOM is crucial for web developers and


security professionals alike. It’s the bridge between HTML
and JavaScript, and any vulnerabilities can lead to
significant security breaches. Being aware of how these
attacks operate is the first step in prevention.
Example : URL Parameter Manipulation
• Vulnerability Setup: A web page uses JavaScript to directly
include a URL parameter in the HTML without proper
sanitization. For instance, a parameter userInput is directly
included in the DOM.
• User Interaction: The URL example1

• Outcome: The script tag gets executed as part of the HTML,


popping up an alert box with the message ‘Injected!’. This
demonstrates how JavaScript code can be injected into the
DOM.
Once the code is injected into the remote process,
an adversary can do the following things:
• Force the remote process to execute the injected code
to perform malicious actions (such as downloading
additional files or stealing keystrokes).
• Inject a malicious module (such as a DLL) and redirect
the API call made by the remote process to a malicious
function in the injected module. The malicious function
can then intercept the input parameters of the API call,
and also filter the output parameters
For example,
• Internet Explorer uses HttpSendRequest() to send a request containing
an optional POST payload to the web server, and it uses
InternetReadFile() to fetch the bytes from the server's response to
display it in the browser.
• An attacker can inject a module into Internet Explorer's process
memory and redirect the HttpSendRequest() to the malicious function
within the injected module to extract credentials from the POST
payload.
• In the same manner, it can intercept the data received from the
InternetReadFile() API to read the data or modify the data received
from the web server.
• This enables an attacker to intercept the data (such as banking
credentials) before it reaches the web server, and it also allows an
attacker to replace or insert additional data into the server’s response
(such as inserting an extra field into the HTML content) before it
reaches the victim's browser.
Once the code is injected into the remote process,
an adversary can do the following things:

• Injecting code into an already running process allows an


adversary to achieve persistence.
• Injecting code into trusted processes allows an attacker
to bypass security products (such as whitelisting
software) and hide from the user.
• In the following code injection techniques, there is a
malware process (launcher or loader) that injects code,
and a legitimate process (such as explorer.exe) into
which the code will be injected.
• Before performing code injection, the launcher needs to
first identify the process to inject the code.
• This is typically done by enumerating the processes
running on the system; it uses three API calls:

• CreateToolhelp32Snapshot(), Process32First(), and


Process32Next()
• CreateToolhelp32Snapshot() is used to obtain the
snapshot of all of the running processes;
• Process32First() gets the information about the first
process in the snapshot;
• Process32Next() is used in a loop to iterate through all
of the processes.
• The Process32First() and Process32Next() APIs get
information about the process, such as the executable
name, the process ID, and the parent process ID; this
information can be used by malware to determine
whether it is the target process or not.
• Sometimes, instead of injecting code into an already
running process, malicious programs launch a new
process (such as notepad.exe) and then inject code into
it.
• Whether the malware injects code into an already
running process or launches a new process to inject
code, the objective in all the code injection techniques
(covered next) is to inject malicious code (either DLL,
executable, or Shellcode) into the address space of the
target (legitimate) process and force the legitimate
process to execute the injected code.
• Depending on the code injection technique, the
malicious component to be injected can reside on the
disk or in the memory.
Remote DLL Injection
• In this technique, the target (remote) process is forced to load a
malicious DLL into its process memory space via the LoadLibrary() API.
• The kernel32.dll exports LoadLibrary(), and this function takes a single
argument, which is the path to the DLL on the disk, and loads that DLL
into the address space of the calling process.
• In this injection technique, the malware process creates a thread in the
target process, and the thread is made to call LoadLibrary() by passing a
malicious DLL path as the argument.
• Since the thread gets created in the target process, the target process
loads the malicious DLL into its address space. Once the target process
loads the malicious DLL, the operating system automatically calls the
DLL's DllMain() function, thus executing the malicious code.
• The following steps describe in detail how this technique
is performed, with an example of a malware named
nps.exe (loader or launcher) that injects a DLL via
LoadLibrary() into the legitimate explorer.exe process.
• Before injecting the malicious DLL component, it is
dropped onto the disk, and then the following steps are
performed:
• The malware process (nps.exe) identifies the target
process (explorer.exe, in this case) and gets its process
ID (pid). The idea of getting the pid is to open a handle
to the target process so that the malware process can
interact with it.
• To open a handle, the OpenProcess() API is used, and
one of the parameters it accepts is the pid of the
process.
• In the following screenshot, the malware calls
OpenProcess() by passing the pid of explorer.exe
(0x624, which is 1572) as the third parameter. The
return value of OpenProcess() is the handle to the
explorer.exe process:
• The malware process then allocates memory in the target
process using the VirutualAllocEx() API.
• In the following screenshot, the 1st argument (0x30) is the
handle to explorer.exe (the target process), which it
acquired from the previous step.
• The 3rd argument, 0x27 (39), represents the number of
bytes to be allocated in the target process, and the 5th
argument (0x4) is a constant value that represents the
memory protection of PAGE_READWRITE.
• The return value of VirtualAllocEx() is the address of the
allocated memory in explorer.exe:
• The reason for allocating the memory in the target
process is to copy a string that identifies the full path of
the malicious DLL on the disk.
• The malware uses WriteProcessMemory() to copy the
DLL pathname to the allocated memory in the target
process. \
• In the following screenshot, the 2nd argument,
0x01E30000, is the address of the allocated memory in
the target process, and the 3rd argument is the full path
to the DLL that will be written to the allocated memory
address 0x01E30000 in explorer.exe:
• The idea of copying the DLL pathname to the target
process memory is that, later, when the remote thread
is created in the target process and when LoadLibrary()
is called via a remote thread, the DLL path will be
passed as the argument to LoadLibrary().
• Before creating a remote thread, malware must
determine the address of LoadLibrary() in kernel32.dll;
to do that, it calls the GetModuleHandleA() API and
passes kernel32.dll as the argument, which will return
the base address of Kernel32.dll.
• Once it gets the base address of kernel32.dll, it
determines the address of LoadLibrary() by calling
GetProcessAddress().
• At this point, the malware has copied the DLL pathname
in the target process memory, and it has determined
the address of LoadLibrary().
• Now, the malware needs to create a thread in the target
process (explorer.exe), and this thread must be made to
execute LoadLibrary() by passing the copied DLL
pathname so that the malicious DLL will be loaded by
explorer.exe.
• To do that, the malware calls CreateRemoteThread() (or
the undocumented API NtCreateThreadEx()), which
creates a thread in the target process.
• Once the injection is complete, the malware calls the
VirtualFree() API to free the memory containing the DLL
path and closes the handle to the target process
(explorer.exe) by using the CloseHandle() API.
DLL Injection Using APC (APC
Injection)
• In the previous technique, after writing the DLL
pathname, CreateRemoteThread() was invoked to
create a thread in the target process, which in turn
called LoadLibrary() to load the malicious DLL.
• The APC injection technique is similar to remote DLL
injection, but instead of using CreateRemoteThread(), a
malware makes use of Asynchronous Procedure Calls
(APCs) to force the thread of a target process to load
the malicious DLL.
• The way the APC injection technique works is, a
malware process identifies the thread in the target
process (the process into which the code will be
injected) that is in an alertable state, or likely to go into
an alertable state.
• It then places the custom code in that thread's APC
queue by using the QueueUserAPC() function.
• The idea of queuing the custom code is that, when the
thread enters the alertable state, the custom code gets
picked up from the APC queue, and it gets executed by
the thread of the target process.
DLL Injection Using
SetWindowsHookEx()
• DLL injection using SetWindowsHookEx() is a technique
employed in Windows programming to inject custom
code (a DLL) into another process's address space and
intercept certain events or messages.
• This method is commonly used for various purposes,
including logging keystrokes, monitoring system events,
and implementing global hooks for applications like
hotkeys or mouse events.
• Here's a basic overview of how this technique works:
• Create a DLL: First, you need to create a DLL that
contains the code you want to inject into the target
process. This DLL typically contains a function that will
be called whenever the desired event occurs.
• Choose a Hook Type: SetWindowsHookEx() is a function
in the Windows API that installs an application-defined
hook procedure into a hook chain. You need to specify
the type of hook you want to install, such as keyboard
(WH_KEYBOARD_LL or WH_KEYBOARD) or mouse
(WH_MOUSE_LL or WH_MOUSE).
• Hook Procedure: You'll also need to define a hook procedure
within your DLL. This procedure will be called whenever the
specified event occurs. The hook procedure receives
information about the event and can perform custom actions
or modify the behavior of the target process.
• Inject the DLL: Once the DLL and hook procedure are ready,
you need to inject the DLL into the target process. This can
be done using various techniques, such as creating a remote
thread in the target process and loading the DLL, or using
functions like CreateRemoteThread() or SetWindowsHookEx()
itself.
Remote Executable/Shellcode
Injection
• In this technique, the malicious code is injected into the target
process memory directly, without dropping the component on the
disk.
• The malicious code can be a shellcode or an executable whose
import address table is configured for the target process.
• The injected malicious code is forced to execute by creating a remote
thread via CreateRemoteThread(), and the start of the thread is
made to point to the code/function within the injected block of code.
• The advantage of this method is that the malware process does not
have to drop the malicious DLL on the disk; it can extract the code to
inject from the resource section of the binary, or get it over the
network and perform code injection directly.
Hooking Techniques
• Another reason an attacker injects code (mostly DLL, but
it can also be an executable or shellcode) into the
legitimate (target) process is to hook the API calls made
by the target process.
• Once a code is injected into the target process, it has full
access to the process memory and can modify its
components.
• The ability to alter the process memory components
allows an attacker to replace the entries in the Import
Address Table(IAT) or modify the API function itself;
this technique is referred to as hooking
By hooking an API, an attacker can control the execution
path of the program and re route it to the malicious code
of his choice. The malicious function can then:

• Block calls made to the API by legitimate applications (such as


security products).
• Monitor and intercept input parameters passed to the API.
• Filter the output parameters returned from the API.
IAT Hooking
• As mentioned earlier, the IAT contains the addresses of
functions that an application imports from DLLs.
• In this technique, after a DLL is injected into the target
(legitimate) process, the code in the injected DLL
(Dllmain() function) hooks the IAT entries in the target
process.
The following gives a high-level overview of the steps
used to perform this type of hooking:
• Locate the IAT by parsing the executable image in
memory.
• Identify the entry of the function to hook.
• Replace the address of the function with the address of
the malicious function.
• Let's look at an example of a legitimate program
deleting a file by calling the DeleteFileA() API.
• The DeleteFileA() object accepts a single parameter,
which is the name of the file to be deleted.
• The following screenshot displays the legitimate process
(before hooking), consulting the IAT normally to
determine the address of DeleteFileA(), and then calling
DeleteFileA() in the kernel32.dll
• When the program's IAT is hooked, the address of DeleteFileA() in
the IAT is replaced with the address of the malicious function,
as follows. Now, when the legitimate program calls
DeleteFileA(), the call is redirected to the malicious function
in the malware module.
• The malicious function then invokes the original DeleteFileA()
function, to make it seem like everything is normal. The malicious
function sitting in between can either prevent the legitimate program
from deleting the file, or monitor the parameter (the file that is being
deleted), and then take some action
• In addition to blocking and monitoring, which typically
happens before invoking the original function, the
malicious function can also filter the output
parameters, which occurs after the re-invocation.
• This way, the malware can hook APIs that display lists
of processes, files, drivers, network ports, and so
on, and filter the output to hide from the tools that use
these API functions.
Inline Hooking (Inline Patching)
• IAT hooking relies on swapping the function pointers, whereas,
in inline hooking, the API function itself is modified
(patched) to redirect the API to the malicious code.
• As in IAT hooking, this technique allows the attacker to
intercept, monitor, and block calls made by a specific
application, and filter output parameters. In inline hooking,
the target API function's first few bytes (instructions)
are usually overwritten with a jump statement that re
routes the program control to the malicious code.
• The malicious code can then intercept the input parameters,
filter output, and redirect the control back to the original
function
• To help you understand, let's suppose that an attacker
wants to hook the DeleteFileA() function call made by a
legitimate application.
• Normally, when the legitimate application's thread
encounters the call to DeleteFileA(), the thread starts
executing from the start of the DeleteFileA() function, as
shown here:
• To replace the first few instructions of a function with a
jump, the malware needs to choose which instructions
to replace. The jmp instruction requires at least 5 bytes,
so the malware needs to choose instructions that
occupy 5 bytes or more.
• In the preceding diagram, it is safe to replace the first
three instructions (highlighted using a different color),
because they take up exactly 5 bytes, and also, these
instructions do not do much, apart from setting up the
stack frame.
• The three instructions to be replaced in DeleteFileA() are
copied, and then replaced with a jump statement of some
sort, which transfers control to the malicious function.
• The malicious function does what it wants to do, and then
executes the original three instructions of DeleteFileA() and
jumps back to the address that lies below the patch (below
the jump instruction), as shown in the following diagram.
The replaced instructions, along with the jump statement
that returns to the target function, are known as the
trampoline:
• This technique can be detected by looking for
unexpected jump instructions at the start of the API
function, but be aware that malware can make
detection difficult by inserting the jump deeper in the
API function, rather than at the start of the function.
• Instead of using a jmp instruction, malware may use a
call instruction, or a combination of push and ret
instructions, to redirect control; this technique bypasses
the security tools, which only look for jmp instructions.

You might also like