64bit dll 인젝팅시 문제점
글쓴이: rlj1202 / 작성시간: 일, 2016/07/31 - 3:21오후
SetWindowsHookEx함수를 이용해서 프로세스에 dll을 인젝트하는데, 구글 크롬과 스팀(Steam), 스윙 브라우저 등의 프로그램에 인젝트 될 때에 해당 프로그램이 프리징이 되더군요. 또 이클립스랑 프로세스 해커(Process Hacker), 파일 탐색기는 아무런 문제가 없어 공통점이 무얼까 찾아보니 비트수의 차이였습니다. 프리징된 프로그램 모두 32비트 이미지 이고 나머지 정상작동한 프로그램은 64비트 이미지 이였습니다.
그러니까, 32비트로 만든 dll은 32비트 프로세스에서만 작동하고 64비트로 만든 dll은 64비트 프로세스에서만 정상 작동한다는 얘긴데 어떻게 해결해야할지 모르겠네요.
부탁드립니다.
Forums:
......
구글에서 SetWindowsHookEx 검색하면 맨 위에 뜨는 게 MSDN 문서입니다. (뭐, 이 분야 원전으로서 가장 권위있는 텍스트일테니 당연할지도.)
https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms644990(v=vs.85).aspx
가서 읽어보면, Remarks 첫 문단부터 "bitness"가 일치해야 한다는 조건 및 일치하지 않을 때 무슨 일이 일어나는가 등에 대해 상세히 설명하고 있습니다. 제대로 만드려면 어떻게 해야 하는가에 대해서도 잘 설명되어 있죠.
SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.
(후략)
누구든 프로그래밍하다가 어려운 문제에 부딛칠 수 있습니다. 그럴 때 도움을 받아서 난관을 빨리 돌파하자는 게 이런 커뮤니티 QnA의 의의라고 할 수 있죠. 하지만 기본적으로 자기 문제는 자기가 노력해서 풀어보려고 시도는 해 본 뒤에 질문을 올리는 게 질문자의 자세가 아닌가 싶습니다. 이렇게 검색해서 맨 위에 해답이 나오는 문제를 질문한다면 좋은 시선으로 바라보기는 조금 어렵겠죠.
덧. 제가 익명으로 활동하고 있으니 모르시겠지만 저는 2주쯤 전에도 질문자님의 질문에 답을 달아 드린 적 있습니다. ( https://kldp.org/node/155762 ) 거기에 추가로 질문하셨던데 방금 봤네요.
어떤 객체가 주소공간을 공유하는 모든 스레드에서 동시에 사용가능하다는 thread-safety와, 해당 객체를 (일반적으로 주소공간을 공유하지 않는) 여러 프로세스 간에 공유한다는 건 전혀 별개의 문제입니다.
현대 OS의 주요 보호 기능 중 하나인 프로세스간 주소 공간 분리가 어떤 의미인지, 그것이 지금 하고 계시는 시스템 전역 후킹에 어떤 영향을 미치는지 잘 모르시겠다면, 제 짧은 소견으로는 질문자님께서 지금 상당히 능력 밖의 일을 시도하고 계신다는 생각이 드는군요.
필요할 때마다 공부해가며 하는 게 프로그래밍이라지만, 이런 경우에는 조금 공부를 먼저 해 보고 진행하시는 게 시간을 아낄 수 있는 길이지 않을까 생각해봅니다.
여러모로 감사합니다.
사실 그 때 문제를 일으킨 주소 공간에 대한 문제는 지금에서야 이해를 어느정도 했습니다. 한 프로세스 내의 쓰레드 끼리는 주소공간을 공유하지만, 다른 프로세스 끼리는 주소 공간이 분리되어 쓰레드세이프한 객체일 지라도 다른 프로세스에서는 사용이 불가능 하다는 사실을 혼자 생각하다가 알아냈습니다.
그래서 지금은 JavaVm이라는 객체를 처음 로드된 dll 에서만 관리하고 처음 로드된 그 dll을 서버, 나머지 후킹으로 인해 삽입된 dll들을 클라이언트라고 생각하고, 서버에서 이름있는 파이프요청을 받아서 서버와 클라이언트간 소통이 가능하도록 하여서 모든 dll이 서버를 통해 자바 가상엔진과 소통이 가능케 되었습니다.
여기까지는 정말정말 좋아서 모든 프로그램이 후킹 되나 실험할겸 이클립스랑 이것저것 하다가 이번에는 비트수의 문제가 생겼으니 짜증나서 너무 이르게 질문을 올리게 된것은 사실입니다. 충고 감사합니다.
=======
본론으로 넘어가서, 64비트 프로세스에 dll을 인젝트 하려면 64비트 어플리케이션에서 SetWindowsHookEx를 실행하고, 32비트 프로세스에 dll을 인젝트 하려면 32비트 어플리케이션에서 SetWindowsHookEx를 실행해야 한다는 것 까지는 저도 읽어보았습니다. 그리고 제가 국어실력이 딸리는지 영어실력이 딸리는지 헷갈리는 부분이 있습니다.
저 영어 본문에서 32비트 후킹 설치 후 64비트 후킹을 설치 하라는 소리인가요? 다른 자료를 보니 훅 체인에서 32비트 훅 프로시져가 64비트 훅 프로시져보다 앞에 와야한다, 이런 얘기를 본것 같습니다.
그리고 무엇보다, dll이 해당 비트수에 맞는 프로세스에만 inject된다면, 왜 64비트 dll이 32비트 프로세스에 영향을 미치느냐는 겁니다. 이게 제가 제일 궁금한 점 입니다.
뭘 공부하든 간에, 영어 독해 및 국어 독해 능력은
뭘 공부하든 간에, 영어 독해 및 국어 독해 능력은 아주 중요하죠.
사견입니다만, 사실 중고등학교 교육과정에 있는 학생이 학교에서 공부하면서 정말로 시간을 들여 갈고닦아야 하는 능력이 그런 것들 아닌가 싶어요.
Because hooks run in the context of an application, they must match the "bitness" of the application. If a 32-bit application installs a global hook on 64-bit Windows, the 32-bit hook is injected into each 32-bit process (the usual security boundaries apply). In a 64-bit process, the threads are still marked as "hooked." However, because a 32-bit application must run the hook code, the system executes the hook in the hooking app's context; specifically, on the thread that called SetWindowsHookEx. This means that the hooking application must continue to pump messages or it might block the normal functioning of the 64-bit processes.
If a 64-bit application installs a global hook on 64-bit Windows, the 64-bit hook is injected into each 64-bit process, while all 32-bit processes use a callback to the hooking application.
32비트 어플리케이션이 64비트 윈도우즈에서 전역 훅을 설치할 경우, 32비트 프로세스에 대해서는 정상적으로 인젝션이 되지만 64비트에서는 (bitness 불일치로 인해) 훅이 직접 실행되지 않습니다. 해당 64비트 스레드들은 hooked 되었다고 표시는 되지만 실제로는 SetWindowsHookEx를 호출한 스레드에서 대신 훅을 실행하게 되는 구조입니다. 따라서, 후킹한 어플리케이션이 계속 메시지 펌프를 해서 훅을 실행해 주지 않으면 그 스레드들은 block당하게 됩니다.
64비트 어플리케이션이 64비트 글로벌 훅을 설치할 경우에는 각각 반대입니다. (64비트 프로세스는 정상적으로 인젝션되고, 32비트 어플리케이션은 SetWindowsHookEx를 호출한 스레드에서 대신 실행)
To hook all applications on the desktop of a 64-bit Windows installation, install a 32-bit global hook and a 64-bit global hook, each from appropriate processes, and be sure to keep pumping messages in the hooking application to avoid blocking normal functioning.
모든 어플리케이션을 후킹하고 싶으면, 32비트 프로세스에서 32비트 전역 훅을 설치하고, 64비트 프로세스에서 64비트 전역 훅을 설치하면 됩니다. 그리고 메시지 펌핑을 계속 유지해 줘야 하고요.
해결했습니다!
ㅋㅋ 성공해서 어서 빨리 알려드리고 싶었어요
메세지 펌핑에 대해 찾아보면서 해결했네요. 감사합니다.
영어 실력보단 국어실력이 딸리는것 같네요. 공부 열심히 하겠습니다 :)
댓글 달기