본문 바로가기
Study/Driver

NtTerminateProcess 사용!!

by 뿡뿡대마왕 2011. 9. 28.
반응형

프로젝트를 진행하면서 약간의 보안기능을 추가해야 할 일이 생겼다...
프로세스 숨기기와 프로세스의 핸들 보호, 그리고 불법프로그램의 강제 종료..

프로세스 숨기기와 핸들 보호는 예전에 작업을 해둔게 있어 그리 어렵지 않게 일을 마무리 한 반면
불법 프로그램 종료에서 문제가 생겼다...;;

불법 프로그램들 중에는 커널에서 자신의 프로세를 보호하는 프로그램들이 은근히 있다..
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함수 내부를 보면
NTSYSCALLAPI NTSTATUS NTAPI NtTerminateProcess ( IN HANDLE  ProcessHandle,
IN NTSTATUS  ExitStatus  
)

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에서도 별반 다를건 없을거 같은데...만약 해봐서 뭔가 틀리면 내용을 좀더 추가 하기로
하겠다..
 


반응형

댓글