Hack Опубликовано 25 октября, 2019 Поделиться Опубликовано 25 октября, 2019 (изменено) Спойлер /* Внедрение C/C++ функций в чужой процесс. Компилятор MinGW. Делаем так: Помещяем функции и переменные в отдельные секции, потом эти секции копируем в чужой процесс. Перед копированием функций - нужно изменять статические адреса на новые, reloc укажет в каких местах изменять. Добавляем параметры для линкера. Добавим reloc [-Wl,-pie], но после этого параметра - точка входа указывает неправильно. Восстанавливаем точку входа [-Wl,--entry,_mainCRTStartup] или [-Wl,--entry,mainCRTStartup]. */ #include <stdio.h> #include <windows.h> #include <tlhelp32.h> typedef DWORD_PTR ADDRESS; //Можно поменять название на свои, максимум 8 символов. #define name_section_text "._text" #define name_section_data "._data" #define __text __attribute__ ((section (name_section_text), used)) #define __data __attribute__ ((section (name_section_data), used)) struct Sections { struct section_region { ADDRESS begin; DWORD size; } text, data, reloc; }; static void sections_clear(struct Sections *s) { s->text.begin = s->text.size = 0; s->data.begin = s->data.size = 0; s->reloc.begin = s->reloc.size = 0; } typedef HMODULE (*WINAPI _GetModuleHandleA) (LPCSTR); typedef FARPROC (*WINAPI _GetProcAddress) (HMODULE, LPCSTR); typedef int (*WINAPI _MessageBoxA) (HWND, LPCSTR, LPCSTR, UINT); //Ставим атрибуты __data для переменных и __text для функций. //const не ставим - работать не будет. __data static _GetModuleHandleA pGetModuleHandleA; __data static _GetProcAddress pGetProcAddress; __data static _MessageBoxA pMessageBoxA; ////////////////////////////////////////////////////////////////////// __data static char str_user32_dll[] = "USER32.dll"; __data static char str_messageboxa[] = "MessageBoxA"; //Выполняем инициализацию в чужом процессе. __text static void process_function_init() { HMODULE kernel32 = pGetModuleHandleA(str_user32_dll); pMessageBoxA = (_MessageBoxA)pGetProcAddress(kernel32, str_messageboxa); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// __data static char str_hello[] = "Hello"; __data static char str_message[] = "message"; //Вызываем MessageBox в чужом процессе. static void process_function_message() asm("process_function_message"); //label for asm __text static void process_function_message() { pMessageBoxA(NULL, str_hello, str_message, MB_OK); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// __data static int process_variable_test asm("process_variable_test") = 0; __text static void ASM() { #ifdef WIN64 __asm__ ( ".intel_syntax noprefix\n\t" "process_function_asm:" "sub rsp, 0x28\n\t" "mov rax, 1\n\t" "mov process_variable_test, rax\n\t" "call process_function_message\n\t" "add rsp, 0x28\n\t" "ret\n\t" ".att_syntax noprefix" ); #else __asm__ ( ".intel_syntax noprefix\n\t" "process_function_asm:" "mov eax, 1\n\t" "mov process_variable_test, eax\n\t" "call process_function_message\n\t" "ret\n\t" ".att_syntax noprefix" ); #endif } ////////////////////////////////////////////////////////////////////// //Функция правит статические адреса. static void displace_addresses(const ADDRESS base, const struct Sections *sections, ADDRESS buffer, const DWORD value) { PIMAGE_BASE_RELOCATION reloc = (PIMAGE_BASE_RELOCATION)sections->reloc.begin; DWORD offset = 0; const ADDRESS text_begin = sections->text.begin; const ADDRESS text_end = sections->text.begin + sections->text.size; while (offset != sections->reloc.size) { DWORD offset_buf_size = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); WORD *type_and_offset = (WORD*)((ADDRESS)reloc + sizeof(IMAGE_BASE_RELOCATION)); for (DWORD i = 0; i != offset_buf_size; i++) { if (type_and_offset[i] >> 12) { ADDRESS address = (base + reloc->VirtualAddress + (type_and_offset[i] & 0x0FFF)); if (text_begin <= address && text_end > address) { const DWORD offset = (address - sections->text.begin); //printf("changed %08lX\n", offset); *(DWORD*)(buffer + offset) += value; } } } offset += reloc->SizeOfBlock; reloc = (PIMAGE_BASE_RELOCATION)((ADDRESS)reloc + reloc->SizeOfBlock); } } static void init_sections(ADDRESS base_address, struct Sections *sections) { sections_clear(sections); const PIMAGE_DOS_HEADER image_dos_header = (PIMAGE_DOS_HEADER)base_address; const PIMAGE_NT_HEADERS image_nt_header = (PIMAGE_NT_HEADERS)(base_address + image_dos_header->e_lfanew); const ADDRESS section = image_dos_header->e_lfanew + image_nt_header->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_FILE_HEADER) + sizeof(DWORD); PIMAGE_SECTION_HEADER image_section_header = (PIMAGE_SECTION_HEADER)(base_address + section); for (WORD i = 0; i < image_nt_header->FileHeader.NumberOfSections; i++, image_section_header++) { const char *name = (const char*)image_section_header->Name; const ADDRESS begin = base_address + image_section_header->VirtualAddress; const DWORD size = image_section_header->Misc.VirtualSize; if (!strcmp(name, name_section_text)) { sections->text.begin = begin; sections->text.size = size; } else if (!strcmp(name, name_section_data)) { sections->data.begin = begin; sections->data.size = size; } } const PIMAGE_DATA_DIRECTORY dir = &image_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; sections->reloc.begin = base_address + dir->VirtualAddress; sections->reloc.size = dir->Size; } static void init_start_functions() { HMODULE kernel32 = GetModuleHandleA("kernel32.dll"); pGetModuleHandleA = (_GetModuleHandleA)GetProcAddress(kernel32, "GetModuleHandleA"); pGetProcAddress = (_GetProcAddress)GetProcAddress(kernel32, "GetProcAddress"); } struct ProcessMemory { ADDRESS base; DWORD size; ADDRESS text, data; }; //0x500 -> 0x1000, 0x2001 -> 0x3000 static DWORD align_size(DWORD size) { union { struct { unsigned a:12; unsigned b:20; }; DWORD c;} u; u.c = size; if (u.a == 0) { return size; } else { u.a = 0; u.b++; } return u.c; } static BOOL injection(const ADDRESS base_address, const struct Sections *sections, const HANDLE hProcess, struct ProcessMemory *memory) { const DWORD text_size = align_size(sections->text.size); const DWORD data_size = align_size(sections->data.size); #ifndef WIN64 //for x86 memory->size = text_size + data_size; memory->base = (ADDRESS)VirtualAllocEx(hProcess, 0, memory->size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (memory->base == 0) return FALSE; memory->text = memory->base; memory->data = memory->text + text_size; #else //for x64 const DWORD intermediate = sections->data.begin - sections->text.begin; memory->size = text_size + intermediate + data_size; memory->base = (ADDRESS)VirtualAllocEx(hProcess, 0, memory->size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (memory->base == 0) return FALSE; memory->text = memory->base; memory->data = memory->text + intermediate; #endif DWORD oldProtect; //text PVOID buffer = malloc(sections->text.size); memcpy(buffer, (PVOID)sections->text.begin, sections->text.size); //Копируем исполняемый код в буфер. displace_addresses(base_address, sections, (ADDRESS)buffer, memory->data - sections->data.begin); //Изменим адреса переменных с помощью reloc. WriteProcessMemory(hProcess, (PVOID)memory->text, buffer, sections->text.size, NULL); //Запишем в процесс. free(buffer); VirtualProtectEx(hProcess, (PVOID)memory->text, sections->text.size, PAGE_EXECUTE_READ, &oldProtect); //Изменим защиту на выполнение. //data WriteProcessMemory(hProcess, (PVOID)memory->data, (PBYTE)sections->data.begin, sections->data.size, NULL); //Записываем данные в процесс. VirtualProtectEx(hProcess, (PVOID)memory->data, sections->data.size, PAGE_READWRITE, &oldProtect); //Изменим защиту на чтение/запись. return TRUE; } //Создаёт поток в чужом процессе. static void createRemoteThread(const HANDLE hProcess, const ADDRESS address) { const HANDLE handle = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)address, NULL, 0, NULL); WaitForSingleObject(handle, INFINITE); CloseHandle(handle); } //Поиск процесса по названию. static DWORD findProcess(const wchar_t *name) { DWORD PID = 0; const HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnap == NULL) return PID; PROCESSENTRY32W proc; proc.dwSize = sizeof(PROCESSENTRY32W); if (Process32FirstW(hSnap, &proc)) { do { if (!wcscmp(proc.szExeFile, name)) { PID = proc.th32ProcessID; break; } } while (Process32NextW(hSnap, &proc)); } CloseHandle(hSnap); return PID; } static ADDRESS getProcessAddressText(void *address, const struct Sections *sections, const struct ProcessMemory *memory) { return ((ADDRESS)address - sections->text.begin) + memory->text; } static ADDRESS getProcessAddressData(void *address, const struct Sections *sections, const struct ProcessMemory *memory) { return ((ADDRESS)address - sections->data.begin) + memory->data; } int main() { const ADDRESS base_address = (ADDRESS)GetModuleHandleA(NULL); //Получим базовый адрес (0x00400000) struct Sections sections; init_sections(base_address, §ions); //Находим ._text, ._data и .reloc if (sections.reloc.size == 0) { printf("no section reloc\n"); return -1; } printf("section text.size %08lX\n", sections.text.size); printf("section data.size %08lX\n", sections.data.size); init_start_functions(); //Получим адреса GetModuleHandleA и GetProcAddress. const DWORD pid = findProcess(L"calc.exe"); if (pid == 0) { printf("not found process\n"); return -1; } const HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if (hProcess == NULL) { printf("error open process\n"); return -1; } //Внедряем struct ProcessMemory memory; if (!injection(base_address, §ions, hProcess, &memory)) { printf("error injection\n"); return -1; } printf("process address %08lX size %08lX\n", (DWORD)memory.base, memory.size); printf("text %08lX\n", (DWORD)memory.text); printf("data %08lX\n", (DWORD)memory.data); void *process_function_asm; asm("lea process_function_asm, %0" : "=r" (process_function_asm)); //Получим адрес метки асм. //Получим адреса наших функций и переменных. const ADDRESS address_init = getProcessAddressText((void*)&process_function_init, §ions, &memory); const ADDRESS address_message = getProcessAddressText((void*)&process_function_message, §ions, &memory); const ADDRESS address_asm = getProcessAddressText(process_function_asm, §ions, &memory); const ADDRESS address_variable_test = getProcessAddressData(&process_variable_test, §ions, &memory); printf("address init %08lX\n", (DWORD)address_init); printf("address message %08lX\n", (DWORD)address_message); printf("address asm %08lX\n", (DWORD)address_asm); printf("address variable_test %08lX\n", (DWORD)address_variable_test); fflush(stdout); //for printf //Выполняем функции в чужом процессе. createRemoteThread(hProcess, address_init); //Инициализируем. createRemoteThread(hProcess, address_message); //Покажем сообщение. createRemoteThread(hProcess, address_message); //Покажем сообщение. createRemoteThread(hProcess, address_asm); //Покажем сообщение через асм. //VirtualFreeEx(hProcess, (PVOID)m.base, 0, MEM_RELEASE); CloseHandle(hProcess); return 0; } Изменено 25 октября, 2019 пользователем Hack Ссылка на комментарий Поделиться на другие сайты Поделиться
gmz Опубликовано 28 октября, 2019 Поделиться Опубликовано 28 октября, 2019 В 25.10.2019 в 21:07, Hack сказал: HMODULE kernel32 = GetModuleHandleA("kernel32.dll"); pGetModuleHandleA = (_GetModuleHandleA)GetProcAddress(kernel32, "GetModuleHandleA"); pGetProcAddress = (_GetProcAddress)GetProcAddress(kernel32, "GetProcAddress"); это и похоже - что бы было больше текста? (LPTHREAD_START_ROUTINE)GetModuleHandleA (LPTHREAD_START_ROUTINE)GetProcAddress Ссылка на комментарий Поделиться на другие сайты Поделиться
Hack Опубликовано 28 октября, 2019 Автор Поделиться Опубликовано 28 октября, 2019 Что? Как это использовать потом? Ссылка на комментарий Поделиться на другие сайты Поделиться
gmz Опубликовано 29 октября, 2019 Поделиться Опубликовано 29 октября, 2019 22 часа назад, Hack сказал: Что? Как это использовать потом? также. просто адреса напрямую из импорта. оно ведь не ASLR в любом варианте. Ссылка на комментарий Поделиться на другие сайты Поделиться
Hack Опубликовано 29 октября, 2019 Автор Поделиться Опубликовано 29 октября, 2019 Так можно адрес функции получить или адрес на jmp в зависимости от настроек компилятора. Затем тут тип LPTHREAD_START_ROUTINE? Ссылка на комментарий Поделиться на другие сайты Поделиться
gmz Опубликовано 29 октября, 2019 Поделиться Опубликовано 29 октября, 2019 2 часа назад, Hack сказал: Затем тут тип LPTHREAD_START_ROUTINE? ну эт как пример. юзал похоже в CreateRemoteThread(hProcess,0,0x1000,(LPTHREAD_START_ROUTINE)LoadLibraryW,RemoteBuffer,0,0); Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения