2012-06-20 2 views
0

프로그램 메인 창에 채팅 UI를 구현하기 위해 DLL을 프로그램에 삽입했습니다. 응용 프로그램 주 창 핸들을 가져온 다음 DC를 가져 와서 그 위에 그릴 수 있다고 생각했습니다. 창에 예측 가능한 제목이 있습니다. 즉, FindWindow을 사용하여 핸들을 가져올 수 있습니다. 유일한 문제는 프로세스가 시작될 때 DLL이 주입된다는 것입니다. 이때 창은 생성되지 않았습니다. 즉 FindWindow은 아무것도 발견하지 못했습니다!주입 된 DLL에서 프로그램 창을 얻으려면 어떻게해야합니까?

어떤 해결책이 있습니까? 창이 생성 될 때까지 DLL에 스레드를 만들고 잠시 동안 잠을자를 수 있습니까? 이것은 매우 불안정하여 오히려하지 않을 것입니다.

내가 시도한 것은 DLL에 SetWindowsHookEx을 사용하여 전역 WndProc를 연결하는 것이 었습니다. 내 창에서 찾을 때까지 메시지를 스캔 할 수 있습니다 (즉, 창을 만들었습니다). 그럼 나는 그 프로그램을 저장하고 프로그램을 계속 진행할 수 있습니다. 나는 그 당시에 같은 이름의 창이 여러 개 있다는 것을 너무 걱정하지 않는다. 유일한 문제는 내 후크가 절대 호출되지 않는다는 것입니다. 유효한 후크를 반환

m_hWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)WndProc, m_hModule, 0); 
if(!m_hWndProcHook) 
{ 
    oss << "Failed to set wndproc hook. Error code: " << GetLastError(); 
    Log(oss.str().c_str()); 
    return false; 
} 

:

는이 같은 후크를 만들 수 있습니다. 의 WndProc는 다음과 같이 : 그것은 밝혀졌다하는 일 경우

LRESULT CALLBACK CChatLibrary::WndProc(int code, WPARAM wParam, LPARAM lParam) 
{ 
    CWPSTRUCT* pData; 
    ostringstream oss; 
    char wndName[256]; 

    gChatLib->Log("WNDPROC"); 

    if(code < 0) 
     return CallNextHookEx(gChatLib->GetWndProcHookHandle(), code, wParam, lParam); 
    else 
    { 
     //Get the data for the wndproc 
     pData = (CWPSTRUCT*)lParam; 

     //Log the message 
     GetWindowText(pData->hwnd, wndName, 256); 
     oss << "Message from window \"" << wndName << "\""; 
     gChatLib->Log(oss.str().c_str()); 

     return CallNextHookEx(gChatLib->GetWndProcHookHandle(), code, wParam, lParam); 
    } 
} 

그러나 더 "WNDPROC"메시지가 내 로그 파일 ... 이전에 기록되지 않습니다, 나는 볼 수있는 MessageBox 대신 로그를했다 끔찍한 생각. 그들이 "OK"를 클릭하기를 기다리고 있었기 때문에 모든 프로그램이 멈 췄고 하드 리셋을해야했습니다 ... 내 컴퓨터를 다시 켜고 MessageBox을 log 명령으로 바꿨을 때 작동하지 않았습니다. 나는 다른 곳에서 작동하기 때문에 내 로그 작업을 알 수 있습니다. 나는 이것으로 무슨 일이 일어나고 있는지 극도로 혼란 스럽다.

메인 윈도우를 얻는 다른 방법이 있습니까? (생성 될 때가 좋음)? 아니면 내 후크 방식이 좋지만 잘못 실행 한 것입니까? 의견을 보내 주셔서 감사합니다.

답변

1

응용 프로그램이 이미 시작된 경우 항상 DLL을 주입 할 수 있습니다. 요즘은 Windows Vista/7의 ASLR 때문에 상당히 복잡하지만 불가능하지는 않습니다. 주어진 PID를 가진 프로세스에 선택된 DLL을 주입 할 짧은 애플리케이션을 작성해야합니다. 다음은 DLL을 실행중인 프로세스에 주입하기 위해 수행해야하는 작업입니다.

kernel32.dll 라이브러리의 주소를 찾을 쉘 코드를 작성하십시오. 파일에서 메모리에

[BITS 32] 

_main: 
    xor  eax, eax 
    mov  esi, [FS:eax+0x30] ; ESI points at PEB 
    mov  esi, [esi+0x0C] ; ESI points at PEB->Ldr 
    mov  esi, [esi+0x1C] ; ESI points at PEB->Ldr.InInitOrder 
    mov  edx, -1   ; EDX is now the current letter pointer 

check_dll: 
    mov  ebp, [esi+0x08] ; EBP points at base address InInitOrder[i] 
    mov  edi, [esi+0x20] ; EDI points at InInitOrder[X] name 
    mov  esi, [esi]  ; ESI points at flink 
    mov  edx, -1  ; set letter pointer at InInitOrder name 
    mov  ebx, 0  ; set pattern letter pointer to null 

check_small_name: 
    inc  edx    ; go to the next letter in InInitOrder name 
    cmp  ebx, 0x7  ; check if we have checked all letters 
    je  library_found  ; if so and no error kernel32.dll found 
    mov  al, BYTE[edi+edx] ; load byte to EAX from InInitOrder name 
    cmp  al,  0x0 ; check if unicode complement 
    je  check_small_name ; ignore if so 
    jmp  s_kernel32 

back1: 
    pop  ecx 
    cmp  BYTE[ecx+ebx], al ; compare characters 
    jne  check_big_name  ; if not equal check upper size 
    inc  ebx   ; if equal then go to the next letter in pattern 
    jmp  check_small_name ; loop 

check_big_name: 
    jmp  b_kernel32 

back2: 
    pop  ecx 
    cmp  BYTE[ecx+ebx], al ; check characters 
    jne  check_dll  ; if not equal then go to the next module 
    inc  ebx   ; if equal go increment the pattern pointer 
    jmp  check_small_name ; loop 

library_found: 
    mov  eax, ebp   ; move kernel32 base address into ECX 

loop: 
    jmp loop  

s_kernel32: 
    call back1 
    db  "kernel32",10,0 

b_kernel32: 
    call back2 
    db  "KERNEL32",10,0 
  1. 로드 컴파일 된 쉘 코드 : 여기 NASM 내 예전의 코드입니다.
  2. 대상 프로세스에 디버거로 연결하십시오. 응용 프로그램의 모든 스레드를 중지하십시오. 일부 메모리를 할당하고 '읽기, 쓰기, 실행'권한을 설정하고 거기에 쉘 코드를 삽입하십시오.
  3. 메인 스레드 핸들을 가져옵니다. 스레드를 열고 스레드 컨텍스트 백업을 만든 다음 EIP 레지스터가 수정 된 새 컨텍스트를 설정합니다 (할당 된 메모리 - 쉘 코드 - 주소로 설정).
  4. 잠시 동안 스레드를 다시 시작하십시오 (예 : 5 초). 프로세스가 활성화되었고 쉘 코드가 실행될 수 있는지 확인하십시오.
  5. 다시 대상 프로세스에 디버거로 연결하십시오. 대상 프로세스에 기본 주소 인 kernel32.dll을 저장해야하는 EAX 레지스터를 읽습니다 (ASLR 덕분에 인젝터 프로세스에서와 다를 수 있음).
  6. LoadLibraryA의 오프셋을 확인하여 처리 과정에서 kernel32.dll의 기능을 확인하십시오.
  7. 원격 프로세스에서 기본 주소 LoadLibraryA을 계산하려면 오프셋이 대상 프로세스에서 동일해야하므로 오프셋에 원격 kernel32.dll 기본 주소를 추가해야합니다.
  8. 함수를 호출하여 계산 된 주소 인 LoadLibraryA을 호출 할 함수로, DLL 경로를 매개 변수로 제공합니다.

나는 (내가 어떤 설명을 찾을 수 없습니다) 몇 시간 전에 내 자신이 모든 것을 파악했지만, 최근에는 비슷한 것을 발견 http://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html

해피 해킹을!

+0

와우, 이것은 유망 해 보인다. 나는 아직 내 자신을 작성하지 않았기 때문에 해킹 게임용으로 설계된 DLL 인젝터를 사용하고 있었다. 하지만 지금 이것을 사용하여 글을 쓸 것입니다. 고맙습니다! – smoth190

관련 문제