社区编辑申请
注册/登录
如何对一个可执行程序进行拦截和包装?
系统 Linux
Ubuntu 18.04操作系统中,重启指令/sbin/reboot是一个软链接,链接到可执行程序/bin/systemctl,那么是否可以在执行systemctl之前,做一些其它的事情(例如:保持一些应用程序的状态数据)?

文中一共讨论了3种方法,来实现对【函数】进行拦截:

  • 在编译阶段插桩;
  • 在链接阶段插桩;
  • 在执行阶段插桩;

昨天一个网友提了另外一个问题:如何对一个可执行程序进行拦截?

他提出了一个实际的示例:

Ubuntu 18.04操作系统中,重启指令/sbin/reboot是一个软链接,链接到可执行程序/bin/systemctl,那么是否可以在执行systemctl之前,做一些其它的事情(例如:保持一些应用程序的状态数据)?

  • Ubuntn18.04 中使用 systemd 来管理系统的所有 Service;
  • 除了 reboot 指令,还有其它几个指令也是软链接到 /bin/systemctl;

图片

这里就引出一个问题了:

既然上面这6个命令都链接到systemctl,那么当systemctl被执行的时候,它是如何知道它是被哪一个命令调用的呢?

看一下源码就知道了:通过参数 argv[0] 来获得的。

我们知道,main函数通过argc和argv[]来获取所有的参数,如下:

// 测试文件:test1.c

#include <stdio.h>

int main(int argc, char *argv[])
{
printf("argc = %d \n", argc);
for (int i = 0; i < argc; i++)
printf("argv[%d] = %s \n", i, argv[i]);
return 0;
}

编译、执行一下:

$ gcc test1.c -o test1
$ ./test1 aaa bbb
argc = 3
argv[0] = ./test1
argv[1] = aaa
argv[2] = bbb

可以看到:argv[0] = ./test1,因为我们是在命令行直接调用test可执行程序的,这很容易理解。

那么:如果test是被一个软链接调用的呢?

测试一下,创建软链接:

$ ln -s test1 link1

图片

执行一下:

图片

此时,argv[0] = ./link1。

也就是说:第一个参数存放的是软链接文件路径,systemctl 的道理也是如此!

知道了这个原理,那我们就可以在reboot与systemc之间横叉一刀,增加一个中间可执行文件:

图片

为了便于描述,我们把这个中间文件创建为脚本pre_systemctl.sh,然后把root软链接到这个脚本。

注意:在理解原理之前,建议不要直接用 reboot 等系统命令进行操作,可以自己写一些测试程序,例如上面的 test。

操作如下:

$ cd /sbin
$ sudo rm root
$ sudo touch pre_systemctl.sh
$ sudo chmod +x pre_systemctl.sh
$ sudo ln -s pre_systemctl.sh reboot

图片

创建了pre_systemctl.sh脚本之后,并且把reboot软链接到它,在脚本中输入如下内容:

图片

此时,在命令行中执行reboot命令,就会执行这个脚本,并且这个脚本也能够正确的把/sbin/root作为第0个参数传递给/bin/systemctl,如下图所示:

图片

在这个脚本中,可以在执行systemctl之前,做任何需要关机前需要处理的一些事情。

问题似乎是解决了,但是好像还有一个问题:

如果用户在执行命令时输入了一些其它的参数,这个脚本程序也应该透明的把这些参数传递给 systemctl 才可以!

为了便于观察,我们在脚本中多打印个参数,并通过exec来启动systemctl,并且强制把参数$0设置为systemctl的第0个参数:

图片

这个脚本文件中的重点是最后一条命令:

exec -a $0 /bin/systemctl $*

此时,在命令行中执行reboot指令,输出如下:

图片

如此调用systemctl,就解决了刚才提出的问题,而且通过 $*,可以把任意多个参数透明的传递下去。

这里的关键还是 exec 的参数 -a ,看一下它的指令说明:

exec [-cl] [-a name] [command [arguments ...]] [redirection ...]

这里还有一个更详细的说明:

图片

责任编辑:武晓燕 来源: IOT物联网小镇
相关推荐

2022-06-07 10:09:42

新技术人工智能5G

2022-06-15 11:02:40

网络安全运营

2022-06-16 17:02:49

微软智能云混合云Azure

2022-06-23 09:49:16

火绒安全英特尔

2022-05-23 09:31:03

MozillaFirefox浏览器

2022-06-15 11:51:14

Vue3开发避坑

2022-06-09 09:20:40

Linux语言编写代码

2022-06-23 14:03:26

混合ITCIOIT管理工具

2022-06-15 09:54:51

PythonIDELinux

2022-05-20 08:55:02

py文件exepython

2022-06-13 08:18:02

操作系统CPU保护模式

2022-06-23 09:22:57

Vue技巧前端

2022-06-16 10:38:24

2022-06-16 16:08:00

Python初学者IDE

2022-06-07 10:13:22

前端沙箱对象

2022-05-23 13:17:32

Linux开源NVIDIA

2022-06-20 14:57:50

漏洞安全威胁

2022-05-23 09:25:39

Pythonexe脚本

2022-05-27 15:06:22

攻击面管理(ASM)网络安全运营

2022-06-20 13:34:46

漏洞网络攻击

同话题下的热门内容

用这些开源工具在 Linux 上编辑 PDF 文件Docker Compose:搭建开发环境的好方式在 Linux 上玩电子游戏的三种方式为什么命令行在 Linux 生态系统中如此重要在 Linux 上使用 WineZGUI 运行 Windows 应用和游戏Linux 网络性能的 15 个优化建议如何构建自己的可引导 Linux Live CD用 Curtail GUI 应用轻松压缩 Linux 中的图像

编辑推荐

Linux系统下安装MySQL的步骤详解CentOS与Ubuntu有什么不同?Linux下如何使用minicom USB串口为什么你可能想要略过Ubuntu 17.04?Linux中7个判断文件系统类型的方法
我收藏的内容
点赞
收藏

51CTO技术栈公众号