* nix信号如何让您读取其他进程的内存

有一个非常古老且根深蒂固的* nix东西叫做“信号”。这些原语背后的想法非常简单:实现中断的软件模拟。不同的进程可以在知道接收方的进程ID(pid)的情况下相互发送信号,并向自己发送信号。接收过程可以自由地分配一个信号处理函数,该函数将在接收时自动调用,或者使用特殊的掩码将其忽略,或者信任默认行为。到现在为止还挺好。



接收信号时的默认行为...这些令人放心的词是什么意思?当然不是您所期望的。 Wiki表示默认的28个信号处理程序(还有其他信号处理程序)如下:2个被忽略,4个导致进程停止,1个继续,11个终止,10个内存转储终止。现在很有趣!因此,情况如下:即使您的程序没有在源代码中以任何方式提及信号,实际上它也以非常戏剧化的方式使用了它们。



从现在开始,我们将不得不更深入地研究。谁可以向谁发送信号? Wiki说:“具有有效UID而不是0(超级用户UID)的进程(或Shell用户)只能向具有相同UID的进程发送信号。”因此,如果您运行100个程序,那么即使所有程序(杀手除外)都没有在源代码中以任何方式提及信号,它们中的任何一个都可以使用系统API轻松杀死这100个程序。如果您是在root帐户下工作的,那么开始执行特定进程的操作根本没有关系,您仍然可以轻松地结束它们。当然,可以找出特定进程的pid并执行其“合同谋杀”,但是杀死所有可能只是蛮力pid-s的人甚至更容易。



“等等,等等,不要开车。您提到可以处理和忽略信号!” -我听见了读者的声音。维琪会怎么说?“对于交替处理除SIGKILL和SIGSTOP以外的所有信号,进程可以分配其自己的处理程序,也可以通过修改其信号掩码来忽略它们的出现。”我们在接收这些信号时会查看默认操作,请参阅:“进程终止”,“进程终止”。事实证明,原则上只要有可能向受害者发送SIGKILL和SIGSTOP信号,我们就可以执行这两个动作。“唯一的例外是具有pid 1(init)的进程,该进程有权忽略或处理任何信号,包括KILL和STOP。”我们甚至可能无法以root用户身份杀死最重要的系统进程之一,但是以友好的方式,这需要进一步的研究。



好吧,情况变得更加乐观,但仍然令人沮丧。如果启动一个进程,那么可以保证它可以终止和停止其他进程。当满足一个非常简单的条件时,“接收过程的开发人员忘记了忽略或以某种方式处理了许多其他信号之一”,这个疯狂的应用程序将能够使该过程以内存转储终止或在停止后继续该过程。如果接收应用程序的开发人员已将其处理程序挂在某些信号上,则可以尝试通过向其发送信号来干扰该应用程序的功能。后者是单独讨论的主题,因为由于处理程序的异步执行,所以可能出现种族和未定义的行为...



一位苛刻的读者会告诉我:“抽象推理非常酷,但是让我们更接近细节。”好的,没问题!任何* nix用户都熟悉bash之类的程序。这个程序已经发展了将近30年,并且有很多可能性。让我们充满她的清晰度,从她的记忆中获得一些美味!



我从宽阔的腿上把Ubuntu 16.04.2带回家,并在其上运行了bash 4.3.46的两个副本。在其中之一中,我将使用一个秘密数据执行一个假设的命令:export password = SECRET。让我们暂时忘记带有命令历史记录的文件,其中还会写入密码。在同一窗口中,键入ps命令以查找此过程的pid-例如3580。



在不关闭第一个窗口的情况下,让我们转到第二个窗口。其中的ps命令将提供此bash实例的另一个pid,例如5378。为清楚起见,正是从第二次bash中,我们将向第一个命令kill -SIGFPE 3580发送信号。是的,亲爱的读者,这是完全荒谬的:过程2表示与以下内容无关在过程1中,在该过程1中发生了错误的算术运算。屏幕上显示以下窗口:







所需的异常是在创建内存转储时发生的,即bash似乎没有处理或忽略此信号。谷歌搜索我应该在哪里寻找转储,我找到了详细的答案()。在我的Ubuntu中,情况是这样的:如果标准软件包中的应用程序由于SIGABRT以外的信号而崩溃,则转储将转移到Apport程序。这只是我们的情况!该程序将汇编一个包含诊断信息的文件,并显示上面显示的窗口。官方网站自豪地指出:“ Apport收集潜在的敏感数据,例如核心转储,堆栈跟踪和日志文件。它们可以包含密码,信用卡号,序列号和其他私人材料。”好吧,好吧,我想知道我们在哪里有这个文件?是的,/ var / crash / _bin_bash.1000.crash。让我们将其内容拉入somedir文件夹:apport-unpack /var/crash/_bin_bash.1000.crash somedir。除了各种有趣的小东西之外,还有一个令人垂涎的内存转储,称为CoreDump。



在这里,关键时刻!让我们在该文件中搜索密码字符串,然后看看我们得到的响应是什么。字符串CoreDump命令| grep password会提醒健忘的黑客该密码是SECRET。精彩!



我使用我最喜欢的文本编辑器gedit进行了相同的操作,开始输入缓冲区,然后从转储中读取它。没问题!此时,Vicki警告道:“有时(例如,代表超级用户执行的程序)出于安全原因不会创建内存转储。” Soooo,让我们检查一下……当从root bash接收到信号时,第二个root bash因创建内存转储而崩溃,但是由于权限(-rw-r -----具有root的拥有者),它不再像以前那样容易阅读由我的用户帐户拥有。好吧,如果假设的杀手级程序设法从超级用户的UID发送信号,那么它可以碰到这样的转储。



细心的读者可能会说:``您很容易在垃圾海中找到想要的数据。''没错,但是我敢肯定:如果您知道要捕获哪种鱼以及在哪里游泳,那么在垃圾网中找到它几乎总是现实的。例如,没有人会去下载包含崩溃程序调试信息的软件包,并通过事后调试找出对GDB感兴趣的变量的内容。



所有这些看起来似乎都无害,但实际上并非如此。我描述的所有动作都可以通过在用户模式下运行的程序或脚本轻松完成,更不用说更高的访问级别了。最重要的是,恶意可执行文件可以轻松地左右分割程序,并且通常还可以自由读取它们的全部内存。这里是信号和错误报告!我敢肯定,在其他* nix平台上以及与其他收件人程序中,情况是类似的,但是我当然不会对其进行检查。



可能会引起反对:恶意软件可以简单地使用调试工具从应用程序中提取有趣的数据。真的是那为什么是这个帖子?我的意思是:尝试停止从应用程序盗窃数据时想到的第一件事就是调试工具的局限性。当然,防病毒工具首先会抓住ptrace()的使用-这是一个非常可疑的事件。信号完全是另一回事。一个过程发送另一个标准信号-那又如何呢?乍一看,这是完全正常的事件。但是,正如我们已经看到的那样,这可能会导致应用程序异常终止,从而在某个文件夹中创建一个核心转储,然后可以尝试从中提取它。



当我尝试打开vk.com登录页面并以相同的致命信号转储Firefox时,它崩溃了,但却称为转储处理程序。棘手的小型转储格式的转储保存在〜/ .mozilla / firefox /崩溃报告/ {待处理或已提交}中,需要进一步调查。如果在设置窗口中,单击对号旁边的“了解更多信息”(下面的文字常在www.mozilla.org/ru/privacy/firefox/#crash-reporter处挂起),则将为您提供以下内容







« Mozilla Firefox. , Firefox, , URL- , . , , . crash-stats.mozilla.com. . .»URL中很少有真正可口的东西,但是转储中是否包含密码或cookie是一个很好的问题!



在这个神秘而有趣的笔记上,我将结束。我收到了忘记进行显式处理的信号。



PS我用这样的信号处理程序SIGUSR1编写了一个简单的程序:在屏幕上打印字符串“ 1”,进入一个无限循环。我希望如果您多次向该程序发送SIGUSR1信号,该处理程序将被多次调用,从而导致堆栈溢出。对我来说不幸的是,该处理程序仅被调用了一次。好的,让我们为SIGUSR2信号编写一个类似的处理程序,并发送两个不同的信号,以希望这将转储受害者。las,它也无济于事:每个处理程序仅被调用一次。溢出,溢出,但没有溢出!



PS 2.在Windows的世界中,有一种信号-可以发送到Windows的消息它们很有可能还可以用于娱乐和获利!



原文发表在我的博客05/05/17上。



All Articles