Assembly Crash Course(1)

简介: Assembly Crash Course(1)

前言

这个模块是关于汇编语言编程的,要求设置寄存器rdi的值为0x1337。在x86-64架构的Linux系统中,rdi是第一个参数寄存器。

为了将0x1337这个值放入rdi寄存器,你可以使用以下的汇编代码:

assembly
mov $0x1337, %rdi

这条指令将立即数0x1337移动到rdi寄存器中。

如果你需要将这条指令转换为字节码形式(即机器码),你可以使用任何支持x86-64汇编的汇编器,如GNU Assembler (GAS)。以下是如何使用GAS将上述汇编指令转换为字节码的步骤:

  1. 创建一个名为set_rdi.s的汇编源文件,其中包含以下内容:
assembly
section .text
global _start
_start:
    mov $0x1337, %rdi
    ; 添加退出代码,以便程序能够正常退出
    mov $60, %rax    ; 系统调用号 (sys_exit)
    xor %rdi, %rdi   ; 退出状态码 0
    syscall
  1. 使用GAS将汇编源文件编译为机器码:
bash
nasm -f elf64 set_rdi.s
  1. 链接生成的目标文件以创建可执行文件:
bash
ld -m elf_x86_64 -o set_rdi set_rdi.o

现在,set_rdi可执行文件包含了将0x1337设置到rdi寄存器的机器码。你可以使用objdump工具来查看这些机器码:

bash
objdump -d ./set_rdi

这将显示反汇编的输出,其中包含了mov $0x1337, %rdi指令的机器码表示。注意,实际的机器码可能会因为不同的系统和编译器选项而有所不同。

1. 寄存器赋值: level 1~level 2

from pwn import *
context.update(arch="amd64")
io = process("/challenge/run")
io.write(asm("""
    mov  rdi,0x1337   # Write your assembly code here
 """))
io.interactive()        #  print(io.readallS())  
mov  rax, 0x1337
mov  r12, 0xCAFED00D1337BEEF
mov  rsp, 0x31337

2. 加减乘除(模):level 3~level 6

add  rdi,0x331337
imul  rdi,rsi  # rdi = rdi*rsi ; imul 有符号乘法,mul无符号乘法;
#       单操作数 imul xxx / mul xxx ==> rax*xxx,放在rax,作用于有符号乘数结果可能有溢出
add  rdi,rdx       
mov  rax,rdi
# div 只有一个操作数。需要先把被除数放入rax寄存器,然后使用 div 除以 除数寄存器,商保存rax
rax,rdi 
div rsi 
#  rax = rdi/rsi  
xor rdx,rdx   # 先清空rdx内容
mov rax ,rdi    # 运算 rax➗rsi
div rsi
mov rax,rdx    #  div 运算余数放在 rdx寄存器

3. 通用数据寄存器高低位:level 7 ~ level 8

通用数据寄存器:rax,rbx,rcx,rdx

以rax寄存器为例:

MSB 【high】 LSB 【low】

±---------------------------------------+

| rax | 64 bit

±-------------------±------------------+

** | eax | 32 bit**

** ±--------±--------+**

** | ax | 16 bit**

** ±—±—+**

** | ah | al | 8 bit each**

** ±—±—+**

mov     ah, 0x42

仅使用 mov 指令完成模运算

mov rcx,rdi    
mov al,cl   # 注意mov前后要对等,mov rax,cl 会报错
mov rcx,rsi
mov bx,cx

4. 逻辑运算:level 9 ~ level 11

#   reg2的数据表示移动位数【这里可以是立即数,如:shl rdi,24】
shl reg1, reg2       <=>     Shift reg1 left by the amount in reg2
shr reg1, reg2       <=>     Shift reg1 right by the amount in reg2
rdi = | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
  Set rax to the value of B4
#  将 rdi 先左移 3*8=24位得到:
# | B4 | B3 | B2 | B1 | B0 | 0  | 0  | 0  |
# 然后右移 7*8 = 56 位得到:
#  | 0  | 0  | 0  | 0  | 0  | 0  | 0  | B4 |
#  最后赋值给 rax即可
shl rdi,24
shr rdi,56
mov rax ,rdi
and rdi,rsi     # 不使用 mov指令,实现:rax = rdi and rsi
xor rax,rax
or rax,rdi
Implement the following logic:
  if x is even then   # x 是 偶数,y = 1;反之 y=0
    y = 1
  else
    y = 0
where:
  x = rdi
  y = rax
and rdi,0x1    # 取 rdi最低位:0/1  (偶/奇)
xor rdi,1       # 反转 ----->  1/0
xor rax,rax   #  清空 rax
or rax,rdi    # 赋值 rax

5. 内存<–>寄存器操作 :level 12~level 14

In x86 we can access the thing at a memory location, called dereferencing, like so:
mov rax, [some_address]   <=>     Moves the thing at 'some_address' into rax
This also works with things in registers:
mov rax, [rdi] <=> Moves the thing stored at the address of what rdi holds to rax
This works the same for writing:
mov [rax], rdi     <=>     Moves rdi to the address of what rax holds.
So if rax was 0xdeadbeef, then rdi would get stored at the address 0xdeadbeef:
[0xdeadbeef] = rdi
Note: memory is linear, and in x86, it goes from 0 - 0xffffffffffffffff (yes, huge).
#取内存地址的值赋给rax寄存器:
mov rax,[0x404000]   #   mov     rax, qword ptr [0x404000]
# 将寄存器值写入内存地址:
 mov [0x404000],rax   #   mov     qword ptr [0x404000],rax
# 将指定地址内容赋值给 rax,接着该地址内容+0x1337
mov rax,[0x404000]
add rax,0x1337
mov [0x404000],rax
sub rax,0x1337
# [或者借助另外寄存器]:
mov rax,[0x404000]
mov rbx,rax
add rbx,0x1337
mov [0x404000],rbx

6. 内存操作:level 15~level 16

Recall the following:
  The breakdown of the names of memory sizes:
    Quad Word   = 8 Bytes = 64 bits
    Double Word = 4 bytes = 32 bits
    Word        = 2 bytes = 16 bits
    Byte        = 1 byte  = 8 bits
In x86_64, you can access each of these sizes when dereferencing an address, just like using
bigger or smaller register accesses:
  mov al, [address]        <=>        moves the least significant byte from address to rax
  mov ax, [address]        <=>        moves the least significant word from address to rax
  mov eax, [address]       <=>        moves the least significant double word from address to rax
  mov rax, [address]       <=>        moves the full quad word from address to rax
mov al, byte [0x403fff]   #  mov     al, byte ptr [0x404000]  
# 如果地址前面加上 byte等,汇编代码地址需要-1,执行时候会自动向后加一位开始赋值。
#  常规:
mov al,  [0x404000]
mov bx ,  [0x404000]
mov ecx ,[0x404000]
mov rdx , [0x404000]
# 加上byte...之后地址需要依此变形
mov al, byte [0x403fff]
mov bx , word [0x403ffe]
mov ecx ,[0x404000]
mov rdx , [0x404000]
mov al, byte [0x403fff]
mov bx , word [0x403ffe]
mov ecx ,dword [0x403ffc]
mov rdx ,qword [0x403ff8]
#  结果
---------------- CODE ----------------
0x400000:       mov     al, byte ptr [0x404000]
0x400007:       mov     bx, word ptr [0x404000]
0x40000f:       mov     ecx, dword ptr [0x404000]
0x400016:       mov     rdx, qword ptr [0x404000]
--------------------------------------

7. 寄存器地址赋值:level 17~level 18

Set [rdi] = 0xdeadbeef00001337
  Set [rsi] = 0xc0ffee0000
mov rax,0xdeadbeef00001337
mov [rdi],rax
mov rax, 0xc0ffee0000
mov [rsi],rax
[0x404190] = 0xd5729
  [0x404198] = 0xe37d2
  rdi = 0x404190    #  task:取出 rdi 与 rdi+8 执向地址数据,求和存入 rsi 指向地址
  rsi = 0x4047a8
    mov rax, [rdi+8]
    mov rbx,[rdi]
    add rbx,rax
    mov [rsi],rbx

8. 栈调用:level 19~level 21

pop rax
sub rax,rdi
push rax
# 或者 
mov rax,[rsp]
sub rax,rdi
mov [rsp],rax
push rdi
    push rsi
    pop rdi
    pop rsi
mov rax, [rsp]
    add rax,[rsp+8]
    add rax,[rsp+16]
    add rax,[rsp+24]
    mov rdi,4
    div rdi
    push rax
---------------- CODE ----------------
0x400000:       mov     rax, qword ptr [rsp]
0x400004:       add     rax, qword ptr [rsp + 8]
0x400009:       add     rax, qword ptr [rsp + 0x10]
0x40000e:       add     rax, qword ptr [rsp + 0x18]
0x400013:       mov     rdi, 4
0x40001a:       div     rdi
0x40001d:       push    rax
--------------------------------------
#  下面汇编不能得到正确结果,可能栈没有对齐
    mov rax,[rsp]
    mov rbx,[rsp+8]
    mov rcx,[rsp+16]
    mov rdx,[rsp+24]
    mov rdi,4
    add rax,rbx
    add rax,rcx
    add rax,rdx
    div rdi
    push rax
---------------- CODE ----------------
0x400000:       mov     rax, qword ptr [rsp]
0x400004:       mov     rbx, qword ptr [rsp + 8]
0x400009:       mov     rcx, qword ptr [rsp + 0x10]
0x40000e:       mov     rdx, qword ptr [rsp + 0x18]
0x400013:       mov     rdi, 4
0x40001a:       add     rax, rbx
0x40001d:       add     rax, rcx
0x400020:       add     rax, rdx
0x400023:       div     rdi
0x400026:       push    rax
--------------------------------------

然而,还有另一种更有趣的除法方法。

除法使用shr

我们知道,字节中的每一位都是某个数字的 2 次方。

±--------------------------------------------------------------+

| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |

| (2^7) | (2^6) | (2^5) | (2^4) | (2^3) | (2^2) | (2^1) | (2^0) |

±--------------------------------------------------------------+

上面字节的值是 1x(2^7),等于 128。

如果我们向右移动 2 位,我们会得到以下结果。

±--------------------------------------------------------------+

| 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |

| (2^7) | (2^6) | (2^5) | (2^4) | (2^3) | (2^2) | (2^1) | (2^0) |

±--------------------------------------------------------------+

字节的值现在是 1x(2^5),即 32。因此,我们基本上在不使用指令的情况下将数字除以 4。div

现在,我们只需要对存储的总和做同样的事情来找到平均值。rax

shr rax, 2

接下来,我们必须使用指令将平均值复制到堆栈上。push

push rax

堆栈将如下所示:

±------------------------+

RSP+0x20 | Quad Word A | <------ rbp

±------------------------+

RSP+0x18 | Quad Word B |

±------------------------+

RSP+0x10 | Quad Word C |

±------------------------+

RSP+0x08 | Quad Word D |

±------------------------+

RSP | Average | <------ rsp

±------------------------+

目录
相关文章
|
2月前
|
缓存
crash命令 —— files
crash命令 —— files
|
5月前
|
前端开发 rax 网络安全
Assembly Crash Course(2)
Assembly Crash Course(2)
40 6
|
Java Android开发
Eclipse中项目报Target runtime com.genuitec.runtime.generic.jee60 is not defined异常的解决方法
Eclipse中项目报Target runtime com.genuitec.runtime.generic.jee60 is not defined异常的解决
553 0
Eclipse中项目报Target runtime com.genuitec.runtime.generic.jee60 is not defined异常的解决方法
|
Windows
用WinDbg分析Debug Diagnostic Tool生成的Userdump文件
1、下载WinDbg(Debugging Tools for Windows):http://www.microsoft.com/whdc/devtools/debugging/default.mspx 2、安装WinDbg 3、运行WinDbg 4、配置Symbol文件路径: File>Symbol File Path,输入:SRV*c:\websymbols*http://msdl.
1065 0