0%

异构pwn学习记录

异构pwn学习记录

MIPS

Mips寄存器

MIPS32寄存器分为两类:通用寄存器(GPR)和特殊寄存器。 通用寄存器:MIPS体系结构中有32个通用寄存器,汇编程序中用$0~$31表示。也可以用名称表示,如$sp、$t1、$ra等。

编号 寄存器名称 描述
$0 $zero 第0号寄存器,其值始终为0。
$1 $at 保留寄存器
$2-$3 $v0-$v1 values,保存表达式或函数返回结果
$4-$7 $a0-$a3 argument,作为函数的前四个参数
$8-$15 $t0-$t7 temporaries,供汇编程序使用的临时寄存器
$16-$23 $s0-$s7 saved values,子函数使用时需先保存原寄存器的值
$24-$25 $t8-$t9 temporaries,供汇编程序使用的临时寄存器,补充$t0-$t7。
$26-$27 $k0-$k1 保留,中断处理函数使用
$28 $gp global pointer,全局指针
$29 $sp stack pointer,堆栈指针,指向堆栈的栈顶
$30 $fp frame pointer,保存栈指针
$31 $ra return address,返回地址

特殊寄存器:有3个特殊寄存器:PC(程序计数器)、HI(乘除结果高位寄存器)和LO(乘除结果低位寄存器)。在乘法时,HI保存高32位,LO保存低32位。除法时HI保存余数,LO保存商。

MIPS常用指令集

lb/lh/lw: 从存储器中读取一个byte/half word/word的数据到寄存器中.如lb $1, 0($2) ($1=$2+0)

li:立即数的值给寄存器 li $1,0x1

lui:把一个16位的立即数填入到寄存器的高16位,低16位补零。

sb/sh/sw: 把一个byte/half word/word的数据从寄存器存储到存储器中.如 sb $1, 0($2) ($2+0=$1)

add/addu:把两个定点寄存器的内容相加add $1,$2,$3($1=$2+$3);u为不带符号加。

addi/addiu:把一个寄存器的内容加上一个立即数add $1,$2,#3($1=$2+3);u为不带符号加。

sub/subu:把两个定点寄存器的内容相减。

div/divu:两个定点寄存器的内容相除。

mul/mulu:两个定点寄存器的内容相乘。

**and/andi:**与运算,两个寄存器中的内容相与and $1,$2,$3($1=$2 & $3);i为立即数。

or/ori:或运算。

xor/xori:异或运算。

beq/beqz/benz/bne:条件转移eq相等,z零,ne不等。

bal:跳转指令

j/jr/jal/jalr:j直接跳转;jr使用寄存器跳转;

sll/srl:逻辑左移/右移sll $1,$2,#2。

slt/slti/sltui:如果$2的值小于$3,那么设置$1的值为1,否则设置$1的值为0。slt $1,$2,$3。

mov/movz/movn:复制,n为负,z为零。mov $1,$2; movz $1,$2,$3($3为零则复制$2到$1)。

trap:根据地址向量转入管态。

eret:从异常中返回到用户态。

Mips函数调用过程

  • mips架构和x86架构中,栈的增长方向相同,都是从高地址向低地址增长,但是没有栈底指针,所以调用一个函数是,需要将当前栈向低地址处移动n比特这个大小为n比特的空间就是此函数的栈桢存储区域;

  • mips架构中有叶子函数和非叶子函数的区别,叶子函数就是此函数自身不再调用别的函数,非叶子函数就是此函数自身调用别的函数。如果函数A调用函数B,调用者函数会在自己的栈顶预留一部分空间来保存被调用者(函数B)的参数,称之为参数调用空间;

  • 函数调用过程中,父函数调用子函数,复制当前$PC的值到$RA寄存器,然后跳转到子函数执行。到子函数是,子函数如果为非叶子函数,则在函数入口子函数的返回地址会先存入堆栈。

  • 参数传递方式,前四个参数通过$a0-$a3来传递,多于的参数会放入调用参数空间(参数会被保存在栈上),可以类比x86_64参数传递规则来进行记忆。

1
2
3
4
5
6
7
8
9
10
11
12
#进入函数
addiu $sp,-0x28
sw $ra,0x28+var_4($sp)
sw $fp,0x28+var_8($sp)
mov $fp,$sp
#返回函数
move $sp,$fp
lw $ra,0x28+var_4($sp)
lw $fp,0x28+var_8($sp)
addiu $sp,0x28
jr $ra
nop

Arm

Arm寄存器

ARM Description x86
R0 General Purpose(可被用作累加器、第一个参数) EAX
R1-R5 General Purpose(第2、3、4个参数) EBX,ECX,EDX,ESI,EDI
R6-R10 General Purpose(R7存储系统调用号) -
R11(FP) Frame Pointer EBP
R12 Intra Procedural Call -
R13(SP) Stack Pointer ESP
R14(LR) Link Register -
R15(PC) <Program Counter/Instruction Pointer> EIP

Arm常用指令集

指令 描述 指令 描述
MOV 移动数据 EOR 按位异或
MVN 移动并取反 LDR 加载
ADD STR 存储
SUB LDM 加载多个
MUL STM 存储多个
LSL 逻辑左移 PUSH 入栈
LSR 逻辑右移 POP 出栈
ASR 算数右移 B 跳转
ROR 右旋 BL link跳转
CMP 比较 BX 分支跳转
AND 按位与 BLX link分支跳转
ORR 按位或 SWI/SVC 系统调用

image-20220119103930687

CMP R0, R1 ; R0与R1比较,做R0-R1的操作

ADDHI R0, R0, #1 ;若R0 > R1, 则R0 = R0 + 1

ADDLS R1, R1, #1 ; 若R0 <= R1, 则R1 = R1 + 1

Aarch64(Arm64)

Aarch64(Arm64)寄存器

ARM64 Descript
X0~X7 传递参数,返回值用X0表示
X8 程序返回地址
X9~X15 临时寄存器,使用时不需要保存
X16~X17 子程序内部调用寄存器
X18 平台寄存器
X19~X28 临时寄存器,使用时必须保存
X29 帧指针寄存器,使用时需要保存()
X30 链接寄存器LR,保存跳转返回信息地址
X31 堆栈指针寄存器SP或零寄存器 (esp)
XZR 64bit Zero寄存器,读出的数据全为0
WZR 32bit Zero寄存器的32bit形式

子程序调用时必须要保存的寄存器:X19~X29和SP(X31)

不需要保存的寄存器:X0X7,X9X15

只用低 32bit的w0-w30

Arm64常用指令集

  • MOV x1,x0; 将寄存器x0的值传送到寄存器x1

  • ADD x0,x1,x2; 寄存器x1和x2的值相加后传送到x0

  • SUB x0,x1,x2; 寄存器x1和x2的值相减后传送到x0

  • AND x0,x0,#0xF; x0的值与0xF相位与后的值传送到x0

  • ORR x0,x0,#9; x0的值与9相位或后的值传送到x0

  • EOR x0,x0,#0xF; x0的值与0xF相异或后的值传送到x0

  • LDR x5,[x6,#0x8]; x6寄存器加0x8地址的内容传送到x5

  • STR x0, [SP, #0x8]; x0寄存器的数据传送到SP+0x8地址值指向的存储空间

  • STP x29, x30, [sp, #0x10]; 入栈指令

  • LDP x29, x30, [sp, #0x10]; 出栈指令

  • CBZ x19, 0x10; 比较,如果结果为零(Zero)就转移(只能跳到后面的指令)

  • CBNZ x19, 0x10; 比较,如果结果非零(Non Zero)就转移(只能跳到后面的指令)

  • B/BL ; 绝对跳转#imm,返回地址保存到LR(x30)

  • b ffff000008283b80

  • bl ffff000008dc566c

MOV 指令只能用于寄存器之间传值,寄存器和内存之间传值通过 LDR 和 STR.

image-20220119104702625

example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
000000000003a150 <example_test>:
3a150: a9be7bfd stp x29, x30, [sp,#-32]! //把x29 x30 的值存到sp-32的地址后,sp=sp-32
3a154: 910003fd mov x29, sp //把 x29的值放在sp中
3a158: a90153f3 stp x19, x20, [sp,#16] //把x19 x20 的值存到sp+16的地址中后sp=sp+16
3a15c: 2a0003f3 mov w19, w0 //把w19 的值存到w0 中
3a160: aa1e03e0 mov x0, x30 //把x0 的值放在x30
3a164: aa0103f4 mov x20, x1 //把x20的值放在x1
3a168: 94000000 bl 0 <_mcount> //跳转到地址0,这里还不太清楚,我理解是需要加载ko后,跳转到某些符号对应的地址上
3a16c: 6b1f027f cmp w19, wzr //比较w19 和 0
3a170: 540000ed b.le 3a18c <example_test+0x3c> //如果小于 就跳转到<example_test+0x3c>这个地址
3a174: 52800020 mov w0, #0x1 // 写w0 为1
3a178: b9000280 str w0, [x20] //w0的值写到x20内
3a17c: 52800000 mov w0, #0x0 // w0 清零
3a180: a94153f3 ldp x19, x20, [sp,#16] // sp+16 地址的值分别放回x19 x20
3a184: a8c27bfd ldp x29, x30, [sp],#32 //sp地址取的值分别放回x29 x30后sp=sp+32
3a188: d65f03c0 ret //返回
3a18c: 52800200 mov w0, #0x10 //w0 的值写成0x10
3a190: b9000280 str w0, [x20] //w0 的值存到 x20
3a194: 52800000 mov w0, #0x0 // w0 清零
3a198: a94153f3 ldp x19, x20, [sp,#16] // sp+16 地址的值分别放回x19 x20
3a19c: a8c27bfd ldp x29, x30, [sp],#32 //sp地址取的值分别放回x29 x30后sp=sp+32
3a1a0: d65f03c0 ret //返回
3a1a4: d503201f nop //空操作

Aarch64函数调用过程

1
2
3
4
5
6
#进入函数
0x4009a8 stp x29, x30, [sp, #-0x20]!#将x29、x30的值存入sp-0x20地址中
0x4009ac mov x29, sp
#返回函数
0x400a04 ldp x29, x30, [sp], #0x20 #将sp的内容放入x29、x30后,sp=sp-0x20
0x400a08 ret

例题

异构pwn的栈题与x86架构的题差别挺大,主要是理解其函数调用的过程以及寄存器的作用。例题都是两个月前做的,现在也忘的差不多了,准备这里是放2022的hws的题,结果他没有出异构题,等到下次遇见好的题再放吧。