pwnable.kr-leg WP

本文深入解析了一道涉及ARM汇编语言的编程谜题,详细分析了key1、key2和key3函数的汇编代码,揭示了ARM处理器的流水线机制如何影响程序计数器(PC)的值,最终解密了正确的key值。

首先看一下源码

#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;
}

这个main函数的逻辑比较清晰明了,输入一个key值,如果key1()+key2()+key3()) == key就能获得flag。但是key1、key2、key3的值都是用汇编代码写的,而且是ARM汇编(通过leg.asm文件发现里面寄存器都是表示成r0什么的) 。X86采用eax作为返回值,ARM使用r0作为返回值。
首先来看key1

(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
   0x00008ce0 <+12>:	mov	r0, r3
   0x00008ce4 <+16>:	sub	sp, r11, #0
   0x00008ce8 <+20>:	pop	{r11}		; (ldr r11, [sp], #4)
   0x00008cec <+24>:	bx	lr

和返回值有关的是下面这两句

   0x00008cdc <+8>:	mov	r3, pc
   0x00008ce0 <+12>:	mov	r0, r3   

由于ARM采用了流水线机制,当正确读取了PC的值时,该值为当前指令地址加8个字节,也就是key1 = 0x00008cdc + 0x8

在ARM中,程序计数器R15又被记作PC
ARM7系列处理器中每条指令分取指(IF)、译码(ID)、执行(EX)三个阶段,分别在不同的功能部件上依次独立完成。取指部件完成从存储器装载一条指令,通过译码部件产生下一周期数据路径需要的控制信号,完成寄存器的解码,再送到执行单元完成寄存器的读取、ALU运算及运算结果的写回,需要访问存储器的指令完成存储器的访问。
流水线上虽然一条指令仍需3个时钟周期来完成,但通过多个部件并行,使得处理器的吞吐率约为每个周期一条指令,提高了流式指令的处理速度

下面通过两个图来说明流水线机制,第一个图为非流水时空图,第二个图为流水时空图

非流水线时空图
流水线时空图

可以看到,在非流水机制中,6个机器时钟周期执行了2条指令。流水机制中6个时间周期执行了4条指令。PC总是指向“正在取指”的指令,从图中可以看到,执行指令1的时候,正在对指令3进行取址,所以,PC值 = 当前程序执行位置 + 8

再来看一下key2

(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
   0x00008d00 <+16>:	bx	r6
   0x00008d04 <+20>:	mov	r3, pc
   0x00008d06 <+22>:	adds	r3, #4
   0x00008d08 <+24>:	push	{r3}
   0x00008d0a <+26>:	pop	{pc}
   0x00008d0c <+28>:	pop	{r6}		; (ldr r6, [sp], #4)
   0x00008d10 <+32>:	mov	r0, r3
   0x00008d14 <+36>:	sub	sp, r11, #0
   0x00008d18 <+40>:	pop	{r11}		; (ldr r11, [sp], #4)
   0x00008d1c <+44>:	bx	lr
End of assembler dump.

BX 指令跳转到指令中指定的目标地址。寄存器中为跳转的目标地址,当寄存器的bit[0]0时,目标地址处的指令为ARM指令;当寄存器的bit[0]1时,目标地址处的指令为Thumb指令,每条指令2byte,所以PC值 = 当前程序执行位置 + 4
0x00008cfc <+12>: add r6, pc, #1 这一行执行r6 = 0x00008d04 + 0x1 = 0x00008d05
0x00008d00 <+16>: bx r6 从而bx r6就跳转thumb模式下。
0x00008d04 <+20>: mov r3, pc这一行执行r3 = 0x00008d04 + 0x4
0x00008d06 <+22>: adds r3, #4 这一行执行r3 = r3 + 0x4 = 0x00008d04 + 0x4 + 0x4 = 0x00008d0c
所以返回值r0(r0的值等于r3的值,0x00008d10 <+32>: mov r0, r3)
所以key2=0x00008d04 + 0x4 + 0x4
最后看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.

0x00008d2c <+12>: mov r0, r3这一行将r3的值给r0,再往上找,0x00008d28 <+8>: mov r3, lr这一行将lr的值给r3。
寄存器R14又被称为连接寄存器(Link Register, LR),在ARM体系中具有下面两种特殊作用:
(1)存放当前子程序的返回地址。
(2)当异常发生时,LR中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行。
这里应该是子程序的返回地址,去main函数中找调用key3函数的地方

   0x00008d7c <+64>:	bl	0x8d20 <key3>
   0x00008d80 <+68>:	mov	r3, r0

在ARM体系中,B和BL指令为跳转指令,二者的不同之处在于,B指令仅仅执行跳转操作;BL指令同时还将下条指令的地址保存到LR寄存器中。所以key3的值为0x00008d80
最后可以得到

key1 = 0x00008cdc + 0x8
key2 = 0x00008d04 + 0x4 + 0x4
key3 = 0x00008d80
key = key1 + key2 + key3
key = 108400

这道题主要是考ARM汇编相关的知识,如果学过这方面的知识,那么这道题非常简单,我对这方面不是很熟,如果有什么不对的地方,还请指出来。

<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hello Kitty</title> <style> body { margin: 0; padding: 50px; background: #c8e6c9; display: flex; justify-content: center; align-items: center; min-height: 100vh; } .container { position: relative; width: 300px; height: 400px; } .hello-kitty { cursor: pointer; transition: transform 0.3s ease; } .hello-kitty:hover { transform: scale(1.05); } /* 头部 */ .head { position: absolute; width: 240px; height: 180px; background: white; border: 4px solid #000; border-radius: 50% 50% 38% 38%; top: 20px; left: 50px; } /* 耳朵 */ .ear { position: absolute; width: 70px; height: 80px; background: white; border: 4px solid #000; z-index: -1; } .ear.left { top: -30px; left: 18px; border-radius: 30% 90% 30% 80%; transform: rotate(-15deg); } .ear.right { top: -30px; right: 18px; border-radius: 90% 30% 80% 30%; transform: rotate(15deg); } /* 蝴蝶结 */ .bow { position: absolute; top: 10px; right: 30px; z-index: 10; } .bow-center { width: 30px; height: 30px; background: #e05555; border: 3px solid #000; border-radius: 50%; position: relative; z-index: 2; } .bow-left, .bow-right { position: absolute; width: 50px; height: 45px; background: #e05555; border: 3px solid #000; border-radius: 50%; top: -8px; } .bow-left { left: -45px; } .bow-right { right: -45px; } /* 眼睛 */ .eye { position: absolute; width: 18px; height: 24px; background: #000; border-radius: 50%; top: 90px; } .eye.left { left: 60px; } .eye.right { right: 60px; } /* 鼻子 */ .nose { position: absolute; width: 22px; height: 12px; background: #ffd54f; border: 4px solid #000; border-radius: 80% 80% 70% 70%; top: 125px; left: 50%; transform: translateX(-50%); } /* 嘴巴 - 默认状态 */ .mouth { position: absolute; top: 130px; left: 50%; transform: translateX(-50%); transition: all 0.3s ease; } /* 悬停时的微笑 */ .hello-kitty:hover .mouth { top: 130px; } .hello-kitty:hover .mouth-line { display: none; } .hello-kitty:hover .mouth::before, .hello-kitty:hover .mouth::after { content: ''; position: absolute; width: 20px; height: 10px; border: 2px solid #000; border-top: none; border-radius: 0 0 20px 20px; } .hello-kitty:hover .mouth::before { left: -22px; top: -5px; } .hello-kitty:hover .mouth::after { right: -22px; top: -5px; } /* 胡须 */ .whisker { position: absolute; height: 4px; background: #000; top: 105px; } .whisker.left-top { width: 50px; left: -10px; transform: rotate(10deg); } .whisker.left-mid { width: 45px; left: -10px; top: 115px; } .whisker.left-bottom { width: 50px; left: -5px; top: 125px; transform: rotate(-10deg); } .whisker.right-top { width: 45px; right: -5px; transform: rotate(-10deg); } .whisker.right-mid { width: 50px; right: -10px; top: 115px; } .whisker.right-bottom { width: 45px; right: -5px; top: 125px; transform: rotate(10deg); } /* 腮红 */ .blush { position: absolute; width: 25px; height: 20px; background: #ffb3d9; border-radius: 50%; top: 120px; opacity: 0.6; } .blush.left { left: 25px; } .blush.right { right: 25px; } /* 身体 */ .body { position: absolute; width: 140px; height: 140px; background: white; border: 4px solid #000; border-radius: 50% 50% 30% 30%; top: 180px; left: 80px; } /* 背带裤 */ .overalls { position: absolute; width: 120px; height: 100px; background: #5DA5DA; border: 4px solid #000; border-radius: 20px 20px 15px 15px; top: 60px; left: 10px; } .overall-pocket { width: 40px; height: 35px; background: #4A8AB8; border: 3px solid #000; border-radius: 50% 50% 10px 10px; position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); } .pocket-bear { width: 20px; height: 20px; background: #8B6F47; border: 2px solid #000; border-radius: 50%; position: absolute; top: 8px; left: 50%; transform: translateX(-50%); } .pocket-bear::before, .pocket-bear::after { content: ''; position: absolute; width: 8px; height: 8px; background: #8B6F47; border: 2px solid #000; border-radius: 50%; top: -5px; } .pocket-bear::before { left: -2px; } .pocket-bear::after { right: -2px; } .strap { position: absolute; width: 15px; height: 50px; background: #5DA5DA; border: 3px solid #000; top: -45px; } .strap.left { left: 15px; } .strap.right { right: 15px; } .button { width: 10px; height: 10px; background: #c62828; border: 2px solid #000; border-radius: 50%; position: absolute; top: 5px; left: 50%; transform: translateX(-50%); } /* 衣领 */ .collar { position: absolute; width: 80px; height: 30px; background: #ffd54f; border: 3px solid #000; border-radius: 10px 10px 0 0; top: 30px; left: 30px; } .collar-side { position: absolute; width: 30px; height: 30px; background: #ffd54f; border: 3px solid #000; top: 30px; } .collar-side.left { left: 5px; border-radius: 0 0 0 10px; } .collar-side.right { right: 5px; border-radius: 0 0 10px 0; } /* 手臂 */ .arm { position: absolute; width: 50px; height: 80px; background: white; border: 4px solid #000; border-radius: 50%; top: 200px; transition: transform 0.3s ease; } .arm.left { left: 20px; transform: rotate(-20deg); } .arm.right { right: 20px; transform: rotate(20deg); transform-origin: top center; } /* 悬停时右手挥手 */ .hello-kitty:hover .arm.right { animation: wave 0.5s ease-in-out infinite; } @keyframes wave { 0%, 100% { transform: rotate(20deg); } 50% { transform: rotate(-10deg); } } /* 腿 */ .leg { position: absolute; width: 45px; height: 60px; background: white; border: 4px solid #000; border-radius: 20px; top: 300px; } .leg.left { left: 90px; } .leg.right { right: 90px; } </style> </head> <body> <div class="container"> <div class="hello-kitty"> <!-- 头部 --> <div class="head"> <div class="ear left"></div> <div class="ear right"></div> <!-- 蝴蝶结 --> <div class="bow"> <div class="bow-left"></div> <div class="bow-center"></div> <div class="bow-right"></div> </div> <!-- 眼睛 --> <div class="eye left"></div> <div class="eye right"></div> <!-- 鼻子 --> <div class="nose"></div> <!-- 嘴巴 --> <div class="mouth"> <div class="mouth-line"></div> </div> <!-- 胡须 --> <div class="whisker left-top"></div> <div class="whisker left-mid"></div> <div class="whisker left-bottom"></div> <div class="whisker right-top"></div> <div class="whisker right-mid"></div> <div class="whisker right-bottom"></div> <!-- 腮红 --> <div class="blush left"></div> <div class="blush right"></div> </div> <!-- 身体 --> <div class="body"> <div class="collar"></div> <div class="collar-side left"></div> <div class="collar-side right"></div> <div class="overalls"> <div class="strap left"> <div class="button"></div> </div> <div class="strap right"> <div class="button"></div> </div> <div class="overall-pocket"> <div class="pocket-bear"></div> </div> </div> </div> <!-- 手臂 --> <div class="arm left"></div> <div class="arm right"></div> <!----> <div class="leg left"></div> <div class="leg right"></div> </div> </div> </body> </html>修改代码,将猫的胡须改成弧形
最新发布
10-13
由于没有提供具体的HTML和CSS代码,下面给出一个示例,展示如何创建一个Hello Kitty形象并将其胡须改成弧形。 #### HTML代码 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="styles.css"> <title>Hello Kitty with Curved Whiskers</title> </head> <body> <div class="hello-kitty"> <div class="head"> <div class="left-whiskers"> <div class="whisker whisker-1"></div> <div class="whisker whisker-2"></div> <div class="whisker whisker-3"></div> </div> <div class="right-whiskers"> <div class="whisker whisker-4"></div> <div class="whisker whisker-5"></div> <div class="whisker whisker-6"></div> </div> </div> </div> </body> </html> ``` #### CSS代码 ```css .hello-kitty { position: relative; width: 200px; height: 200px; margin: 50px auto; } .head { position: absolute; top: 0; left: 0; width: 200px; height: 200px; background-color: white; border-radius: 50%; border: 2px solid black; } .left-whiskers, .right-whiskers { position: absolute; top: 100px; width: 80px; height: 20px; } .left-whiskers { left: -70px; } .right-whiskers { right: -70px; } .whisker { position: absolute; width: 80px; height: 2px; background-color: black; border-radius: 50%; } .whisker-1 { top: 0; transform: rotate(-15deg); } .whisker-2 { top: 10px; transform: rotate(0deg); } .whisker-3 { top: 20px; transform: rotate(15deg); } .whisker-4 { top: 0; transform: rotate(15deg); } .whisker-5 { top: 10px; transform: rotate(0deg); } .whisker-6 { top: 20px; transform: rotate(-15deg); } ``` 在上述代码中,通过`border-radius`属性将胡须设置为弧形,并且通过`transform: rotate()`属性来调整胡须的角度,从而模拟出弧形胡须的效果。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值