프로젝트를 진행하면서 약간의 보안기능을 추가해야 할 일이 생겼다...
프로세스 숨기기와 프로세스의 핸들 보호, 그리고 불법프로그램의 강제 종료..
프로세스 숨기기와 핸들 보호는 예전에 작업을 해둔게 있어 그리 어렵지 않게 일을 마무리 한 반면
불법 프로그램 종료에서 문제가 생겼다...;;
불법 프로그램들 중에는 커널에서 자신의 프로세를 보호하는 프로그램들이 은근히 있다..
ntopenprocess, ntterminateprocess등을 후킹을 걸어 자기 자신자신을 보호하는 경우가 이경우 였다..
ntopenprocess의 관련해서는 복원함으로써 문제를 해결하였지만 ntterminateprocess 복원하여 처리하기가 무척이나
귀찮았다..ntopenprocess는 같은 함수를 공동으로 후킹하므로 원복함수를 이용하여 덮어씌우면 되지만
ntterminateprocess에 대해서는 아무런 작업을 해둔게 없었다..
원복하려면..;; 무척이나 귀찮다...어차피 프로세스 종료만 시키면 되는것을...
그냥 후킹된 부분을 건너뛰어 nttreminateprocess를 호출하기로 했다..(트램벌린?)..
********************************************************************************************************
즉 아래와 같이 되어 있다면
jmp 후킹함수 주소 (op코드가 5바이트로 구성됨, 일반적인 인라인 함수 후킹은 앞에 5바이틀 많이 후킹한다.;;)
mov eax, 0
mov ecx, [ebp-4]
...
**********************************************************************************************************
난 nttreminateprocess의 실제 주소를 구한뒤 후킹된 부분의 코드를 실행하고 'jmp 후킹된 이후 번지' 로 호출하면 그만이엇다.
아래 처럼 말이다.
-------------------------------------------------------------------------------------------
mov edi, edi
push ebp
mov ebp, esp
jmp ntterminateprocess+5
-------------------------------------------------------------------------------------------
위와 같이 호출해버리면 후킹이 되어 있어도 원래 함수를 호출할수 있어 ntterminateprocess가 정상 실행되므로
원하는 프로세스를 커널단에서 종료할 수 있다..
근데 여기서 위와 같이 했는데..자꾸 ntterminateprocess가 0xC0000008을 내뱉는게 아닌가.??
찾아보니 핸들이 Invalid handle이란다..뭥미??;;;;
뭔가 내가 잘못했다..여기저기 소스를 봐도 전혀 문제가 보이지 않았다...흠..
그래서 우선 ZwTerminateProcess함수를 호출해보았다. 이함수는 잘먹는다.(물론 후킹되지 않은 상태에서..)
뭐가 문제지...아오...저 함수를 일일이 타보기가 너무 귀찮고;;;ㅜㅜ;;
그래서 NtTerminateprocess를 한줄씩 타보면 어디서 무슨이유로 에러를 내뱉는지 확인해 보기로 했다..
원인을 찾을수 있을지는 미지수...내가 뭐 어셈을 잘하는 것도 아니고.ㅠㅠ
일단 타보자...이정도 삽질했으면 이거라도 한번타봐야지..
(사실상은 이걸 제일 먼저 해봤으면 문제는 단시간에 끝났을텐데..ㅠㅠ)
자 함 봐보자...ㅡㅡ;
nt!NtTerminateProcess:
805842e0 8bff mov edi,edi
805842e2 55 push ebp
805842e3 8bec mov ebp,esp
805842e5 83ec10 sub esp,10h
805842e8 53 push ebx
805842e9 56 push esi
805842ea 57 push edi
805842eb 64a124010000 mov eax,dword ptr fs:[00000124h]
805842f1 837d0800 cmp dword ptr [ebp+8],0
805842f5 8bf8 mov edi,eax
805842f7 8b4744 mov eax,dword ptr [edi+44h]
805842fa 8945f0 mov dword ptr [ebp-10h],eax
805842fd 0f84cf050000 je nt!NtTerminateProcess+0x25 (805848d2)
80584303 c645ff01 mov byte ptr [ebp-1],1
80584307 8a8740010000 mov al,byte ptr [edi+140h]
8058430d 6a00 push 0
8058430f 8845f8 mov byte ptr [ebp-8],al
80584312 8d45f8 lea eax,[ebp-8]
80584315 50 push eax
80584316 ff75f8 push dword ptr [ebp-8]
80584319 ff3558345680 push dword ptr [nt!PsProcessType (80563458)]
8058431f 6a01 push 1
80584321 ff7508 push dword ptr [ebp+8]
80584324 e8bf28feff call nt!ObReferenceObjectByHandle (80566be8)
ㅋㅋ....이런 제길슨 저기서 0xC0000008을 리턴해 버리네..이런 뉭기미.;;
와이??!!
저 함수의 원형을 보면 아래와 같았다..
NTSTATUS ObReferenceObjectByHandle( __in HANDLE Handle, __in ACCESS_MASK DesiredAccess, __in_opt POBJECT_TYPE ObjectType, __in KPROCESSOR_MODE AccessMode, __out PVOID *Object, __out_opt POBJECT_HANDLE_INFORMATION HandleInformation );여기서 다른건 다 정상인듯 보였느데 KPROCESSOR_MODE 요놈의 모드가 1이 아닌가??
헐..1이면 UserMode가 아닌가?? 이런 니기미..;;?? 왜?
여긴 커널단이란 말이다!!!.ㅠㅠ
NtTerminateProces함수 내부를 보면
Definition at line 1110 of file kill.c.
Referenced by _main(), CreateProcessInternalW(), CsrApiRequestThread(), CsrUnhandledExceptionFilter(), ExitProcess(),NtProcessStartup(), RunUSetup(), SmpDestroyClientObject(), and TerminateProcess().
01112 { 01113 NTSTATUS Status; 01114 PEPROCESS Process, CurrentProcess = PsGetCurrentProcess(); 01115 PETHREAD Thread, CurrentThread = PsGetCurrentThread(); 01116 BOOLEAN KillByHandle; 01117 PAGED_CODE(); 01118 PSTRACE(PS_KILL_DEBUG, 01119 "ProcessHandle: %p ExitStatus: %p\n", ProcessHandle, ExitStatus); 01120 01121 /* Were we passed a process handle? */ 01122 if (ProcessHandle) 01123 { 01124 /* Yes we were, use it */ 01125 KillByHandle = TRUE; 01126 } 01127 else 01128 { 01129 /* We weren't... we assume this is suicide */ 01130 KillByHandle = FALSE; 01131 ProcessHandle = NtCurrentProcess(); 01132 } 01133 01134 /* Get the Process Object */ 01135 Status = ObReferenceObjectByHandle(ProcessHandle, 01136 PROCESS_TERMINATE, 01137 PsProcessType, 01138 KeGetPreviousMode(), 01139 (PVOID*)&Process, 01140 NULL); 01141 if (!NT_SUCCESS(Status)) return(Status);
................
...............
..............
...........
.....
..
.
저기서 녹색으로 색칠된 부분이 보이는가???
저기서 현재 PreviousMode를 usermode로 가져와 버리더라..;;헐
ZwTerminateprocess부터 타본결과 저부분을 1로 바꾼뒤 NtTerminateprocess함수를 호출하는걸
볼 수있었다...
물론 저 부분만 찾아서 봤기때문에 다른 어떤부분이 변경되는지를 잘 모르겠다..
암튼 그래서 그냥 내가 직접 NtTerminateprocess호출 하기 전에 KTHREAD에서 Previous값을
0(커널모드)로 강제로 변경해놓고 NtTerminateprocess를 호출해버렸다...
물론 결과는 잘된다.;;;
ㅡ.,ㅡ 근데..과연 문제가 없을까??흠...
KTHREAD는 xp환경에서
mov esi, fs:[0x124]
mov byte PTR[esi + 140h], 0; //esi + 140h 위치가 Previous 값이 있는곳이다..난 이곳을
0으로 바꾸었징..ㅋㅋ
암튼 이렇게 함으로써 문제가 되었던 NtTerminateProcess는 해결되었다..
물론 환경은 XP기준에서 이다....
Win7에서도 별반 다를건 없을거 같은데...만약 해봐서 뭔가 틀리면 내용을 좀더 추가 하기로
하겠다..
'Study > Driver' 카테고리의 다른 글
Win7 64bit Eprocess 구조체 (1) | 2011.11.25 |
---|---|
윈도우7(Win7) 64bit 코드사인 없이 드라이버 로드하기!! (2) | 2011.11.21 |
Win7 64비트에서 드라이버(sys파일) 빌드하기!! vs2008에서.. (0) | 2011.11.21 |
Driver Unload할때~ (0) | 2011.09.28 |
버츄얼 PC 공유 폴더 설정 (0) | 2011.09.28 |
댓글