Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "pch.h"
- #include <Windows.h>
- #include <Psapi.h>
- #include <string>
- #include <iostream>
- /**
- * \brief Gratis to Microsoft's documentation! Note this can be done by enumerating through the PEB of the process,
- * but that requires utilizing some not so well-documented functions so for simplicity I used the standard way.
- * If you want the specifics of how this works: https://docs.microsoft.com/en-us/windows/win32/psapi/enumerating-all-modules-for-a-process
- * \param hProcess Process Handle
- * \return ModuleHandle of the main module
- */
- MODULEINFO GetExternalModule(HANDLE hProcess, const TCHAR* mName)
- {
- HMODULE module_handles[1024];
- DWORD cb_needed = 0;
- if (EnumProcessModules(hProcess, module_handles, sizeof(module_handles), &cb_needed))
- {
- for (unsigned int i = 0; i < (cb_needed / sizeof(HMODULE)); i++)
- {
- TCHAR szModName[MAX_PATH];
- if (GetModuleBaseName(hProcess, module_handles[i], szModName,
- sizeof(szModName) / sizeof(TCHAR)))
- {
- if (wcscmp(szModName, mName) == 0)
- {
- MODULEINFO module_information = {};
- GetModuleInformation(hProcess, module_handles[i], &module_information, cb_needed);
- return module_information;
- }
- }
- }
- }
- }
- /**
- * \brief The shell_code buffer includes the epilogue and prologue for the function along with the mCode already implemented by the 0x0, 0x0, 0x0, 0x0 are purposely there
- * to be later replaced in the loops below that write in the correct address. This utilizes the correct rel32 address for the call. If you wish to learn more, just
- * research how calls are done in x86. Furthermore, we allocate memory in the process that will be enough for our injection code + message which is referenced in the
- * shell code!
- * \param hProcess Handle to Process
- * \param pAddress Rebased address
- * \param mCode Which print code to use (I think any value 0-2)
- * \param sMsg Message you have to print
- * \return Location of shellcode in process
- */
- void* InjectShellCode(HANDLE hProcess, const unsigned pAddress, int mCode, const char* sMsg)
- {
- unsigned char shell_code[] = {
- 0x55, //push ebp
- 0x8B, 0xEC, //mov ebp, esp
- 0x68, 0x0, 0x0, 0x0, 0x0, //push (address of string)
- 0x6A, (unsigned char)mCode, //push (value of mCode)
- 0xE8, 0x0, 0x0, 0x0, 0x0, //call (address of print function)
- 0x83, 0xC4, 0x08, //add esp, 8
- 0x8B, 0xE5, //mov esp, ebp
- 0x5D, //pop ebp
- 0xC3 //retn
- };
- const PVOID kAllocatedMemory = VirtualAllocEx(hProcess, NULL, 51 + strlen(sMsg), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
- SIZE_T bytes_written = NULL;
- const LPVOID kHeapHandle = HeapCreate(NULL, NULL, sizeof(shell_code));
- const LPVOID kHeapBytes = HeapAlloc(kHeapHandle, HEAP_ZERO_MEMORY, sizeof(shell_code));
- memcpy(kHeapBytes, shell_code, sizeof(shell_code));
- WriteProcessMemory(hProcess, (LPVOID)((unsigned)kAllocatedMemory + 50), sMsg, strlen(sMsg) + 1, &bytes_written); //The string will be written
- //50 bytes into our allocated memory.
- for (unsigned i = 0, j = 0; i < sizeof(shell_code); ++i)
- {
- if (*(unsigned*)((unsigned)kHeapBytes + i) == 0) //0x0 0x0 0x0 0x0 = 0; thereby this looks for our filler-shell code that we hope to actually fill in now.
- {
- if (j == 0)
- {
- *(unsigned*)((unsigned)kHeapBytes + i) = ((unsigned)kAllocatedMemory + 50); //Write the string's address into our shell code.
- j++;
- }
- else if (j == 1)
- {
- *(unsigned*)((unsigned)kHeapBytes + i) = 0 - ((unsigned)kAllocatedMemory + i - pAddress) - 4; //rel32 offset for the call instruction to the print function
- }
- }
- }
- WriteProcessMemory(hProcess, (LPVOID)kAllocatedMemory, kHeapBytes, sizeof(shell_code), &bytes_written); //write our shell code into the allocated memory
- HeapFree(kHeapHandle, NULL, kHeapBytes); //free the heap that I allocated so I could edit my shell code.
- HeapDestroy(kHeapHandle); //ditto
- return kAllocatedMemory; //return the address of our allocated memory that is now ready to be executed!
- }
- /**
- * \brief Gets Process Handle, and then injects the shellcode and frees the allocated shellcode! This uses the API WaitForSingleObjectEx to make sure the thread concluded
- * before we free up the memory!
- * \return
- */
- int main()
- {
- const unsigned kPrintAddress = 0x5A36C0; //address of console print function
- unsigned rebased_print_address = NULL;
- MODULEINFO external_main_module = {};
- HWND window_handle = NULL;
- HANDLE process_handle = NULL;
- DWORD process_id = NULL;
- window_handle = FindWindow(NULL, L"Roblox");
- if (!window_handle)
- return -1;
- GetWindowThreadProcessId(window_handle, &process_id);
- if (!process_id)
- return -1;
- process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);
- if (!process_handle)
- return -1;
- external_main_module = GetExternalModule(process_handle, L"RobloxPlayerBeta.exe");
- rebased_print_address = kPrintAddress - 0x400000 + (unsigned)external_main_module.lpBaseOfDll; //rebase address
- std::string input;
- while (true)
- {
- std::getline(std::cin, input);
- void* shell_code_location = InjectShellCode(process_handle, rebased_print_address, 1, input.c_str());
- if (shell_code_location)
- {
- const HANDLE kThread = CreateRemoteThread(process_handle, NULL, NULL, (LPTHREAD_START_ROUTINE)shell_code_location, NULL, NULL, NULL);
- if (WaitForSingleObjectEx(kThread, INFINITE, FALSE) == WAIT_OBJECT_0)
- VirtualFreeEx(process_handle, shell_code_location, 0, MEM_RELEASE);
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement