메뉴 건너뛰기

프로세스 이름 감추기

 > 운영체제 개발 > 강좌


 Windows에서 프로세스 이름 숨기기 
 (Delete the process name from being displayed in Windows task manager.)

For the advanced technology   



뭐?  
Windows Task manager의 프로세스 탭에 나타나는 프로세스 이름을 숨기기 위한 가이드 강좌입니다.
이글과 관련한 내용이 인터넷을 뒤지면 수백개 이상이지만, 속시원히 드라이버 코드를 제시해 놓은 예는 별로 없더군요.
(아예 없지는 않습니다.) 그냥 이유가 있겠지 생각하고 저도 걍 따라 하는 대신^^- 자세히 써보려 합니다.


준비물  
 


 - 환경
	Microsoft Windows® XP에서 테스트 되었습니다. 

 - Tool	
	Microsoft Visual C++® 6.0
	Windows® XP DDK

 - Library
	GunShadow Library [(배포중단)]
ntifs.h [ntifs.h]
 

 


구성  

진행해 볼 전체 목록 구성은 대충 이렇습니다.

- Windows 프로세스 관리를 위한 구조체 파악
- GunShadow Library 드라이버 일부 코드 제시

 

 


내용  
 

자, 그럼 시작합니다!

아래 자료는 Windows가 프로세스를 관리하는 내부적인 구조체의 모습입니다.
위의 준비물 링크에서 얻을 수 있는 ntifs.h 파일에서 EPROCESS 구조체의 모습이기도 합니다.
커널 디버거에서 아래와 같이 커맨드를 입력하면 나타납니다.

kd> !processfields
 EPROCESS structure offsets:
    Pcb:                               0x0
    ExitStatus:                        0x6c
    LockEvent:                         0x70
    LockCount:                         0x80
    CreateTime:                        0x88
    ExitTime:                          0x90
    LockOwner:                         0x98
    UniqueProcessId:                   0x9c
    ActiveProcessLinks:                0xa0
    QuotaPeakPoolUsage[0]:             0xa8
    QuotaPoolUsage[0]:                 0xb0
    PagefileUsage:                     0xb8
    CommitCharge:                      0xbc
    PeakPagefileUsage:                 0xc0
    PeakVirtualSize:                   0xc4
    VirtualSize:                       0xc8
    Vm:                                0xd0
    DebugPort:                         0x120
    ExceptionPort:                     0x124
    ObjectTable:                       0x128
    Token:                             0x12c
    WorkingSetLock:                    0x130
    WorkingSetPage:                    0x150
    ProcessOutswapEnabled:             0x154
    ProcessOutswapped:                 0x155
    AddressSpaceInitialized:           0x156
    AddressSpaceDeleted:               0x157
    AddressCreationLock:               0x158
    ForkInProgress:                    0x17c
    VmOperation:                       0x180
    VmOperationEvent:                  0x184
    PageDirectoryPte:                  0x1f0
    LastFaultCount:                    0x18c
    VadRoot:                           0x194
    VadHint:                           0x198
    CloneRoot:                         0x19c
    NumberOfPrivatePages:              0x1a0
    NumberOfLockedPages:               0x1a4
    ForkWasSuccessful:                 0x182
    ExitProcessCalled:                 0x1aa
    CreateProcessReported:             0x1ab
    SectionHandle:                     0x1ac
    Peb:                               0x1b0
    SectionBaseAddress:                0x1b4
    QuotaBlock:                        0x1b8
    LastThreadExitStatus:              0x1bc
    WorkingSetWatch:                   0x1c0
    InheritedFromUniqueProcessId:      0x1c8
    GrantedAccess:                     0x1cc
    DefaultHardErrorProcessing         0x1d0
    LdtInformation:                    0x1d4
    VadFreeHint:                       0x1d8
    VdmObjects:                        0x1dc
    DeviceMap:                         0x1e0
    ImageFileName[0]:                  0x1fc
    VmTrimFaultValue:                  0x20c
    Win32Process:                      0x214
    Win32WindowStation:                0x1c4



UniqueProcessId 는 프로세스의 고유 ID입니다.

ImageFileName스트링은 Ctrl - Alt - Tab키를 누를 경우 나타나는 태스크 관리자의 프로세스 탭에서
리스트되어 볼 수 있는 프로세스 이미지 이름입니다.
자- 나머지 하나 ActiveProcessLinks 가 중요합니다. 잠시 아래의 그림을 보겠습니다.



프로세스 정보들은 위와 같이 순환큐처럼 Linked list되어 앞과 뒤의 프로세스 정보를 가르키고 있습니다.
그렇게 앞과 뒤의 프로세스 정보를 가르키고 있는 링크가 바로 ActiveProcessLinks인 것입니다.
이 리스트의 제일 첫 헤드를 가르키고 있는 PsActiveProcessHead를 통해 우리는 프로세스 정보 링크를 순환할 수 있습니다.
하지만, PsActiveProcessHead는 Windows에서 Export되지 않은 심볼입니다. 그래서 다른 방법으로 우회하여 접근해야 하는데,
PsInitialSystemProcess라는 노출되어 있는 심볼을 통해서 가능합니다.
물론 이것조차 노출되어 있지 않다 하더라도 각종 서적이나 웹에서 제시하고 있는 방법처럼,
현재 프로세스를 가르키는 PsGetCurrentProcess등의 API로부터 얻는 ActiveProcessLinks 포인터를 순환하여
PsActiveProcessHead를 찾을 수도 있습니다. 그렇게, 얻게되는 PsInitialSystemProcess를 통해 프로세스 정보 리스트를
순환하여 우리는 각각의 프로세스 구조체에서 ImageFileName 변수를 얻어올 수 있습니다.

#include <ntifs.h>
//:
__declspec(dllimport) void *PsInitialSystemProcess;
//:
//:
PLIST_ENTRY KPEBListPtr, KPEBListPtr;
PEPROCESS PFirstProcess = (PEPROCESS) PsInitialSystemProcess;
PEPROCESS kpeb = NULL;
ULONG uOffset_ActiveProcessLinks = 0x88; /* XP일 경우, 2000 -> 0xA0, NT 4.0 -> 0x98 */
char ProcessName[16];
//:
//:
KPEBListPtr = KPEBListPtr = (PLIST_ENTRY) &PFirstProcess->ActiveProcessLinks;
kpeb = (PEPROCESS)( ( (char *)KPEBListPtr ) - uOffset_ActiveProcessLinks );
memcpy( ProcessName, kpeb-ImageFileName, 16 );
//:
//:

프로세스를 순환하는 방법은 링크드 리스트 순환방법이랑 똑같습니다.


while (KPEBListPtr->Flink!=KPEBListHead) {
//:
//:
KPEBListPtr=KPEBListPtr->Flink;
}


자 그럼 프로세스를 숨겨 볼까요? 
각프로세스 이름도 얻어올 수 있겠다, 프로세스 정보들도 순환할 수 있다면-

프로세스 숨기는 일도 간단하겠죠? 바로 이 링크의 순서를 바꾸는 것입니다.


데브구루(www.devguru.co.kr) 곽태진씨가 작성한 "아무도 모르는 Process"의 방법처럼
소프트아이스등의 각종 툴을 이용하여서도 조작이 가능합니다. 드라이버 상에서는 아래의 코드처럼 되겠죠?

//:
//:
 PLIST_ENTRY tempKPEBListPtrBlink, tempKPEBListPtrFlink;

 if(strcmp(toFindProcessName, ProcessName) == 0){
                        __asm{ PUSHFD };
                        __asm{ CLI };
                        tempKPEBListPtrBlink = KPEBListPtr->Blink;
                        tempKPEBListPtrFlink = KPEBListPtr->Flink;
                        tempKPEBListPtrBlink->Flink = tempKPEBListPtrFlink;
                        tempKPEBListPtrFlink->Blink = tempKPEBListPtrBlink;
                        __asm{ POPFD };
 }
//:
//:






2005.08.26, 이건우

참고  


 Undocumented Windows 2000 Secrets - A Programmer's Cookbook (SVEN B. SCHREIBER)
 Windows구조와 원리 그리고 Codes (정덕영)
 아무도 모르는 Process (www.devguru.co.kr, 곽태진)



 GunShadow Library page
 GunShadow Application page 배포중단 사유

 마이크로 소프트웨어 기고 자료

- 윈도우 커널 해킹 1(마이크로소프트웨어 2005년 11월호) - 윈도우 커널 해킹 2(마이크로소프트웨어 2005년 12월호)


위로