Внедренный dll сбой процесса владельца. Зачем? - PullRequest
0 голосов
/ 01 сентября 2011

У меня есть DLL, которую я ввел в процессе.Он ищет «file: //», пока не найдет недопустимый символ.Через несколько минут происходит сбой основного процесса.Это почему?Как я могу проверить?Я обнаружил, что при меньшем размере стека в CreateThread он падает быстрее, так что это может быть как-то переполнением стека, но я не выделяю ничего, кроме одной структуры.

BOOL APIENTRY DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:

        CreateThread(NULL, 500, SampleFunction, 0, 0, NULL);            
            break;

        case DLL_THREAD_ATTACH:

            break;

        case DLL_THREAD_DETACH:
            break;

        case DLL_PROCESS_DETACH:
            break;
    }

    /* Return success */
    return TRUE;
}



int Send(char* strDataToSend) {
    HWND hWnd = FindWindow(NULL, "Test");
    if (hWnd) {
        COPYDATASTRUCT cpd;
        cpd.dwData = 0;
        cpd.cbData = (strlen(strDataToSend) + 1) * 2;
        cpd.lpData = (PVOID)strDataToSend;
        SendMessage(hWnd, WM_COPYDATA, (WPARAM) hWnd, (LPARAM)&cpd);
    }
}

int isurl(char c) {
    char* chars = "-._~:/?#[]@!$&'()*+,;=%";
    for(int i = 0; i < strlen(chars); i++) {
        if (chars[i] == c || isalnum(c)) {
            return 1;
        }           
    }

    return 0;
}

TESTDLLMAPI void WINAPI SampleFunction(void) {
    MessageBox(0,"LOADED !",0,0);
    MEMORY_BASIC_INFORMATION info;  
    MEMORY_BASIC_INFORMATION* pinfo = &info;

    while(1) {


    int cnt = 0;
    unsigned long addr = 0;
    do {
        ZeroMemory(&info, sizeof(info));

        if (!VirtualQueryEx(GetCurrentProcess(), (LPCVOID) addr, pinfo, sizeof(info))) {
            //MessageBox(0,"FAILED",0,0);
        }       

            if (info.State == 0x1000) {
            if (info.Protect == PAGE_READONLY || info.Protect == PAGE_READWRITE) {
                __try {

                if (info.RegionSize < 128) continue;

                for(long i = 0; i < info.RegionSize - 10; i+=7) {

                char* buff = info.BaseAddress;
                    if (buff[i] == 'f' && buff[i+1] == 'i' && buff[i+2] == 'l' && buff[i+3] == 'e' && buff[i+4] == ':' && buff[i+5] == '/' && buff[i+6] == '/') {

                        long start = i;
                        long end   = start+7;

                        while(end < info.RegionSize - 10 && isurl(buff[end])) end++; 

                        int len = end - start + 1;
                        char* test = (char*) calloc(len, 1);
                        //memcpy(test, buff+start, len);
                        int k = 0;
                        for (int j = start; j <= end; j++, k++) {
                            test[k] = buff[j];
                        }


                            Send(test);
                                                    free(test); 
                            cnt++;      
                        }

                    }
                } __finally {}
            }
        }

        addr = (unsigned long) info.BaseAddress + (unsigned long) info.RegionSize;
    } while (addr != 0 && addr < 0x7FFF0000);

    Sleep(1000);

}

Ответы [ 2 ]

3 голосов
/ 01 сентября 2011

В вашей функции отправки вы устанавливаете размер буфера равным длине строки x2 , но вы передаете данные в указателе на char, что составляет один байт.


Еще несколько советов:

  • Вы читаете память с шагом 7 за раз.Есть две проблемы с этим:
    • в качестве примера, что если конец info.RegionSize - 10 равен 500000, а i = 499999?Вы прочтете 6 байтов в прошлом, что приведет к сбою.
    • "file://" не обязательно будет найден в каком-либо месте в памяти с адресом, кратным 7. Если вы оказалисьтестируя «123file: // ....», вы просто пропустите его, потому что вы найдете «123file» и «: // ....»
  • VirtualQueryEx(GetCurrentProcess(), ... является избыточным.Просто используйте VirtualQuery.
  • Вы вызываете VirtualQuery с адресом 0.
  • Существует гораздо более простой способ выполнить сравнение строк, которое вы пытаетесь выполнить - strstr.
  • Это только у меня или у меня есть бесконечный цикл?
  • Ваша функция даже не закрыта.
  • Я могуНе вижу, для каких целей cnt должен служить.
  • Вы создали поток в DllMain.закрывайте дескрипторы для потоков с помощью CloseHandle, если вы больше не собираетесь их использовать (в данном случае, т.е. сразу после того, как вы его создали)

Я переписал ваш1044 * для вас.Я написал на ходу, и он, вероятно, не скомпилируется, но вы должны получить общее представление.

#include <windows.h>

BOOL IsPageReaable(PMEMORY_BASIC_INFORMATION pmbi)
{
  if (pmbi->Protect & PAGE_GUARD)
    return FALSE;

  if (pmbi->Protect &
    (PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE
    | PAGE_EXECUTE_WRITECOPY | PAGE_READONLY
    | PAGE_READWRITE | PAGE_WRITECOPY))
    return TRUE;

  return FALSE;
}

#define POLL_INTERVAL 1000

TESTDLLMAPI VOID WINAPI SampleFunction(VOID)
{
  MEMORY_BASIC_INFO mbi;
  ULONG_PTR         ulAddress = GetModuleHandle(NULL); // base address
  LPSTR             lpszBase;

  ZeroMemory(&mbi, sizeof(mbi));
  if (!VirtualQuery(ulAddress, &mbi, sizeof(mbi)))
    return;

  if (!IsPageReadable(&mbi))
    return;

  lpszBase = info.BaseAddress;
  for (;; Sleep(POLL_INTERVAL))
  {
    for (ULONG_PTR i = 0; i < info.RegionSize; i++)
    {
      int   j;
      LPSTR lpszBuffer;

      if (strstr(&lpszBase[i], "file://") == NULL)
        continue;

      j = i + 1;
      do {
        j++;
      } while (j < info.RegionSize && isurl(lpszBase[j])

      lpszBuffer = (LPSTR)HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, sizeof(CHAR) * (j - i + 1));
      if (lpszBuffer != NULL)
      {
        CopyMemory(lpszBuffer, &lpszBase[i], j - i);
        Send(lpszBuffer);
        HeapFree(GetProcessHeap(), 0, lpszbuffer);
      }
    }
  }
}
0 голосов
/ 01 сентября 2011

без теста трудно сказать, где возникла проблема, но вы можете отладить ваш процесс с помощью Ollydbg или Windbg, чтобы найти ошибку, вот шаг, который вы должны сделать:

1 - Присоединиться к вашему процессу (например, с помощьюOllydbg form File-> Atach)

2 - Зависит от метода внедрения, удаленного потока или SetWindowsHookEx:

  • удаленный поток (LoadLibrary): точка останова на LoadLibrary, затем используйте ollyпрервать новую загрузку dll и выполнить запись dll

  • SetWindowsHookEx: я не проверял это, но я думаю, что предыдущие способы также работают и здесь, за исключением точки останова на LoadLibrary часть

3 - затем выполнить отладку, чтобы найти проблему

...