• 如果您想对本站表示支持,请随手点击一下广告即可~
  • 本站致力于提供原创、优秀的技术文章~
  • 有任何疑问或建议 均可以在站点右侧栏处 通过各种方式联系站长哦~
  • CTF – RootMe解题报告 [Cracking : ELF C++ – 0 protection]

    渗透测试 EXP 98阅读 0评论

    挑战入口:Root-Me(https://www.root-me.org/en/Challenges/Cracking/ELF-C-0-protection)
      分类目录:Link to …(http://exp-blog.com/2019/01/02/pid-2597/4/)

    初步分析

    不太水的水题,需要懂得反汇编工具的使用,以及一些汇编原理。


    开始挑战后下载了一个 ch25.bin 文件,判断是 Linux 下编译的可执行二进制文件。

    放到 Linux 下执行 ./ch25.bin (注意赋予 x 执行权限),提示使用方法为 ./ch25.bin password

    尝试输入任意密码执行,提示密码错误。

    初步判断可能密码以常量方式存储在代码中。

    使用文本编辑器打开,尝试搜索关键字 password ,发现一段常量文字,但是密码被隐藏其中:

    看来只能 反编译 了。

    反汇编

    Linux 下的反汇编可以直接使用 objdump 工具,执行以下命令生成反汇编源码:

    objdump ch25.bin -S >> ch25-src.asm

    从源码可知这是一个 32 位的 ELF 文件,但是纯文本的组织方式不好分析代码。

    这里改用 Windows 的 IDA 工具打开 ch25.bin 文件(注意使用 ELF for Intel 386 方式打开)。

    从左侧的 Fouction name 列表找到 main 函数,定位到 main 函数的代码块。

    在代码块的最后有一个条件分支语句 jg short loc_8048AEE

    根据图例可知,当 loc_8048AEE <= 0 时,代码会走红色分支;而当 loc_8048AEE > 0 时,代码会走绿色分支。

    跟踪红色分支,发现分支代码中的一些常量字符串就是前面在 Linux 运行脚本时,没有给定 password 入参时的使用说明,说明这个红色分支不是我们的目标分支。

    由此也可以推断,绿色分支的功能就是当我们给定 password 入参时,进行密码比较的代码分支。

    定位关键代码

    进而分析绿色分支的代码块,暂时看不出个所以然,但是在这个代码块的最后依然有一个条件分支语句 jz short loc_8048BE5

    根据图例可知,当 loc_8048BE5 != 0 时,代码会走红色分支;而当 loc_8048AEE == 0 时,代码会走绿色分支,其中从红绿分支代码中的常量字符串中可以知道,当 password 正确时会走红色分支,而当 password 错误时会走绿色分支。

    而影响 loc_8048BE5 值的是前面一个调用的一个名为 _ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_ 的函数。

    分析可知该函数作用是比较两个字符串是否相同,其中入参 1 是一个字符串变量(推断就是脚本输入的 password),而入参 2 是一个字符串常量(推断就是真正的 password)。


    很明显,真正的密码就隐藏在 _ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_ 函数前面的代码块。

    发现这部分代码块中用到了两个变量 unk_8048DC4unk_8048DCC

    跟踪这两个变量到数据段,发现不是直接可读的字符串,推测是做了某些运算。

    但是从汇编代码直接分析做了什么操作还是有点麻烦的,于是我决定走个捷径:

    _ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_ 函数做断点,直接通过 debug 从内存获取函数参数 2 (即真正 password )的值。

    DEBUG

    回到 Linux 系统,这次使用 gdb 工具进行 debug 调试。

    输入命令 gdb ch25.bin 进入 debug 模式:

    通过输入 layout asm 命令可以查看反汇编源码,此时通过键盘的 按键可以前后滚动代码,找到 _ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_ 函数,发现该函数的地址为 0x8048b92

    知道地址就可以添加断点了,输入命令:break *0x8048b92 (注意 * 不能丢,表示地址指针)。

    gdb 提示成功在 0x8048b92 位置添加了 1 号断点。

    此时输入命令 info break 可以查看当前的断点信息。

    执行命令 r www.exp-blog.com (其中 r 是命令 run 的缩写,表示运行代码,后面的是给代码的入参,任意值均可,如此处为 www.exp-blog.com ),代码运行到前面设置的断点处暂停了。

    查看内存值

    现在要查看函数 _ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_ 的内存值。

    需知道函数内存是存储在【栈】的,因此我们需要查看【栈指针】 ESP(Extended stack pointer) 的内容。

    输入命令 x/50wx $esp 查看栈指针 ESP 当前所指向的栈中,从栈顶开始向后 50 个单位所存储的内容。

    x/50wx 命令释义:
        x : examine 命令的缩写,用于查看内存地址中的值
        / : 分隔符,前面是命令名称,后面是控制输出内容的格式
        50 : 表示取 50 个单位(数值任意控制均可)
        w : 表示每个单位的长度为 4 字节
        x : 表示按十六进制显示

    不难发现均是地址值(需要知道这些地址每次运行程序都会变化的),为了查看真正的内容,

    再输入命令 x/s address 查看特定地址中存储的值,如:x/s 0x08050c8c

    x/s 命令释义:
        x : examine 命令的缩写,用于查看内存地址中的值
        / : 分隔符,前面是命令名称,后面是控制输出内容的格式
        s : 表示按字符串形式显示

    有兴趣可以每个地址都查一下内容是什么,这里我就不逐个看了。

    第一行第二列的地址,存储的就是入参 1 的值,亦即前面我们随意输入的 www.exp-blog.com

    第二行第二列的地址,存储的就是入参 2 的值,亦即前面我们推测的真正的密码,可以发现其值为 Here_you_have_to_understand_a_little_C++_stuffs

    为了验证猜想,我们退出 gdb 模式执行脚本,输入命令:

    ./ch25.bin Here_you_have_to_understand_a_little_C++_stuffs

    提示密码正确,猜测是对的。完成挑战。


    转载请注明:EXP 技术分享博客 » CTF – RootMe解题报告 [Cracking : ELF C++ – 0 protection]

    喜欢 (1) 分享 (0)
    发表我的评论
    取消评论

    表情

    Hi,您需要填写昵称和邮箱!

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址