逆向练习10

每日逆向的理解和积累。

汇编阅读练习

练习1

汇编代码及解释——


C的release版本

  • main函数


我是用Visual Studio 2017编译生成exe的,拖到ida中并不会像之前一样直接显示main函数,所有的函数都是以sub_xxx的形式命名的。最开始是通过在字符串中寻找程序运行时会显示的字符串信息定位到关键代码处的。但后来发现用Visual Studio 2017编译生成的release版的exe的main函数都是以sub_1400010E0命名的,由此在后续的分析中可以更快速的定位到main函数处。

注意——

  1. 在windows x64中,被调用函数的前四个参数是通过四个寄存器传递的:RCX、RDX、R8、R9,如果还有更多的参数,才通过椎栈传递
  1. X64多了8个通用寄存器:R8、R9、R10、R11、R12、R13、R14、R15,当然,它们都是64位的。另外还增加了8个128位XMM寄存器,不过通常用不着。X32中原有的寄存器在X64中均为扩展为64位,且名称的第一个字母从E改为R。不过我们还是可以在64位程序中调用32位的寄存器,如RAX(64位)、EAX(低32)、AX(低16位)、AL(低8位)、AH(8到15位),相应的有R8(64位)、R8d(低32)、R8w(低16位)和R8b(低8位)。不过不要在程序中使用如AH之类的寄存器,因为在AMD的CPU上这种用法会与某些指令产生冲突。

参考资料——Windows X64汇编入门


C的debug版本

  • main函数


对应源码——

问题描述——CC语言统计文件中的字符数、单词数以及总行数:统计文件的字符数、单词数以及总行数,包括:每行的字符数和单词数、文件的总字符数、总单词数以及总行数。注意:

  • 空白字符(空格和tab缩进)不计入字符总数;
  • 单词以空格为分隔;
  • 不考虑一个单词在两行的情况;
  • 限制每行的字符数不能超过1000。

练习2

汇编代码及解释——


C的release版本

  • main函数

  • countDay函数



可以看到,优化后的代码中对应如下源码的部分被优化成了浮点数操作,很不易于理解,这里我们也没必要一句一句汇编的进行理解。我们可以结合main函数和该函数上下文之间提供的信息,大胆的猜测该函数要实现的具体功能,在分析较大的项目时,要注意这一点。


C的debug版本

  • countDay函数


对应源码——

问题描述——C语言打鱼还是晒网问题:中国有句俗语叫“三天打鱼两天晒网”。某人从1990年1月1日起开始“三天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”。

参考资料——

XORPS - 单精度浮点值逻辑位异或
哪些指令会改变汇编的标志位(再附个总结)
汇编指令速查表
X86的SIMD指令 …simd instrucitons in X86

练习3

汇编代码及解释——


C的release版本

  • main函数


C的debug版本

  • main函数(其余2个子函数略)


对应源码——

问题描述1——用C语言编写一个函数,把一个字符串循环右移n位。

问题描述2——自定义一个函数,实现C语言中strcpy()函数的功能。

练习4

汇编代码及解释——


C的release版本

  • main函数

  • 在理解cmp和紧挨其后的条件跳转jp时存在问题,除了上网查阅资料外,最快的方法是利用idaF5辅助理解。
  • 对于如下图所示的汇编常量的具体值的计算,除了积累常用的之外,同样可以借助idaF5功能辅助理解。


C的debug版本

  • main函数


对应源码——

问题描述——C语言计算一个数的平方根。

正数n的平方根可以通过计算一系列近似值来获得,每个近似值都比前一个更加接近准确值。第一个近似值是1,接下来的近似值则通过下面的公式来获得。

编写一个程序,读入一个值,计算并打印出它的平方根。如果你将所有的近似值都打印出来,你会发现这种方法获得准确结果的速度有多快。原则上,这种计算可以永远进行下去,它会不断产生更加精确的结果。但在实际中,由于浮点变量的精度限制,程序无法一直计算下去。当某个近似值与前一个近似值相等时,你就可以让程序停止继续计算了。

必须使用浮点变量,而且程序应该对负值输入进行检查。

参考资料——

浅谈汇编指令CMP运行机制
CMP详解
关于汇编cmp后的一些走向
汇编指令速查

练习5-1

汇编代码及解释——


C的release版本

  • main函数

  • 可以看到,release版的经过优化后的应用程序中,已经看不出源码中2个结构体变量的初始化及指针访问操作了。
  • 可以看到,图中main函数的其实地址不再是sub_1400010E0,所以之前以为的规律应该是不存在的,除非是在同一个项目中编译生成的exe。还是需要通过关键字符串定位main函数的位置。

C的debug版本

  • main函数


对应源码——

问题描述——C语言结构体简单应用范例。

参考资料——

汇编:rep movsb

练习5-2-1

汇编代码及解释——


C的release版本

  • main函数

  • 可以看到,图中main函数的地址和练习5-1中一样,而二者的共同点是在同一个时间段内用同一个Visual Studio在同一个项目中编译生成的。

C的debug版本

  • main函数


对应源码——

问题描述——关于C语言作用域的例子1。

练习5-2-2

汇编代码及解释——


C的release版本

  • main函数


C的debug版本

  • main函数


对应源码——

问题描述——关于C语言作用域的例子2。