注册通行证 用户名 密码
  • 文章投稿
  • 博客
  • 论坛
  • 设为首页
  • 加入收藏
jztop.com网络技术
  • 首页
  • | iT新闻
  • | 操作系统
  • | 组网建网
  • | 网络安全
  • | 程序开发
  • | 办公一族
  • | 工具软件
  • | 网页制作
  • | 多媒体制作
  • | 网吧技术
  • | 服务器
  • | 专题教程
Vista | 软件评测 | 系统备份 | 优化 | 进程 | 聊天 | 病毒 | Linux | 黑客 | 防火墙 | 数据库 | Web开发 | Java | Word | 游戏 | 32位开发 | 移动开发
当前位置:首页 > 程序开发 > 数据库 > Delphi 内容正文:Delphi深度探索之外壳执行操作记录器

Delphi深度探索之外壳执行操作记录器

发布时间:2006-02-07 21:56:18 来源:希赛网 网友评论 0 条
  记录外壳活动有很多好处,比如当需要监控用户的行为,回溯系统崩溃前的过程。实现这一功能的关键工具相当简单,它就是COM接口IShellExecuteHook。编写一个实现了这一接口的COM对象后,再在系统中注册,就可以容易地控制并影响Windows外壳的运行。Windows 98和Windows 2000都支持IShellExecuteHook外壳扩展,而在Windows 95和Windows NT 4.0上则必须安装活动桌面扩展后才支持(也就是说必须安装IE 4.01)。

  一个实现了IShellExecuteHook接口的COM对象可以截获所有对ShellExecute和ShellExecuteEx函数的调用。ShellExecute和ShellExecuteEx函数主要用于执行应用程序,它们可以接收一个文件名并能自动获得同文件名相关的可执行文件名。此外,它们还支持系统安全认证。如果在NT上设定了用户的可执行权限,ShellExecute和ShellExecuteEx函数将会在创建新的进程前检查权限(CreateProcess和WinExec函数则没有这项功能)。函数调用的流程如下:

  (1)获得将要运行的可执行文件名。

  (2)根据程序名检查用户执行权限。

  (3)激活全部已注册的IshellExecuteHook扩展。

  (4)当所有扩展和权限都同意执行,创建新的进程并返回。

  Windows外壳大量调用ShellExecute和ShellExecuteEx函数来执行几乎是所有的资源管理器的操作,比如双击目录、浏览文件夹内容、打印编辑文档、查看文件属性、选择文档的上下文相关菜单等等。此外,开始菜单的运行对话框和DOS方式下的Start.exe也使用ShellExecuteEx函数来执行程序。简单地说几乎用户的所有外壳操作都可以被扩展截获,包括其他应用程序对ShellExecute和ShellExecteEx的调用。



  编写外壳活动记录器

  首先需要创建一个进程内COM对象,选菜单命令New | ActiveX Library,然后点击菜单New|Com Object,创建COM对象框架,按图2.14填充对话框的内容,然后点击OK按钮。Delphi就会自动生成框架文件,并保存生成的文件。

  IShellExecuteHook的接口定义在shlobj.pas单元中,添加shlobj到单元uses部分,然后添加IShellExecuteHooko方法原型到COM对象声明部分,声明部分代码如下:

unit ShellExecuteHookObj;
interface
uses
Windows, ActiveX, ComObj, ShlObj, ShellAPI;
type
 TTShellExecuteHook = class (TComObject, IShellExecuteHook)
protected
 function Execute(var ShellExecuteInfo: TShellExecuteInfo): HResult; stdcall;
end;
const
 Class_TShellExecuteHook: TGUID = '{935FA400-243D-11D3-B06E-857B2AE2BE64}';

  下面就是用来截获并记录外壳操作的实现部分,一旦外壳扩展被注册后,每次ShellExecute 和ShellExecuteEx函数运行时都会调用COM对象的Execute函数。我们的核心代码就是通过Execute方法实现的。方法定义如下:

function TTShellExecuteHook.Execute(
var ShellExecuteInfo: TShellExecuteInfo): HResult;

  Execute方法会从外壳获得一个类型为TshellExecuteInfo的参数,参数定义如下:

_SHELLEXECUTEINFOA = record
cbSize: DWORD;
fMask: ULONG;
Wnd: HWND;
lpVerb: PAnsiChar;
lpFile: PAnsiChar;
lpParameters: PAnsiChar;
lpDirectory: PAnsiChar;
nShow: Integer;
hInstApp: HINST;
{ Optional fields }
lpIDList: Pointer;
lpClass: PAnsiChar;
hkeyClass: HKEY;
dwHotKey: DWORD;
hIcon: THandle;
hProcess: THandle;
end;

  这个记录结构中的lpFile包含了要运行的文件名,而lpVerb则表明执行的动作,动作由一些标准的字符串代表,比如,open(打开)、print(打印)、edit(编辑)、explore(浏览)、properties(属性)、find(查找)和其他上下文菜单的命令名。 有时,lpFile并不包含可执行文件名,这是因为ShellExecute接到的运行参数是一个文档名。比如当我们在资源管理器中双击文本文件时,Windows用文本文件名作为参数调用ShellExecute函数,而ShellExecute函数则获得同文本文件相关联的可执行文件名,然后执行。

  TShellExecuteInfo结构中还记录了要运行程序的很多信息,然而这里我们只能在Execute方法中修改nCmdShow参数,nCmdShow参数定义了窗口在运行后的显示状态,包括最大化、最小化、正常等选项,对于其他参数的修改都会被外壳忽略。除此之外,在Execute方法中可以根据情况允许外壳继续缺省的任务或通知外壳取消执行,这可以通过Execute函数的返回值来实现。

  如果Execute的返回值为S_FALSE,外壳就继续缺省的任务,如果返回S_OK,则外壳认为扩展已经成功,就不再继续执行了。另外如果返回一个错误代码或系统无法识别的值,则外壳会弹出错误信息。这给了我们一个控制程序运行的机会,比如可以限制任何对记事本的调用,代码如下:

function TTShellExecuteHook.Execute(var ShellExecuteInfo: TShellExecuteInfo): HResult;

var
 FileName: String;
begin
 Result := S_FALSE;
 with ShellExecuteInfo do
 begin
  FileName := UpperCase(ExtractFileName(lpFile));
  if Pos('NOTEPAD', FileName) = 1 then
  begin
   Result := S_OK;
   hInstApp := 32;
   MessageBox(Wnd, '不允许记事本运行!', '错误', MB_OK or MB_ICONERROR);
  end;
 end;
end;

  进一步,我们甚至可以利用这点实现一个自定义的安全认证机制,根据用户要求限制运行的程序。有兴趣的朋友可以试验一下,一定很有意思。

  有一点要注意的是,在Execute方法下不能调用ShellExecute和ShellExecuteEx函数外部程序,如果是这样的话,我们的Execute方法又会被新的ShellExecute调用,这样系统就会进入死循环。如果我们确实想在Execute方法中调用外部程序的话,可以使用CreateProcess或WinExec函数来替代。这两个函数不会被ShellExecuteHook截获。

  对于外壳动作记录器来说,只要在Execute方法中记录程序信息到日志文件中就可以了,代码非常简单,因为所有需要的信息都在TShellExecuteInfo记录中包含了,这里只记录运行的动作、文件名和时间,需要记录其他信息的话,大家可自行修改,代码示意如下:

function TTShellExecuteHook.Execute(
var ShellExecuteInfo: TShellExecuteInfo): HResult;

var
 FileStream: TFileStream;
 a:TStringList;
 S:string;
begin
 Result := S_FALSE;
 with ShellExecuteInfo do
 begin
  FileStream:=TFileStream.Create('c:/shellexecutehook.txt',fmopenwrite);
  S:=string(lpVerb)+':'+string(lpFile)+DateTimeToStr(Now)+#13#10;
  FileStream.Seek(FileStream.Size,soFromBeginning);
  FileStream.Write(PChar(S)^,Length(S));
  FileStream.Free;
 end;
end;
注册ShellExecuteHook

  要想使COM对象被外壳加载,需要在注册表中注册一些信息。在下面这个子键中添加COM类的GUID及描述字符串后就可以了(描述字符串可以不赋值,但不妨给一个以便于识别)。

HKEY_LOCAL_MACHINE
SOFTWARE
Microsoft
Windows
CurrentVersion
Explorer
ShellExecuteHooks
{CLSID}= '描述字符串'

  修改注册表可以通过重载COM的类工厂的UpdateRegistry方法来实现。代码示意如下:

implementation
uses ComServ, SysUtils;
resourcestring
sCreateRegKeyError = '创建注册表项失败';
type
 TShellExComObjectFactory = class(TComObjectFactory)
public
 procedure UpdateRegistry(Register: Boolean); override;
end;
{ TShellExComObjectFactory }
procedure TShellExComObjectFactory.UpdateRegistry(Register: Boolean);
const
 hellExecuteHooksKey='SOFTWAREMicrosoftWindowsCurrentVersionExplorerShellExecuteHooks';
var
 Handle: HKey;
 Status, Disposition: Integer;
 ClassID: String;
begin
 ClassID := GUIDToString(Class_TShellExecuteHook);
 if Register then
 begin
  Status := RegCreateKeyEx(HKEY_LOCAL_MACHINE, PChar(
   ShellExecuteHooksKey), 0, '',REG_OPTION_NON_VOLATILE,
   KEY_READ or KEY_WRITE, nil, Handle, @Disposition);
  if Status = 0 then
  begin
   Status := RegSetValueEx(Handle, PChar(ClassID), 0, REG_SZ,
    PChar(Description), Length(Description) + 1);
   RegCloseKey(Handle);
  end;
  end else
  begin
   Status := RegOpenKeyEx(HKEY_LOCAL_MACHINE, PChar(ShellExecuteHooksKey), 0,
    KEY_READ or KEY_WRITE, Handle);
   if Status = 0 then
   begin
    Status := RegDeleteValue(Handle, PChar(ClassID));
    RegCloseKey(Handle);
   end;
  end;
  if Status <> 0 then raise EOleError.Create(sCreateRegKeyError);
   inherited UpdateRegistry(Register);
  end;
  initialization
  TShellExComObjectFactory.Create(
   ComServer, TTShellExecuteHook, Class_TShellExecuteHook,'TShellExecuteHook',
'ShellExecute hook sample', ciMultiInstance, tmApartment);
 end.

  如果系统中有多个ShellExecuteHook的话,外壳会按照ShellExecuteHook的安装顺序进行调用,如果要想使某个外壳扩展优先运行,可先删除其他扩展然后添加优先扩展,原来的扩展依次放在后面,不过这样做也可能意义不大,因为别人也会这么干。最后,程序运行的结果。



  记住ShellExecuteHook并不是一个完善的用于监视系统运行的扩展。它只能监视ShellExecute和ShellExecuteEx的运行,它不能保证记录系统所有的行为。特别是很多情况下外壳并不使用ShellExecute来进行一些常用的操作,比如我们在资源管理器中选择一个文件,然后调用右键菜单的属性命令后,记录器没有记录这个动作,但如果直接调用ShellExecute(如下示)的话,ShellExecuteHook却会正确执行。

ShellExecute(nil, 'properties', 'foo.txt',nil,nil,SW_SHOW);

  这说明外壳并不使用ShellExecute函数显示属性对话框。总之一定要谨慎使用这项技术,确保它确实符合工作的需求
相关文章
  • Delphi 2005注册码
【评论】【收藏本文】【打印】【关闭】
上一篇文章:下面没有链接了
下一篇文章:没落的奇迹 谁会买下Delphi?
讨论区
查看
已有 0 位对此新闻感兴趣的网友发表了看法
匿名发表
注册通行证 登陆
图文阅读推荐
推荐阅讯
  • 数据库系统 防止黑客入侵之技术综述
  • Delphi快速入门(二)
  • 系统构架设计应考虑的因素
  • 杜绝安全隐患 容易忽视的Oracle安全问题
  • 用NoahWeb表现层制作动态网站 - 第二天
  • 用NoahWeb表现层制作动态网站 - 第五天
  • Oracle数据库中分区表的操作方法
  • 用NoahWeb表现层制作动态网站 - 第一天
  • Delphi快速入门(六)
  • Oracle数据库日常维护手册
阅读排行
  • 1.全面剖析Delphi 2006新增特性
  • 2.用Delphi开发视频聊天软件
  • 3.用Win32 API枚举应用程序窗口和进程
  • 4.软件的架构与设计模式之什么是架构
  • 5.软件的架构与设计模式之模式的种类
  • 6.Delphi中为TreeView添加单选和复选框
  • 7.用Delphi实现24位真彩色图标
  • 8.VS.NET2005 Beta2初体验之感受2005
  • 9.程序界面设计模式慨述
  • 10.没落的奇迹 谁会买下Delphi?
专题教程
  • 大话G游 专题:手机病毒揭密
  • ARP攻击防范与解决方案 路由故障处理手册
  • Picasa中文版_Picasa教程 专题:清除流氓软件
  • Firefox专题 seo搜索引擎优化专区
  • 重装Windows必知的事情 装机之必备软件大行动
病毒专杀栏
  • 杀毒软件反被病毒杀 连"救命"都不能喊
  • 金山ARP防火墙
  • 还原卡神话破灭“机器狗”病毒来势汹汹
  • cctv经济半小时:你的手机现在安全吗?
  • 新挂马方式开始流行 ARP挂马称雄局域网
  • 木马和病毒清除的通用解法
  • IP地址不再冲突 查找ARP攻击者元凶
  • 教你几招识别和防御Web网页木马
  • 分析:封杀BT只是暂时的止痛药
  • QQ爆危险漏洞,“QQ游戏邀请大盗”邀请你玩病
关于我们 | 诚聘英才 | 联系我们 | 版权声明 | 网站大事 | 网站地图 | 意见建议
CopyRight 2005-2007 Jztop.Com 版权所有 未经许可 请勿转载