mov 汇编指令混淆


mov

这个程序拿来初看可能比较乏味,但也很有趣。马后炮地说,多用一点脚本就会轻松很多,因为在调试时做了很多繁琐的工作。

运行程序

我们得到一个名为 mov 的二进制文件。容易看出,这个二进制文件是用名为 "movfuscator"(https://github.com/xoreaxeaxeax/movfuscator)的混淆器编译的,(因为笔者之前看到过 movfuscator)。

$ ./mov 
hello
hello

Nope sorry :(
$ echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" | ./mov
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp��
Nope sorry :(

看来,我们的输入被放在一个长度为32的缓冲区里。在开始逆向之前,先对它进行解密。

去混淆

Google 了一下,发现了反混淆器:Demovfuscator (https://github.com/kirschju/demovfuscator).

Usage: demov [-o patched] [-g graph] [-i idc]

Demovfuscator 不会移除所有的 mov 操作!

它只能做到以下几点:

  • 处理加固的二进制文件
  • 重构函数和它们的控制流图
  • 为 IDA 生成符号
  • 产生一个经过修补的二进制文件
  • 进行部分指令的重新替换

-> 方便逆向

静态调试

在IDA中观察了一段时间的二进制文件后,我们注意到有一堆

test eax, eax 指令之后是

jne 0x0804XXXX

分析控制流

生成一张控制流图

我们看到这里,可以怀疑二进制每次都是对输入的一个或几个字符进行比较。

Battle plan

如果我们一次发送一个唯一的字符的话,就能看到字符被 check 的顺序。构造输入:

ABCDEFGHIJKLMNOPQRSTUVWXYZ012345

我们创建了一个gdb init文件,在.png中提到的每一个ADDRESS(共42个)设置断点,然后运行程序。

调试

我们注意到在指令 0x804be37 后不久,字符开始被引用。看一下我们的流图,这看起来像是一个循环。

第一个被引用的字符是'G'。同时,'_'也被引用。这两个字符被多次放在eaxedx中。再往下,和前面一样,我们遇到了一个test eax, eax,然后是一个jne/jnz。正是这个跳转导致了Nope sorry :(被打印出来,程序中途终止。

所以我们在'G'和'_'都在寄存器内的地方打一个断点,相应地修改我们的输入字符串并继续。最终获得字符串。

ABCDEFGHIJKLMNOPQRSTUVWXYZ012345

->

ABCDEF_HIJKL_NOPQ_STU_WX_Z012345
看着像 flag 了吧。

在循环之后继续,我们看到的是看起来更像if语句而不是循环条件。换句话说,这个过程在一个基本块中比较一个或多个字符,然后继续到程序的下一个部分。

当程序开始引用两个以上的字符串时,会难一些。在0x080513e7处,程序似乎要检查我们的第9个字符(I)减去8后是否等于j。这意味着我们的字符实际上应该是 r

解决

按照上面的解释,步入程序的过程相当顺利。有些条件我们无法满足(这就是为什么我们应该编写解决方案的脚本!),所以我们最后手动引导程序向正确的方向发展(set $eip=0xcorrect),以避免程序终止。

最后东拼西凑:

MBkeys_breKt_tObt_bad_:)_!012345

可见其原本是

Mykeys_arent_that_bad_:)_! 然后包上flag提交!

Flag: flag{Mykeys_arent_that_bad_:)_!}


文章作者: sfc9982
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 sfc9982 !
  目录