2011-09-01 4 views
0

나는 프로세스에서 주입 한 dll을 가지고있다. 유효하지 않은 심볼을 찾을 때까지 'file : //'을 검색합니다. 몇 분이 지나면 주 프로세스가 중단됩니다. 왜 그런가요? 어떻게 확인할 수 있습니까? CreateThread의 스택 크기가 작을수록 충돌이 빨라서 스택 오버플로가 될 수 있지만 아무것도 할당하지 않고 단일 구조체를 사용한다는 것을 알게되었습니다. 프로세스에 연결합니다 (대한 -주입 된 dll이 소유자 프로세스를 충돌시킵니다. 왜?

1 : 시험없이

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

파스타를 사용하지 마십시오. 소스를 붙이고 잘 포맷되었는지 확인하십시오. –

답변

3

를 찾을 수 있습니다. 더


몇 가지 팁 :

  • 은 한 번에 7의 단위로 메모리를 읽고. 이 문제에는 두 가지가 있습니다.
    • 예를 들어, info.RegionSize - 10의 끝이 500000이고 i = 499999 인 경우 어떻게해야합니까? 6 바이트를 읽으면 충돌이 발생합니다.
    • 은 7의 배수가되는 주소의 메모리에서 찾을 수있는 것은 아닙니다. "123file : // ...."을 테스트하면 우연히 발견되지 않을 것입니다 왜냐하면 "123file"과 ": // ...."을 찾을 것이기 때문입니다.
  • VirtualQueryEx(GetCurrentProcess(), ...은 중복됩니다. 그냥 VirtualQuery을 사용하십시오.
  • 주소가 0 인 VirtualQuery를 호출하고 있습니다.
  • 달성하려는 문자열 비교를 수행하는 훨씬 쉬운 방법이 있습니다 (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 ++ = 7로 고정 시켰습니다. 나는 실수를했기 때문에 서둘러야했습니다. – blez

0

가 여기에 문제가 occurd 그러나 당신이 버그를 찾아 올리 디버그 또는 Windbg에서와 프로세스를 디버깅 할 수있는 말하기 어렵다 당신이해야 할 단계입니다

  • 원격 스레드 (에서 LoadLibrary) : LoadL에 브레이크 -

    2 올리 디버그 양식 파일 -> Atach)와 예 주입법 원격 스레드 또는 SetWindowsHookEx에 의존 나는 이것을 테스트하지 않습니다하지만 난 이전의 방법이 일부

을 '을 LoadLibrary에 중단 점'을 제외하고도 여기서 일 생각 :

  • SetWindowsHookEx ibrary 다음 새 DLL로드에 휴식 및 DLL의 항목을 따라 올리 사용 3 - 그리고 디버그는 문자열 X2의 길이에 버퍼 크기를 설정하는하지만 당신은 한 바이트 인 char, 포인터의 데이터를 전달하는 문제에게 보내기 기능에서

  • +1

    Visual Studio에서 DLL을 디버깅 할 수 있다는 것을 알고 계십니까? –

    +0

    @Mike Kwan : 네, 다른 프로세스에 dll을 주입 할 때 알아요. – Arash

    +0

    먼저로드하지 않고 디버깅 할 수 있다고 생각하십니까? –

    관련 문제