2011-09-01 91 views
0

我有一個dll,我注入了一個進程。它搜索'file://'直到找到無效符號。幾分鐘後,它會導致主流程崩潰。這是爲什麼?我該如何檢查?我發現CreateThread的堆棧大小越小,它崩潰的速度就越快,所以它可能會以某種方式堆棧溢出,但我沒有分配任何東西,而是分配一個結構。注入的DLL崩潰了所有者進程。爲什麼?

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); 

} 
+0

您可以隨時登錄到文件以檢查崩潰發生的位置。畢竟,正如你所說,這似乎不是堆棧相關的,因爲你沒有使用遞歸或大型本地緩衝區。 –

+0

不要使用pastie。粘貼源並確保它格式正確。 –

回答

3

在你發送功能你緩衝區的大小設置爲字符串X2的長度,但你傳遞數據的指針,char,這是一個字節。


再提一些建議:

  • 您正在閱讀在7增量內存在的時間。這有兩個問題:
    • 作爲一個例子,如果info.RegionSize - 10的結尾是500000,並且i = 499999?您將讀取6個字節,這會導致崩潰。
    • "file://"不一定會在內存中的地址爲7的倍數的地方找到。如果您碰巧在測試「123file:// ....」,那麼您將會錯過它,因爲你會發現「123file」和「:// ....」
  • VirtualQueryEx(GetCurrentProcess(), ...是多餘的。只需使用VirtualQuery即可。
  • 您打電話給VirtualQuery,地址爲0
  • 有一種更簡單的方法來執行字符串比較,你正試圖完成 - strstr
  • 它只是我還是做/無限循環?
  • 您的功能甚至沒有關閉。
  • 我看不到cnt應該提供什麼服務。
  • 您在DllMain中創建了一個線程。一旦你不再使用它們,你應該關閉CloseHandle的線程句柄(在這種情況下,即您創建的話)之後

我改寫了你的SampleFunction你。我隨時隨地寫信,可能無法編譯,但您應該瞭解一般想法。

#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

謝謝,問題在於使用calloc()。隨着HeapAlloc和HeapFree的確定。我用i ++修正了i + = 7,我犯了這個錯誤,因爲我很匆忙。 – blez

0

沒有測試就很難說得清問題occurd,但你可以調試用Ollydbg的或WinDBG的你的過程中找到了這個錯誤,這裏是一步你必須做到:

1 - 連接到您的處理(例如用Ollydbg的形式文件 - > Atach)

2 - 依靠注射法,遠程線程或調用SetWindowsHookEx:

  • 遠程線程(的LoadLibrary):上LoadL斷點ibrary然後使用奧利打破新的DLL加載和後續的dll進入

  • 和SetWindowsHookEx:我不考這個,但是我覺得這裏太以前的工作方式,除了「斷點調用LoadLibrary」部分

3 - 然後調試找到問題

+1

你知道你可以在Visual Studio中調試DLL嗎? –

+0

@Mike Kwan:是的,我知道但不是當你注入dll到另一個進程 – Arash

+0

你認爲它可以讓你在不加載的情況下進行調試嗎? –