뭉근 : 느긋하게 타는 불

렌즈 판매

카테고리 없음2019. 12. 29. 22:01

Evoluent Mouse 수리기

생활2016. 6. 22. 20:10

Evoluent Mouse 수리기는 원래 작성했던 내용인데...

내용을 추가하려는데 실수로 삭제해버렸다. ㅡㅡ...

댓글로 문의해주셨던 분들에게 미안하다.

그래서 다시 이렇게 쓴다. :)


일단 나는 이 에볼루언트 마우스를 2년 넘게 써왔다.

1년이 지나자 휠이 잘 작동을 안했는데 그러려니 하고 쓰다가

더 이상 안되겠다 싶어서 A/S 관련 문의를 했고

내 판단으로 배송비나 배송기간이 너무 오래 걸릴거 같아

자가 수리 방법을 물어보았다.

친절하게도 Evoluent 사에서는 아래와 같은 답변을 달아주었다.


Hello,
 
To get the bottom off of the mouse, there are 4 screws.  3 of them are under the feet, 1 at the front, and 1 on each side.  The feet are like stickers, and can be peeled off.  The should stick back on if you keep the sticky side clean.
 
Once the bottom is off, you have to remove the rear case (black area).  To do that it’s held on by 3-4 screw.  Once the screws are removed, you need to pry between the inner and outer case at the rear ne the Evoluent logo.  It should pop off.
 
You can then access the screw that hold the buttons on.  You should now have access to the wheel, and the board it’s mounted on.
 
Thank you, 

Bradley Maris

www.evoluent.com



자 마우스 수리를 시작해보자.

일단 마우스 아래의 스티커 4장을 떼면 아래와 같이 검은 나사 4개가 보인다.

다 풀어주도록 하자.



다 풀면 아래와 같이 아랫단?을 분리할 수 있다. 

여기서 몸체 안쪽 나사 3개를 분리한다.

사진이 없지만... 아래 사진의 아랫 부분 나사 말고 몸체쪽 나사이다.

몸체의 안쪽 나사가 위 뚜껑을 잡고 있기 때문에

분리해주어야한다.



위 뚜껑과 연결된 나사 3개를 풀고

아래와 같이 지렛대 원리를 이용해 뚜껑을 올려준다.

처음에는 빡빡한데 힘줘서 올리면 툭 하고 윗 뚜껑이 몸체와 분리된다.

간혹 툭 하고 분리가 일부만 안되는 경우가 있는데

뚜껑을 지렛대 원리를 이용해 더 올려주자.



아래는 더 가까이서 찍은 사진이다.





분리하면 아래와 같다.

쓰던 마우스를 분리한거라 때가 있다. 부끄럽다. ;;;

저 가운데 검은색 나사를 분리해주자.




분리하고 아래 처럼 지렛대 원리를 이용해 툭 올려주면

검은색 판이 분리된다.




그리고 마우스 버튼 판이 남아있는데

몸체 안쪽에서 들어올려주면 분리된다.

아래는 분리 완료 후 ~사진이다.




나중에 합칠 때는 역순으로 해주면 된다.

마우스를 손으로 잡는 시점에서 봤을 때 왼쪽 은색 판과 버튼 2개만 주의해서 조립해주면 된다.

맨 처음 분리한 윗 뚜껑을 먼저 눌러서 딸깍 소리가 나게 맞추고

버튼 2개를 딸깔 소리나게 눌러주고

은색 판을 눌러주면 된다.


나 같은 경우에는 한 2주마다 한번씩 분해해서 휠 부분에 공기를 쏴준다.(라고 말하지만 입으로 훅! 불어준다)

그러면 마우스 휠이 잘 동작한다. 휠과 센서 사이에 이물질이 너무 잘 들어가는 거 같다. ㅡㅡ...


ps. 휠이 휙휙 돌아가는거 같다면 마우스 옵션에서 휠 가속을 꺼주도록 하자. 윈도우 8.1에서 관련 드라이버가 이상하게 동작하는거 같았다.


2016.06.22 추가.

마우스 드라이버는 아래와 같이 구글의 캐시된 페이지(저장된 페이지)를 이용하여홈페이지에 접속하여 다운받으면 된다.

해당 홈페이지가 한국 IP에서 접속되는 걸 막아놓아서 안들어가진다.








'생활' 카테고리의 다른 글

비트레이얼 - 더글라스 케네디  (0) 2016.03.09
라플라스의 마녀 - 히가시노 게이고  (0) 2016.01.15
USB 3.0 허브 구입기 및 재구입기  (2) 2015.08.11
논문 영어 쓰기  (0) 2015.04.20
'배려'의 명언  (0) 2014.11.24

PsSetCreateProcessNotifyRoutineEx를 실행하면 아래와 같이 STATUS_ACCESS_DENIED(0xc0000022) 에러가 반환된다.

   

ObCallbackTest: DriverEntry: Driver loaded. Use ed nt!Kd_IHVDRIVER_Mask f (or 7) to enable more traces

ObCallbackTest: DriverEntry: PsSetCreateProcessNotifyRoutineEx(2) returned 0xc0000022

   

이상하게 MS측에서 제공하는 드라이버 샘플 파일은 접근 거부가 일어나지 않는데, 내가 직접 똑같은 소스코드를 사용하여 컴파일한 드라이버를 로드할 경우에는 저 에러가 떴다.

   

MS에 의하면 PsSetCreateProcessNotifyRoutineEx는 Highest Level 드라이버에서만 동작한다고 되어 있어서 드라이버도 권한이 있는건가 싶어서 계속 알아보았는데 아무것도 안나왔다. 따라서 소스코드 문제인가 싶어 WDM, KMDF 드라이버 등을 생성하여 여러 방면으로 함수 호출을 시도해보았지만 문제가 해결되지 않았다.

   

그러나 위의 에러 문구를 검색하니 정말 간단한 문제 해결 방법이 나왔다.

링커 옵션에 INTEGRITYCHECK 옵션을 넣어주면 되는 것이다.

   

다음과 같이 프로젝트 속성의 링커 옵션을 추가해주면 된다.

   

   

아래는 obcallback 샘플의 링커 옵션이다.

   

   

   

INTEGRITYCHECK 옵션이란 메모리 메니저가 PE Header의 플래그값을 확인하여 드라이버 이미지를 로드하기 위하여 디지털 시그너처를 검사하는 것이다. MS에 의하면 모든 드라이버들이 이 기능을 사용하길 추천한다고 명시되어 있다.

   

integritycheck를 검색해보니 이 기능을 사용하지 않을 경우 일부 API를 사용할 수 없다고 한다.

'프로그래밍' 카테고리의 다른 글

Rstudio 3.3.0 스케일링 문제  (0) 2016.05.06
드라이버 개발 삽질 #1  (0) 2015.03.12
ofstream 한글 출력 문제  (0) 2014.10.22
ifstream 64  (0) 2014.09.25
CPP 벡터 반복문 중 원소 지우기  (0) 2014.09.22

Rstudio 3.3.0을 깔고 실행했더니

아래 그림과 같이 폰트 사이즈나 리소스 크기 등이 굉장히 불편하게 되어 있었다.

   

   

처음엔 Rstudio 버그인가 싶어서 resolution, window size, resource bug 등의 키워드로 검색해보았는데 대부분 plot 부분의 resolution을 처리하는 방법에 대한 문서들만 나왔다. 문득 떠오른 생각이 Rstduio 설치 할 때 QT 라이브러리도 같이 설치했던 기억이 나서 이 문제인가 싶어서 검색해보았더니 QT의 high resolution 지원으로 인한 스케일링 문제인 것으로 알 수 있었다. 몇 번의 검색 시도 끝에 다음과 같은 해결 방법이 있는 문서를 찾았다.

   

Qt fully supports high DPI monitors from Qt 5.6 onward, via attribute or environment variable (except on OS X where support is native). For the attribute method, use:

#include <QApplication>

int main(int argc, char *argv[])
{
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // DPI support

QApplication app(argc, argv);
return app.exec();
}

or set the system environment variable:

QT_AUTO_SCREEN_SCALE_FACTOR=1

I've tested both methods on windows 10 with a high-DPI surfacebook monitor and the results are scaled properly as expected.

   

출처: <http://stackoverflow.com/questions/24367355/automatic-rescaling-of-an-application-on-high-dpi-windows-platform>

   

시스템 환경변수에서 저 부분을 변경하려고 들어갔더니 QT_DEVICE_PIXEL_RATIO가 2로 설정되어 있었다. 뜻을 보니 딱 스케일링 관련 환경 변수같아서 다음과 같이 1로 설정하였더니 문제가 해결되었다.

   

   

아래는 잘 실행되는 Rstudio이다

   

   

- 요약

시스템 환경 변수의 QT_DEVICE_PIXEL_RATIO 값을 확인하여 1이 아닌 값으로 되어 있을 경우 1로 변경

* QHD, UHD 등이 고해상도 환경에서는 이 부분의 배율을 조정하여 눈에 편하게 볼 수 있을 것 같다.

'프로그래밍' 카테고리의 다른 글

PsSetCreateProcessNotifyRoutineEx 접근 권한 문제  (1) 2016.05.10
드라이버 개발 삽질 #1  (0) 2015.03.12
ofstream 한글 출력 문제  (0) 2014.10.22
ifstream 64  (0) 2014.09.25
CPP 벡터 반복문 중 원소 지우기  (0) 2014.09.22

비트레이얼 - 더글라스 케네디


원제는 THE HEAT OF BETRAYAL 배반의 온도이다. 한국어판의 제목이 단순히 배반을 의미하는 비트레이얼이라고만 했을까? 작가 자체가 흥행 보증 수표라 제목에 대해 생각없이 옮긴 같다.

 

선택은 자신의 것인가? 나의 문제는 자신이 이미 만들어 놓은 것인가?

 

작가는 전작들과 같이 계속해서 위와 같이 작품을 관통하는 주제를 묻고 있다. 빅처에서 더글라스 케네디가 단순히 선택과 문제에 대한 의문을 제기했다면, 이번 작에서는 로빈이 선택을 함으로써 소설의 마지막 부분에서 겪은 외상후 스트레스 장애와 일련의 사건들을 , 해답의 실마리를 찾았다.

 

결과가 어떻든 간에 선택은 네가 하는 것이다. 설사 결과가 안좋더라도 주위의 사람들이 너를 도울 것이다. 결과가 좋다면 주위 사람들은 너를 축하할 것이다.

 

이번 소설의 배경은 모로코로 외국 관광지에서 경험할 있을 법한 일들을 엮어 현실성있게 쓰였다. 특히 마지막에 로빈의 살인 사건 문제를 해결해버리는 과정은 굉장히 설득력있게 다가왔다. 마치 기존에 이런 사건이 있었던 것처럼 자연스러운 구성이었다. 또한 미국인들의 돈으로 모든 것을 해결하려는 마음가짐을 보여주었다.

 

다만 후반부에서 로빈이 베르베르족의 도움으로 몸을 회복하는 부분부터 소설의 힘이 빠져버린다. 마치 다른 소설속의 로빈을 만나는 같다. 1인칭 시점에서 서술하지만 작가가 남자라 치욕을 당한 여성의 심리를 풀어내지 못한다. 소설의 후반부에서 이야기 구성이 약해지는 것은 픽쳐 한번 경험해봐서 이질적이지 않았다.

 

어쨌든!

나에게 재밌는 시간을 작가, 더글라스 케네디에게 고맙다는 인사를 하고 싶다. :)

 

덤으로 번역에 많은 문제가 있는 같다. (http://asnever.blog.me/220621790834) 옮긴이가 작업한 도서들은 피해야겠다.

'생활' 카테고리의 다른 글

Evoluent Mouse 수리기  (3) 2016.06.22
라플라스의 마녀 - 히가시노 게이고  (0) 2016.01.15
USB 3.0 허브 구입기 및 재구입기  (2) 2015.08.11
논문 영어 쓰기  (0) 2015.04.20
'배려'의 명언  (0) 2014.11.24

라플라스의 마녀 - 히가시노 게이고


  책의 서평을 쓸려고 하는데 이 책은 도대체 무엇이 주제인가? 라는 의문이 생겼다.


  후반에 나와야할 살인 트릭이 이미 작품 중반부터 나와버려 추리소설로 보기에는 애매하다. 더욱이 트릭도 트릭이 아니다. 또한 추리 소설의 묘미는 반전인데, 이 책의 반전은 반전이라 하기도 애매하다. 책 뒤에 작품 설명을 보면 엄청난 반전이 있다고 하지만 세삼 새로울게 없다.


  그렇다면 뇌 과학을 다룬 공상 과학 소설인가? 책을 읽으면서 느낀 점은 컴퓨터가 매우 발달한 근미래에서 가능한 범죄 방식을 현대에서 어느 정도 가능성이 있는 뇌 과학과 연결지어 표현했다는 것이다.


  사랑과 복수야 대부분의 추리 소설에서 나오는 흔히 나오는 주제이니 이를 반영하면 내 생각에는 공상과학 70% 추리 30% 느낌의 소설로 볼 수 있다.


  책 전체의 스토리텔링은 80여권의 책을 쓴 작가 답지 않게 후반부에 너무 떨어진다. 이는 31장에서 보이지도 않던 경찰들이 나타나고, 39장에서 사건 수습 편지를 쉽게 믿어버리는 직원들을 볼 때 소설의 전체 판을 너무 크게 만들어 수습하는 것 자체가 버거워 쓸데 없는 부분을 넣지 않았나 싶다. 굳이 저 내용을 넣어야 했을까? :(


  또한 책을 읽다보면 마도카나 그의 아버지가 아오에 박사에게 "이 이야기는 복잡해서 너는 이해할 수 없으니까 알려고 하지 마라"라고 하는데 이 이야기에 어떤 추리가 있는것이 아니라 과학적인 성과를 함부로 얘기할 수 없다는 단순한 이유였을 때 너무 허탈했고, 또한 주요 스토리텔러인 아오에에게 그렇게 말함으로써 독자인 내가 무시당하는 것 같은 느낌이 들었다.


  전작들은 우리가 충분히 만날 수 있는 사람들이었는데 반해 이번 작은 보통 사회에선 볼 수 없는 특별한 존재들이 등장한다. 사건을 일으킨 인물(들)의 특징을 살펴보면 부성애가 결핍되고 완벽주의자인 사람인 특정 인물, 뇌 과학으로 미래를 예측할 수 있는 특정 인물, 그리고 수술로 인해 미래를 예측할 수 있는 특정 인물들이다. 사건의 트릭이 비범하고 현실성이 있을 때는 대단하다할 수 있지만, 범인이 보통 사람들과 달라 현실성 없는 트릭을 쓸 때는 재미가 없다. 또한 그 범인을 잡는 사람도 공상과학에서나 등장할 법한 존재면 더욱 재미가 없다.


  책의 절정에서는 천재들만이 이끄는 세상이 아닌 보통 사람 또한 원자로서 세상을 구성한다 메시지를 전하는데 작품 내용을 보면 다른 보통의 사람들의 도움으로 추리를 해나가 사건을 막는다는 것을 생각해 볼 때 메시지는 잘 전달되는 것 같다.


  전체적으로 볼 때 꼭 봐야할 도서는 아닌 읽을게 없을 때 한번 쯤 읽어볼만한 도서이다.



'생활' 카테고리의 다른 글

Evoluent Mouse 수리기  (3) 2016.06.22
비트레이얼 - 더글라스 케네디  (0) 2016.03.09
USB 3.0 허브 구입기 및 재구입기  (2) 2015.08.11
논문 영어 쓰기  (0) 2015.04.20
'배려'의 명언  (0) 2014.11.24

이번 포스트는 Windbg에서 프로세스 리스트를 볼 때 왜 유휴 프로세스(Idle Process)는 없는가? 에 대한 내용이다. Process Explorer로 보면 아래와 같이 Idle Process가 나오는데, 왜 프로세스 리스트를 직접 출력해보면 유휴 프로세스를 찾을 수 없는 것일까? 궁금하면 아래의 글을 읽어보기 바란다.



들어가기

윈도우는 시스템 프로세스 중 커널 영역에서만 동작하는 프로세스로 Idle Process(유휴 프로세스)와 System Process(시스템 프로세스)를 사용한다. 이 두 프로세스들은 유저 모드에서 실행되지 않기 때문에 커널 영역에서만 존재한다.   

System Process는 커널 모드 시스템 스레드(kernel-mode system thread)들을 포함한다. 이 스레드들은 오직 커널 주소 공간의 코드들만을 실행하여 커널 레벨에서만 동작한다.

Idle Process는 CPU의 각 프로세서의 유휴 상태를 나타내기 위한 Idle Thread(유휴 스레드)를 포함한다. 프로세서에 더 이상 실행 가능한 스레드가 없을 때, 윈도우는 해당 프로세서의 유휴 스레드를 실행한다. 이는 멀티프로세서 시스템에서 하나의 CPU가 실행될 때, 다른 CPU들이 실행할 스레드들을 가지지 않는 상황이 있기 때문이다. 따라서 Idle Thread는 프로세서의 수만큼 생성된다.

Idle Process와 Idle Thread들은 특수한 케이스로 EPROCESS / ETHREAD 구조체로 표현되지만 익스큐티브 오브젝트 관리자에 의해 생성되는 프로세스와 스레드 오브젝트들이 아니기 때문에 시스템의 프로세스 리스트에 포함되지 않는다[0].


---------------------------------------------------------------------------------

0: kd> !process 0 0

**** NT ACTIVE PROCESS DUMP ****

PROCESS fffffa800ccc2990

SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000

DirBase: 00187000 ObjectTable: fffff8a000001740 HandleCount: 479.

Image: System

   

PROCESS fffffa800d2fcb30

SessionId: none Cid: 00e8 Peb: 7fffffde000 ParentCid: 0004

DirBase: 2495c000 ObjectTable: fffff8a0005c07d0 HandleCount: 30.

Image: smss.exe

   

… (생략)

   

PROCESS fffffa800f2b3b30

SessionId: 1 Cid: 0948 Peb: 7fffffd4000 ParentCid: 08d8

DirBase: 3091b000 ObjectTable: fffff8a0017fdea0 HandleCount: 134.

Image: vmtoolsd.exe

   

PROCESS fffffa800f2e6b30

SessionId: 1 Cid: 0954 Peb: 7efdf000 ParentCid: 08d8

DirBase: 30cce000 ObjectTable: fffff8a0018be990 HandleCount: 41.

Image: runonce.exe

---------------------------------------------------------------------------------


위의 결과를 보면 프로세스 리스트가 System Process부터 시작한다는 것을 알 수 있다. 물론 언급했던 것과 같이 Idle Process는 나오지 않는다.

커널은 프로세스 리스트를 유지하기 위해 이중 연결 리스트(double-linked list)를 사용한다. 프로세스들은 생성된 순서대로 이 이중 연결 리스트에 들어가고, 프로세스가 종료된다면 역시 이중 연결 리스트에서 제거된다.

따라서 !process 0 0 명령어를 사용하지 않고도 직접 이 이중 연결 리스트를 따라가 리스트에 있는 각각의 프로세스를 추출할 수 있다. (* 아마도 !process 명령어도 이 리스트를 따라가지 않나 싶다. 실제로 확인해보지는 않았다 :) )   

윈도우 커널은 프로세스 리스트의 헤드를 전역 변수로 관리하며, 이에 대한 심볼 정보를 PsActiveProcessHead로 공개하고 있다. 간단히 말해서 전역 변수인 PsActiveProcessHead를 시작으로 실행 중인 프로세스들의 정보에 접근한다.   

Windbg의 dq 명령을 통해 직접 순회하여 볼 수도 있지만, !list 명령을 통해 다음과 같이 각각의 리스트 요소에 대해 정보를 일괄적으로 얻을 수 있다. 아래의 !list 명령어는 리스트의 각 요소인 ActiveProcessLinks를 참조한다.


---------------------------------------------------------------------------------

0: kd> !list "-t nt!_EPROCESS.ActiveProcessLinks.Flink -e -x \"dd @$extret L1; dt nt!_EPROCESS @$extret ImageFileName\" poi(nt!PsActiveProcessHead)-0x188"

dd @$extret L1; dt nt!_EPROCESS @$extret ImageFileName

fffffa80`0ccc2990 00580003

+0x2e0 ImageFileName : [15] "System"

   

dd @$extret L1; dt nt!_EPROCESS @$extret ImageFileName

fffffa80`0d2fcb30 00580003

+0x2e0 ImageFileName : [15] "smss.exe"

   

… (생략)

   

dd @$extret L1; dt nt!_EPROCESS @$extret ImageFileName

fffffa80`0f2b3b30 00580003

+0x2e0 ImageFileName : [15] "vmtoolsd.exe"

   

dd @$extret L1; dt nt!_EPROCESS @$extret ImageFileName

fffffa80`0f2e6b30 00580003

+0x2e0 ImageFileName : [15] "runonce.exe"

---------------------------------------------------------------------------------

* 0x188은 Windows 7 x64 시스템의 ActiveProcessLinks 오프셋이다. 이는 버전마다 다를 수 있다.

  

!process 명령어를 사용했을 때와 마찬가지로 System Process는 나타나지만, Idle Process는 나타나지 않는다. 즉 Idle 프로세스는 프로세스의 이중 연결 리스트에 포함되지 않는다.

그렇다면 Idle Process는 어떻게 생성되길래 System Process도 포함되어 있는 프로세스 리스트에는 존재하지 않는건가?

   

Idle Process 찾아가기

일단 Idle Process의 존재부터 알아본다. 윈도우 인터널스[0]에 Idle Process로 접근하는 방법이 나와있지만, Windbg로 디버깅시에는 전역 심볼인 PsIdleProcess을 이용하여 더 간단하게 접근할 수 있다.

   

---------------------------------------------------------------------------------

0: kd> dt _EPROCESS poi(PsIdleProcess) ImageFileName ActiveProcessLinks

nt!_EPROCESS

+0x188 ActiveProcessLinks : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]

+0x2e0 ImageFileName : [15] "Idle"

---------------------------------------------------------------------------------

   

이 Idle Process의 ActiveProcessLinks 필드를 살펴보면 Flink와 Blink가 모두 NULL로 처리되어 있음을 확인할 수 있다. 즉 Idle Process는 다른 프로세스들을 가리키지 않는다.

* KiInitialProcess 로도 접근할 수 있다. PsIdleProcess는 EPROCESS 구조체의 주소에 대한 주소를 가진 반면 KiInitialProcess는 _EPROCESS 구조체의 주소를 가진다.


Idle Process는 시스템에서 반드시 생성하는 정적인 데이터이기 때문에 전역 심볼로 관리된다. 생성 및 파괴를 반복하는 일반적인 프로세스와 다르게 한번 생성되면 시스템이 실행되는 동안 파괴되지 않는다. 그렇다면 System 프로세스는 어떨까? System 프로세스 또한 아래와 같이 전역 변수인 PsInitialSystemProcess로 관리된다.

   

---------------------------------------------------------------------------------

0: kd> dt _EPROCESS poi(PsInitialSystemProcess) ImageFileName

nt!_EPROCESS

+0x2e0 ImageFileName : [15] "System"

---------------------------------------------------------------------------------

   

사실 커널 디버깅이 아닌, 실제 커널 코드 코딩(ex. 드라이버)를 할 때에 PsInitialSystemProcess는 전역 변수로 export[1]되어 있어 프로그래머가 접근할 수 있다. 하지만 Idle Process의 디버깅 심볼인 PsIdleProcess는 MS에서 심볼 정보만 제공하기 때문에 커널 코드 작성 시에 사용할 수 없다. 사실 생각해보면 유휴 프로세스에 드라이버가 접근할 필요가 없다. 인터널스에서도 언급한대로, 유휴 프로세스는 유휴 스레드를 위한 프로세스로 내부 객체를 살펴보면 일반적인 프로세스들과 달리 대부분의 필드들이 사용할 필요가 없기 때문에 NULL(0)으로 채워져 있다.

또한 구현 측면에서 보면 인터널스에 업근된 대로, 초기 유휴 스레드(PsInitialSystemThread)와 유휴 프로세스(PsInitialSystemProcess) 구조체는 정적으로 할당돼 프로세스 관리자와 객체 관리자가 초기화되기 전에 시스템 부팅을 위해 사용된다. 그 이후 유휴 스레드 구조체는 추가 프로세서가 동작할 때 동적으로 할당된다.

그렇다면 위의 말이 진짜일까? 궁금해진다.

   

Idle Process 생성

디버깅 심볼 정보인 PsIdleProcess와 PsInitialSystemProcess가 사용되는 부분을 찾으면 아래와 같이 PspInitPhase0 함수에서 Idle Process와 System Process의 EPROCESS.ImageFileName에 각 프로세스 이름을 쓰는 것을 볼 수 있다. 다른 프로세스들은 파일 이름을 기반으로 프로세스 이름이 정해지는데 비해, 이 두 프로세스들은 특수한 프로세스로서 프로세스 이름이 정해진 커널 코드에 의해 정해진다.

   

* 0x16c는 윈도우 7 32비트 상에서 _EPROCESS.ImageFileName 필드의 오프셋이다.

   

PspInitPhase0 함수는 커널을 초기화할 때 실행되는 함수 중 하나로, 커널은 KiSystemStartup 함수를 시작으로 다음과 초기화 함수를 호출한다. PsActiveProcessHead를 참조하는 모든 코드를 살펴보면 이 PspInitPhase0 함수에서 아래와 같이 PsActiveProcessHead를 초기화하는 것을 볼 수 있다.

   

   

코드를 살펴보면 KeGetCurrentThread 함수를 이용하여 현재 쓰레드가 속한 프로세스를 얻는다. 프로세스의 몇몇 필드를 초기화한 후 전역 변수 PsIdleProcess에 해당 프로세스의 주소를 대입한다. EPROCESS 구조체 필드는 이게 다가 아닌데 나머지는 어디서 초기화하는 걸까? 또한 KeGetCurrentThread는 어떤 쓰레드를 얻어오는건가?

   

커널 초기 쓰레드의 생성

KiSystemStartup 함수부터 살펴보면 다음과 같은 순서로 커널 초기화 함수가 실행된다.

   

KiSystemStartup()

  - KiInitialThread를 스택에 저장

  - KiInitilizePcr()

  - KiIntializeKernel()

    - KiInitializeProcess()

    - KiInitializeThread()

    - InitBootProcessor()

      - PsInitSystem()

      - PspInitPhase0()

   

KiSystemStartup 함수는 전역 변수 KiInitialThread를 스택에 저장한다.

   

   

이후 코드에서 스택에 저장한 값을 커널 프로세서 관리 구조체(Kernel Processor Control Region)인 KPCR의 IdleThread에 그 값을 등록한다.

   

   

   

이후 KiInitializeKernel 함수를 실행한다. 이 때 스레드 초기화를 위해 앞서 스택에 저장한 KiInitialThread를 호출 인자로 넘겨준다. KiInitilizeKernel을 호출할 때 KiInitialProcess 또한 인자로 같이 넘긴다.

   


KiInitializeProcess 함수를 먼저 실행하여 Idle Process의 나머지 필드들을 초기화한다. 사실 이 함수의 내부를 보면 복잡한 초기화가 아니라 앞에서 0으로 채웠던 것처럼 다른 필드들도 NULL 값으로 채운다.

   

   

Idle Process의 필드를 초기화한 후, 시스템 스레드를 초기화하는 KiInitializeThread 함수를 실행한다.

   

   

이 함수에서는 크게 KeInitThread 함수와 KeStartThread 함수를 호출한다. KeInitThread 함수를 호출하는 코드를 찾아보면 일반적인 스레드를 생성할 때 호출하는 용도로도 사용되는 것을 알 수 있는데, 이 때 입력받는 인자가 다르다. 실제로 PspAllocateThread를 찾아가보면 아래와 같이 인자가 일반적인 스레드와 다르게 들어간다는 것을 알 수 있다.

   

   

   

다시 KiInitilizeThread 함수로 돌아와 생각해보면 이 함수가 호출될 때 입력 받는 인자는 Idle Thread와 Idle Process이다. KiInitializeThread 함수에서 실행되는 KeInitThread 함수는 다음 코드와 같이 Idle Thread가 속한 프로세스를 Idle Process라고 명시한다.

   

   

앞서 커널의 첫 쓰레드는 언제 어떻게 생성되어 이 스레드로부터 Idle Process를 어떻게 얻어올 수 있는지 궁금했었는데 이제 해결되었다. KeGetCurrentThread 함수를 호출하기 전에 첫번째로 KPCR.Prcb.CurrentThread에KiInitialThread (Idle Thread)를 등록하고 KiInitializeThread 함수에서 Idle Thread가 속한 프로세스로 Idle Process를 등록하는 것이다.

   

프로세스 리스트에 Idle Process가 포함되지 않는 이유

IdleProcess는 PspCreateProcess에 의해 생성되지 않기 때문에 PsActiveProcessHead의 리스트에 등록되지 않는다. 물론 다음 코드처럼 System 프로세스부터는 PspCreateProcess에 의해 생성되고, 이 PspCreateProcess 함수 내부에서 PsActiveProcessHead를 참조하여 프로세스 리스트에 새로 생성되는 프로세스를 등록한다.

   

   

PspCreateProcess 함수의 내부에서 호출하는 PspInsertProcess 함수는 다음 코드와 같이 이중 연결 리스트의 마지막에 새로운 프로세스를 추가한다.

   

   

이 때까지의 Idle Process를 초기화하는 과정을 정리하면 아래와 같다.

   

   

결론

Idle Process는 커널에 _EPROCESS 구조체 자체, 즉 C언어의 변수 선언으로 "EPROCESS KiInitialProcess"처럼 정적으로 존재하기 때문에 PspCreateProcess와 같은 프로세스 할당 함수를 사용하지 않는다. 따라서 PsActiveProcessHead로부터 얻을 수 있는 프로세스 리스트에는 Idle Process가 없다. 더욱이 Idle Process는 다른 여타 프로세스와 달리 실행 파일이 없기 때문에 커널 코드 내에서 프로세스 이름이 정해진다. (System Process 또한 커널 코드 내에서 프로세스 이름이 정해진다. )

   

참조

[0] Windows Internals, 마크 러시노비치 등, 5장, p616

[1] https://msdn.microsoft.com/en-us/library/windows/hardware/ff559943(v=vs.85).aspx

   

커널 함수에서 사용하는 구조체 분석에 사용된 문서들

http://www.nirsoft.net/kernel_struct/vista/LOADER_PARAMETER_BLOCK.html

https://translate.google.co.kr/translate?hl=ko&sl=ru&tl=en&u=http%3A%2F%2Fhex.pp.ua%2Fntstatus%2Fpage024.php

http://www.osronline.com/showThread.cfm?link=3787

http://doxygen.reactos.org/d3/d0c/ntoskrnl_2include_2internal_2powerpc_2ke_8h_a88a282c034ffdbc59b89bab1b67676bb.html

http://www.osronline.com/showThread.cfm?link=72000

   

이외에 커널 분석에 도움될만한 내용

이번에 커널 코드를 살펴보면서 _LIST_ENTRY 구조체의 초기화 방식을 알게 되었다. 대부분이 자기 자신을 가리키도록 해놓았다. 이렇게 해놓으면 리스트 엔트리가 초기화 되었는지 되지 않았는지를 바로 파악할 수 있구나 생각하였다.

   

   

따라서 커널 구조체 분석시 LIST_ENTRY 구조체로 이루어진 필드 멤버가 자기 자신을 가리킨다면 별 다른 의미를 가진 것이 아니라 단순히 초기화된 상태라는 것이다.

'디버깅' 카테고리의 다른 글

MS 심볼 구성에 관하여  (0) 2014.12.17
Windows 10 _KPCR and _KPRCB  (0) 2014.11.14
8바이트 변수 초기화 문제  (0) 2014.11.14
Windbg에서 KDBG 찾기  (0) 2014.06.19
Window8 Remote Kernel Debugging on Vmware using WinDbg  (0) 2014.04.11

사용하는 USB가 점점 늘어나고 USB 충전이 필요한 장치도 많아져, USB 3.0 제품 허브를 알아보고 그 때 싸게 팔던 NEXT-UH308 허브를 구입하였습니다. 싼 맛에 구입하였죠.

   

NEXT-UH308 제품 사진

   

제품을 6개월 이상 사용하였는데, 그 동안 USB와 다른 장치들에 중대한 문제를 끼친 문제들이 있었고 이번 포스팅은 이를 다루고자 합니다. 


1.외장하드 인식 불가

NEXT 허브를 구입하기전부터 Seegate Freeagent GoFlex 제품을 사용하였습니다. 따라서 구입한 NEXT 허브에 꽂고 사용하려는데 인식불가 상태가 되더군요. 내 외장하드에 이상이 생긴건가 싶어 외장하드를 그냥 본체에 꽂았더니 잘 됩니다. 네 허브 자체에서 인식이 안되더군요.

인식이 안되는 상황에 몇 가지 실험을 해봤는데, 직장 동료의 SONY 외장하드를 빌려서 허브에 꽂았더니 잘 됩니다. 그러면 Seegate Freeagent GoFlex 제품이 국제표준을 지키지 않은건가 싶어서 직장 동료의 NEXT 4포트 허브(UH305)에 꽂아보았더니 잘되더군요. -_-;;

이런 현상과 관련하여 A/S 센터에 관련 전화 문의를 해보니 USB 외장하드 제품에 따라 인식할 수 있는게 다르다는 답변이 왔습니다. 일단 USB들은 잘 인식되니 계속 사용하였습니다.


2. USB 먹통

기존 잘 사용하던 USB가 NEXT 제품을 사용하면서부터 제 컴퓨터에선 인식이 가능한데 다른 컴퓨터에서는 인식이 안되더군요. 제 컴퓨터에서도 종종 인식이 안되서 chkdsk 도구로 디스크 포맷을 다시 고치기도 했습니다. 그런데 다른 USB도 먹통이 되니까 개인적으로 "이 제품을 계속 사용하면 내 남은 USB들이 모두 먹통이될 것이다"라 판단하였습니다. 이후로 이 USB 허브는 먹통된 USB 전용 허브로 바뀌었고 나머지 용도는 충전용으로만 사용하였습니다.


충전용으로만 사용하다가 불편함을 느껴 새로운 USB 3.0 허브 제품을 구매하려고 안정성있는 제품이 무엇인지 알아보았습니다. 국내에선 오리코 제품이 가장 안정성있는 제품이고 추천이 많더군요. 추천하는 사이트를 살펴보면 안정성있는 USB 3.0 허브를 사용하려면 USB-IF 인증받은 칩셋을 사용하는 제품을 찾아봐라 라는 내용을 볼 수 있습니다. 쉽게 말하면 인증을 받은 VL810, VL812 등의 칩셋을 사용하는 제품이 안정성이 있다는 것입니다. 2014년 1월에 적힌 내용이라 지금은 어떤지 제품 스펙을 찾아보니 오리코는 다음과 같이 VL812 칩셋을 사용한다는 것을 알 수 있습니다.

   

(http://www.oricoonline.us/goods.php?id=5544)

   

반면 NEXT 제품군은 컨트롤러를 찾아볼 수 없더군요.

   

   

(http://www.ez-net.co.kr/new_2012/product/view.php?cid=3&sid=&q=&seq=335&page=&q=&PHPSESSID=52adcfc3b7e3362fb6c6df0548e8f0c3)

   

다른 회사(IPTIxx, NETMAxx) 제품들 또한 USB-IF 인증받은 칩셋을 사용하는지에 대해서 전혀 적혀있지 않더군요. 국내 USB 제품들을 보면 주로 속도(5Gbps)와 편의성(포트 개수)를 위주로 설명하는데 안정성에 대해선 전원 유뮤만 어필하고 있습니다. 오리코도 공식사이트 들어가야 저 컨트롤러 내용이 보이고 판매업자가 제공하는 정보에선 컨트롤러 내용이 안보이더군요. 오리코에서 안정성에 대해 어필하면 더 잘 팔리지 않을까 싶습니다. 가격이 두배 정도 비싸서 모르는 사람은 구매하지 않을 것 같네요.

   

어제 오리코 제품을 주문했는데 몇개월 사용하다가 실사용기 남기려 합니다.

   

   

논문 영어 쓰기

생활2015. 4. 20. 19:04

1. with using이냐 그냥 using이냐 by using이냐?

 

논문을 작성하던 중 "그 도구를 이용하여 분석한다."라는 표현을 써야했다.

이 표현은 뭐 "그 도구로 분석한다." 정도로도 바꿔 번역할 수 있는데

영어로는 다음과 같은 표현을 쓸 수 있다.

 

we analyzes it with the tool.

we analyzes it using the tool.

we analyzes it by using the tool.

 

검색해보니 모두다 가능한 표현이다. 하지만 미국 영어에서는 강조 정도가 다르다는데

첫번째 예문(with를 사용하는)은 무엇이 분석되었는가? 즉 동사의 목적어를 강조한다.

여기서는 'it'을 강조한다.

즉 "도구로 그것을 분석을 분석한다." 정도의 문장으로 번역할 수 있다.

 

두번째 예문(using을 사용하는)은 무엇이 분석을 하였는가? 즉 using 뒤의 보어 목적어(?)를 강조한다.

여기서는 'the tool'이 되겠다.

또한 분석 가능한 도구(the tool)을 선택할 수 있을 때 사용된다고 한다.

즉 "여러 도구 중에서 이 도구를 사용해서 분석한다." 정도의 문장으로 번역할 수 있다.

 

세번째 예문 또한 'the tool'을 강조한다. 두번째 예문보다 강하게 강조한다.

하지만 이 표현은 자주 사용되지 않는 진짜로 강조하고 싶을 때 쓰는 용어로 보편적으로 쓰이지 않는다.

즉 "여러 도구 중에서 특히 이 도구만을 사용해서 분석한다." 정도의 문장으로 번역할 수 있다.

 

영어 어렵다..

 

참고 http://www.grammarly.com/answers/questions/4579-usingby-using/

 

본 내용은 계속 추가됩니다. 15.04.20

1. vmware를 이용한 드라이버 디버깅 방법

데브구루의 기술 칼럼을 따라했는데 잘 되지 않았다.

프로젝트 생성한 후, 호스트가 윈도우 7 x64이고 타겟이 가상머신 윈도우 7 x86인 환경에서

디버깅 환경 설정을 진행하였는데 드라이버 컴파일 후 가상 머신으로 전송하고 Driver Install 하는 부분에서 막혔다.

이후 타겟을 윈도우 8.1 x64로 변경하였는데 잘되었다.

컴파일 설정은 당연히 바꾸고 했는데 이상했다... 

아무튼 디버깅을 해보니 타겟으로 Driver Install 하는데 시간도 오래 걸리고 디버깅하는데도 버벅 거렸다.

간단한 제작에는 DbgPrint 등으로 디버깅하는게 더 빠르겠다.


참고
http://devguru.co.kr/blog/6619/

https://msdn.microsoft.com/en-us/library/windows/hardware/hh439654(v=vs.85).aspx



2. WinDbg에 DbgPrint 출력하기

DbgPrint 출력 전에 WinDbg 커맨드 라인에 아래와 같이 해주면 된다.

kd> ed Kd_DEFAULT_MASK 8


3. 커널 페이지 메모리 보호 해제

MDL을 사용하여 페이지 메모리 보호 해제를 하려다 

예전에 공부한 CR0 레지스터 변경을 찾아서 적용했더니 바로 되었다.

짬내어 MDL 공부도 해놓아야겠다.


참고 

http://resources.infosecinstitute.com/hooking-system-service-dispatch-table-ssdt/


4. 드라이버 로드 & 언로드 1

윈도우 서비스 메니저(SCM)을 이용하여 로드까진 진행이 잘 되었는데

드라이버를 언로드하려 할 때 아래 코드에서 자꾸 에러가 났다.

ControlService(service, SERVICE_CONTROL_STOP, &ss)

알고보니 드라이버 언로드 루틴이 없어서 그런거였다.

또는 MJ_IRP_CLOSE 루틴인가? .. 사실 언로드 루틴과 클로즈 루틴을 다 넣어놨다.

뭐 때문인지는 테스트해봐야겠지만 일단 그냥 둔다.


참고

https://msdn.microsoft.com/en-us/library/windows/desktop/ms682571(v=vs.85).aspx


5. 드라이버 로드 & 언로드 2

이번엔 드라이버가 처음에는 잘 로드되는데

처음 로드한 드라이버를 언로드 후 다시 로드하면 시스템 에러 0x02가 났다.

확인해보니 디바이스 생성 후 삭제를 안해서 

커널에 똑같은 이름의 디바이스가 남아있었다.

드라이버 언로드 루틴에 디바이스 오브젝트 삭제 코드를 추가하였다.


실행 상태(SERVICE_RUNNING)인 드라이버를 언로드하기 위해서는 반드시

QueryServiceStatusEx를 호출하여 서비스 실행 상태를 얻고

실행 중이면 ControlService를 이용해 중지 명령을 내려야 한다.

(일부 드라이버는 delete pending에 들어가 재부팅 후에만 제대로 언로드가 될 수 있다.)


참고

IOCTL 예제 코드(https://code.msdn.microsoft.com/IOCTL-a583bbeb?SRC=VSIDE)

* VS2013에서는 New Project 다이얼로그의 Online - Samples에서 바로 컴파일 가능한 형태로 다운받을 수 있다.


6. 디바이스 핸들 얻기

CreateFile을 이용하여 디바이스 핸들을 얻기 위해서 드라이버에 반드시 추가해야할 코드가 있다.

첫번째는 IoCreateDevice, IoCreateSymbolicLink, IoDeleteSymbolicLink, IoDeleteDevice 함수 셋이다.

이 함수들이 뭐냐하면 디바이스를 생성하고 생성한 디바이스에 대해 유저 영역(Win32)에서 디바이스로 접근할 수 있는 이름을 생성하는 것이다.

IoCreateDevice에서 인자로 넣어주는 이름은 디바이스 이름이고, IoCreateSymbolicLink에서 넣어주는 이름은 유저 핸들 이름(?)이라 할 수 있겠다.

꼭 이렇게 해주고 드라이버 언로드 루틴에서 디바이스와 심볼릭 링크를 삭제해야 다음 로드시 드라이버 로드가 된다.

두번째는 IPR_MJ_CREATE와 IRP_MJ_CLOSE이다. 이 함수가 드라이버에 등록되지 않으면 CreateFile로 핸들 생성 자체가 안된다.

예전에 디폴트 커널 코드가 있다고 알고 있었는데 없어졌나 싶다.

(IRP_MJ_CLOSE는 아닐 수도 있다... 테스트할 시간이 없다.)


0. 드라이버 개발에 좋은 도구들

devicetree : 디바이스가 제대로 등록되어 있는지 확인할 수 있다.

osrloader : 등록한 드라이버가 서비스에 등록되어 있는지 확인할 수 있다.

winobj : 디바이스와 디바이스의 심볼릭 링크가 있는 전역이름공간(\\??\, 즉 \\.\)을 확인할 수 있다.


계속 추가 예정이다.

'프로그래밍' 카테고리의 다른 글

PsSetCreateProcessNotifyRoutineEx 접근 권한 문제  (1) 2016.05.10
Rstudio 3.3.0 스케일링 문제  (0) 2016.05.06
ofstream 한글 출력 문제  (0) 2014.10.22
ifstream 64  (0) 2014.09.25
CPP 벡터 반복문 중 원소 지우기  (0) 2014.09.22