2016-10-11 7 views
0

Я пытаюсь запустить 64-разрядную DLL исключительно в виртуальной памяти процессов без «вручную отображать» ее (то есть вручную разрешать перемещение/импорт).64-битная кодовая строка Возврат Неправильная точка входа

План заключается в том, чтобы вводить код в целевое приложение и загружать модуль с помощью обычных средств, таких как LoadLibrary.

Я был в предположении, что LoadLibrary будет исправлять перемещение/импорт модулей самостоятельно, так как это то, что он предназначен для выполнения.

После загрузки модуля введенный код получит информацию о модуле с GetModuleInformation, передаст его во временный буфер памяти, освободит модуль, распределит память по тому же адресу, на который он был первоначально загружен, запишет его и выполнить точку входа.

Этот последний шаг - это то место, где я считаю, что ошибка происходит.

Чтобы проверить эту теорию, у меня есть жестко кодирующие адреса точек входа, отладка удаленного приложения с помощью функции «Присоединить к процессу» Visual Studio, эмуляция аналогичной среды для исправления арифметики с плохими указателями, чтобы получить бит больше информации о том, что может быть ошибкой.


Вот некоторые общие сведения, которые могут или не могут быть полезны:

  • Оба приложения (инжектор, и DLL), составляются для работы в 64-разрядных архитектур
  • тестовое приложение, которое я использовал для тестирования метода инъекции, - это приложение для обновления Windows (wuauclt.exe - находится в/System32 /), оно, конечно, скомпилировано для запуска в виде 64-разрядного PE
  • Хост-компьютер: Windows 7 Home до Mium (тип системы: 64-разрядная операционная система)

Насколько информация, относящаяся непосредственно к инжектору идет:

  • Способ первичной инъекции код работает (насколько я могу сказать) , и я это доказал с помощью отладчика caveman с MessageBoxA
  • Проект использует многобайтовый набор символов с отключенными оптимизациями кода. Код был составлен с использованием VS 2013 Ultimate (с обоих проектов, построенных для выпуска x64)
  • СВД проверки выключены, поскольку используются небезопасные функции (STRCPY и друзей)
  • Инжектор отлажена с повышенными привилегиями (так высоко, как SE_DEBUG_PRIVILEGES) каждый время его побежало.

Код Предисловие: Код экспонировались ниже не в любой, какой путь означало выглядеть довольно или экспонат хорошо практики программирования. Помните об этом при просмотре кода. Он был специально разработан для тестирования метода ввода кода для проверки его работоспособности. Если у вас есть проблемы с макетом программы, структурой и т. Д., Не стесняйтесь исправлять их и/или реструктурировать их самостоятельно. Это не причина, по которой я здесь.Если это не то, что в результате ошибки, то это полностью причина, почему я здесь :)

Код для инжектора:http://pastebin.com/FF5G9nnR

/* 
    Some of the code was truncated (functions not pertaining to the injection), but 
    I have verified the code compiles and works correctly with it's injeteme.dll counterpart 
*/ 

#include <Windows.h> 
#include <Psapi.h> 

#define TARGET_PID    1124 

typedef BOOL(WINAPI* pFreeLibrary)(HMODULE); 
typedef HMODULE(WINAPI* pLoadLibraryA)(LPCSTR); 
typedef HANDLE(WINAPI* pGetCurrentProcess)(void); 
typedef BOOL(WINAPI* DLL_MAIN)(HMODULE, DWORD, LPVOID); 
typedef HANDLE(WINAPI* pOpenProcess)(DWORD, BOOL, DWORD); 
typedef BOOL(WINAPI* pVirtualFree)(LPVOID, SIZE_T, DWORD); 
typedef int(__stdcall* pMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT); 
typedef LPVOID(WINAPI* pVirtualAlloc)(LPVOID, SIZE_T, DWORD, DWORD); 
typedef BOOL(WINAPI* pGetModuleInformation)(HANDLE, HMODULE, LPMODULEINFO, DWORD); 
typedef BOOL(WINAPI* pWriteProcessMemory)(HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T*); 

////////////////////////////////////////////////////////////////// 
struct IINFO 
{ 
    LPVOID stubAddr; 
    LPVOID retStatusPtr; 
    char fullModulePath[MAX_PATH]; 
    DWORD pId, sizeOfCurrStruct; 

    // DEBUG 
    pMessageBoxA messageBox; 

    pOpenProcess openProcess; 
    pVirtualFree virtualFree; 
    pFreeLibrary freeLibrary; 
    pLoadLibraryA loadLibrary; 
    pVirtualAlloc virtualAlloc; 
    pGetCurrentProcess getCurrProc; 
    pWriteProcessMemory writeMemory; 
    pGetModuleInformation getModInfo; 
}; 

static DWORD WINAPI stub(IINFO *iInfo) 
{ 
    HMODULE hMod; 
    MODULEINFO mInfo; 
    DLL_MAIN dllMain; 
    LPVOID lpNewMod, lpTempModBuff; 

    PIMAGE_DOS_HEADER pIDH; 
    PIMAGE_NT_HEADERS pINH; 

    iInfo->messageBox(NULL, iInfo->fullModulePath, NULL, 0); 

    hMod = iInfo->loadLibrary(iInfo->fullModulePath); 
    if (!hMod) 
     return 0; 

    if (!iInfo->getModInfo(iInfo->getCurrProc(), hMod, &mInfo, sizeof(MODULEINFO))) 
     return 0; 

    lpTempModBuff = iInfo->virtualAlloc(NULL, mInfo.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 
    if (!lpTempModBuff) 
     return 0; 
    if (!iInfo->writeMemory(iInfo->getCurrProc(), lpTempModBuff, mInfo.lpBaseOfDll, mInfo.SizeOfImage, NULL)) 
     return 0; 

    if (!iInfo->freeLibrary(hMod)) 
     return 0; 

    lpNewMod = iInfo->virtualAlloc(mInfo.lpBaseOfDll, mInfo.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 
    if (!lpNewMod) 
     return 0; 

    // using wpm since we have already acquired the function 
    if (!iInfo->writeMemory(iInfo->getCurrProc(), lpNewMod, lpTempModBuff, mInfo.SizeOfImage, NULL)) 
     return 0; 

    if (!iInfo->virtualFree(lpTempModBuff, 0, MEM_RELEASE)) 
     return 0; 

    /*if (!iInfo->virtualFree(iInfo, 0, MEM_RELEASE)) 
    return 0; 
    iInfo->messageBox(NULL, NULL, NULL, 0); */ 

    pIDH = (PIMAGE_DOS_HEADER)lpNewMod; 
    if (!pIDH) 
     return 0; 
    pINH = (PIMAGE_NT_HEADERS)((LPBYTE)lpNewMod + pIDH->e_lfanew); 
    if (!pINH) 
     return 0; 
    dllMain = (DLL_MAIN)((LPBYTE)lpNewMod + pINH->OptionalHeader.AddressOfEntryPoint); 
    if (!dllMain) 
     return 0; 
    iInfo->messageBox(NULL, NULL, NULL, 0); 
    dllMain((HINSTANCE)lpNewMod, DLL_PROCESS_ATTACH, NULL); 
    return 1; 
} 
static DWORD WINAPI stubEnd(){ return 0; } 
////////////////////////////////////////////////////////////////// 

int main() 
{ 
    HANDLE hThread = 0; 
    DWORD dwStubSize = 0; 
    int sucResp = 0, count = 0; 
    HMODULE hUser32 = 0, hNtdll = 0; 
    char fullPathName[] = "C:\\injectme.dll"; 

    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, TARGET_PID); 
    if (!hProc || hProc == INVALID_HANDLE_VALUE) 
     return 0; 

    __int64 SizeOfStub = (LPBYTE)stubEnd - (LPBYTE)stub; 
    LPVOID lpStub = VirtualAllocEx(hProc, NULL, SizeOfStub, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 
    if (!lpStub) 
     return 0; 

    hUser32 = LoadLibraryA("user32.dll"); 
    if (!hUser32) 
     return 0; 
    hNtdll = LoadLibraryA("kernel32.dll"); 
    if (!hNtdll) 
     return 0; 

    IINFO iInfo = {}; 
    iInfo.retStatusPtr = &sucResp; 
    strcpy(iInfo.fullModulePath, fullPathName); 
    iInfo.sizeOfCurrStruct = sizeof(IINFO); 
    iInfo.stubAddr = lpStub; 
    iInfo.pId = GetCurrentProcessId(); 
    iInfo.messageBox = (pMessageBoxA)GetProcAddress(hUser32, "MessageBoxA"); 
    iInfo.openProcess = (pOpenProcess)GetProcAddress(hNtdll, "OpenProcess"); 
    iInfo.virtualFree = (pVirtualFree)GetProcAddress(hNtdll, "VirtualFree"); 
    iInfo.freeLibrary = (pFreeLibrary)GetProcAddress(hNtdll, "FreeLibrary"); 
    iInfo.loadLibrary = (pLoadLibraryA)GetProcAddress(hNtdll, "LoadLibraryA"); 
    iInfo.virtualAlloc = (pVirtualAlloc)GetProcAddress(hNtdll, "VirtualAlloc"); 
    iInfo.getCurrProc = (pGetCurrentProcess)GetProcAddress(hNtdll, "GetCurrentProcess"); 
    iInfo.writeMemory = (pWriteProcessMemory)GetProcAddress(hNtdll, "WriteProcessMemory"); 
    iInfo.getModInfo = (pGetModuleInformation)GetProcAddress(hNtdll, "K32GetModuleInformation"); 

    LPVOID lpStubInfo = VirtualAllocEx(hProc, NULL, sizeof(IINFO), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 
    if (!lpStubInfo) 
     return 0; 

    if (!WriteProcessMemory(hProc, lpStub, stub, SizeOfStub, NULL)) 
     return 0; 
    if (!WriteProcessMemory(hProc, lpStubInfo, &iInfo, sizeof(iInfo), NULL)) 
     return 0; 

    hThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lpStub, lpStubInfo, 0, NULL); 
    if (!hThread || hThread == INVALID_HANDLE_VALUE) 
     return 0; 

    WaitForSingleObject(hThread, INFINITE); 

    return 1; 
} 

Код для DLL, который будет введен :http://pastebin.com/8WXxcpu1

#include <Windows.h> 

BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpParam) 
{ 
    switch (fdwReason) 
    { 
     case DLL_PROCESS_ATTACH: 
     { 
      MessageBoxA(NULL, "Hello from injectme.dll!", "", MB_OK | MB_ICONINFORMATION); 
      break; 
     } 
     case DLL_THREAD_ATTACH: 
     case DLL_THREAD_DETACH: 
     case DLL_PROCESS_DETACH: 
      break; 
    } 

    return TRUE; 
} 

Погрешность при запуске код выше дословное (если вы также применены вышеуказанные настройки и имеют сходную среду) в отладчике VS2013 заключается в следующем:

«Необработанное исключение в 0x000007FEEA5125D4 в wuauclt.exe: 0xC0000005: нарушение прав доступа выполнение местоположения 0x000007FEEA5125D4.»

При просмотре процесса «wuauclt.exe» в Process Hacker я отчетливо вижу, что модуль был первоначально изначально (после загрузки через LoadLibrary) на 0x7fef67c0000. Это показано в контекстном меню-> по разным-> разгруженным модулям.

После двойного щелчка «wuauclt.exe» вы можете просматривать виртуальную память приложения, чтобы все работало должным образом. Я могу подтвердить этот текущий сеанс, буфер памяти RWX был выделен на 0x7fef67c0000 с точным размером разгруженного модуля, содержащим модуль injectme.dll. При перекопании в injectme.dll с CFF Explorer, точка входа RVA кажется 0x132C, что не складывается, учитывая, что ошибка намного больше в памяти. Кроме того, я могу проверить еще два буфера памяти RWX, содержащих заглушку ввода кода, и структуру информации. Оглядываясь назад, структура информации, вероятно, не нуждается в RWX. Во всяком случае, я не могу за всю жизнь понять ошибку.

Я надеюсь, что вы сможете мне помочь. Я очень благодарен за ваше время.

+0

введите код здесь – manetsus

+0

@manetsus my bad, код был перемещен из pastebin. Извините за любые неудобства. – astra

ответ

1

У меня возникает ощущение, что вам не хватает фундаментального понимания такого сложного проекта. Вы смешиваете понятия из довольно разных сфер.

Windows сама заботится очень, очень мало о языке программирования, который вы использовали в разработке. Либо вы получаете код CLR (.Net), либо собственный код. В этом случае это x64. Но Windows действительно не заботится о strcpy или SDL чеках. Это касается компилятора, а не ОС. Шансы strcpy даже не выживут, когда его код полностью вложен. Но вы, по-видимому, отключили оптимизацию по какой-то странной причине - опять-таки компилятор против путаницы ОС.

Однако Windows делает заботиться о других концепциях, о которых вы не упоминаете. В основном это будут ASLR и DEP - ранжирование макета адресного пространства и предотвращение выполнения данных. Они - методы, чтобы держать хакеров, и вы взламываете. Так что это не удивительно.

Я не уверен, что если на «RWX» вы имеете в виду Read Write Execute», потому что вы должны знать, что просит проблем. DEP вдохновлен более метко назвал W^X, запись XOR Execute.

Скорее всего, виновником является ASLR, но Windows по дизайну пытается загрузить DLL на непредсказуемые адреса, поскольку это исключает целый класс хаков. Похоже, вы принимаете адрес загрузки, а Windows действительно использует другой адрес.

Последней ошибкой может быть то, что вы не понимаете , где перемещение выполнено. Чтобы улучшить количество разделяемых страниц, перемещение выполняется в таблице адресов импорта, а не в самом коде. IAT является таблицей батута и, следовательно, исполняемым. Ваш отказ также может быть недостающим IAT.

+0

Прежде всего, я хотел бы искренне поблагодарить вас за ответ. Полное раскрытие, я только работаю над этим в течение нескольких дней и не думал о DEP/ASLR. – astra

+0

(Извините, мой предыдущий комментарий был отрезан, прежде чем я смог полностью ответить) – astra

+0

Ну, похоже, что удары будут возвращены автоматически. Я новичок в этом и предполагаю, что они не должны быть очень длинными. То, что я пытаюсь спросить, - двигаться вперед, где, по-вашему, я должен позиционировать свое внимание? Насколько я понимаю, LoadLibrary должен выполнять любые модификации, чтобы переданный ему модуль мог эффективно выполнять. Как только у него есть шанс сделать это, он просто перемещается в памяти. Это место для окончательного отдыха, где оно началось. И не предполагает, что точка входа «на лету». Извините, но я немного смущен. – astra

 Смежные вопросы

  • Нет связанных вопросов^_^