为什么要写这篇教程呢?
本文章仅提供学习,切勿将其用于不法手段!
因为想要成为一名白帽黑客,汇编语言是必须要掌握的!
无论是二进制漏洞挖掘,还是逆向工程!汇编语言,都是硬性基础之一!当然,你还需要学会C语言!为什么要学会C语言呢?IDA软件 会将 二进制代码 翻译成 汇编语言 和 C语言 !
你不会汇编语言,不会C语言,想要进行逆向工程,以及更深层次的 二进制漏洞挖掘,是非常困难!如果你希望挖掘 二进制漏洞 ,你还要学会 代码审计 !
你必须看得懂,汇编语言代码 和 C语言代码,这是硬性要求!
想要参加CTF竞赛,汇编语言 和 C语言 都是重要的底层基础知识。
我们想要进行漏洞挖掘工作,就必须学会使用 IDA 软件!
IDA 软件,目前分为 免费版本(社区版)和 收费版本(专业版)这两个版本!
对于基础学习 和 简单的 二进制漏洞挖掘工作,免费的 社区版本,基本就够用了!
笔者使用的 IDA 软件为 IDA Freeware 系列的免费产品!
通过IDA 软件的 F5快捷键,我们可以将 汇编代码 翻译成 C语言代码 !
如果你掌握了C语言,那么你进行二进制漏洞的挖掘工作,就会变得相对容易一些了。
在某一方面,C语言代码 对比 ASM 汇编语言,具有更高的可阅读性!
但是,笔者更加喜欢直接阅读 ASM 汇编语言 的代码,笔者认为,汇编语言代码,是最接近于机器的,是更加能够有效揭示 代码本质 的!
想要阅读 ASM 汇编语言代码,首先,你要有汇编语言基础!
学习这方面的基础内容,大概需要 3~6个月的时间(这里指的是,脱产学习)。
如果你想在职学习这方面的内容,那么大概可能需要6个月到1年半左右的时间!
你需要从16位汇编语言开始学习,因为最底层的汇编语言代码,往往是建立在实模式基础上的!
在BIOS引导开始后,在操作系统正式载入之前,计算机运行在实模式环境下!
想打好基础,想要更加透彻地了解汇编语言,需要从实模式下的汇编语言开始学起!
这里推荐,王爽老师写的汇编语言教程,是非常不错的入门教程!
在学习完16位汇编之后,你需要学习操作系统原理,以及 32位汇编语言!
这里推荐,从WIN32环境下的汇编语言开始学习,在WIN32环境下,你会接触并调用大量的WINDOWS API 函数!想要进行 WIN32环境下的恶意软件分析工作,你起码要做到,能够看的懂WIN32环境下的 ASM汇编语言代码!
在 WIN32环境下,你会接触到大量的 使用到 PUSH 、CALL 、TEST 、JP 、JNP 、JMP 等汇编指令的软件代码!实际上,WIN32环境下的汇编语言,会更加的简单,因为 你经常会用到的 汇编指令数量,是相对有限的!你更多会接触到的是 WINDOWS API 函数!
无论是病毒木马,还是其它类型的恶意软件,它们想实现 对于操作系统的劫持与控制,就势必会使用到这些 API 函数 ! 当然,内核级的,例如 ROOTKIT 级别的 恶意软件除外,它们更多调用的是驱动级的,WINDOWS操作系统的 内核函数集合,以及一些中断、内存页 等。
如果你想要进行WINDOWS环境下的恶意软件分析工作,那么知道 恶意黑客们 会使用到 哪些 API函数 去进行 恶意软件编程,是非常有必要的!
通过 IDA 软件,你可以比较清晰地知道,恶意软件调用了哪些API函数!
通过明文的 ASM汇编代码 阅读,以及 了解当前软件使用了 哪些 API 函数,可以初步协助我们分析 恶意软件的实现原理,当然对于安全漏洞的挖掘工作,也是会利用到这些信息的!
如果你学会了 汇编语言 ,你可以知道 push rbp 这条指令,通常是函数过程的开始,push rbp指令所在的内存地址,通常就是函数过程的起始执行地址!
push rbp
mov rbp,rsp
和
mov rsp,rbp
pop rbp
这样的汇编指令组合,主要是为了实现 栈平衡 !
栈平衡,这个概念,大家自行百度下!
栈平衡,是操作系统和软件程序能够正常运行的硬性基础机制!
栈偏移,往往是 渗透测试工程师 进行二进制漏洞利用测试时,经常被采用的一种技术手段!
在 64位环境下,汇编语言使用 寄存器 和 栈空间来实现 函数参数的传递过程!
在 64位 WINDOWS 环境下(Windows下的x64 ABI),前4个参数,使用寄存器来传递(
第一个参数:RCX ,
第二个参数:RDX ,
第三个参数:R8 ,
第四个参数:R9)
!当然,我们要考虑到浮点数参数传递而使用到XMM系列寄存器的情况(XMM0
- XMM3
)!,其它参数使用栈空间进行传递!
在64位 LINUX 环境下(System V ABI(Application Binary Interface)),前6个参数,使用寄存器来传递(第一个参数:RDI ,
第二个参数:RSI ,
第三个参数:RDX ,
第四个参数:RCX ,
第五个参数:R8 ,
第六个参数:R9
)!当然,我们要考虑到浮点数参数传递而使用到XMM系列寄存器的情况(XMM0
- XMM7
)!,其它参数使用栈空间进行传递!
我们来分析一下这段代码 ,push rbp 和 mov rbp,rsp,以及 leave 和 retn 共同组成了 函数过程的 前言 和 后言,大家可以理解为,这是 函数过程的汇编代码的 开始 与 结束 !
leave 这条汇编指令 等同于 mov rsp,rbp 和 pop rbp 。
retn 这条汇编指令的作用是 将控制权返回到调用该过程的地址!
如果是 retn 立即数 ,则代表,在函数返回时,会将传递给函数的参数在栈结构中所占用的空间,也一同清理掉!
如果没有执行 retn 立即数 这样的操作,那么往往需要在被调用函数的外部(当前函数调用结束后,使用 add rsp,n 这条汇编指令,将传递给已过时函数的参数在栈结构中所占用的空间清理掉!
大家有没有注意到,为什么在这段代码中执行了 retn 而不是 retn 立即数 呢?
注意,在这段代码中,传递给 pwnme 函数的参数,是全部通过寄存器来实现的!并没有使用到栈空间去实现函数参数传递,因此,也就不需要再执行 retn 立即数 这样的栈空间清理了!
你明白了吗?
下一章节中,我们将重点讲解,通过代码审计的方式,进行二进制漏洞挖掘的相关知识点内容!
(未完待续)