Question7:leg

Daddy told me I should study arm.
But I prefer to study my leg!

Download : http://pwnable.kr/bin/leg.c
Download : http://pwnable.kr/bin/leg.asm

ssh leg@pwnable.kr -p2222 (pw:guest)


Writeup:

题目给了一份源码一份反汇编代码

C

asm

第一次看arm汇编,去查了下资料。
首先确定pc寄存器和lr寄存器是什么
pc寄存器(r15)是程序计数器,它很像X86里的ip寄存器,保存下一条指令的地址,严格来讲,r15(pc)总是指向“正在取指”的指令。这里下面会做说明。
lr寄存器(r14)是连接寄存器,它保存函数调用过程中的返回地址。也就是说函数返回的时候程序就是跳转到lr存的地址。
另外,arm用r0来保存函数返回的值。

由此我们来分析以上代码,key1返回pc的值,key2返回pc + 4,key3返回lr的值。

因为对pc的理解不完全正确,我当时在这里卡了很久,后来翻了ET的博客终于发现pc存的其实不是接下来要执行的地址。

PC 代表程序计数器,流水线使用三个阶段,因此指令分为三个阶段执行:1.取指(从存储器装载一条指令);2.译码(识别将要被执行的指令);3.执行(处理 指令并将结果写回寄存器)。而R15(PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或正在“译码”的指令。一般来说,人们习惯性约定 将“正在执行的指令作为参考点”,称之为当前第一条指令,因此PC总是指向第三条指令。当ARM状态时,每条指令为4字节长,所以PC始终指向该指令地址 加8字节的地址,即:PC值=当前程序执行位置+8;
ARM指令是三级流水线,取指,译指,执行时同时执行的,现在PC指向的是正在取指的地址,那么cpu正在译指的指令地址是PC-4(假设在ARM状态 下,一个指令占4个字节),cpu正在执行的指令地址是PC-8,也就是说PC所指向的地址和现在所执行的指令地址相差8。

这里再注意一下key2中的.code这样的伪指令。
.code 16表示下面的代码被声明为thumb指令集编译
.code 32表示下面的代码被声明为arm指令集编译
thumb指令集是16位而arm指令集是32位,所以在这里pc的值也要相应的修改。

综上我们可以计算出
key1(pc) = 0x00008cdc+0x8=0x00008ce4

key2(pc + 4) = 0x00008d04+0x4+0x4=0x00008d0c

key3(lr) = 0x00008d80

相加得到108400