Я пытаюсь изучить некоторые ручные инъекции DLL, но, похоже, не может заставить выполнение кода DLL работать. Я новичок в Windows C ++, поэтому любые советы по улучшению моего кода приветствуются. Я также только опубликовал соответствующий код.

Инжекторная программа:

hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, getPID(TARGET_NAME));

DWORD gotDLL = GetFullPathName(DLL_NAME, MAX_PATH, dllPath, NULL);

hFile = CreateFile(dllPath, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

dllFileSize = GetFileSize(hFile, NULL);
memAddrForDLL = VirtualAllocEx(hProcess, NULL, dllFileSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

loadedDLL = HeapAlloc(GetProcessHeap(), NULL, dllFileSize);

// Load dll into allocated memory in current process
ReadFile(hFile, loadedDLL, dllFileSize, &bytesRead, NULL))

// Find offset of dll entry point
IMAGE_NT_HEADERS* pOldNtHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(reinterpret_cast<BYTE*>(loadedDLL) + reinterpret_cast<IMAGE_DOS_HEADER*>(loadedDLL)->e_lfanew);
IMAGE_OPTIONAL_HEADER* pOldOptHeader = &pOldNtHeader->OptionalHeader;

entryPointOffset = pOldOptHeader->AddressOfEntryPoint;

// Load dll into allocated memory in target process
WriteProcessMemory(hProcess, memAddrForDLL, loadedDLL, bytesRead, NULL)

LPTHREAD_START_ROUTINE entryPoint = (LPTHREAD_START_ROUTINE)((unsigned __int64)memAddrForDLL + entryPointOffset);

CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibrary, entryPoint, NULL, NULL)

DLL :

DWORD WINAPI OnDllAttach(LPVOID base){
    typedef void func(void);
    func* f = (func*)0x00007FF605EC5835;
    f();
    FreeLibraryAndExitThread(static_cast<HMODULE>(base),1);
}

BOOL WINAPI OnDllDetach(){
    return TRUE;
}

BOOL WINAPI DllMain(_In_ HINSTANCE hinstDll,
                    _In_ DWORD fdwReason,
                    _In_opt_ LPVOID lpvReserved){
    typedef void func(void);
    func* f = (func*)0x00007FF605EC5835;
    f();
    switch(fdwReason) {
        case DLL_PROCESS_ATTACH:
            DisableThreadLibraryCalls(hinstDll);
            CreateThread(nullptr, 0, OnDllAttach, hinstDll, 0, nullptr);
            return TRUE;
        case DLL_PROCESS_DETACH:
            if(lpvReserved == nullptr)
                return OnDllDetach();
            return TRUE;
        default:
            return TRUE;
    }
}

Целевая программа содержит эту функцию:

void printer(){
    cout << "test" << endl;
}

Мой инжектор выдает следующий вывод

1. Attempting to attatch to process target.exe
--- Got target.exe PID: 14640
--- Got target.exe Handle: 0x0000000000000084
2. Attempting to allocate memory
--- Found dll: D:\projects\injector\hack.dll
--- Got hack.dll Handle: 0x0000000000000088
--- Allocated memory in target.exe at 0x0000017BEB690000
3. Attempting to copy dll to target.exe
--- Allocated memory at 0x00000226A060FFE0
--- Loaded hack.dll in current process at 0x00000226A060FFE0
--- hack.dll is a valid DLL
--- Loaded hack.dll into target.exe at 0x0000017BEB690000
4. Attempting to execute dll
--- Offset from start of file to entrypoint: 0x3cf6
--- Began execution of hack.dll in target.exe at 0x0000017BEB693CF6

Используя Гидру, я могу подтвердить, что это правильное смещение для точки входа dll. Но при запуске моего инжектора ничего не происходит в целевом процессе, я также пытался использовать cout для печати сообщения из dll, но я ничего не получаю (я не думаю, что это будет работать даже потому, что ничего не было перемещено)

Я использовал

CreateRemoteThread(hProcess, NULL, NULL, entryPoint, memAddrForDLL, NULL, NULL)

До того, как 4-й параметр называется lpStartAddress, и я подумал, что для этого нужна точка входа, но это приводило к сбою целевого процесса, и каждый пример, который я видел, использовал то, что у меня сейчас есть в моем коде.

В моей dll я вызываю функцию в целевом процессе по адресу.

РЕДАКТИРОВАТЬ: я тестирую это на моем собственном консольном приложении.

-2
Mumphus 20 Апр 2019 в 00:59

2 ответа

Лучший ответ

Самая основная форма внедрения DLL:

  • Выделение памяти в целевом процессе с помощью VirtualAllocEx ()
  • Запись пути DLL в эту область памяти с помощью WriteProcessMemory
  • Вызов LoadLibrary () через CreateRemoteThread () в целевом процессе
  • Передача области памяти, где путь к DLL записан в этот вызов

У вас уже есть это, но ваша цель состоит в том, чтобы вручную отобразить DLL и избегать использования LoadLibrary (). Код, который вы предоставили, не сработает, есть еще около 5 шагов. Вам нужно эмулировать все, что обычно делает LoadLibrary ():

  • Загрузить сырые двоичные данные
  • Карта разделов в целевой процесс
  • Внедрить шеллкод загрузчика
  • Делать переезды
  • Исправить импорт
  • Выполнить обратные вызовы TLS
  • Позвонить в DllMain
  • Очистка

Преимущества сопоставления вручную состоят в том, что вы будете скрыты от ToolHelp32Snapshot (), пройдя список связанных модулей в PEB и NtQueryVirtualMemory.

Если вы хотите сделать это правильно, с достойной проверкой ошибок, это около 350 строк кода, и это становится сложным. Все это делается путем анализа PE-заголовка.

  1. Получить идентификатор процесса цели
  2. Прочитайте файл DLL
  3. Выделите память в целевом процессе того же размера, что и ImageBase из PE-заголовка
  4. Цикл по секциям PE после анализа заголовка PE
  5. Запишите раздел в память в правильном относительном адресе
  6. Написать шелл-код в целевой процесс
  7. Вызовите CreateRemoteThread и установите свой шеллкод для выполнения
  8. Ваш шеллкод исправляет импорт и делает перемещения
  9. Ваш Shellcode выполняет обратные вызовы TLS
  10. Вышеуказанные 2 шага выполняются при разборе DataDirectory в необязательном заголовке.
  11. Вызовите DllMain () с аргументом DLL_PROCESS_ATTACH

Теперь ваша DLL загружена и выполняется сценарий переключения DLL_PROCESS_ATTACH. Очевидно, что это сложнее, но это идея.

Я бы ничего не знал об этом, если бы мой друг Бройхон не научил меня этому, поэтому я хочу отдать ему должное. Удачи

1
GuidedHacking 15 Май 2019 в 01:26

Загруженный в память файл .DLL - это не то же самое, что файл .DLL на диске. Расположение разделов не одинаково, и вам нужно иметь дело с перемещениями, таблицей импорта и списком загруженных модулей PEB. Вы в основном должны повторно реализовать NTDLL!Ldr*.

Вызов CreateRemoteThread для LoadLibrary - это другой метод, и когда вы делаете это, параметр потока должен указывать на путь .DLLs в удаленном процессе, а не на точку входа.

0
Anders 20 Апр 2019 в 09:03