我在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与此可执行文件一起使用。


UPDATE:我能够解决此问题。查看答案。

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

评论

您是只在寻找一种动态分析技术,还是一般在寻找解决方案?

我猜只有动态分析技术在这里起作用。但我乐于接受任何有助于理解可执行文件功能的内容。我没有对文件系统等的“物理”访问。

如果strace有效,请尝试附加GDB并转储内存(请参见此处)

@IgorSkochinsky,我只是在机器上尝试过,没有运气。 GDB拒绝附加:无法附加到进程。 ...以root用户身份重试。它取决于ptrace(会给出相同的错误),因此ltrace也不起作用。

@IgorSkochinsky如果您运行strace ./bin,它将在没有额外特权的情况下运行该程序。如果正常启动该程序,则该程序将以提升的特权运行,然后您自己拥有提升的特权就无法跟踪它。

#1 楼

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

运行程序

大多数常用方法无法执行,因为可执行文件是setuid。如果正常启动该程序,它将以提升的特权(euid≠ruid)运行,并且大多数调试功能都保留给root用户。例如,任何依赖于使用ptrace附加到程序的内容都保留给root用户。这几乎包括您可以在调试器中执行的所有操作。 Linux允许您转储正在运行的进程的内存(使用ptrace或通过/proc/$pid/maps/proc/$pid/mem),但是对于setuid可执行文件也已禁用该内存。制造。但是,这将在没有任何其他特权的情况下运行该程序。它可能很早就停止,并抱怨它无法读取文件,或者该文件没有以正确的用户身份运行。

您可以看到诸如CPU使用率,IO使用率,网络使用率, strace ./bin中的内存使用情况等:/proc/$pidstatussched之类的文件是世界可读的文件(无论该程序是否实际上以附加特权启动,都适用setuid限制)。我看到的一件有趣的事是程序的网络连接。诸如内存内容(net/netstat)甚至打开的文件(mem)之类的真正多汁的东西都被禁用。两种方式都禁止使用fd预加载库或使用其他LD_PRELOAD运行程序。您也不会得到核心转储。

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

如果您有权访问计算机上的chroot监狱,请尝试从那里运行该程序。如果可以运行实现共享文件夹(例如VMware或VirtualBox)的虚拟机,请查看是否可以从那里访问该程序。这一切都是为了破坏系统的安全性:权限被设计为阻碍您执行任务。

一项高级技术是在负载沉重的情况下观察程序,并尝试从程序中推断出程序的作用。时间。污染磁盘缓存,查看哪些文件可以快速访问。查看交换使用情况如何根据程序的工作而变化(这样您就可以了解其工作集中有多少个不同的页面,而不仅仅是它正在使用多少总内存)。将需要大量的反复试验。当您知道代码并尝试获取数据时,这就是众所周知的旁路攻击。当您不知道代码时,我希望通过这种方式很难获得有用的信息。

转储内存内容

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

samuirai表示感谢。

这里概述了如何转储程序的内存:


Fork,并在子级中调用PTRACE_PEEKEXEC然后执行程序(ptrace(PTRACE_TRACEME, ...))。父母,请致电execl("./bin", "./bin", NULL)等待孩子从waitpid返回。
找出加载代码的地址。 IP寄存器的值(通过execve获得)应该可以提供一个线索,您可以查找文件格式的头文件。
逐字读取孩子的内存(PTRACE_GETREGSPTRACE_PEEKTEXT)。
重构文件格式(例如,根据文本和数据部分制作ELF二进制文件)。将数据转储到文件中。
杀死孩子-甚至什么也执行不了。

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

评论


实际上,我认为我可以不以root身份使用ptrace。 gdb与其他可执行文件配合良好。问题在于该可执行文件不可读,因此gdb不会加载该文件。我认为,因为我可以执行它,所以可以在我的特权下运行它并以这种方式对其进行调试(并接受使用setuid运行所需的特权不会起作用)。但是再说一次。 gdb无法读取,因为它不可读。

– Samuirai
13年3月21日在0:54



@samuirai:一旦运行,您将无法附加该进程?

–伊戈尔·斯科钦斯基♦
13年3月21日在0:59

@IgorSkochinsky:我尝试过,但是我太慢了。可执行文件非常快速地完成。

– Samuirai
13年3月21日在1:05

工作PoC gist.github.com/Samuirai/5217680和我的问题中的一个小更新

– Samuirai
13年3月21日在23:21

@samuirai从寄存器中推断出有趣地址的好主意。我将尝试在本周末将代码升级到可以使用的代码。

–吉尔斯'所以-不再是邪恶的'
13年3月21日在23:32

#2 楼

我找到了一个小型工具,该工具使用ptrace来执行执行另一个程序的分支孩子的单步指令:我得到了所有使用说明的转储。我知道它没有使用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;
}


正如Gilles指出的那样,您无法阅读/proc/<pid>/maps来获取代码区域的地址,但是我认识到strace的单行代码brk(0) = 0x804a000很漂亮。

我单步执行子进程,直到EIP达到该值为止。然后,我转储0x1000字节。

评论


为什么不修改它以转储内存而不是进行跟踪呢?已经使用PTRACE_PEEKTEXT进行了读取,您只需要修改它即可读取所有进程内存。在这里查看一些示例代码

–伊戈尔·斯科钦斯基♦
13年3月21日在3:03

在SE上,我们通常希望看到代码(不要太长)仅在答案中,而不是在链接后面。这是因为pastebin不能保证存储代码。您可以将代码添加到答案中吗?

–user187
13年3月22日在18:45

与我的问题更新中的代码相同。我将添加参考

– Samuirai
13年3月23日在21:14

#3 楼

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

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

评论


这个工具有64位版本吗?它似乎不适用于64位elf文件。 :/

– Skylion
16年2月29日在1:46

#4 楼

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


skpd,显然是基于Phrack的文章。 >请先阅读/proc/<pid>/maps,然后阅读dd /proc/<pid>/mem

如果您在其中的任何一项上都取得了成功,我将很感兴趣。

评论


这些都不适用于setuid可执行文件。

–吉尔斯'所以-不再是邪恶的'
13年3月20日在22:00

@Guiles,这不是setuid,他也从未说过。

–cb88
13年3月21日在4:18

@ cb88是公平的,引用的权限确实显示s标志。虽然我认为应该已经明确提及。

–伊戈尔·斯科钦斯基♦
13年3月21日在11:10

#5 楼


以root身份读取文件
将文件系统复制到另一个系统中,并在有权限的情况下将其读取(将fs复制到具有root访问权限的系统中)。
检查进程执行时的内存。如果它是setuid且您不是那个用户,将不起作用。
我只是很傻,但是您可以一遍又一遍地执行它,直到它填满交换,然后从那里复制它:P或创建一个优先级高于系统交换的主文件夹中的交换文件。然后执行上述操作...,当系统交换开始填充时,请复制交换文件以保存它。我建议在脚本中这样做,否则您的系统可能最终被锁定。我可以免费或免费地监视交换使用情况,否则会从/ proc中解析出使用情况。当然,在复制交换文件之后,请杀死所有创建的任务。

可能是您无权执行任何上述操作:P。那说明您可能需要提供有关在此系统上可以执行/不能执行的操作的更多详细信息。

评论


那就对了。我只是普通用户,无法访问/ proc。尽管strace可行,但我认为还有其他我不知道的东西。

– Samuirai
13年3月20日在22:05