방학프로젝트 Shadower _3 C#Process 실행 감시
나의 Shodower 프로젝트의 핵심이라고 할수 있는 부분이다.
바로 프로그램이 시작되면 처음에 디비에서 가져온 denied Process 목록과 비교해서
일치하면 프로세스를 종료해버리는 원리이기 때문이다.
우선 denied Process 는 디비를 연동해서 가져오는데에 성공했다.
(경진이형이 말한 xml 형태로 파싱하는건 좀더 연구를 해봐야 할듯하다)
그리고 Process 가 시작될때를 어떻게 아느냐!?
1. 첫번째 방법
주기적으로 현재 Process 목록을 가져와서 일일히 denied Process 와 비교하는 것이다.
우선은
MSDN 의 Process 클래스를 참조해보자.
http://msdn.microsoft.com/ko-kr/library/system.diagnostics.process%28VS.80%29.aspx
Process 의 메소드중에 GetProcesses 메서드를 이용하면 현재 프로세스 목록을 가져올수있다.
http://msdn.microsoft.com/ko-kr/library/system.diagnostics.process.getprocesses%28VS.80%29.aspx
허나, 이건 우선 주기적이기 때문에 실기간이 아니고, 나중에 denied Process 의 목록이 많아지고 사용자 컴퓨터의 프로세스 목록도 많아지면 컴퓨터에 과부하가 염려되었다.
우선은 기각
2. 두번째 방법
두번째는 말그대로 프로그램이 시작할때! 를 캐취하는 것이다. 분명 프로그램이 시작할 때 발생하는 이벤트가 있을 거라 믿고 무작정 MSDN을 뒤지시 시작했다.
하지만 Process 클래스에는 Exited 라는 프로세스가 종료될때 발생하는 이벤트 만 있고 시작할대 발생하는 이벤트는 없었다.
하지만 Exited을 사용하면 사용자가 Shadower를 강제종료 시켯을때 이벤트를 받아 다시 실행시킬수 있겠다는 생각이 들었다.
그리곤 다시 구글링
좌절해갈때쯤.. 멋진 글을 찾을 수 있었다.
정말 엄청나다 심지어 뚝딱 만들었덴다.. 역시 세상에는 엄청난 사람들이 많쿠나.
해서 소스는 없고, 힌트가 있었다. 바로
ManagementEventWatcher 였다.
http://msdn.microsoft.com/ko-kr/library/system.management.managementeventwatcher.aspx
MSDN 의 설명을 빌리면
네임스페이스:
System.Management
어셈블리: System.Management(System.Management.dll)
이건 뭔소리인가...
여튼 다시 ManagementEventWatcher 으로 구글링을 하였고 적당한 예제소스를 찾을 수 있었다.
해서 소스는 없고, 힌트가 있었다. 바로
ManagementEventWatcher 였다.
http://msdn.microsoft.com/ko-kr/library/system.management.managementeventwatcher.aspx
MSDN 의 설명을 빌리면
.NET Framework 클래스 라이브러리
ManagementEventWatcher 클래스
업데이트: 2007년 11월
지정된 이벤트 쿼리에 따라 임시 이벤트 알림을 신청합니다.
어셈블리: System.Management(System.Management.dll)
이건 뭔소리인가...
여튼 다시 ManagementEventWatcher 으로 구글링을 하였고 적당한 예제소스를 찾을 수 있었다.
try
{
string scope = @"\\.\root\CIMV2";
ManagementScope MgtScope = new ManagementScope(scope);
// create the wql query to subscribe to a process deletion event
WqlEventQuery query =
new WqlEventQuery("__InstanceDeletionEvent",
new TimeSpan(0, 0, 10),
"TargetInstance isa \"Win32_Process\"");
// Initialize an event watcher and subscribe to events
// that match this query
//for deletion event
ManagementEventWatcher watcherDel =
new ManagementEventWatcher() ;
watcherDel.Query = query;
watcherDel.Scope = MgtScope;
watcherDel.EventArrived += new EventArrivedEventHandler(DeletionArrived);
watcherDel.Start();
Console.ReadLine();
watcherDel.Stop();
watcherDel.Dispose();
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
Console.ReadLine();
}
private void DeletionArrived(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject eventArg = (ManagementBaseObject)(e.NewEvent["TargetInstance"]);
string ProcessName = eventArg["Name"].ToString();
Console.WriteLine(ProcessName);
//check for my processes and send mail
}
{
string scope = @"\\.\root\CIMV2";
ManagementScope MgtScope = new ManagementScope(scope);
// create the wql query to subscribe to a process deletion event
WqlEventQuery query =
new WqlEventQuery("__InstanceDeletionEvent",
new TimeSpan(0, 0, 10),
"TargetInstance isa \"Win32_Process\"");
// Initialize an event watcher and subscribe to events
// that match this query
//for deletion event
ManagementEventWatcher watcherDel =
new ManagementEventWatcher() ;
watcherDel.Query = query;
watcherDel.Scope = MgtScope;
watcherDel.EventArrived += new EventArrivedEventHandler(DeletionArrived);
watcherDel.Start();
Console.ReadLine();
watcherDel.Stop();
watcherDel.Dispose();
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
Console.ReadLine();
}
private void DeletionArrived(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject eventArg = (ManagementBaseObject)(e.NewEvent["TargetInstance"]);
string ProcessName = eventArg["Name"].ToString();
Console.WriteLine(ProcessName);
//check for my processes and send mail
}
( 위 예제는 프로세스 삭제 이벤트이다)
http://social.technet.microsoft.com/Forums/ko-KR/netfxbcl/thread/49f9c4c3-925e-4bb6-a304-7d0e93d8be58
대충 보면 중간의 Query문 바로 WMI 를 사용하는 것이었다.
프로그램이 실행될때 발생하는 이벤트를 WMI로 캐취 가능하다는 것이다.
WMI는 작년 여름방학때와 이전 학기 프로젝트에서 좀 써봐서 다시보니 정말 방가웠다. 이런데서 만날 줄이야!
여튼 WMI 를 이용해 발생하는 이벤트 __InstanceCreationEvent 에서 가져오는 것이다.
ManagementEventWatcher 는 말그대로 관리이벤트가 일어나는 감시하는 클래스였던 것이다.
ManagementEventWatcher 개체를 생성해 __InstanceCreationEvent 에 Select 쿼리를 보내 이벤트가 발생하는지 보고
ManagementEventWatcher 의 Event 인 EventArrived 로 이벤트를 핸들링 해줬다.
그것이 DeletionArrived 함수이다.
여기서 __InstanceCreationEvent 는 아마도(!) 인스턴스 생성 이벤트만을 가지고 있으리라
프로세스가 실행되면 __InstanceCreationEvent 에 추가되고 ManagementEventWatcher 는 기다리고 있다가 __InstanceCreationEvent 에 추가된 이벤트를 EventArrived 를 통해 받아서 DeletionArrived 함수를 호출하는 것이다!
이것으로 Shadower 의 핵심이 해결되었다.
나는 계속해서 프로그램을 작성했다.
우선 DeletionArrived 함수에서
실행된 프로그램의 이름을 리스트박에 넣고
deniedProcess 와 비교해서 일치하면
프로세스를 죽이는 것이다.
프로세스는
Process.GetProcessesByName() 함수로 Process 객체를 만들어 연결하여
Process.Kill() 함수를 호출하면되었다.
여기서 중요한것은 바로 ProcessName 이다.
Shadower 에서 deniedProcess 나 이벤트에서 가져온 실행된 프로세스 이름이다 모두
*.exe 로 되었다.
하지만
GetProcessByName()함수에서 인자인 ProcessName 은 .exe 가 없는 순수한 이름이 있어야한다. 이것을 알아낼려고 좀 고생을 하였다.
그래서
ProcessName을 "," 을 기준으로 한번 짤라줘야할 필요가 있었다.
이렇게 하니 프로세스도 잘 종료되었다.
처음에 디비에 연결하여 deniedProcess 가져오고
그리고 프로그램을 실행시켜 실행이벤트가 잘기록이 되는 지 확인해봤다
(디비에 Connect 를 안하면 프로그램 실행이벤트 발생시 DeniedProcess 와 비교를 할때 DeniedProcess 가 없기 때문에 "개체 참조가 개체의 인스턴스로 설정되지 않았습니다." 라는 에러가 뜬다. 테스트를 위해 일부러 했다.)
우선 디비에 연결안하니 에러가 발생한다. 그리고 ProcessStarting Log 에 cmd.exe가 실행 되었다고 잘 나온다.
다음으로
디비에 연결해 다시 cmd.exe 를 실행시켜 보자 cmd.exe는 테스트를 위해 deniedProcess 넣어두었다.


경고창 뜨면서 바로 cmd.exe 가 종료되었다!
기쁘군하!!
드디어 성공하였다.. 어느정도!!
하지만 아직 끝난게 아니다.
문제점이 발견되었으니, Shadower 는 프로세스 이름만 가지고 비교를 하기때문에 실행파일명을 바꿔버리면 아무런 감지를 못하게 되는것이다!
그러나 내가 알기론 온라인게임은 실행파일이름을 바꾸면 실행되지 않는걸로 알고 있으니(?) 우선 온라인게임이라도 어디냐 라는 심정이다. 하아.
이제 프로세스를 숨기는 일이 남아있다!
프로그램이 실행될때 발생하는 이벤트를 WMI로 캐취 가능하다는 것이다.
WMI는 작년 여름방학때와 이전 학기 프로젝트에서 좀 써봐서 다시보니 정말 방가웠다. 이런데서 만날 줄이야!
여튼 WMI 를 이용해 발생하는 이벤트 __InstanceCreationEvent 에서 가져오는 것이다.
ManagementEventWatcher 는 말그대로 관리이벤트가 일어나는 감시하는 클래스였던 것이다.
ManagementEventWatcher 개체를 생성해 __InstanceCreationEvent 에 Select 쿼리를 보내 이벤트가 발생하는지 보고
ManagementEventWatcher 의 Event 인 EventArrived 로 이벤트를 핸들링 해줬다.
그것이 DeletionArrived 함수이다.
여기서 __InstanceCreationEvent 는 아마도(!) 인스턴스 생성 이벤트만을 가지고 있으리라
프로세스가 실행되면 __InstanceCreationEvent 에 추가되고 ManagementEventWatcher 는 기다리고 있다가 __InstanceCreationEvent 에 추가된 이벤트를 EventArrived 를 통해 받아서 DeletionArrived 함수를 호출하는 것이다!
이것으로 Shadower 의 핵심이 해결되었다.
나는 계속해서 프로그램을 작성했다.
우선 DeletionArrived 함수에서
실행된 프로그램의 이름을 리스트박에 넣고
deniedProcess 와 비교해서 일치하면
프로세스를 죽이는 것이다.
프로세스는
Process.GetProcessesByName() 함수로 Process 객체를 만들어 연결하여
Process.Kill() 함수를 호출하면되었다.
Process[] processes = Process.GetProcessesByName(ProcessName);
foreach (Process process in processes)
{
process.Kill();
}
foreach (Process process in processes)
{
process.Kill();
}
여기서 중요한것은 바로 ProcessName 이다.
Shadower 에서 deniedProcess 나 이벤트에서 가져온 실행된 프로세스 이름이다 모두
*.exe 로 되었다.
하지만
GetProcessByName()함수에서 인자인 ProcessName 은 .exe 가 없는 순수한 이름이 있어야한다. 이것을 알아낼려고 좀 고생을 하였다.
그래서
ProcessName을 "," 을 기준으로 한번 짤라줘야할 필요가 있었다.
String[] temp = ProcessName.Split(new char[] { '.' });
MessageBox.Show(temp[0]);
Process[] processes = Process.GetProcessesByName(temp[0]);
foreach (Process process in processes)
{
process.Kill();
}
MessageBox.Show(temp[0]);
Process[] processes = Process.GetProcessesByName(temp[0]);
foreach (Process process in processes)
{
process.Kill();
}
이렇게 하니 프로세스도 잘 종료되었다.
처음에 디비에 연결하여 deniedProcess 가져오고
그리고 프로그램을 실행시켜 실행이벤트가 잘기록이 되는 지 확인해봤다
우선 디비에 연결안하니 에러가 발생한다. 그리고 ProcessStarting Log 에 cmd.exe가 실행 되었다고 잘 나온다.
다음으로
디비에 연결해 다시 cmd.exe 를 실행시켜 보자 cmd.exe는 테스트를 위해 deniedProcess 넣어두었다.

경고창 뜨면서 바로 cmd.exe 가 종료되었다!
기쁘군하!!
드디어 성공하였다.. 어느정도!!
하지만 아직 끝난게 아니다.
문제점이 발견되었으니, Shadower 는 프로세스 이름만 가지고 비교를 하기때문에 실행파일명을 바꿔버리면 아무런 감지를 못하게 되는것이다!
그러나 내가 알기론 온라인게임은 실행파일이름을 바꾸면 실행되지 않는걸로 알고 있으니(?) 우선 온라인게임이라도 어디냐 라는 심정이다. 하아.
이제 프로세스를 숨기는 일이 남아있다!
'공부 > 0x01 C / C++' 카테고리의 다른 글
| 방학프로젝트 Shadower _4 Process 감추기(2) (0) | 2009/08/20 |
|---|---|
| 방학프로젝트 Shadower _4 Process 감추기 (0) | 2009/08/07 |
| 방학프로젝트 Shadower _3 C#Process 실행 감시 (0) | 2009/08/06 |
| 방학프로젝트 Shadower _2 C#원격 DB 연동2 (0) | 2009/08/06 |
| 방학프로젝트 Shadower _1 C#원격 DB 연동 (3) | 2009/08/05 |
| 방학프로젝트 Shadower (0) | 2009/07/21 |