본문 바로가기

My Study/Programming&Theory

Context 는 매우 중요하다!!

커널 프로그래밍을 조금씩 제대로 시작하는 과정에서 초보적인 실수를 해버렸다. 바로 Context를 개무시하고 코드를 작성.. -_-


( 개무시.. 출처 : 구글.. )


유저 프로그램에서 어떠한 리스트를 배열 형태가 아닌 링크드 리스트 형태로 관리하고 있었는데 이 리스트를 후킹 드라이버에서 사용해야하는 일이 발생했다. 먼저 유저와 커널간 데이터 통신을 위한 방법이 3가지 있는데 시스템 버퍼를 사용하는 것과 MDL을 사용하는 방법으로는 이 링크드 리스트로 관리되는 리스트를 옮기는게 번거로웠다. 그래서 단순히 Neither I/O 방법을 사용해 스레드의 가상 주소를 바로 사용하는 방법을 택하였다. 이제 유저에서 DeviceIoControl을 호출해 나의 드라이버를 호출시켰다. IRP_MJ_DEVICE_CONTROL 디스패치 루틴으로 들어오게 되는데 이때는 당연히 Context가 나의 유저 프로그램의 쓰레드이다. IRP_MJ_DEVICE_CONTROL 디스패치 루틴에서 링크드 리스트의 첫번째 주소를 드라이버의 전역 변수에 저장해두었다. 이제 후킹 루틴에서는 이를 이용해 리스트를 참고하고 후킹 코드를 수행할 거라고.. 생각했다.


드라이버 조금만 공부하신 분이라면 아 저 아이가 미쳤구나 라고 생각하겠다.


 결론은 후킹 코드에선 현재 어떠한 Context 인지 알 수 없으며 위와 같이 코드를 작성할 경우 전역 변수에 넣어두었던 링크드 리스트의 첫번째 주소는 다른 Context 일 경우.. 잘못된 주소를 참고하게 되고 결국 .. BSOD라는 매우 멋진 화면을 보게될 것이다.


결국 Neither I/O 방식은 그대로 사용하면서 주소를 가져오는 것이 아닌 IRP_MJ_DEVICE_CONTROL 디스패치 루틴에서 링크드 리스트를 쭉 따라가며 드라이버의 메모리로 전부 복사하는 방식을 사용해 해결하긴 했지만 뭔가 찝찝하다.


아무튼 저 같은 초보적인 실수는 하지말도록 합시다. :D