pwn的学习8 leg

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35396598/article/details/85640808

首先看 。

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 [email protected] -p2222 (pw:guest)

那就首先下载leg.c   

#include <stdio.h>
#include <fcntl.h>
int key1(){
	asm("mov r3, pc\n");
}
int key2(){
	asm(
	"push	{r6}\n"
	"add	r6, pc, $1\n"
	"bx	r6\n"
	".code   16\n"
	"mov	r3, pc\n"
	"add	r3, $0x4\n"
	"push	{r3}\n"
	"pop	{pc}\n"
	".code	32\n"
	"pop	{r6}\n"
	);
}
int key3(){
	asm("mov r3, lr\n");
}
int main(){
	int key=0;
	printf("Daddy has very strong arm! : ");
	scanf("%d", &key);
	if( (key1()+key2()+key3()) == key ){
		printf("Congratz!\n");
		int fd = open("flag", O_RDONLY);
		char buf[100];
		int r = read(fd, buf, 100);
		write(0, buf, r);
	}
	else{
		printf("I have strong leg :P\n");
	}
	return 0;
}

首先看

代码啥意思。。。

int key=0;  #这里定义int
    printf("Daddy has very strong arm! : ");
    scanf("%d", &key); #输入key 值

if( (key1()+key2()+key3()) == key ){
        printf("Congratz!\n"); #如果  函数 key 1,2,3 的和为key值。则读取flag
        int fd = open("flag", O_RDONLY);
        char buf[100];
        int r = read(fd, buf, 100);
        write(0, buf, r);
    }
    else{
        printf("I have strong leg :P\n");
    }
    return 0;

也就说,这道题重点是考3个函数的理解

首先看 函数1

int key1(){
    asm("mov r3, pc\n");
}

没啥作用啊。那就只有去看它给的汇编代码了。好难,想放弃

(gdb) disass key1
Dump of assembler code for function key1:
   0x00008cd4 <+0>:	push	{r11}		; (str r11, [sp, #-4]!) #压栈
   0x00008cd8 <+4>:	add	r11, sp, #0  #记录返回点
   0x00008cdc <+8>:	mov	r3, pc   # r3  = pc
   0x00008ce0 <+12>:	mov	r0, r3  # r0=  r3
   0x00008ce4 <+16>:	sub	sp, r11, #0   #弹栈
   0x00008ce8 <+20>:	pop	{r11}		; (ldr r11, [sp], #4)   #弹出
   0x00008cec <+24>:	bx	lr  #返回
End of assembler dump.

也就是说,返回的参数是 r0  =r3=pc  =   0x00008cdc +8 =36068

然后是 key2()

这里我看不懂了。。所以场外求助百度。。地址 https://blog.csdn.net/lee_ham/article/details/78398551

int key2(){
	asm(
	"push	{r6}\n"
	"add	r6, pc, $1\n"
	"bx	r6\n"
	".code   16\n"
	"mov	r3, pc\n"
	"add	r3, $0x4\n"
	"push	{r3}\n"
	"pop	{pc}\n"
	".code	32\n"
	"pop	{r6}\n"
	);
}
(gdb) disass key2
Dump of assembler code for function key2:
   0x00008cf0 <+0>:	push	{r11}		; (str r11, [sp, #-4]!)
   0x00008cf4 <+4>:	add	r11, sp, #0
   0x00008cf8 <+8>:	push	{r6}		; (str r6, [sp, #-4]!)
   0x00008cfc <+12>:	add	r6, pc, #1  
###pc+8+1的值赋给r6,即r6=0x00008cfc+8+1;
   0x00008d00 <+16>:	bx	r6
###有bx指令,这条指令表示r6是跳转的目的地址,并且根据地址的最低位确定是否状态切换。如果末尾是1则切###换到thumb状态,否则保留在asm状态;当前状态下是应该切换到thumb状态
   0x00008d04 <+20>:	mov	r3, pc
### r3=pc
   0x00008d06 <+22>:	adds	r3, #4
###  r3=r3+4  ==>  r3=0x00008d04+4+4   
0x00008d08 <+24>:	push	{r3}
   0x00008d0a <+26>:	pop	{pc}
   0x00008d0c <+28>:	pop	{r6}		; (ldr r6, [sp], #4)
   0x00008d10 <+32>:	mov	r0, r3 #r0=r3
###  PS  r0 都是最后的返回值  
   0x00008d14 <+36>:	sub	sp, r11, #0
   0x00008d18 <+40>:	pop	{r11}		; (ldr r11, [sp], #4)
   0x00008d1c <+44>:	bx	lr
End of assembler dump.

也就是说 key2()=0x00008d04+4+4=36108

key3 ()

(gdb) disass key3
Dump of assembler code for function key3:
   0x00008d20 <+0>:	push	{r11}		; (str r11, [sp, #-4]!)
   0x00008d24 <+4>:	add	r11, sp, #0
   0x00008d28 <+8>:	mov	r3, lr
   0x00008d2c <+12>:	mov	r0, r3
   0x00008d30 <+16>:	sub	sp, r11, #0
   0x00008d34 <+20>:	pop	{r11}		; (ldr r11, [sp], #4)
   0x00008d38 <+24>:	bx	lr
End of assembler dump.

lr(link register)的值赋值给r3,r0;

而lr寄存器中存储的是子函数的返回地址,那么应该在main()函数的反汇编代码中找key3()函数返回后下一条指令地址:

0x00008d7c <+64>:    bl    0x8d20 <key3>

也就说  key3()=0x00008d7c <+64>=0x00008d80=36224

加起来

36224+36108+36068=108400

成功

emmm  我记住了。。Dump中  r0是返回参数的寄存器

猜你喜欢

转载自blog.csdn.net/qq_35396598/article/details/85640808
今日推荐