54. 디버깅 실습1 - 서비스
서비스 프로세스란?
Windows에서 "서비스 프로그램" 은 일반 프로세스와 다른 특성을 가지는 특별한 백그라운드 프로세스 를 의미한다.
서비스 프로세스 동작 원리
서비스 프로그램은 SCM(Service Control Manager) 에 의해 관리
서비스 애플리케이션이 실행되기 위해서는 이를 제어할 수 있는 서비스 컨트롤러(Service Controller) 가 필요
서비스 컨트롤러는 SCM에 서비스 제어 요청을 전달하면, SCM은 해당 요청을 서비스 프로그램에 전달하고 실행 결과를 돌려받는 구조
SCM은 시스템 내에서 서비스의 시작, 중지, 일시 정지, 재시작 등의 명령을 처리하는 역할
SCM(Service Control Manager)이란?
SCM(Service Control Manager)은 Windows 운영 체제에서 서비스 프로그램을 관리하는 핵심 구성 요소
SCM의 주요 역할
- 서비스 등록 및 관리: 시스템에 설치된 모든 서비스의 정보를 저장하고 관리
- 서비스 시작(Start): StartService() API를 호출하여 서비스를 시작
- 서비스 중지(Stop): ControlService() API를 통해 서비스 중지 요청을 처리
- 서비스 상태 모니터링: 실행 중인 서비스의 상태 정보를 유지하고 업데이트
- 자동 실행 관리: 시스템 부팅 시 자동 실행되어야 하는 서비스를 시작
- 서비스 간 의존성 관리: 특정 서비스가 실행되기 전에 필요한 서비스가 먼저 실행될 수 있도록 제어
서비스 제어기 실행 방법
책이랑 다르게 그냥 윈도우 탐색기에 서비스라 치면 나온다..
왼쪽에 파란거 시작 누르면 시작도 됨
서비스 시작 과정
- StartService() 호출
- 서비스 제어기(SCM)가 서비스 프로세스를 생성하고 실행
- StartServiceCtrlDispatcher() 호출
- 서비스 프로세스가 SCM과 연결됨
- SCM이 SvcMain()을 호출
- SetServiceStatus(SERVICE_RUNNING) 호출
- 서비스가 초기화됨
- SCM이 서비스가 정상 실행 중임을 확인
DebugMe1.exe 예제
서비스 설치를 아래처럼 했다
관리자모드로 열어서 해야됨
위에처럼 서비스 목록에 올라오게 된당
동작 - 속성에서
서비스 다이얼로그 뜨는데 여기에 실행 파일 경로랑 서비스의 시작 유형 서비스 상태 등이 뜸
그러고 나서 서비스 시작을 시켰다
그러고 나서 프로세스 익스플로러에서 보면 services.exe 프로세스의 자식으로 보인다는데 프로세스가 너무 많아서.. 찾을수가..............
포기..^^
암튼 그러고 나서 저 프로그램이 일정 시간 간격으로 디버그 문자열을 출력하는 건데 DebugView 유틸리티 이용해서 디버그 문자열을 확인해봐야함
맨 아래에 "service is running"이라고 뜨는거 볼 수 있음!!
서비스 프로세스의 디버깅 이슈
서비스 프로그램 정확히 디버깅 하려면 디버거로 서비스 프로그램 시작 하면 안되고 SCM에 의해 실행되는 서비스 프로그램에 디버거를 붙여서 디버깅 해야됨(attach)
왜?
SCM때문에...
- 서비스 프로세스는 SCM에 의해서 실행됨
- 서비스 핵심 코드는 주로 서비스 메인함수에 존재
- 서비스 메인 함수는 SCM에 의해서 정상 호출됨
결국에 디버거로 열면 서비스 메인함수가 실행이 안되니까 디버거로 열면 안되고 실행되고있는거에 디버거를 attach해야된다는 것
근데 또 디버거로 안되는게 없다 강제로 할 수도 있음
먼저 강제로 하려면 EIP를 강제로 세팅하는 것이다..
일단 파일을 올리디버거로 열고 메인함수로 이동했다.
아래 드래그한 주소를 보면 40106C가 StartServiceCtrlDispatcher() API다
exe 파일 형태의 윈도우 서비스 프로그램은 반드시 EP 코드에서 저 api를 호출해서 SCM에게 서비스 메인 함수를 알려줘야하므로 이 걸 찾으면 SvcMain()을 찾을 수 있음
우측 하단에 스택으로 보면 SvcMain주소가 00401320인걸알 수 있다.
pServiceTable(19FD08)의 첫번째 멤버 40A9CC는 SvcHost문자열
두번째 멤버 401320이 SvcMain()함수의 주소
그래서 이동해보았다.
이제 이 주소를 new origin here 설정을 하면 디버깅 위치를 변경할 수 있게됨.
이렇게 해두고 디버깅 하면 된다.
근데 원래는 저렇게 말고 정석대로 attach해야된다.
과정은
1. 서비스 설치: 디버깅할 서비스를 시스템에 설치
2. 파일 패치: 서비스 실행 코드(EP, Entry Point)에 무한 루프를 삽입
3. 서비스 실행: 서비스가 실행되면 무한 루프에 걸려 SCM이 대기 상태 유지
4. 디버거 Attach: 디버거를 서비스 프로세스에 연결(Attach)
5. 프로세스 패치: 원래의 EP 코드를 복원
6. 프로세스 디버깅: 정상적으로 EP 코드 디버깅 가능
이렇게 attach시킬 때까지 서비스 프로세스 중요 코드 안나오게 무한 루프를 돌림
근데 이걸 하려면 service start timeout안에 완료해야됨. 근데 이 기본 값이 보통 30초라 시간이 너무 짧으니까 늘려야함.
아래처럼 레지스트리 편집기에서 값을 생성해서 늘려준다
그러고 나서 파일 패치: 무한루프 설치
서비스 실행 파일의 EP에 무한 루프를 덮어씌워야함
EP의 파일 옵셋이 C24인걸 저 빨간줄 밑에 있는걸로 확인할 수 있음
이제 저 위치를 수정하면 되니까 hxd를 켜서 수정한당
근데 하려고하다가 실패함...
접근하고 있대서 수정이 안된대서... 다시 다 끄고 다시 했는데도 똑같음..
걍 영원히 이상태...
ㅠㅠ
일단 그냥 책 읽고 정리만 해야겠음 쩝
암튼 저기 드래그 한 값을 잘 기억했다가 저 부분이 원래는 call인데 무한 루프로 돌 수잇도록 EB FE로 바꾼다(자기자신으로 점프한다는 의미..)
그러고 나서 서비스 시작을 하면 무한 루프에 빠져서 CPU 점유율이 아주 높은 것을 알 수있음
그러고 올리디버거 가서 [file-attach] 메뉴를 보면 attach 다이얼로그가 나온다고 함. 거기에 debugme1.exe(예제 파일)을 선택해서 어태치 하면 시스템 라이브러리 영역에서 멈춘다고 한다
그러면 예제 파일 프로세스의 EP주소로 가서 BP 설치하고 실행하면 CP 주소에서 제어가 멈추는데 여기서 원래 수정하기 전 hxd값으로 다시 바꾼다.
그러면 정상코드로 돌아갈테고 루프가 풀리니 넘기면서 디버깅하면 되는것..