0%

hxpctf-passpx

upx+rc4

  1. 拿到文件发现加了upx的壳,尝试用upx -d脱壳会失败,显然upx被魔改过了。那么我们可以试着用dump的方法来脱壳分析。
  1. 通过gdb catch syscall write在程序输出try harder时断下(0x408614),这时程序已经执行到用户原本的代码领域了,因此在这个时候dump 内存,可以获得原始的反汇编代码。vmmap找到代码块,dump memory passpx_dump 0x400000到0x613000的。放到ida中进行分析。

  2. 0x408614这时观察寄存器,可以看到0x617440里面存放了Try harder的字符串。在ida中搜索这个字符串却没有办法找到,猜测这个字符串应该是动态生成的。这个时候搜索内存,看能不能直接搜索到flag
    1

  1. 没有搜索到flag相关的字符串,而且0x617440附近也不存在其他的数据。

  2. 为了找到我们感兴趣的函数,我们在0x617440位置下内存访问的断点,看一下这个字符串是什么时候生成的
    2

  3. 下了内存断点以后,run程序会在401b02中断,我们去ida分析一下。401b02属于函数401aa0,动静结合分析,似乎是用来拷贝内存的一个函数,在第16被调用的时候,会将0x7fffffffe130处的try harder 写入0x617440。那我们再看一下0x7fffffffe130处的try harder 是什么时候写入的

  4. watch *0x7fffffffe130 在一次run程序会在0x400335断下,我们ida里面看一下400335处在干什么
    3

  5. 可以看到此时的rdx被ida标记为V7,而V7是61507f位置的索引,0x7fffffffe130处的Try harder 便是由0x61507f处编码的字符串经过一系列计算得到的。

  6. 我们在ida分析一下0x400335所在的大函数4001a0,如果输入为P4sSw0rd!则进入4003A9分支,很不幸的是这个分支最后会根据614060处编码的字符串经过一系列计算得到Try harderer

  7. 这里我们还是没有找到关键的cmp,这时候会出现两个思路

    • 0x4001A0之前还有其他的cmp,使程序进入其他分支,而输出其他的字符串,但是我们通过ida的交叉引用可以看到start函数中必定会调用4001a0这个函数,而没有进入其他函数的分支。
      • 用户的输入应该可以改变0x61507f处编码的字符串,经过计算后得到其他的字符串?(我们可以通过改变0x61507f处的数据观察程序的输出,来验证我们的猜测)因此我们在0x61507f下内存断点 watch 0x61507f,run程序以后我们断在了一个奇怪的地方0x7ffff7ff8cf3
  8. 这块代码段是我们没有dump出来的,如果我们从头开始调试程序就会发现0x409E8D通过sys_mmap申请了内存,并往上面拷贝的代码,而后在409F44 会执行jmp r13跳到新申请的代码段7FFFF7FF8F60

  9. 我们在gdb开启record,然后单步走,观察一下从7FFFF7FF8F60 执行到7ffff7ff8cf3会执行哪些指令

  10. 会调用的函数passpx:00007FFFF7FF8F60 call near ptr unk_7FFFF7FF8FAF - > passpx:00007FFFF7FF908A call near ptr unk_7FFFF7FFA809->debug001:00007FFFF7FFA86E call near ptr unk_7FFFF7FF9AF4\debug001:00007FFFF7FFA89B call near ptr unk_7FFFF7FFA438

  11. call 7FFFF7FFA438之后会触发0x7ffff7ff8cf3处的0x61507f的写入断点,因此我们跟进这个函数继续观察debug001:00007FFFF7FFA6D2 call loc_7FFFF7FF9AF4 调用的时候会触发中断,然后分析调试7FFFF7FF9AF4可以看到程序会朝0x7fffffff9680、0x7fffffffda2a拷贝一系列数据,拷贝完成后在00007FFFF7FFA286处发现了大量cmp,如果修改7FFFFFFFDB08处的数据,与cmp的字符串一样,程序会在0x61507f上写入flag解密前的字符串