csapp-linklab之第3阶段“输出学号”实验报告(强弱符号)

题目

新建一个phase3_patch.o,使其与main.o和phase3.o链接后,运行输出自己的学号:

$ gcc -o linkbomb main.o phase3.o phase3_patch.o

$ ./linkbomb

$学号

提示

利用符号解析中的强弱符号规则。(COOKIE字符串未初始化,可以利用强弱符号,在phase3_patch.c中定义一个初始化的COOKIE字符串。)

解决

先链接main.o 与phase3.o(linux> gcc main.o phase3.o linux> objdump -d a.out )以便看do_phase里做了什么。这时就需要使用在bomb lab中的“逆向工程”技能,猜这个函数在干嘛。

080484dd :
 80484dd:	55                   	push   %ebp
 80484de:	89 e5                	mov    %esp,%ebp
 80484e0:	83 ec 28             	sub    $0x28,%esp
 80484e3:	65 a1 14 00 00 00    	mov    %gs:0x14,%eax
 80484e9:	89 45 f4             	mov    %eax,-0xc(%ebp)
 80484ec:	31 c0                	xor    %eax,%eax
 80484ee:	c7 45 e9 67 6f 71 69 	movl   $0x69716f67,-0x17(%ebp)
 80484f5:	c7 45 ed 76 68 6a 77 	movl   $0x776a6876,-0x13(%ebp)
 80484fc:	66 c7 45 f1 78 63    	movw   $0x6378,-0xf(%ebp)
 8048502:	c6 45 f3 00          	movb   $0x0,-0xd(%ebp)
 8048506:	c7 45 e4 00 00 00 00 	movl   $0x0,-0x1c(%ebp)
 804850d:	eb 28                	jmp    8048537 
 804850f:	8d 55 e9             	lea    -0x17(%ebp),%edx
 8048512:	8b 45 e4             	mov    -0x1c(%ebp),%eax
 8048515:	01 d0                	add    %edx,%eax
 8048517:	0f b6 00             	movzbl (%eax),%eax
 804851a:	0f b6 c0             	movzbl %al,%eax
 804851d:	0f b6 80 60 a0 04 08 	movzbl 0x804a060(%eax),%eax
 8048524:	0f be c0             	movsbl %al,%eax
 8048527:	83 ec 0c             	sub    $0xc,%esp
 804852a:	50                   	push   %eax
 804852b:	e8 60 fe ff ff       	call   8048390 
 8048530:	83 c4 10             	add    $0x10,%esp
 8048533:	83 45 e4 01          	addl   $0x1,-0x1c(%ebp)
 8048537:	8b 45 e4             	mov    -0x1c(%ebp),%eax
 804853a:	83 f8 09             	cmp    $0x9,%eax
 804853d:	76 d0                	jbe    804850f 
 804853f:	83 ec 0c             	sub    $0xc,%esp
 8048542:	6a 0a                	push   $0xa
 8048544:	e8 47 fe ff ff       	call   8048390 
 8048549:	83 c4 10             	add    $0x10,%esp
 804854c:	90                   	nop
 804854d:	8b 45 f4             	mov    -0xc(%ebp),%eax
 8048550:	65 33 05 14 00 00 00 	xor    %gs:0x14,%eax
 8048557:	74 05                	je     804855e 
 8048559:	e8 f2 fd ff ff       	call   8048350 <__stack_chk_fail@plt>
 804855e:	c9                   	leave  
 804855f:	c3                   	ret    

以下是逐句解释: 

080484dd :
 80484dd:	55                   	push   %ebp
 80484de:	89 e5                	mov    %esp,%ebp
前两行,函数调用的惯常操作,基址寄存器存sp

 80484e0:	83 ec 28             	sub    $0x28,%esp
栈扩展0x28字节

 80484e3:	65 a1 14 00 00 00    	mov    %gs:0x14,%eax
 80484e9:	89 45 f4             	mov    %eax,-0xc(%ebp)
金丝雀

 80484ec:	31 c0                	xor    %eax,%eax
ax清零

 80484ee:	c7 45 e9 67 6f 71 69 	movl   $0x69716f67,-0x17(%ebp)
 80484f5:	c7 45 ed 76 68 6a 77 	movl   $0x776a6876,-0x13(%ebp)
 80484fc:	66 c7 45 f1 78 63    	movw   $0x6378,-0xf(%ebp)
 8048502:	c6 45 f3 00          	movb   $0x0,-0xd(%ebp)
往栈里放一个字符串(局部变量)
————————————————————————————————
地址:bp-17  bp-13  bp-f  bp-d
内容:goqi   vhjw   xc    \0
————————————————————————————————

 8048506:	c7 45 e4 00 00 00 00 	movl   $0x0,-0x1c(%ebp)
-0x1c(%ebp)处赋为0(局部变量)

 804850d:	eb 28                	jmp    8048537 

 804850f:	8d 55 e9             	lea    -0x17(%ebp),%edx
 8048512:	8b 45 e4             	mov    -0x1c(%ebp),%eax
ax = i

 8048515:	01 d0                	add    %edx,%eax
ax = bp-0x17+i(取上面那个字符串的第i个字符的地址)

 8048517:	0f b6 00             	movzbl (%eax),%eax
取第i个字符

 804851a:	0f b6 c0             	movzbl %al,%eax
不知道

 804851d:	0f b6 80 60 a0 04 08 	movzbl 0x804a060(%eax),%eax
取绝对地址为(0x804a060+ax)处的东西存到ax里

 8048524:	0f be c0             	movsbl %al,%eax
不知道

 8048527:	83 ec 0c             	sub    $0xc,%esp
栈变大12字节

 804852a:	50                   	push   %eax
栈变大4字节

 804852b:	e8 60 fe ff ff       	call   8048390 
打出ax里的东西,以ascii码对应字符的方式

 8048530:	83 c4 10             	add    $0x10,%esp
栈变小16字节

 8048533:	83 45 e4 01          	addl   $0x1,-0x1c(%ebp)
 8048537:	8b 45 e4             	mov    -0x1c(%ebp),%eax
看出-0x1c(%ebp)处的局部变量存的是循环变量,每次自增1

 804853a:	83 f8 09             	cmp    $0x9,%eax
循环10次

 804853d:	76 d0                	jbe    804850f 
 804853f:	83 ec 0c             	sub    $0xc,%esp
栈变大12字节

 8048542:	6a 0a                	push   $0xa
 8048544:	e8 47 fe ff ff       	call   8048390 
此时ax为十进制10,打印10刚好是一个换行符(\n),完美

 8048549:	83 c4 10             	add    $0x10,%esp
 804854c:	90                   	nop

以下是金丝雀的检查
 804854d:	8b 45 f4             	mov    -0xc(%ebp),%eax
 8048550:	65 33 05 14 00 00 00 	xor    %gs:0x14,%eax
 8048557:	74 05                	je     804855e 
 8048559:	e8 f2 fd ff ff       	call   8048350 <__stack_chk_fail@plt>
 804855e:	c9                   	leave  
 804855f:	c3                   	ret    

所以绝对地址0x804a060处有用,readelf -s a.out 打印符号表

看来这个lOXXBDHjiI就是COOKIE字符串(我一开始还以为COOKIE字符串的变量名就叫COOKIE =_=)

————————————————————————————————
地址:bp-17  bp-13  bp-f  bp-d
内容:goqi   vhjw   xc    \0
————————————————————————————————

位置分别是103 111 113 105 118 104 106 119 120 99

假设学号是0123456789,在phase3_patch.c文件中,写入

char lOXXBDHjiI [256] = "666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666966605366666162666647866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666";

成功

后记

本例看出如果学号全是一样的数字(比如0000000000)你只需要把lOXXBDHjiI字符串赋为256个0即可,根本不用考虑究竟是哪个位置被打印(幸运号的福利)

你可能感兴趣的:(csapp,linux,链接,link,lab,重定位,强弱符号,Ubuntu)