2004年01月31日

プロセスの実行の防止

多くの学校では、生徒がフロッピーディスクにまずいプログラムを入れてきて実行することがあると思う。フロッピーディスクだから、NTFSのアクセス権でなんとかできる問題ではない。
Microsoft の TechNet にプロセスの実行の防止という記事があった。WSHからWMIを使って、プロセスが起動するたびにその名前をチェックして条件に合えばプロセスを kill する。

それを perl に移してみたのが以下のもの(Windows XP 用) 。
A:ドライブと E:ドライブの実行ファイルが起動されるとそのプロセスが kill される。フロッピーディスクだけでなく、CD-ROMドライブや、ユーザのホームディレクトリからの実行を防止するように改造するのは簡単だろう。
use Win32::OLE;
$strComputer=".";
$wmi = Win32::OLE->GetObject(
  "WinMgmts:{impersonationLevel=impersonate}!//".
  "$strComputer\\root\\cimv2"
) or die;
$colMonitoredProc = $wmi->ExecNotificationQuery(
  "select * from __instancecreationevent within 1".
  " where TargetInstance isa 'Win32_Process'"
);
while(1){
  $objLatestProcess = $colMonitoredProc->{NextEvent};
  $proc_name=$objLatestProcess->TargetInstance->Name();
  if($proc_name=~/a:/ or $proc_name=~/e:/){
    $objLatestProcess->TargetInstance->Terminate();
  }
}

上記のスクリプトだとコマンドプロンプトが開いてしまうので、別のプロセスからウィンドウを開かないようにして起動するのが使いやすいかも。
use Win32;
use Win32::OLE;
use Win32::Process;

if($ARGV[0] eq "-eXecute"){
  shift;
  procchk(@ARGV);
}else{
  my $path=Win32::ExpandEnvironmentStrings("%PATH%");
  ($perl_path)=grep(/perl/i, split(/;/,$path));
  $perl_path=~s/\\$//;
  $perl_path.="\\perl.exe";
  $perl_path="" if(! -e $perl_path);
  $script_path=Win32::GetFullPathName($0);
  
  ($strComputer, @inhibit)=@ARGV;
  $strComputer ||= ".";
  @inhibit = qw/a:\ z:\ e:\ install/ if(! @inhibit);
  Win32::Process::Create($ProcessObj, $perl_path,
    $perl_path.' "'.$script_path.
    "\" -eXecute $strComputer @inhibit",
    0, NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW, "."
  )|| die ErrorReport();
}

sub ErrorReport{
  die;
}

sub procchk{
  my ($strComputer, @inhibit)=@_;
  return if $inhibit[0] eq "";
  grep(s/\\/\\\\/g,@inhibit);
  $check_str=join(" or ",map("\$_[0]=~/$_/i",@inhibit));
  eval("\$check_name = sub {$check_str}");

  $wmi = Win32::OLE->GetObject(
    "WinMgmts:{impersonationLevel=impersonate}!//"."
    $strComputer\\root\\cimv2"
  );
  $colMonitoredProc = $wmi->ExecNotificationQuery(
    "select * from __instancecreationevent within 1 ".
    "where TargetInstance isa 'Win32_Process'"
  );
  while(1){
    $objLatestProcess = $colMonitoredProc->{NextEvent};
    $proc_name=
      $objLatestProcess->TargetInstance->Name();
    if($check_name->($proc_name)){
      $objLatestProcess->TargetInstance->Terminate();
    }
  }
}
Posted by augustus at 2004年01月31日 21:29 | TrackBack
Comments
Post a comment









Remember personal info?