如何分析没有读取权限的可执行文件?

逆向工程 linux 动态分析
2021-06-25 01:07:38

我在 Linux(内核 2.6)上有一个可以执行但无法读取的二进制文件(chmod 0711)。因此,不可能进行静态分析。

user1: $ ls -l bin 
-r-s--x--- user2 user1 bin
user1: $ file bin
setuid executable, regular file, no read permission

我正在寻找不同的动态技术来收集尽可能多的信息。

例如strace使用这个可执行文件。


更新:我能够解决这个问题。见答案。

谢谢大家<3 这个新的逆向工程社区太棒了!

4个回答

我最初认为您无法转储该程序,但事实证明您可以 - 请参阅此答案的第二部分。

运行程序

大多数常用方法将不起作用,因为可执行文件是 setuid。如果您正常启动程序,它会以提升的权限(euid ≠ ruid)运行,并且大多数调试工具都保留给 root。例如,任何依赖于附加到程序的东西ptrace都保留给 root。这包括您可以在调试器中执行的任何操作。Linux 允许您转储正在运行的进程的内存(使用ptrace或通过/proc/$pid/maps/proc/$pid/mem),但对于 setuid 可执行文件也禁用了该功能。

您可以运行strace ./bin,并查看程序进行了哪些系统调用。但是,这会在没有任何额外权限的情况下运行程序。它很可能会提前停止并抱怨它无法读取文件,或者它没有以正确的用户身份运行。

您可以在/proc/$pid:文件中查看 CPU 使用率、IO 使用率、网络使用率、内存使用率等统计信息statussched并且net/netstat是全局可读的(无论程序是否实际以额外权限启动,都适用 setuid 限制)。我看到的一件有趣的事情是程序的网络连接。无论哪种方式,真正有趣的东西,如内存内容 ( mem) 甚至打开的文件 ( fd) 都被禁用。无论哪种方式LD_PRELOAD,使用不同的库预加载库或使用不同的库运行程序LD_LIBRARY_PATH也都被禁用。您也不会得到核心转储。

那么什么有效呢?您可以看到开放的网络连接,也许其中一个会给您提供线索或会被欺骗。您可以尝试通过修改程序访问哪些文件,或者通过从另一个目录运行程序(尝试创建符号链接)来找出程序访问的文件。

如果您可以访问机器上的 chroot jail,请尝试从那里运行该程序。如果您可以运行实现共享文件夹(例如 VMware 或 VirtualBox)的虚拟机,请查看您是否可以从那里访问该程序。这完全是为了破坏系统的安全性:权限旨在阻碍您完成任务。

一种先进的技术是在重负载下观察程序并尝试从它所花费的时间推断出它做了什么。污染磁盘缓存并查看哪些文件可以快速访问。查看交换使用情况如何根据程序执行的操作而变化(这样您就可以了解其工作集中有多少不同的页面,而不仅仅是它使用了多少总内存)。将需要大量的试验和错误。当您知道代码并试图获取数据时,这就是众所周知的旁道攻击。当您不知道代码时,我预计以这种方式获取有用信息会非常困难。

转储内存内容

我最初认为你不能因为 setuid 位而转储程序的内存(这通常不会成为问题,因为你只是复制可执行文件,但在这里这是不可能的,因为可执行文件不可读) . 事实证明这是错误的。如果您使用ptracebefore 调用附加到程序execve(就像运行strace ./bin一样),您确实可以访问它ptrace的所有荣耀,包括PTRACE_PEEKDATAPTRACE_PEEKEXEC这不会运行程序 setuid,因此它的行为可能有所不同,但加载到内存中的代码和静态数据是相同的。

荣誉对samuirai指出这一点。

以下是如何转储程序内存的概述:

  • Fork,并调用ptrace(PTRACE_TRACEME, ...)子进程然后执行程序 ( execl("./bin", "./bin", NULL))。
  • 在父级中,调用waitpid以等待子级从 返回execve
  • 找出代码加载的地址。IP 寄存器的值(通过 获得PTRACE_GETREGS)应该提供线索,您可以查找文件格式头。
  • 逐字阅读孩子的记忆(PTRACE_PEEKTEXT, PTRACE_PEEKDATA)。
  • 如果需要,重建文件格式(例如,从文本和数据部分制作 ELF 二进制文件)。将数据转储到文件中。
  • 杀死孩子——它甚至无法执行任何操作。

Dougall 指出了一个用于 ELF 可执行文件的概念验证工具xocopy

我找到了一个小工具,它使用 ptrace 来单步执行来自执行另一个程序的分叉子指令:

http://pastebin.com/yHbkc0Je

这工作得很好。我得到了所有使用的指令的转储。我知道它没有以 setuid 权限运行,但无论如何它可能会对我有所帮助。现在我只需要一些东西来反汇编指令跟踪。


基于此的PoC ( https://gist.github.com/Samuirai/5217680 )。

/*
This tool was developed through the awesome community effort on reverseengineering.stackexchange.com

The Thread: http://reverseengineering.stackexchange.com/questions/98/how-can-i-analyse-an-executable-with-no-read-permission

Special thanks to:
 + igor-skochinsky who pointed at this Phrack article and gave the initial idea: http://www.phrack.com/issues.html?issue=63&id=12&mode=txt
 + gilles for his engagement and enthisiasm about this question and his code attempt
 + and all others who were involved

This new stackexchange reverseengineering community is F**KING AWESOME!!! <3

*/
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/user.h>
#include <sys/syscall.h>

int main()
{
    pid_t pid;

    pid = fork();
    if(pid == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execl("./bin", "./bin", NULL);
    }
    else {
        int status;
        struct user_regs_struct regs;

        // single stepping until it reached the real code segment
        while(1) {

            wait(&status);
            if(WIFEXITED(status))
                break;

            // get registers for the instruction pointer
            ptrace(PTRACE_GETREGS, pid, NULL, &regs);

            // strace ./bin
            // brk(0) = 0x804a000
            if(regs.eip>0x804a000)
            {
                printf("in code section at EIP=%lx\n",regs.eip);
                unsigned int i;

                // Dump code
                for(i=0; i<0x1000; i+=4) {
                    long data = ptrace(PTRACE_PEEKTEXT, pid, regs.eip+i, 0);
                    printf("%lx",data);
                }
            }

            // single step in child process
            ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL);
        }
    }
    return 0;
}

正如吉尔斯所指出的,您无法通过阅读/proc/<pid>/maps来获取代码区域的地址,但我认识到它strace有这么好的单行brk(0) = 0x804a000

我单步执行子进程,直到 EIP 接近这个值;然后,我转储 0x1000 字节。

在 suid 二进制文件上使用基于 ptrace 的动态分析工具可以使它们在没有特权的情况下运行。因此,以您的用户身份运行的文件副本可能足以用于分析目的。

当我不得不这样做时,我使用了xocopy 工具,它用于ptrace在标头映射到内存时重建 ELF 文件(大多数编译器都这样做,可能供动态链接器使用)。我尚未使用 ASLR 测试该工具,但您可以将其与其他答案中涵盖的一些技术结合使用。转储文件后,可以对其进行静态分析,或使用任何动态分析工具运行。

以下是一些可能有效也可能无效的工具:

我很想知道您是否在其中任何一个方面取得了成功。