1

CREATE_SUSPENDED과 함께 CreateProcess()을 사용하여 프로세스를 만든 다음 원격 프로세스 내에서 코드를 작성하여 DLL을로드하고 해당 DLL에서 내 보낸 함수를 호출하려면 VirtualAllocEx()을 사용하십시오 (..., MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE) WriteProcessMemory()을 입력 한 다음 코드가있는 해당 패치에서 FlushInstructionCache()을 호출하십시오.Win32 프로세스 내에서 실행되는 첫 번째 스레드가 "주 스레드"프로세스입니까?

그 후 CreateRemoteThread()을 호출하여 해당 코드를 호출하여 나를 hRemoteThread으로 만듭니다. 원격 코드가 의도 한대로 작동하는지 확인했습니다. 참고 :이 코드는 단순히 반환하고 LoadLibrary()GetProcAddress() 이외의 API는 호출하지 않고 내 보낸 스텁 함수를 호출 한 다음 현재 스레드의 종료 상태로 전달되는 값을 반환하기 만합니다.

이제 특이한 관찰이 있습니다. PROCESS_INFORMATION::hThread은 여전히 ​​정지 상태입니다. hRemoteThread의 종료 코드를 무시하고 종료 될 때까지 기다리지 않고 모두 "괜찮습니다". CreateRemoteThread()을 호출하고 PROCESS_INFORMATION::hThread을 호출하는 루틴이 재개되고 (원격) 프로그램이 실제로 실행됩니다. 그러나

, 내가 WaitForSingleObject(hRemoteThread, INFINITE)로 문의하거나 (같은 효과를 가지고있는) 다음을 수행하는 경우 :

CloseHandle() 다음
DWORD exitCode = STILL_ACTIVE; 
while(STILL_ACTIVE == exitCode) 
{ 
    Sleep(500); 
    if(!GetExitCodeThread(hRemoteThread, &exitCode)) 
     break; 
} 

PROCESS_INFORMATION::hThread가 다시 시작되기 전에 hRemoteThread 마무리로 연결 프로세스가 단순히 "사라"를. 프로세스가 종료되도록하려면 PROCESS_INFORMATION::hThread없이 hRemoteThread을 완료하는 것으로 충분합니다.

특정 상황에서 hRemoteThread이 여전히 빠를 수 있고 코드를 그대로 두어도 프로세스가 여전히 "사라질"수 있기 때문에 이것은 의심스러운 경쟁 조건처럼 보입니다.

프로세스 내에서 실행되는 첫 번째 스레드가 자동으로 기본 스레드가되고 해당 기본 스레드에 대한 특수 규칙이 있음을 의미합니까?

나는 항상 스레드가 죽을 때가 아니라, 마지막 스레드가 죽을 때 프로세스가 끝난다는 인상을 받고있었습니다.

또한주의 :hRemoteThread 단순히 반환하고 내가 돌아 hRemoteThread 기다릴 때 PROCESS_INFORMATION::hThread 여전히 중단되기 때문에 어떤 식 으로든 여기에 포함 ExitProcess()에는 전화가 없다.

Windows XP SP3, 32 비트에서 발생합니다.

편집 : 나는 Sysinternals 프로세스 모니터를 사용하여 어떤 일이 일어나고 있는지를 보았고 이전의 관찰 내용을 확인할 수있었습니다. 삽입 된 코드가 충돌하지 않거나 아무것도 아닌 대신 코드를 주입 ​​한 프로그램을 닫기 전에 스레드를 기다리지 않으면 종료되지 않습니다.이 CloseHandle()가 아니다 : 나는

편집 + 1 ... CloseHandle(hRemoteThread)에 대한 호출이 연기 또는 뭔가해야하는지 여부를 생각하고 있어요. 테스트를 위해서만 남겨두면 쓰레드가 끝나기를 기다릴 때 동작이 바뀌지 않습니다.

답변

0

첫 번째 스레드는 특별하지 않다.

예를 들어, 중단 된 스레드를 만들고 exitThread를 호출하여 원래 스레드를 종료하는 콘솔 응용 프로그램을 만듭니다. 이 프로세스는 절대로 종료되지 않습니다 (어쨌든 Windows 7).

또는 새 스레드를 5 초 동안 기다린 다음 종료하십시오. 예상대로 프로세스는 5 초 동안 지속되고 보조 스레드가 종료되면 종료됩니다.

예를 들어 어떤 일이 일어나고 있는지 알 수 없습니다. 경주를 피하는 가장 쉬운 방법은 새 스레드가 원래 스레드를 다시 시작하도록하는 것입니다.

당신이하는 일이 어쨌든 문제를 일으키지 않는지 궁금합니다. 예를 들어 암시 적으로로드 된 DLL에 대한 모든 DllMain 호출은 어떻게됩니까? 예상치 않게 잘못된 스레드에서 발생 했습니까? 건너 뛰었습니까? 아니면 코드가 실행되고 주 스레드가 시작될 때까지 연기됩니까?

+0

마지막 요점을 설명하십시오. ** ** ** 같은 기본 addr에 DLL이로드되었다고 가정하는 데 문제가 발생할 것입니다. 내 프로세스에서 원격 프로세스처럼,'CreateRemoteThread'에 전달 된 명백한 오래된'LoadLibrary'는 날지 않습니다. 이것이 바로 이런 이유입니다. 게다가 메인 스레드가 프로세스를 생성 한 후 일시 중단되었을 때, DLL이 이미로드되었지만, 그때까지 'DllMain'이 호출되었는지 확실하지는 않습니다. 하지만 메인 쓰레드가 시작되고'DllMain' 내부에있을 수있게 된 후에'LoadLibrary'를 호출하지 않는 한 그것은 중요하지 않습니다. Thx – 0xC0000022L

+0

정적 DLL이 초기화되기 전에 Windows는 일반적으로 'LoadLibrary'에 대한 호출을 보지 못합니다. 이것은 아마도 문제를 일으킬 수 있습니다. 또는 스레드에서 정적 DllMains가 호출되는 경우 초기화 스레드가 프로세스의 수명 동안 지속되는 것으로 간주하는 DLL을 혼동하게됩니다. 일반적으로 이는 사실입니다. 내가 말했듯이, 나는 추측하고 있지만 파손 가능성은 충분히있는 것으로 보인다. – arx

+0

흠, 알았어. 다른 DLL의'DllMain'이 호출되었는지 어떻게 확인할 수 있습니까? 과거의 경험에서 나는'kernel32.dll'이 초기화되고 Win32에 대한 연결이 성립되지 않으면'CreateRemoteProcess'를 성공적으로 호출 할 수 없다는 것을 알고 있습니다. 그러나'CreateRemoteProcess' **에 대한 호출은 ** 여기서 성공적입니다. 당신이 옳을 수도 있지만, 지금은 그렇게 생각하지 않습니다. – 0xC0000022L

0

main (또는 동등한) 기능을 가진 스레드가 ExitProcess (명시 적으로 또는 런타임 라이브러리에서)을 호출하는 것이 좋습니다. ExitProcess은 모든 스레드를 죽이는 것을 포함하여 전체 프로세스를 종료합니다. 주 스레드는 삽입 된 코드를 알지 못하기 때문에 완료 될 때까지 기다리지 않습니다. 실행 나는 당신을 완료 할 메인 스레드 대기를 만들 수있는 좋은 방법이 모르겠어요

...

+0

어떻게? ti가 실행되지 않으면'main()'을 포함하는 스레드가'ExitProcess()'를 어떻게 호출 할 수 있습니까? 내 질문에 문제가 발생할 때 주 스레드가 주입 된 코드 전에 실행되지 않는다고 썼습니다. 그들이 "병행하여"달릴 때 문제는 ** 발생하지 않습니다 **. – 0xC0000022L

+0

오, 제 사과, 당신의 질문을 잘못 읽었습니다. 그것은 수수께끼입니다. 스레드가 정상적으로 종료되고 프로세스를 종료하지 않지만 프로세스가 여전히 종료됩니까? 이상한. –

+0

실제로는 : -/... OS에 대한 세부 정보를 알려줍니다. – 0xC0000022L