翻译自:https://medium.com/@danielabloom/bolo-reverse-engineering-part-2-advanced-programming-concepts-b4e292b2f3e
前言
在本文中,我们将分解以下编程概念并分析每条指令的反编译的汇编版本:
1.数组
2.指针
3.动态内存分配
4.套接字编程(网络编程)
5.线程
对于逆向工程系列的第1部分,请单击此处。
请注意:虽然本文使用IDA Pro来反汇编编译代码,但IDA Pro的许多功能(即图形,伪代码转换等)都可以在其他免费反汇编程序(如radare2)的插件和构建中实现。此外,在准备本文时,我冒昧地将反汇编代码中的一些变量名称从IDA预设(如“v20”)更改为它们在C代码中对应的内容。这样做是为了使每个部分更容易理解。最后,请注意,此C代码已编译为64位可执行文件,并使用IDA Pro的64位版本进行反汇编。尤其是在计算数组大小,32位寄存器(即eax)的大小通常加倍并转换为64位寄存器(即rax)。
好的,我们开始吧!
虽然第1部分介绍并描述了循环和IF语句等基本编程概念,但本文旨在解释在逆向工程时必须解密的更高级主题。
数组
让我们从数组开始,首先,让我们看一下整个代码:
现在,我们来看一下整个反编译程序集:
如您所见,12行代码变成了相当大的代码块。但不要被吓倒!请记住,我们在这里所做的就是设置数组!
让我们一点一点地分解它:
在使用整型初始化数组时,编译器只需通过局部变量初始化长度。
注意:上面的声明数组的反编译的图片实际上标注时错误的。但是在使用整型初始化数组时,编译器首先需通过局部变量初始化长度。上面的屏幕截图实际上是Stack Canaries的初始化。Stack Canaries用于检测溢出攻击,如果不这样的话,可能会导致执行恶意代码。在编译期间,编译器要为litArray的元素分配足够的使用空间。litArray[0](见下图标注有“局部变量-数组”的图片)如你所见,唯一被分配的litArray元素是litArray [0 ])。编译器优化可以显着提高应用程序的速度。
如果因此而产生困惑的话,我表示抱歉!
首先,将数组长度保存到局部变量(ArraySize),然后计算最大和最小索引值以及数组的总长度,然后使用它们计算内存中数组的基本位置。
当声明具有预定义索引定义的数组时,编译器只需将每个预定义对象保存到自己的变量中,此变量名反映数组中的索引号。(如objArray4 = objArray [4])。
就像声明具有预定义索引定义的数组一样,在初始化(或设置)数组中的索引时,编译器会为所述索引创建一个新变量。
从数组中检索项时,该项从数组中的索引中获取并设置为所需的变量。
创建矩阵时,首先将行和列大小设置为它们的row和col变量。接下来,计算行和列的最大和最小索引,并用于计算内存中矩阵的基本位置或者总大小。
当从矩阵中检索时,再次执行与在矩阵索引的输入序列期间执行的相同的计算,但是不是将某些内容输入到索引中,而是检索索引的内容并将其设置为期望的变量(如,MatrixLeet)。
指针
现在我们已经了解了如何使用/查看汇编数组,让我们继续讨论指针。
让我们现在来分解汇编代码:
首先我们将int num赋值为10。
接下来,我们将num变量(即10)的内容设置为指针变量的内容。
我们输出num变量。
我们输出指针变量。
我们使用lea(加载有效地址)操作码而不是用mov输出num变量的地址。
我们使用lea(加载有效地址)操作码而不是用mov来输出指针变量的地址。
动态内存分配
我们列表中的下一个项目是动态内存分配。在本教程中,我将内存分配分解为以下内容: