Вклинивание dll в новый процесс
От: Аноним  
Дата: 28.03.07 15:24
Оценка:
Остался последний этап. Помогите уже добить эту прогу. Итак , я перехватываю CreateProcess из своей длл. Теперь я дожен внедрится в новое приложение.. Вот как я это делаю

BOOL WINAPI UnrealMyCreateProccessA(IN LPCSTR lpApplicationName,IN LPSTR lpCommandLine,IN LPSECURITY_ATTRIBUTES lpProcessAttributes,IN LPSECURITY_ATTRIBUTES lpThreadAttributes,IN BOOL bInheritHandles,IN DWORD dwCreationFlags,IN LPVOID lpEnvironment,IN LPCSTR lpCurrentDirectory,IN LPSTARTUPINFOA lpStartupInfo,OUT LPPROCESS_INFORMATION lpProcessInformation)

{
  dwCreationFlags=CREATE_SUSPENDED; //Замораживаю
//Вызываю оригинальную
  BOOL handle=MyCreateProccessA(  lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
  if(handle)

  {
    WaitForSingleObject(hMutex, INFINITE);
    //.... Тут код мой, где передаю проге id процесса и вклиниваюсь,по Рихтеру
    WaitForSingleObject(Event,INFINITE);
    ReleaseMutex(hMutex);
  }

  ResumeThread(lpProcessInformation->hThread);// Продолжаю работать

  return handle;
}


А вот собствено вклинивание, т.е. функция OpenProcessin(DWORD dwProcessId, CString Dll_name), которой я передаю id перехваченого процесса для вклинивания



BOOL CExInjectDlg::OpenProcessin(DWORD dwProcessId, CString Dll_name)
{
  BOOL fOk = FALSE; // Assume that the function fails
  HANDLE hProcess = NULL, hThread = NULL;
  PWSTR pszLibFileRemote = NULL;

    // Get a handle for the target process.
    hProcess = OpenProcess(
      PROCESS_QUERY_INFORMATION |   // Required by Alpha
      PROCESS_CREATE_THREAD     |   // For CreateRemoteThread
      PROCESS_VM_OPERATION      |   // For VirtualAllocEx/VirtualFreeEx
      PROCESS_VM_WRITE,             // For WriteProcessMemory
      FALSE, dwProcessId);
    if (hProcess == NULL)
    {
      if (pszLibFileRemote != NULL) 
        VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

      if (hThread  != NULL) 
        CloseHandle(hThread);

      if (hProcess != NULL) 
        CloseHandle(hProcess);
      return FALSE;
    }

    // Calculate the number of bytes needed for the DLL's pathname
    int cch = 1 + lstrlenW(Dll_name.GetBuffer());
    int cb  = cch * sizeof(WCHAR);

    // Allocate space in the remote process for the pathname
    pszLibFileRemote = (PWSTR) 
      VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
    if (pszLibFileRemote == NULL) 
    {
      if (pszLibFileRemote != NULL) 
        VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

      if (hThread  != NULL) 
        CloseHandle(hThread);

      if (hProcess != NULL) 
        CloseHandle(hProcess);
      return FALSE;
    }

    // Copy the DLL's pathname to the remote process's address space
    if (!WriteProcessMemory(hProcess, pszLibFileRemote, 
      (PVOID) Dll_name.GetBuffer(), cb, NULL))
    {
      if (pszLibFileRemote != NULL) 
        VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

      if (hThread  != NULL) 
        CloseHandle(hThread);

      if (hProcess != NULL) 
        CloseHandle(hProcess);
      return FALSE;
    }

    // Get the real address of LoadLibraryW in Kernel32.dll
    PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
      GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
    if (pfnThreadRtn == NULL)
    {
      if (pszLibFileRemote != NULL) 
        VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

      if (hThread  != NULL) 
        CloseHandle(hThread);

      if (hProcess != NULL) 
        CloseHandle(hProcess);
      return FALSE;
    }

    // Create a remote thread that calls LoadLibraryW(DLLPathname)
    hThread = CreateRemoteThread(hProcess, NULL, 0, 
      pfnThreadRtn, pszLibFileRemote, 0, NULL);
    if (hThread == NULL)
    {
      if (pszLibFileRemote != NULL) 
        VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

      if (hThread  != NULL) 
        CloseHandle(hThread);

      if (hProcess != NULL) 
        CloseHandle(hProcess);
      return FALSE;
    }

    // Wait for the remote thread to terminate
    WaitForSingleObject(hThread, INFINITE);

    fOk = TRUE; // Everything executed successfully

    // Free the remote memory that contained the DLL's pathname
    if (pszLibFileRemote != NULL) 
      VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

    if (hThread  != NULL) 
      CloseHandle(hThread);

    if (hProcess != NULL) 
      CloseHandle(hProcess);
  return fOk;
}

Так вот некоторые программы запускаются НЕ ДО ОКНЦА, а в ХР вообще ни опера и IExplorer не запускаются.. Хотя с блокнотом, офисными приложениями и многими другими-все ок..
Стоит убрать dwCreationFlags=CREATE_SUSPENDED;ResumeThread(lpProcessInformation->hThread)- все работает ,как по маслу..
Если закоментировать код, где передаю проге id — тоже все работает.Не пойму-что ж делать? Кто мешает? И почему не все приложения глючат? Почему 2000 и ХР по разному работают. И как все это побороть. Я уверен, что все же кто-то делал подобное, ведь я не первый.
Re: Вклинивание dll в новый процесс
От: Константин Л.  
Дата: 28.03.07 15:48
Оценка:
Здравствуйте, Аноним, Вы писали:

[]

а не проще ли просто поставить system-wide hook?
Re[2]: Вклинивание dll в новый процесс
От: Аноним  
Дата: 28.03.07 16:51
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, Аноним, Вы писали:


КЛ>[]


КЛ>а не проще ли просто поставить system-wide hook?


Конечно проще! Только вот вы пробывали перехват функций WinRAR или FAR Вообщем жаль.. Я думал дали ответ, а тут вопрос : )
Re[3]: Вклинивание dll в новый процесс
От: Аноним  
Дата: 29.03.07 06:57
Оценка:
Блин, мужики, но неужели никто не знает?
Re: Вклинивание dll в новый процесс
От: gear nuke  
Дата: 29.03.07 09:16
Оценка:
Здравствуйте, <Аноним>, Вы писали:

[]

А>Стоит убрать dwCreationFlags=CREATE_SUSPENDED;ResumeThread(lpProcessInformation->hThread)- все работает ,как по маслу..


А зачем надо CREATE_SUSPENDED, что бы инициализация не была произведена?
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[2]: Вклинивание dll в новый процесс
От: Аноним  
Дата: 29.03.07 11:56
Оценка:
GN>А зачем надо CREATE_SUSPENDED, что бы инициализация не была произведена?
Да. Мне нужно вклинится до тех пор, пока программа не станет вызывать оригинальне функции, что б их перехватывать.. Секрета здесь никакого нет.. Правда не вижу ответа, почему-то только одни вопросы.. Если так нужно, значит так и делаю.. Может хотите предложить другой вариант?
Re[3]: Вклинивание dll в новый процесс
От: gear nuke  
Дата: 29.03.07 23:38
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Правда не вижу ответа, почему-то только одни вопросы.. Если так нужно, значит так и делаю..


Это был ответ, почему не работает.

А>Может хотите предложить другой вариант?


PsSetCreateProcessNotifyRoutine
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re: Вклинивание dll в новый процесс
От: Аноним  
Дата: 30.03.07 09:04
Оценка:
Честно говоря, лень разбирать, но если еще надо то могу дать код
который запускает замороженный процесс внедряет туда длл и продолжает
загрузку основного процесса, Проверено на IE7 и прочем софте, все работает.

П.С. Внедрять в замороженный процесс можно dllки которые зависят только
от kernel32.dll и ntdll.dll, если надо какие-то еще dllки используй LoadLibrary.
В особо сложных случаях даже от kernel32.dll надо отказаться.

вот код:

int cmd_load(int argc, char * argv[])
{
    if (argc < 3)
    {
        printf("Syntax: TACLoader.exe load [-d] <DLLImage> <Programm> [param1, [param2 ...]]\n");
        return 1;
    }

    bool memdump = false;
    if (!strcmpi(argv[1], "-d"))
    {
        memdump = true;
        argc--; argv++;
        if (argc < 3)
        {
            printf("Invalid params count\n");
            return 1;
        }
    }
    char *dll = argv[1];
    argc--; argv++;

    std::string application = argv[1];
    std::string args = "\""+application+"\"";
    argc--;
    argv++;

    for (int i = 1; i < argc; ++i)
    {
        if (!args.empty()) args += " ";
        args+= argv[i];
    }

    char    fullpath[_MAX_PATH];
    char    *filename;

    if (!GetFullPathName(dll, sizeof(fullpath), fullpath, &filename))
    {
        printf("Get full path to %s failed with error %d\n", dll, GetLastError());
        return 1;
    }
    if (GetFileAttributes(dll) ==  INVALID_FILE_ATTRIBUTES)
    {
        printf("Checking '%s' failed with error %d\n", fullpath, GetLastError());
        return 1;
    }

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    if(!CreateProcess(application.c_str(),
        (LPSTR)args.c_str(), NULL, NULL, FALSE, 
        CREATE_SUSPENDED, 
        NULL, NULL, &si, &pi))
    {
        printf("Rum application '%s' failed with error %d\n", 
            application.c_str(), GetLastError());
        return 1;
    }
    printf("suspended PID=%d\n", pi.dwProcessId);
    if (memdump) {
        printf("=== MEMORY DUMP BEGIN (BEFORE INJECT)===\n");
        std::vector<VMQUERYEX>    dump;
        VQMemDump(pi.hProcess, dump);
        std::string output = MemDumpStr(pi.hProcess, dump);
        printf("%s\n", output.c_str());
        printf("===  MEMORY DUMP END ===\n");
    } 

    if (!InjectLib(pi.dwProcessId, fullpath))
        printf("DLL injection failed of '%s' to %d failed\n", fullpath, pi.dwProcessId);

    if (memdump) {
        printf("=== MEMORY DUMP BEGIN (AFTER INJECT)===\n");
        std::vector<VMQUERYEX>    dump;
        VQMemDump(pi.hProcess, dump);
        std::string output = MemDumpStr(pi.hProcess, dump);
        printf("%s\n", output.c_str());
        printf("===  MEMORY DUMP END ===\n");
    } 
    ResumeThread(pi.hThread);

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return 0;
}


InjectLib (c) Рихтер

#include <windows.h>

#ifdef UNICODE
#define InjectLib InjectLibW
#else
#define InjectLib InjectLibA
#endif   // !UNICODE

BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile);
BOOL WINAPI InjectLibA(DWORD dwProcessId, PCSTR pszLibFile);

BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) {

    BOOL fOk = FALSE; // Assume that the function fails
    HANDLE hProcess = NULL, hThread = NULL;
    PWSTR pszLibFileRemote = NULL;

    __try {
        // Get a handle for the target process.
        hProcess = OpenProcess(
            PROCESS_QUERY_INFORMATION |   // Required by Alpha
            PROCESS_CREATE_THREAD     |   // For CreateRemoteThread
            PROCESS_VM_OPERATION      |   // For VirtualAllocEx/VirtualFreeEx
            PROCESS_VM_WRITE,             // For WriteProcessMemory
            FALSE, dwProcessId);
        if (hProcess == NULL) __leave;

        // Calculate the number of bytes needed for the DLL's pathname
        int cch = 1 + lstrlenW(pszLibFile);
        int cb  = cch * sizeof(WCHAR);

        // Allocate space in the remote process for the pathname
        pszLibFileRemote = (PWSTR) 
            VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
        if (pszLibFileRemote == NULL) __leave;

        // Copy the DLL's pathname to the remote process's address space
        if (!WriteProcessMemory(hProcess, pszLibFileRemote, 
            (PVOID) pszLibFile, cb, NULL)) __leave;

        // Get the real address of LoadLibraryW in Kernel32.dll
        PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
            GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
        if (pfnThreadRtn == NULL) __leave;

        // Create a remote thread that calls LoadLibraryW(DLLPathname)
        hThread = CreateRemoteThread(hProcess, NULL, 0, 
            pfnThreadRtn, pszLibFileRemote, 0, NULL);
        if (hThread == NULL) __leave;

        // Wait for the remote thread to terminate
        WaitForSingleObject(hThread, INFINITE);

        fOk = TRUE; // Everything executed successfully
    }
    __finally { // Now, we can clean everthing up

        // Free the remote memory that contained the DLL's pathname
        if (pszLibFileRemote != NULL) 
            VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

        if (hThread  != NULL) 
            CloseHandle(hThread);

        if (hProcess != NULL) 
            CloseHandle(hProcess);
    }

    return(fOk);
}

BOOL WINAPI InjectLibA(DWORD dwProcessId, PCSTR pszLibFile) {

    // Allocate a (stack) buffer for the Unicode version of the pathname
    PWSTR pszLibFileW = (PWSTR) 
        _alloca((lstrlenA(pszLibFile) + 1) * sizeof(WCHAR));

    // Convert the ANSI pathname to its Unicode equivalent
    wsprintfW(pszLibFileW, L"%S", pszLibFile);

    // Call the Unicode version of the function to actually do the work.
    return(InjectLibW(dwProcessId, pszLibFileW));
}
Re[2]: Вклинивание dll в новый процесс
От: Аноним  
Дата: 30.03.07 09:25
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Честно говоря, лень разбирать, но если еще надо то могу дать код

А>который запускает замороженный процесс внедряет туда длл и продолжает
А>загрузку основного процесса, Проверено на IE7 и прочем софте, все работает.
Спасибо.. Посмотрел. Все в точности, как у меня. Единственая разница, что ты запускаешь приложение из своей софтины, а я перехватываю у експлорера создание процесса, внедряюсь в своем приложении (из него),и продолжаю запуск замороженого процесса снова из эксплорера.Может тут и вся фича. Нашел еще одну статью про данный метод и данный баг. Люди решили его ,путем перехвата
не CraeteProcessW , а NtCreateThread и NtResumeThread. А так у них так же были глюки, как у меня. Вообщем буду рыть дальше . Спасибо.
Re[4]: Вклинивание dll в новый процесс
От: coockies2  
Дата: 30.03.07 09:28
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Здравствуйте, <Аноним>, Вы писали:


А>>Правда не вижу ответа, почему-то только одни вопросы.. Если так нужно, значит так и делаю..


GN>Это был ответ, почему не работает.


А>>Может хотите предложить другой вариант?


GN>PsSetCreateProcessNotifyRoutine


Спасибо. Я просто наверное не так вас понял.. Сорри. Посмотрю
Re[3]: Вклинивание dll в новый процесс
От: BoberPlus  
Дата: 30.03.07 10:58
Оценка:
Здравствуйте, Аноним, Вы писали:



GN>>А зачем надо CREATE_SUSPENDED, что бы инициализация не была произведена?

А>Да. Мне нужно вклинится до тех пор, пока программа не станет вызывать оригинальне функции, что б их перехватывать.. Секрета здесь никакого нет.. Правда не вижу ответа, почему-то только одни вопросы.. Если так нужно, значит так и делаю.. Может хотите предложить другой вариант?

Наступал на теже грабли, победил при помощи GetThreadContext/SetThreadContext.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.