2016-07-31 11 views
0

Я сделал простую программу, которая вычисляет RVA функции MessaegBoxA в user32.dll, а затем добавляет это смещение к базовому адресу загрузки DLL в память удаленного процесса, чтобы получить адрес функции MessageBoxA. Я сделал фиктивную программу, которая выводит адрес функции в своей памяти с помощью GetProcAddress, а затем реализует мою собственную функцию в моей программе, чтобы отобразить адрес, который он рассчитал для одной и той же функции в удаленном процессе. Они всегда совпадают, поэтому я уверен, что моя функция поиска адреса MessageBoxA в удаленном процессе - это не проблема.CreateRemoteThread MessageBoxA заставляет удаленный процесс сбой

Я сделал struct, который содержит всю необходимую информацию и параметры, необходимые для ThreadProc выполнить MessageBoxA в удаленном процессе, когда я загрузить его, используя WriteProcessMemory.

typedef struct 
{ 
    typedef int (WINAPI* _MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT); 
    _MessageBoxA MessageBoxA; 
    //These are the four parameters passed to MessageBoxA 
    HWND hwnd; 
    LPCSTR msg; 
    LPCSTR caption; 
    UINT mb; 
}MB_DATA, *PMB_DATA; 

Когда я попробовать это на моей собственной фиктивной программы, окно сообщения появляется, но с странным текстом, противоречащими строками я указал в msg и caption членах MB_DATA. Для заголовка asic_string::erase указано следующее: для сообщения указано u). И когда я пытаюсь сделать это в любом другом процессе, чем мой фиктивный процесс, он сбрасывает удаленный процесс. Я сделал функцию для итерации через модули, которые были загружены в процесс с помощью функций tlhelp32, чтобы убедиться, что user32.dll присутствует, и это так, и моя функция поиска адреса функции в процессе не возвращает NULL, как если бы это было dll отсутствовали.

Здесь все соответствующие функции и моя main функция:

dependencies.hpp

#include <windows.h> 
#include <tlhelp32.h> 
#include <stdio.h> 
#include <iostream> 
using namespace std; 

typedef struct 
{ 
    typedef int (WINAPI* _MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT); 
    _MessageBoxA MessageBoxA; 
    HWND hwnd; 
    LPCSTR msg; 
    LPCSTR caption; 
    UINT mb; 
}MB_DATA, *PMB_DATA; 

//Map the dll into memory 
void* GetFileImage(char path[]) 
{ 
    HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); 
    if(hFile == INVALID_HANDLE_VALUE){printf("Error getting file handle: %d", (int)GetLastError());return NULL;} 

    HANDLE file_map = CreateFileMapping(hFile, NULL, PAGE_READONLY|SEC_IMAGE, 0, 0, "KernelMap"); 
    if(file_map == INVALID_HANDLE_VALUE){printf("Error mapping file: %d", (int)GetLastError());return NULL;} 

    LPVOID file_image = MapViewOfFile(file_map, FILE_MAP_READ, 0, 0, 0); 
    if(file_image == 0){printf("Error getting mapped view: %d", (int)GetLastError());return NULL;} 

    return file_image; 
} 

//Get to the function export directory and find the offset for the specified function from the 
//address in memory the dll was loaded at 
DWORD_PTR RVAddress(char* image, const char* proc_name) 
{ 
    PIMAGE_DOS_HEADER pDos_hdr = (PIMAGE_DOS_HEADER)image; 
    PIMAGE_NT_HEADERS pNt_hdr = (PIMAGE_NT_HEADERS)(image+pDos_hdr->e_lfanew); 
    IMAGE_OPTIONAL_HEADER opt_hdr = pNt_hdr->OptionalHeader; 
    IMAGE_DATA_DIRECTORY exp_entry = opt_hdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 
    PIMAGE_EXPORT_DIRECTORY pExp_dir = (PIMAGE_EXPORT_DIRECTORY)(image+exp_entry.VirtualAddress); 

    DWORD* func_table = (DWORD*)(image+pExp_dir->AddressOfFunctions); 
    WORD* ord_table = (WORD*)(image+pExp_dir->AddressOfNameOrdinals); 
    DWORD* name_table = (DWORD*)(image+pExp_dir->AddressOfNames); 

    for(u_int i=0;i<pExp_dir->NumberOfNames;i++) 
    { 
     char* name = (char*)(image+name_table[i]); 
     if(strcmp(proc_name, name) == 0) 
     { 
      return (DWORD_PTR)func_table[ord_table[i]]; 
     } 
    } 

    return (DWORD_PTR)0; 
} 

//Add the RVA returned from RVAddress to the address of the dll to find the function in the 
//process memory 
LPVOID GetProcAddressEx(DWORD dwPid, char* mod_path, char* function_name, char* mod_name) 
{ 
    HANDLE hSnapshot = INVALID_HANDLE_VALUE; 
    MODULEENTRY32 me32; 
    me32.dwSize = sizeof(MODULEENTRY32); 

    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE|TH32CS_SNAPMODULE32, dwPid); 
    if(hSnapshot == INVALID_HANDLE_VALUE){printf("Snapshot failed");return 0;} 

    if(!(Module32First(hSnapshot, &me32))) 
    { 
     printf("Mod32First failed"); 
     return 0; 
    } 

    BOOL found = FALSE; 

    while(Module32Next(hSnapshot, &me32)) 
    { 
     if(stricmp(me32.szModule, mod_name) == 0) 
     { 
      CloseHandle(hSnapshot); 
      found = TRUE; 
      break; 
     } 
    } 

    if(found == FALSE){return 0;} 

    DWORD_PTR RVA = (DWORD_PTR)RVAddress((char*)GetFileImage(mod_path), function_name); 

    LPVOID func_addr = me32.modBaseAddr+RVA; 
    return func_addr; 
} 

main.cpp

#include "dependencies.hpp" 
#define FUNC_SIZE 1024 

typedef int (WINAPI* _MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT); 

int main() 
{ 
    MB_DATA mb_data; 
    mb_data.hwnd = NULL; 
    mb_data.msg = "Hey"; 
    mb_data.caption = "Yo"; 
    mb_data.mb = MB_OK; 

    SIZE_T nBytes = 0; 

    char proc_path[MAX_PATH]; 
    char kernel_path[MAX_PATH]; 
    char user32_path[MAX_PATH]; 

    //get full path to the current process and store it in proc_path 
    GetModuleFileName(GetModuleHandle(NULL), proc_path, MAX_PATH); 
    //get full path to kernel32.dll and store it in kernel_path 
    GetModuleFileName(GetModuleHandle("kernel32.dll"), kernel_path, MAX_PATH); 
    //get full path to user3.dll and store it in user32_path 
    GetModuleFileName(GetModuleHandle("user32.dll"), user32_path, MAX_PATH); 

    //show all processes running and their PID's 
    system("tasklist"); 

    DWORD dwPid = 0; 
    printf("PID: "); 
    scanf("%lu", &dwPid); 
    //if dwPid is 0 assign it the pid of the current process 
    if(dwPid == 0) 
    { 
     dwPid = GetCurrentProcessId(); 
    } 

    //Get a handle to the process with all access rights 
    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); 
    //make sure the handle is valid 
    if(hProc == NULL){printf("Error obtaining handle to process: %lu", GetLastError());return 1;} 

    //Get the address of the function in the remote process 
    LPVOID _MessageBoxA1 = GetProcAddressEx(dwPid, user32_path, (char*)"MessageBoxA", (char*)"user32.dll"); 
    //assign the pointer to the address to the member MessageBoxA of the MB_DATA structure 
    mb_data.MessageBoxA = (_MessageBoxA)_MessageBoxA1; 

    //allocate 2mb for our the ThreadProc callback function and the MB_DATA structure 
    LPVOID lpBase = VirtualAllocEx(hProc, NULL, 2048, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); 
    //did the allocation work 
    if(lpBase == NULL){printf("Error allocating space: %lu", GetLastError());return 1;} 

    //so I can check what was written with CheatEngine 
    cout << "Base address of memory allocated in remote process: " << lpBase << endl; 

    //Write the function into memory 
    if(WriteProcessMemory(hProc, lpBase, (LPVOID)ThreadProc, FUNC_SIZE, &nBytes) == 0) 
    { 
     printf("Error writing function to process"); 
     return 1; 
    } 

    //the address the space left after having written ThreadProc into memory 
    LPVOID lpBuffer = lpBase+FUNC_SIZE; 

    //Write the MB_DATA structure into the memory of the remote process 
    if(WriteProcessMemory(hProc, lpBuffer, &mb_data, sizeof(MB_DATA), &nBytes) == 0) 
    { 
     printf("Error writing buffer to process"); 
    } 

    //Run the ThreadProc function passing the MB_DATA structure to it as its lpParam parameter 
    if(CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lpBase, lpBuffer, 0, NULL) == NULL) 
    { 
     printf("Error creating remote thread: %lu", GetLastError()); 
     return 1; 
    } 

    //print a list of all the dll's being used by the process 
    EnumerateModules(dwPid); 

    system("pause"); 

    return 0; 
} 

Любая помощь был бы весьма признателен. Большое спасибо! :)

+0

Код, который опубликовал, не является полным - вы не показываете, что такое «ThreadProc». –

+0

@HarryJohnston Я значительно изменил его и нашел решение. Так что это уже не нужно. –

ответ

0

mb_data.msg и mb_data.caption указывают на то, что в другом процессе? этого достаточно для ошибки сбоя. что в ThreadProc не видно, но я не уверен, что у него нет релоков. действительно ThreadProc должен быть членом функции MB_DATA и получать доступ только к ее членам. очевидно, что вы не отлаживаете удаленный процесс во время впрыска. также очевидно, что задача выполнена по вашему текущему уровню

+0

Я могу окунуться как невыносимый маленький нооблет, но почему 'ThreadProc' должен быть членом' MB_DATA'? И спасибо, что указали на проблему с msg и заголовком. Я забыл, что массивы персонажей автоматически распадаются на указатели. –

+0

«Почему ThreadProc должен быть членом MB_DATA» - это не должно быть, но оно не должно содержать релоков. как решение - быть функцией-членом и доступ только к элементам данных MB_DATA. из другой точки это во всех случаях член или MB_DATA по факту. void ThreadProc (MB_DATA *); - думайте, что это текущая подпись.GetFileImage - вы даже не пытаетесь освободить ресурсы, и вообще, почему бы не использовать LoadLibraryEx (DONT_RESOLVE_DLL_REFERENCES) и GetprocAddress в общем случае – RbMm

+0

, что вы подразумеваете под «relocs»? Переезды? –