修改phase4.o相应节中的内容,使其与main.o链接后运行能够输出自己的学号:
$ gcc -o linkbomb main.o phase4.o
$ ./linkbomb
$学号
掌握switch语句的机器语言表示及其跳转表的实现。
反汇编phase4.o,看看里面干了些什么内容。
粗略一看,那么长;看到中间,猜到是switch;看看头尾,和phase3一模一样。
头尾我还是一字一句的看了一遍,真的完全一样。细节略。
找到这里就是跳转表了。在56位置重定位,看看重定位到哪了。
如下图,重定位到rodata节去了。
看rodata节,跳转表就是这里。
我做的时候是先链接的,这样似乎不用查重定位表,比较不用动脑子。
找到0x8048734位置,还是只读数据节。
对照写出ax是几时跳到哪,如下。
53: 8b 04 85 00 00 00 00 mov 0x0(,%eax,4),%eax
5a: ff e0 jmp *%eax
5c: c6 45 e3 33 movb $0x33,-0x1d(%ebp)——————————0
60: e9 9e 00 00 00 jmp 103
65: c6 45 e3 34 movb $0x34,-0x1d(%ebp)——————————1
69: e9 95 00 00 00 jmp 103
6e: c6 45 e3 74 movb $0x74,-0x1d(%ebp)——————————2
72: e9 8c 00 00 00 jmp 103
77: c6 45 e3 36 movb $0x36,-0x1d(%ebp)——————————3
7b: e9 83 00 00 00 jmp 103
80: c6 45 e3 6d movb $0x6d,-0x1d(%ebp)——————————4
84: eb 7d jmp 103
86: c6 45 e3 38 movb $0x38,-0x1d(%ebp)——————————5
8a: eb 77 jmp 103
8c: c6 45 e3 62 movb $0x62,-0x1d(%ebp)——————————6
90: eb 71 jmp 103
92: c6 45 e3 30 movb $0x30,-0x1d(%ebp)——————————7
96: eb 6b jmp 103
98: c6 45 e3 79 movb $0x79,-0x1d(%ebp)——————————8
9c: eb 65 jmp 103
9e: c6 45 e3 3b movb $0x3b,-0x1d(%ebp)——————————9
a2: eb 5f jmp 103
a4: c6 45 e3 37 movb $0x37,-0x1d(%ebp)——————————a
a8: eb 59 jmp 103
aa: c6 45 e3 47 movb $0x47,-0x1d(%ebp)——————————b
ae: eb 53 jmp 103
b0: c6 45 e3 4d movb $0x4d,-0x1d(%ebp)——————————c
b4: eb 4d jmp 103
b6: c6 45 e3 5a movb $0x5a,-0x1d(%ebp)——————————d
ba: eb 47 jmp 103
bc: c6 45 e3 3f movb $0x3f,-0x1d(%ebp)——————————e
c0: eb 41 jmp 103
c2: c6 45 e3 39 movb $0x39,-0x1d(%ebp)——————————f
c6: eb 3b jmp 103
c8: c6 45 e3 40 movb $0x40,-0x1d(%ebp)——————————10
cc: eb 35 jmp 103
ce: c6 45 e3 6b movb $0x6b,-0x1d(%ebp)——————————11
d2: eb 2f jmp 103
d4: c6 45 e3 70 movb $0x70,-0x1d(%ebp)——————————12
d8: eb 29 jmp 103
da: c6 45 e3 32 movb $0x32,-0x1d(%ebp)——————————13
de: eb 23 jmp 103
e0: c6 45 e3 31 movb $0x31,-0x1d(%ebp)——————————14
e4: eb 1d jmp 103
e6: c6 45 e3 7c movb $0x7c,-0x1d(%ebp)——————————15
ea: eb 17 jmp 103
ec: c6 45 e3 40 movb $0x40,-0x1d(%ebp)——————————16
f0: eb 11 jmp 103
f2: c6 45 e3 6e movb $0x6e,-0x1d(%ebp)——————————17
f6: eb 0b jmp 103
f8: c6 45 e3 35 movb $0x35,-0x1d(%ebp)——————————18
fc: eb 05 jmp 103
fe: c6 45 e3 5e movb $0x5e,-0x1d(%ebp)——————————19
102: 90 nop
然后看当什么都不改时,程序的输出
第一个字符的ascii码是0x4f,减去0x41就是0xe,
11: c7 45 e9 4f 58 59 44 movl $0x4459584f,-0x17(%ebp)
18: c7 45 ed 4b 50 56 47 movl $0x4756504b,-0x13(%ebp)
1f: 66 c7 45 f1 46 5a movw $0x5a46,-0xf(%ebp)
25: c6 45 f3 00 movb $0x0,-0xd(%ebp)
29: c7 45 e4 00 00 00 00 movl $0x0,-0x1c(%ebp)
跟phase3一模一样,局部变量字符串放在起始位置为-0x17(%ebp)处
跳到这里,那么第一个打印的字符的ascii码就是3f,即一个问号("?"),对照输出结果,的确是。以此类推,后续9个字符也是如此。
bc: c6 45 e3 3f movb $0x3f,-0x1d(%ebp)——————————e
c0: eb 41 jmp 103
那么只需要修改phase4.o的text节,将跳转之后的语句改为我们学号的ascii码即可。例如第一个字符那里就把3f改为30(如果学号第一位是0的话)。
完成。
阶段四几乎跟阶段三一模一样。十分简单。