首页
社区
课程
招聘
[原创]第十三题 NeuralCrackme Writeup
发表于: 2018-7-11 23:51 3968

[原创]第十三题 NeuralCrackme Writeup

2018-7-11 23:51
3968

题目没有花指令、未加壳,没有反调试,结构清晰明了,除了使用 Cygwin 编译导致某一些库函数在IDA里面识别出来"不太正常"和使用浮点指令外,似乎并没有什么分析上的障碍,字符串异或后使用不算障碍。先拖入IDA,看main结构,先看到了这一段:


基本可以确定出输入的长度是10个, 长度验证通过后再大致按如下步骤验证:
1.  if ( (unsigned int)sub_401CE0(Format, &v27, &v14, &v27, 10LL) != 5 ) 
2. 然后调用sub_4015E0(Format, &v27, &v18, &v19)做了一些运算
3.   Format[0] = byte_408D72 ^ 0x12;               // %
      Format[1] = (byte_408D73 ^ 0x12) - 1;         // l
      Format[2] = (byte_408D74 ^ 0x12) - 2;         // f
      sprintf(Format, &v26, Format, &v26, *(_QWORD *)&v17, v17, v3, v17);  可能是把 sub_4015E0的一个输出作为浮点数打印到了字符串
3.   Format[0] = byte_408D72 ^ 0x12;               // %
      Format[1] = (byte_408D73 ^ 0x12) - 1;         // l
      Format[2] = (byte_408D74 ^ 0x12) - 2;         // f
      sprintf(Format, &v26, Format, &v26, *(_QWORD *)&v17, v17, v3, v17);  可能是把 sub_4015E0的一个输出作为浮点数打印到了字符串
4. if ( v27 != '.' ) 验证上一步 sprintf 的结果是否为 A.BCDEFG... 这种样式
5. sub_403360 对第4的输出,分别取 A * A + B * B + C * C 做某种运算后,要使输出的值 > 15.5并且 v13 & 0xF0000必须为0
6. if ( COERCE_DOUBLE(COERCE_UNSIGNED_INT64(v20 + v21 - v17) & xmmword_409080) < 0.003 ) 需要成立.
第5, 6步的通过条件简单调试或者直接深入分析下输出,把打印信息异或回来看即可。现在逐步分析各个验证步骤,找到它的成立条件....

先看 sub_401CE0

然后到 sub_4015E0, 看起来也不太复杂一样,只是各种double的运算,调用了一个 sub_4034D0 函数,点进 sub_4034D0,看到了比较明显的"exp"字符串,结合mingw-w64,猜测它就是exp函数。纵观整个 sub_4015E0,取了一堆全局变量做浮点运算,中途涉及到一个修改全局变量qword_40C980的操作

前面的一堆运算过后,函数结尾出现一个对比的条件,该条件是求取值范围的一个关键:

继续回到main函数,来到 sub_403360的调用,点进子函数就发现了标志性的sqrt,看起来它可能就是sqrt函数。根据这个调用时的判断条件输入要大于15.5 * 15.5=240.25, 输入是三个整数的平方,看来输入的就只有可能是9.99*****了.也就是sub_4015E0 输出的结果必须是9.99****, 同样,也得到了sub_4015E0函数末尾的那个 if 条件不能成立。同时在对 sub_403360的判断中还增加了 v13 & 0xF0000 必须为0的判断,可以确定,v13的值必须为0x???0???? 这种值。

程序结构大体摸清了,懒得再去仔细理解细节,输入12345678AB直接在IDA中调试。顺便一提:IDA分析的main函数有问题,局部变量对应的栈位置不正确,平常一直用的 windbg 命令通过栈偏移看局部变量行不通..,很奇怪,不知道是怎么回事
第一个转换函数 sub_401CE0 的调用后把结果存入到RDX, RDX值为 000000000022FCC0  12 34 56 78 AB 00 00 00,回到main后把前四个字节给v13, 后一个字节给v14, 再通过下面的语句,把转换的结果送给 sub_4015E0做入参和放到两个临时变量中:
  HIWORD(v18) = v13;
  v20 = v18;
  *(_WORD *)((char *)&v19 + 5) = HIWORD(v13);
  HIBYTE(v19) = v14;
  v21 = v19;
  HIWORD(v18) = v13;
  v20 = v18;

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2018-7-11 23:58 被leavesth编辑 ,原因:
上传的附件:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//