异构pwn学习记录
发表于:2022-01-19 |
字数统计: 3.4k | 阅读时长: 13分钟 | 阅读量:

异构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

move:将寄存器里的值赋值给寄存器

la:将地址传递给寄存器

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地址值指向的存储空间
  • STR x0, [x1], #8 将x0中的字数据写入以x1为地址的存储器中,并将新地址x1+8写入x1
  • STP x29, x30, [sp, #0x10]; 入栈指令
  • LDP x29, x30, [sp, #0x10]; 出栈指令,将sp-0x10 前8bytes给x29,后8bytes给x30
  • CBZ x19, 0x10; 比较,如果结果为零(Zero)就转移(只能跳到后面的指令)
  • CBNZ x19, 0x10; 比较,如果x19非零(Non Zero)就转移PC+0x10(只能跳到后面的指令)
  • B/BL ; 绝对跳转#imm,返回地址保存到LR(x30)
  • B.NE
  • 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地址中,同时sp=sp-0x20
0x4009ac mov x29, sp
#返回函数
0x400a04 ldp x29, x30, [sp], #0x20 #将sp的内容放入x29、x30后,sp=sp-0x20
0x400a08 ret

PowerPC

PowerPC寄存器

  • r0   在函数開始(function prologs)时使用。

  • r1   堆栈指针,相当于ia32架构中的esp寄存器,idapro把这个寄存器反汇编标识为sp。

  • r2   内容表(toc)指针,idapro把这个寄存器反汇编标识为rtoc。系统调用时。它包括系统调用号(这个好像跟系统有关吧)。

  • r3   作为第一个參数和返回值。

  • r4-r10 函数或系统调用開始的參数。

  • r11   用在指针的调用和当作一些语言的环境指针。

  • r12   它用在异常处理和glink(动态连接器)代码。

  • r13   保留作为系统线程ID。

  • r14-r31 作为本地变量。非易失性。

  • lr   链接寄存器,它用来存放函数调用结束处的返回地址。

  • ctr   计数寄存器,它用来当作循环计数器,会随特定转移操作而递减。

  • xer   定点异常寄存器。存放整数运算操作的进位以及溢出信息。

  • msr   机器状态寄存器,用来配置微处理器的设定。

  • cr   条件寄存器。它分成8个4位字段,cr0-cr7。它反映了某个算法操作的结果而且提供条件分支的机制。

PowerPC指令

名称 助记符 语法格式
字节存储(偏移地址寻址) stb rS, d(rA)
字节存储(寄存器寻址) stbx rS, rA, rB
记录有效地址的字节存储(偏移地址寻址) stbu rS, d(rA)
记录有效地址的字节存储(寄存器寻址) stbux rS, rA, rB
半字存储(偏移地址寻址) sth rS, d(rA)
半字存储(寄存器寻址) sthx rS, rA, rB
记录有效地址的半字存储(偏移地址寻址) sthu rS, d(rA)
记录有效地址的半字存储(寄存器寻址) sthux rS, rA, rB
字存储(偏移地址寻址) stw rS, d(rA)
字存储(寄存器寻址) stwx rS, rA, rB
记录有效地址的字存储(偏移地址寻址) stwu rS, d(rA)
记录有效地址的字存储(寄存器寻址) stwux rS, rA, rB
名称 助记符 语法格式
高位清零载入字节指令(偏移地址寻址) lbz rD, d(rA)
高位清零的载入字节指令(寄存器寻址) lbzx rD, rA, rB
高位清零的载入字节并记录有效地址指令(偏移地址寻址) lbzu rD, d(rA)
高位清零的载入字节并记录有效地址指令(寄存器寻址) lbzux rD, rA, rB
高位清零的载入半字指令(偏移地址寻址) lhz rD, d(rA)
高位清零的载入半字指令(寄存器寻址) lhzx rD, rA, rB
高位清零的载入半字并记录有效地址指令(偏移地址寻址) lhzu rD, d(rA)
高位清零的载入半字并记录有效地址指令(寄存器寻址) lhzux rD, rA, rB
载入半字指令(偏移地址寻址) lha rD, d(rA)
载入半字指令(寄存器寻址) lhax rD, rA, rB
载入半字并记录有效地址指令(偏移地址寻址) lhau rD, d(rA)
载入半字并记录有效地址指令(寄存器寻址) lhaux rD, rA, rB
载入字指令(偏移地址寻址) lwz rD, d(rA)
载入字指令(寄存器寻址) lwzx rD, rA, rB
载入字并记录有效地址指令(偏移地址寻址) lwzu rD, d(rA)
载入字并记录有效地址指令(寄存器寻址) lwzux rD, rA, rB
名称 助记符 语法格式
多字载入 lmw rD,d(rA)
多字存储 stmw rS,d(rA)
名称 助记符 语法格式
无条件转移 b( ba bl bla) target_addr
条件转移 bc( bca bcl bcla) BO,BI,target_addr
条件转移(转移目标地址由LR指出) bclr(bclrl) BO,BI
条件转移(转移目标地址由CTR指出) bcctr(bcctrl) BO,BI
名称 助记符 语法格式
读取机器状态寄存器 mfmsr rD
写入机器状态寄存器 mtmsr rS
读取特殊功能寄存器 mfspr rD, SPR
写入特殊功能寄存器 mtspr SPR, rS
读取段寄存器 mfsr rD, SR
写入段寄存器 mtsr SR, rS
间接读取段寄存器 mfsrin rD, rB
间接写入段寄存器 mtsrin rS, rB
读取时基寄存器 mftb rD, TBR

例题

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

上一篇:
年终总结-2022
下一篇:
webpwn初探