当前位置: 首页> 娱乐> 明星 > shellcode汇编复习

shellcode汇编复习

时间:2025/7/9 22:58:10来源:https://blog.csdn.net/arv002/article/details/141421407 浏览次数:0次

shellcode汇编复习

  • 一、 汇编代码复习
  • 二、 基础寄存器
    • 1. EAX (Accumulator Register)
    • 2. EBX (Base Register)
    • 3. ECX (Count Register)
    • 4. EDX (Data Register)
    • 5. ESI (Source Index Register)
    • 6. EDI (Destination Index Register)
  • 二、 基础指令
    • 1. `mov` - 数据传送
    • 2. `add` - 加法
    • 3. `sub` - 减法
    • 4. `inc` - 自增
    • 5. `dec` - 自减
    • 6. `lea` - Load Effective Address
    • 7. `jmp` - Jump
    • 8. `cmp` - Compare
    • 9. `push` - Push
    • 10. `pop` - Pop
    • 11. `xor` - Exclusive OR
    • 12. `xchg` - Exchange
    • 13. jz (Jump if Zero)
    • 14. call

一、 汇编代码复习

EAX,EBX,ECX,EDX,ESI和EDI使用详解。
在这里插入图片描述

二、 基础寄存器

在计算机体系结构中,特别是在x86架构中,通用寄存器(General Purpose Registers, GPRs)是CPU中用于存储临时数据或地址的关键组成部分。这些寄存器对于执行各种算术、逻辑和数据转移操作至关重要。在x86架构中,EAX、EBX、ECX、EDX、ESI和EDI是32位模式下的主要通用寄存器,它们在64位模式下(如x86-64)通常扩展为RAX、RBX、RCX、RDX、RSI和RDI,但保持相似的用途和特性。这里,我们将专注于32位模式下的这些寄存器。

1. EAX (Accumulator Register)

EAX寄存器通常用作累加器,在算术和逻辑运算中扮演主要角色。它经常用于存储操作数、结果以及中间值。在函数调用中,EAX也常用于返回函数的结果。

2. EBX (Base Register)

EBX通常用作基址寄存器,特别是在数组和字符串操作中,它可以用来存储数组或字符串的基地址。此外,在调用操作系统函数时,EBX有时也用于传递参数。

3. ECX (Count Register)

ECX通常用作计数器寄存器,在循环操作中尤其重要。它存储了循环的迭代次数,很多指令(如REP前缀的字符串操作指令)都会递减ECX的值来控制循环次数。

4. EDX (Data Register)

EDX是一个数据寄存器,它在执行双操作数指令时与EAX协同工作。对于较大的数据操作(如64位除法),EDX用于存储高位结果。此外,在多字节操作中,EDX也常用于存储扩展的数据。

5. ESI (Source Index Register)

ESI作为源索引寄存器,在字符串操作中非常有用。它通常用于存储源字符串或数据数组的起始地址,在字符串指令(如MOVSB, CMPSB等)中自动递增,以便按顺序处理数据。

6. EDI (Destination Index Register)

EDI作为目的索引寄存器,与ESI相对应,在字符串操作中用于存储目标字符串或数据数组的起始地址。与ESI相似,EDI也在字符串指令中自动递增,以接收来自源地址的数据。

二、 基础指令

1. mov - 数据传送

mov 指令用于将一个数据(可以是立即数、寄存器内容、内存地址中的数据)传送到另一个地方(寄存器或内存地址)。

语法

mov destination, source

示例

mov eax, 10          ; 将立即数 10 传送到寄存器 eax
mov ebx, eax         ; 将寄存器 eax 的内容传送到寄存器 ebx
mov [var], eax       ; 假设 var 是一个内存地址,将 eax 的内容传送到该地址

2. add - 加法

add 指令用于将两个操作数相加,并将结果存储在第一个操作数中(即目标操作数)。

语法

add destination, source

示例

mov eax, 5
add eax, 3           ; eax 的值变为 8
add [var], eax       ; 假设 var 是一个内存地址,将其内容与 eax 相加,结果存回 var

3. sub - 减法

sub 指令用于从第一个操作数中减去第二个操作数,并将结果存储在第一个操作数中。

语法

sub destination, source

示例

mov eax, 10
sub eax, 3           ; eax 的值变为 7
sub [var], eax       ; 假设 var 是一个内存地址,从其内容中减去 eax,结果存回 var

4. inc - 自增

inc 指令用于将指定操作数的值加 1。

语法

inc operand

示例

mov eax, 5
inc eax             ; eax 的值变为 6
inc [var]           ; 假设 var 是一个内存地址,将其内容加 1

5. dec - 自减

dec 指令用于将指定操作数的值减 1。

语法

dec operand

示例

mov eax, 5
dec eax             ; eax 的值变为 4
dec [var]           ; 假设 var 是一个内存地址,将其内容减 1

当然可以,下面我将详细解释汇编命令 leajmpcmppushpop 的使用方法,并给出对应的使用示例。请注意,这些示例是基于常见的x86汇编语言格式,但不同的汇编器(如NASM、MASM等)可能在语法细节上有所不同。

6. lea - Load Effective Address

lea 指令用于加载有效地址(即将地址计算的结果存储到目标寄存器中,而不是执行内存访问)。这通常用于复杂的地址计算,但不希望实际从内存中加载数据。

语法

lea destination, source

示例

; 假设有一个数组 array,其基地址为 array_base
; 我们想要计算 array[index] 的地址
mov index, 4       ; 索引为 4
lea eax, [array_base + index * 4] ; 假设每个元素是 4 字节的,计算 array[4] 的地址并存储到 eax
; 此时 eax 中存储的是 array[4] 的地址

注意:在上面的示例中,[array_base + index * 4] 实际上是一个地址计算表达式,而 lea 指令将其结果(即地址)存储到 eax 中,而不实际访问该地址处的内存。

7. jmp - Jump

jmp 指令用于无条件跳转到程序中的另一个位置执行。

语法

  • 直接跳转:jmp label
  • 间接跳转:jmp register(寄存器中存储的是跳转目标的地址)

示例

; 直接跳转
label1:; 一些代码
jmp label2
label2:; 跳转到这里执行; 间接跳转
mov eax, offset label3
jmp eax
label3:; 跳转到这里执行(通过寄存器跳转)

8. cmp - Compare

cmp 指令用于比较两个操作数,并根据比较结果设置条件码(如零标志ZF、符号标志SF、溢出标志OF等)。它不存储比较结果,但随后的条件跳转指令(如 jejne 等)会根据这些条件码来决定是否跳转。

语法

cmp operand1, operand2

示例

mov eax, 5
mov ebx, 10
cmp eax, ebx
; 此时 ZF=0(不相等),SF、OF 等可能根据具体值设置
; 接下来可以用 je、jne 等条件跳转指令

9. push - Push

push 指令用于将一个操作数(通常是寄存器或立即数)压入堆栈。堆栈是一种后进先出(LIFO)的数据结构,用于临时存储数据。

语法

push operand

示例

push eax    ; 将 eax 的值压入堆栈
push 10     ; 将立即数 10 压入堆栈

10. pop - Pop

pop 指令用于从堆栈中弹出一个值,并将其存储到指定的寄存器或内存中。

语法

pop destination

示例

; 假设之前已经用 push 指令压入了数据
pop eax     ; 将堆栈顶部的值弹出并存储到 eax
pop [var]   ; 假设 var 是一个内存地址,将堆栈顶部的值弹出并存储到该地址

在x86汇编语言中,xorlodsd(或更常见的lodsd的变体,如lodsd本身通常用于字符串操作,但可能指的是movsd或其他与加载双字相关的指令,因为lodsd不是标准x86指令集中的直接指令)和xchg是几种有用的指令,用于不同的目的。不过,为了回答,我将解释xorxchg,并假设你想要了解的是与lodsd相似的双字加载操作(比如movsd),因为lodsd不是标准指令。

11. xor - Exclusive OR

xor 指令执行两个操作数的按位异或(XOR)操作,并将结果存储在第一个操作数中。异或操作的特点是,当两个比较的位不相同时,结果为1;相同时,结果为0。此外,xor 指令经常用于清零寄存器,因为任何数与自身异或的结果都是0。

语法

xor destination, source

示例

; 使用 xor 清零寄存器
xor eax, eax    ; eax 的值变为 0; 使用 xor 翻转寄存器的位
mov eax, 0xFF   ; eax = 1111 1111b
xor eax, 0x55   ; eax = 0101 0101b (因为 1 ^ 1 = 0, 0 ^ 0 = 0, 1 ^ 0 = 1)

12. xchg - Exchange

xchg 指令交换两个操作数的值。这两个操作数可以是寄存器或内存地址。

语法

xchg operand1, operand2

示例

; 交换两个寄存器的值
mov eax, 10
mov ebx, 20
xchg eax, ebx  ; 现在 eax = 20, ebx = 10; 交换寄存器与内存中的值
mov [var], 30
xchg eax, [var] ; 假设 var 是一个内存地址,现在 eax = 30, [var] = 10

13. jz (Jump if Zero)

jz 指令用于条件跳转。当紧接在jz之前的指令(通常是某种算术或逻辑操作,如addsubcmp等)影响到的标志寄存器中的零标志(ZF)被设置为1时(即,结果为零时),jz会导致程序控制流跳转到指定的标签(label)处继续执行。如果ZF为0,则跳过跳转,继续顺序执行下一条指令。

语法:

jz label

这里,label是程序中定义的一个标签,用于指定跳转的目标位置。

示例:

section .text
global _start_start:mov eax, 1sub eax, 1jz zero_found    ; eax现在是0,ZF被设置,跳转到zero_found; 如果上面的jz没有执行,则会继续执行下面的指令; 这里可以添加一些未找到零时执行的代码; ...zero_found:; 如果执行到这里,说明找到了零(或者某个操作导致了ZF被设置); 这里可以添加找到零时执行的代码; ... 结束程序或继续其他操作

14. call

call 指令用于函数调用。它将当前指令的地址(即,紧接在call指令之后的那条指令的地址)压入堆栈,然后跳转到由call指令后紧跟的操作数指定的地址执行。这个操作数可以是标签、函数名、或是一个直接地址。函数执行完毕后,通常通过ret指令返回,ret会从堆栈中弹出之前保存的返回地址,并跳转到那个地址继续执行。

语法:

call label/function_name/direct_address

示例:

section .text
global _startprint_hello:; 假设这里有一段打印"Hello, World!"的代码; 注意:实际的系统调用依赖于操作系统和具体架构; 这里只是一个示意ret_start:; 调用print_hello函数call print_hello; 接下来可以是程序的其他部分; ...; 注意:在实际的Linux程序中,你需要通过系统调用来退出程序; 这里为了示例的简洁性省略了
关键字:shellcode汇编复习

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: