CSAPP BOMB LAB part1

BOMB LAB part 1

lab phase1

bomb.c phase1 code:
CSAPP BOMB LAB part1_第1张图片
bomb.s phase1 code:
CSAPP BOMB LAB part1_第2张图片
phase_1的参数被存入寄存器esi, 之后调用strings_not_equal函数,
401338 对应 string_not_equal函数:
CSAPP BOMB LAB part1_第3张图片
调用strings_not_equal函数之后,会进行3次push(stack操作), 然后将寄存器rsi的值放入寄存器rbp(callee 存储临时变量的寄存器)
CSAPP BOMB LAB part1_第4张图片
使用gdb 查看寄存信息
CSAPP BOMB LAB part1_第5张图片
在调用strings_not_equal函数时,寄存器rdi和寄存器rsi的内容是不一样,更新寄存器rax
CSAPP BOMB LAB part1_第6张图片
BOOM!!!
CSAPP BOMB LAB part1_第7张图片

lab phase2

bomb.c phase_2 代码:
CSAPP BOMB LAB part1_第8张图片
bomb.s phase_2 代码:
CSAPP BOMB LAB part1_第9张图片
400f02,将寄存器rsp的内容赋值给rsi, 然后调用read_six_numbers函数,
bomb.s read_six_numbers代码:
CSAPP BOMB LAB part1_第10张图片
在read_six_numbers函数中,将rsi分别赋值给不同的存储临时变量的寄存器。sscanf函数是C语言中的一个输入函数,用于从字符串中按照指定的格式提取数据。

在这里插入图片描述
sscanf 函数的参数格式是"%d %d %d %d %d %d"
CSAPP BOMB LAB part1_第11张图片
sscanf 函数获取的参数分别是 rsi+0x4 or rcx, rsi+0x14 or rsp+0x8, rsi+0x10 or rsp, rsi+oxc or r9, rsi+0x8 or r8, 和 0x4025c3。 rsp就是第一个参数,…。
CSAPP BOMB LAB part1_第12张图片
read_six_numbers 函数执行过后,会到phase_2函数:
CSAPP BOMB LAB part1_第13张图片
cmpl 比较 0x1 和 rsp存储的值,然后跳转到400f30, 将rsp+0x4保存到rbx, 将rsp+0x18保存到rbp,然后跳转到400f17, rbx-0x4就是rsp的地址, rax or eax保存rsp的值,rbx存储(rax+rax)的值,比较rbx和rax的值, int类型是4字节,所以rsp+0x4就是第二个参数, 所以第二个参数应该是第一个参数的二倍,然后跳转到400f25, 更新rbx+0x4, 以此类推,第三个参数是第二个参数的二倍。

工具介绍

objdump 使用

objdump是一个用于分析可执行文件、目标文件和共享库的工具。它可以显示这些文件的二进制指令、符号表、段信息、重定位表等内容,帮助开发者了解和调试程序。

objdump的常用选项和用法如下:

  1. 显示二进制指令:objdump -d ,这会以汇编代码的形式显示可执行文件或目标文件的二进制指令。

  2. 显示符号表:objdump -t ,这会显示可执行文件或目标文件的符号表,包括函数名、变量名等信息。

  3. 显示段信息:objdump -h ,这会显示可执行文件或目标文件的段信息,包括段名、段地址、段大小等。

  4. 显示重定位表:objdump -r ,这会显示可执行文件或目标文件的重定位表,用于动态链接和地址重定位。

  5. 显示动态符号表:objdump -T ,这会显示可执行文件或共享库的动态符号表,包括动态链接的函数和变量。

  6. 反汇编指定函数:objdump -d -j

    ,这会反汇编指定节(section)的内容,可以用于分析特定函数的汇编代码。

除了上述常用选项,objdump还提供了许多其他选项,可以根据需要进行使用。可以通过 objdump --help 命令查看完整的选项列表和使用说明。

请注意,objdump是一个命令行工具,可以在Linux、Unix和类似系统中使用。在Windows系统上,可以使用MinGW或Cygwin等工具来使用objdump。

CSAPP BOMB LAB part1_第14张图片

gdb 使用

在使用GDB调试程序时,可以使用info registers命令来打印寄存器的值。该命令会显示所有通用寄存器和特殊寄存器的当前值。

以下是在GDB中打印寄存器值的步骤:

  1. 启动GDB并加载要调试的程序。
  2. 在GDB提示符下,可以使用start命令开始执行程序,或者使用run命令来执行程序。
  3. 当程序停止在断点处或遇到异常时,在GDB提示符下输入info registers命令。
  4. GDB将打印所有通用寄存器和特殊寄存器的当前值。

除了info registers命令外,还可以使用以下命令来打印特定寄存器的值:

  • info register <寄存器名>:打印指定寄存器的值,例如info register eax
  • print $<寄存器名>:打印指定寄存器的值,例如print $rax

需要注意的是,寄存器的名称在不同的体系结构和编译器中可能有所不同。因此,需要查阅相关文档或参考特定体系结构的寄存器命名约定来确定正确的寄存器名称。

要查看寄存器中存储的地址的值,可以使用GDB中的x(examine)命令。该命令用于查看内存中的数据,可以通过指定地址和格式来打印出相应的值。

以下是在GDB中查看寄存器中地址的值的步骤:

  1. 启动GDB并加载要调试的程序。
  2. 在GDB提示符下,可以使用start命令开始执行程序,或者使用run命令来执行程序。
  3. 当程序停止在断点处或遇到异常时,在GDB提示符下输入info registers命令以查看寄存器的值。
  4. 找到包含所需地址的寄存器,并记下其名称(例如,假设要查看rax寄存器中的地址)。
  5. 在GDB提示符下输入x/<格式> $<寄存器名>命令,其中<格式>是指定打印格式的选项,常用的格式有:
    • x:十六进制格式
    • d:十进制格式
    • s:字符串格式
    • i:汇编指令格式
    • f:浮点数格式
    • 等等
      例如,要以十六进制格式查看rax寄存器中的地址,可以输入x/x $rax
  6. GDB将打印出寄存器中地址的值。

需要注意的是,寄存器中存储的地址必须是有效的,并且对应的内存区域必须可访问,否则将打印出错误信息。

汇编语法

sub 指令

在汇编语言中,SUB(Subtract)指令用于执行两个操作数的减法运算,并将结果存储到目标操作数中。SUB指令有多种形式,可以用于不同的数据类型和寻址方式。

以下是x86汇编语言中SUB指令的一些常见形式:

  1. SUB reg, reg/mem:执行两个寄存器或内存位置的减法操作,并将结果存储到第一个操作数中。例如,SUB EAX, EBX 将EBX的值从EAX中减去,并将结果存储回EAX寄存器。

  2. SUB reg, imm:执行寄存器和立即数之间的减法操作,并将结果存储到寄存器中。例如,SUB EAX, 10 将EAX寄存器的值减去10,并将结果存储回EAX寄存器。

  3. SUB mem, reg/imm:执行内存位置和寄存器或立即数之间的减法操作,并将结果存储到内存位置中。例如,SUB [EBX], ECX 将ECX寄存器的值从EBX指向的内存位置中减去,并将结果存储回该内存位置。

SUB指令的结果影响标志位寄存器(Flags Register),可以通过检查这些标志位来判断减法操作的结果。例如,ZF(Zero Flag)被设置为1表示结果为零,SF(Sign Flag)被设置为1表示结果为负数。

需要注意的是,SUB指令会修改操作数的值,因此在使用之前需要确保操作数的值是正确的,并且结果不会溢出。

mov指令

在汇编语言中,MOV(Move)指令用于将数据从一个位置复制到另一个位置。它是汇编语言中最常用的指令之一,用于数据的加载、存储和传递。

MOV指令有多种形式,可以用于不同的数据类型和寻址方式。以下是x86汇编语言中MOV指令的一些常见形式:

  1. MOV reg, reg/mem:将一个寄存器或内存位置的值复制到另一个寄存器中。例如,MOV EAX, EBX 将EBX寄存器的值复制到EAX寄存器中。

  2. MOV reg, imm:将一个立即数(常数)复制到寄存器中。例如,MOV EAX, 10 将值10复制到EAX寄存器中。

  3. MOV mem, reg/imm:将一个寄存器或立即数的值复制到内存位置中。例如,MOV [EBX], ECX 将ECX寄存器的值复制到EBX指向的内存位置中。

MOV指令可以用于不同的寻址方式,如直接寻址、间接寻址、基址加变址寻址等。它允许在寄存器和内存之间进行数据传输,以及在寄存器之间进行数据交换。

需要注意的是,MOV指令只能将数据从源位置复制到目标位置,而不能进行数学运算。如果需要进行数学运算,需要使用其他指令,如ADD(加法)、SUB(减法)等。

MOV指令的执行速度非常快,因为它是在寄存器之间直接进行数据传输,而不涉及内存访问。因此,在性能要求较高的场景中,使用MOV指令可以提高程序的执行效率。

movq 指令

movq指令:
CSAPP BOMB LAB part1_第15张图片
movq 参数
CSAPP BOMB LAB part1_第16张图片
movq 参数介绍
CSAPP BOMB LAB part1_第17张图片

地址格式:
CSAPP BOMB LAB part1_第18张图片

call 指令

CSAPP BOMB LAB part1_第19张图片

callq 指令

callq 指令例子:
CSAPP BOMB LAB part1_第20张图片

leaq 指令

CSAPP BOMB LAB part1_第21张图片

cmpq 指令

CSAPP BOMB LAB part1_第22张图片

testq 指令

CSAPP BOMB LAB part1_第23张图片

pushq 指令

CSAPP BOMB LAB part1_第24张图片

popq 指令

CSAPP BOMB LAB part1_第25张图片

关于指令的思考

call 和 callq的区别

在汇编语言中,CALL和CALLQ是两种不同的指令,它们在不同的体系结构中使用。

  1. CALL指令:
    CALL指令是在x86体系结构中使用的指令。它用于调用(跳转到)一个子程序或函数。CALL指令的操作数可以是一个标签、一个寄存器或一个内存地址。

当执行CALL指令时,会将当前指令的下一条指令的地址(即CALL指令的下一条指令)压入栈中,然后跳转到操作数所指定的子程序或函数的起始地址。

  1. CALLQ指令:
    CALLQ指令是在x86-64体系结构中使用的指令。它与CALL指令的功能相同,都是用于调用(跳转到)一个子程序或函数。但是,CALLQ指令是64位模式下的指令,用于支持更大的地址空间。

CALLQ指令的操作数可以是一个标签、一个寄存器或一个内存地址。它与CALL指令的区别在于,CALLQ指令使用64位的地址寻址方式,可以访问更大的内存空间。

总结:
CALL指令是在32位x86体系结构中使用的指令,而CALLQ指令是在64位x86-64体系结构中使用的指令。它们的功能相同,都用于调用(跳转到)一个子程序或函数,但是CALLQ指令适用于64位模式下的更大地址空间。

leaq和movq的区别

leaq指令和movq指令是x86汇编语言中常用的指令,用于处理数据的加载和传输。它们的区别如下:

  1. 功能:

    • leaq指令用于将一个内存地址或偏移量加载到寄存器中,而不是将内存中的值加载到寄存器。它主要用于计算地址,而不是数据传输。
    • movq指令用于将一个值从一个位置(寄存器、内存或立即数)复制到另一个位置(寄存器或内存)。
  2. 语法:

    • leaq指令的语法为leaq <源操作数>, <目的操作数>,其中源操作数是一个内存地址或偏移量,目的操作数是一个寄存器。
    • movq指令的语法为movq <源操作数>, <目的操作数>,其中源操作数和目的操作数可以是寄存器、内存位置或立即数。
  3. 执行时间:

    • leaq指令通常比movq指令更快,因为它只执行地址计算,而不涉及内存读取或写入操作。
  4. 使用场景:

    • leaq指令常用于计算数组元素的地址、计算偏移量、进行指针运算等需要计算地址的场景。
    • movq指令常用于数据传输、寄存器之间的值交换、常量加载等数据操作场景。

总之,leaq指令用于计算地址,而movq指令用于数据传输和复制。它们在功能、语法和使用场景上有明显的区别。

寄存器知识点

寄存器

x86 寄存器:
CSAPP BOMB LAB part1_第26张图片

寄存器功能:

CSAPP BOMB LAB part1_第27张图片

condition code:

CSAPP BOMB LAB part1_第28张图片

寄存器存储内容:
CSAPP BOMB LAB part1_第29张图片

寄存器用途 part1:

CSAPP BOMB LAB part1_第30张图片

寄存器用途 part2:

CSAPP BOMB LAB part1_第31张图片

rbx 简介

rbx是x86架构中的一个通用寄存器,具有多种功能和用途。以下是rbx寄存器的主要功能:

  1. 通用数据存储:rbx寄存器可以用于存储通用数据,例如整数、指针或其他数据。它可以用作临时存储器或在算术和逻辑运算中作为操作数使用。

  2. 基址寄存器:在内存寻址中,rbx寄存器可以作为基址寄存器使用。当进行间接寻址时,可以将rbx寄存器与偏移量相加来计算内存地址。

  3. 数组和缓冲区访问:rbx寄存器经常用于访问数组、缓冲区或数据结构中的元素。通过将数组或缓冲区的基地址存储在rbx寄存器中,可以使用偏移量或索引来访问特定的元素。

  4. 函数调用:rbx寄存器在函数调用时可以用作通用寄存器。它可以用于存储函数的返回值、参数传递或保存调用者保存的寄存器。

需要注意的是,rbx寄存器在函数调用过程中可能会被破坏,因此在使用之前需要保存其值,并在使用后进行恢复。此外,rbx寄存器也可以被用作循环计数器或其他需要通用寄存器的场景。

rbp 简介

rbp是x86架构中的一个通用寄存器,具有多种功能和用途。以下是rbp寄存器的主要功能:

  1. 基址指针:rbp寄存器通常被用作基址指针寄存器。在函数调用过程中,rbp寄存器用于指向当前函数的栈帧基址。栈帧是用于存储局部变量、函数参数和其他与函数调用相关的信息的一块内存区域。通过rbp寄存器可以在栈上定位和访问这些数据。

  2. 栈帧指针:rbp寄存器还可以用作栈帧指针。在函数调用过程中,rbp寄存器指向栈帧的底部,即局部变量和函数参数的起始位置。通过调整rbp寄存器的值,可以在栈上分配和释放局部变量的空间。

  3. 函数调用:rbp寄存器在函数调用过程中用于保存调用者的栈帧基址。在函数调用时,调用者的rbp寄存器的值会被保存到栈上,以便在函数返回后能够恢复调用者的上下文。

  4. 栈帧操作:rbp寄存器可以用于栈帧的操作,如栈帧的创建、销毁和访问。通过调整rbp寄存器的值,可以在栈上分配和释放内存空间,并通过偏移量访问栈上的局部变量和函数参数。

需要注意的是,rbp寄存器在函数调用过程中可能会被破坏,因此在使用之前需要保存其值,并在使用后进行恢复。此外,rbp寄存器还可以用作通用寄存器,存储临时数据或作为操作数使用。

data flow 例子

CSAPP BOMB LAB part1_第32张图片

memory 地址

地址模型

CSAPP BOMB LAB part1_第33张图片

参考链接

https://www.cs.cmu.edu/afs/cs/academic/class/15213-f15/www/lectures/05-machine-basics.pdf
https://www.cs.cmu.edu/afs/cs/academic/class/15213-f15/www/lectures/06-machine-control.pdf
https://www.cs.cmu.edu/afs/cs/academic/class/15213-f15/www/lectures/07-machine-procedures.pdf

你可能感兴趣的:(面试题,笔试,C++,c++)