Skip to content

Link Lab

Posted on:2022.01.16

TOC

Open TOC

Link Lab

https://www.icourse163.org/course/NJU-1449521162

MOOC 的版本似乎只有四个阶段,而原版似乎有六个阶段……

编译选项

-no-pie
Don't produce a dynamically linked position independent executable.

注意加上 -m32 选项

Terminal window
$ gcc -m32 -no-pie -o linkbomb main.o phase1.o

不如写个 makefile

.PHONY: phase1 clean
phase1: main.o phase1.o
gcc -m32 -no-pie -o linkbomb main.o phase1.o
./linkbomb
clean:
rm linkbomb

main

readelf

ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 852 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 13
Section header string table index: 12
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000040 00 AX 0 0 1
[ 2] .rel.text REL 00000000 0002cc 000020 08 I 10 1 4
[ 3] .data PROGBITS 00000000 000074 000000 00 WA 0 0 1
[ 4] .bss NOBITS 00000000 000074 000000 00 WA 0 0 1
[ 5] .rodata PROGBITS 00000000 000080 0000c4 00 A 0 0 32
[ 6] .comment PROGBITS 00000000 000144 00001d 01 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 00000000 000161 000000 00 0 0 1
[ 8] .eh_frame PROGBITS 00000000 000164 000044 00 A 0 0 4
[ 9] .rel.eh_frame REL 00000000 0002ec 000008 08 I 10 8 4
[10] .symtab SYMTAB 00000000 0001a8 0000f0 10 11 9 4
[11] .strtab STRTAB 00000000 000298 000032 00 0 0 1
[12] .shstrtab STRTAB 00000000 0002f4 00005f 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
There is no dynamic section in this file.
Relocation section '.rel.text' at offset 0x2cc contains 4 entries:
Offset Info Type Sym.Value Sym. Name
00000012 00000a01 R_386_32 00000004 phase
0000001b 00000a01 R_386_32 00000004 phase
00000027 00000501 R_386_32 00000000 .rodata
0000002c 00000e02 R_386_PC32 00000000 puts
Relocation section '.rel.eh_frame' at offset 0x2ec contains 1 entry:
Offset Info Type Sym.Value Sym. Name
00000020 00000202 R_386_PC32 00000000 .text
The decoding of unwind sections for machine type Intel 80386 is not currently supported.
Symbol table '.symtab' contains 15 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS main.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 8
8: 00000000 0 SECTION LOCAL DEFAULT 6
9: 00000000 64 OBJECT GLOBAL DEFAULT 5 zzGSwc
10: 00000004 4 OBJECT GLOBAL DEFAULT COM phase
11: 00000004 4 OBJECT GLOBAL DEFAULT COM phase_id
12: 00000040 15 OBJECT GLOBAL DEFAULT 5 challenge
13: 00000000 64 FUNC GLOBAL DEFAULT 1 main
14: 00000000 0 NOTYPE GLOBAL DEFAULT UND puts
No version information found in this file.

objdump

main.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
0: 8d 4c 24 04 lea 0x4(%esp),%ecx
4: 83 e4 f0 and $0xfffffff0,%esp
7: ff 71 fc push -0x4(%ecx)
a: 55 push %ebp
b: 89 e5 mov %esp,%ebp
d: 51 push %ecx
e: 83 ec 04 sub $0x4,%esp
11: a1 00 00 00 00 mov 0x0,%eax
16: 85 c0 test %eax,%eax
18: 74 09 je 23 <main+0x23>
1a: a1 00 00 00 00 mov 0x0,%eax
1f: ff d0 call *%eax
21: eb 10 jmp 33 <main+0x33>
23: 83 ec 0c sub $0xc,%esp
26: 68 50 00 00 00 push $0x50
2b: e8 fc ff ff ff call 2c <main+0x2c>
30: 83 c4 10 add $0x10,%esp
33: b8 00 00 00 00 mov $0x0,%eax
38: 8b 4d fc mov -0x4(%ebp),%ecx
3b: c9 leave
3c: 8d 61 fc lea -0x4(%ecx),%esp
3f: c3 ret

main.o 中会调用相应模块 phase[n].o 中如下定义的一个全局函数指针变量 phase

void (*phase)() = do_phase;

其中,作为其初始值的 do_phase 是各阶段模块中实现的一个全局函数,用来完成该阶段的具体功能

所以似乎现在 main 没啥用

phase1 - 静态数据与 ELF 数据节

修改 .data section 的内容

readelf

ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 892 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 14
Section header string table index: 13
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 00001a 00 AX 0 0 1
[ 2] .rel.text REL 00000000 0002f0 000010 08 I 11 1 4
[ 3] .data PROGBITS 00000000 000060 000100 00 WA 0 0 32
[ 4] .rel.data REL 00000000 000300 000010 08 I 11 3 4
[ 5] .bss NOBITS 00000000 000160 000000 00 WA 0 0 1
[ 6] .rodata PROGBITS 00000000 000160 000002 00 A 0 0 1
[ 7] .comment PROGBITS 00000000 000162 00001d 01 MS 0 0 1
[ 8] .note.GNU-stack PROGBITS 00000000 00017f 000000 00 0 0 1
[ 9] .eh_frame PROGBITS 00000000 000180 000038 00 A 0 0 4
[10] .rel.eh_frame REL 00000000 000310 000008 08 I 11 9 4
[11] .symtab SYMTAB 00000000 0001b8 000100 10 12 12 4
[12] .strtab STRTAB 00000000 0002b8 000038 00 0 0 1
[13] .shstrtab STRTAB 00000000 000318 000063 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
There is no dynamic section in this file.
Relocation section '.rel.text' at offset 0x2f0 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
00000007 00000301 R_386_32 00000000 .data
00000010 00000e02 R_386_PC32 00000000 puts
Relocation section '.rel.data' at offset 0x300 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
0000003c 00000601 R_386_32 00000000 .rodata
000000fc 00000d01 R_386_32 00000000 do_phase
Relocation section '.rel.eh_frame' at offset 0x310 contains 1 entry:
Offset Info Type Sym.Value Sym. Name
00000020 00000202 R_386_PC32 00000000 .text
The decoding of unwind sections for machine type Intel 80386 is not currently supported.
Symbol table '.symtab' contains 16 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS phase1.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 5
5: 00000000 60 OBJECT LOCAL DEFAULT 3 IOcgnr
6: 00000000 0 SECTION LOCAL DEFAULT 6
7: 00000040 187 OBJECT LOCAL DEFAULT 3 OdZAJybs
8: 000000fb 1 OBJECT LOCAL DEFAULT 3 FUGsLK
9: 00000000 0 SECTION LOCAL DEFAULT 8
10: 00000000 0 SECTION LOCAL DEFAULT 9
11: 00000000 0 SECTION LOCAL DEFAULT 7
12: 0000003c 4 OBJECT GLOBAL DEFAULT 3 phase_id
13: 00000000 26 FUNC GLOBAL DEFAULT 1 do_phase
14: 00000000 0 NOTYPE GLOBAL DEFAULT UND puts
15: 000000fc 4 OBJECT GLOBAL DEFAULT 3 phase
No version information found in this file.

objdump

phase1.o: file format elf32-i386
Disassembly of section .text:
00000000 <do_phase>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: b8 79 00 00 00 mov $0x79,%eax
b: 83 ec 0c sub $0xc,%esp
e: 50 push %eax
f: e8 fc ff ff ff call 10 <do_phase+0x10>
14: 83 c4 10 add $0x10,%esp
17: 90 nop
18: c9 leave
19: c3 ret

这一阶段比较简单,先介绍暴力方法,先观察默认的输出:

uh Xlsly tUcYqD8AJBKqcGvAALrTuUiXUzOdbcIlIoUCERLgN5 q FKgQDngkZg32zwxuJ8z1cd owMmQkYOxjb1wAu0zpyjX tv8KMwbS6BGydD2aDG69UIIES5Fa

然后定位 phase1.o 中这段字符串的位置,起始在 0xd9,暴力修改为:

30 38 30 39 4e 4a 55 30 36 34 00

即 0809NJU064,即可……

查看和修改二进制文件:

$ vi -b phase1.o

然后切换到十六进制模式:

:%!xxd

修改完后切换回来

:%!xxd -r

最后保存即可

下面介绍正常的方法,注意到 IA-32 使用栈来传递参数,我们定位 phase1.o 的反汇编

6: b8 79 00 00 00 mov $0x79,%eax
b: 83 ec 0c sub $0xc,%esp
e: 50 push %eax
f: e8 fc ff ff ff call 10 <do_phase+0x10>

可以传递给 puts 函数的参数为 0x79

至于为什么是 puts 函数,观察 .rel.text 知在 .text section 偏移 0x10 的地方有一个重定位表项,其名字为 puts

猜测 fc ff ff ff 是为了在重定位时弥补 PC + 4

IA-32 和 x86-64 似乎有略微不同

而 .data section 在 ELF 文件中的偏移为 0x60,两者相加立得 0xd9

可以通过反汇编可执行文件 linkbomb 进一步观察:

080491b6 <do_phase>:
80491b6: 55 push %ebp
80491b7: 89 e5 mov %esp,%ebp
80491b9: 83 ec 08 sub $0x8,%esp
80491bc: b8 b9 c0 04 08 mov $0x804c0b9,%eax
80491c1: 83 ec 0c sub $0xc,%esp
80491c4: 50 push %eax
80491c5: e8 76 fe ff ff call 8049040 <puts@plt>
80491ca: 83 c4 10 add $0x10,%esp
80491cd: 90 nop
80491ce: c9 leave
80491cf: c3 ret

phase2 - 指令与 ELF 代码节

修改 .text section 的内容

readelf

ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 1012 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 14
Section header string table index: 13
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000116 00 AX 0 0 1
[ 2] .rel.text REL 00000000 000348 000020 08 I 11 1 4
[ 3] .data PROGBITS 00000000 00014c 000008 00 WA 0 0 4
[ 4] .rel.data REL 00000000 000368 000010 08 I 11 3 4
[ 5] .bss NOBITS 00000000 000154 000000 00 WA 0 0 1
[ 6] .rodata PROGBITS 00000000 000154 00000a 00 A 0 0 1
[ 7] .comment PROGBITS 00000000 00015e 00001d 01 MS 0 0 1
[ 8] .note.GNU-stack PROGBITS 00000000 00017b 000000 00 0 0 1
[ 9] .eh_frame PROGBITS 00000000 00017c 000078 00 A 0 0 4
[10] .rel.eh_frame REL 00000000 000378 000018 08 I 11 9 4
[11] .symtab SYMTAB 00000000 0001f4 000110 10 12 10 4
[12] .strtab STRTAB 00000000 000304 000043 00 0 0 1
[13] .shstrtab STRTAB 00000000 000390 000063 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
There is no dynamic section in this file.
Relocation section '.rel.text' at offset 0x348 contains 4 entries:
Offset Info Type Sym.Value Sym. Name
00000074 00000c02 R_386_PC32 00000000 strlen
000000aa 00000501 R_386_32 00000000 .rodata
000000b2 00000d02 R_386_PC32 00000000 strcmp
000000c4 00000e02 R_386_PC32 00000000 puts
Relocation section '.rel.data' at offset 0x368 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
00000000 00000501 R_386_32 00000000 .rodata
00000004 00000f01 R_386_32 000000d0 do_phase
Relocation section '.rel.eh_frame' at offset 0x378 contains 3 entries:
Offset Info Type Sym.Value Sym. Name
00000020 00000202 R_386_PC32 00000000 .text
00000040 00000202 R_386_PC32 00000000 .text
00000060 00000202 R_386_PC32 00000000 .text
The decoding of unwind sections for machine type Intel 80386 is not currently supported.
Symbol table '.symtab' contains 17 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS phase2.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 5
5: 00000000 0 SECTION LOCAL DEFAULT 6
6: 000000a0 48 FUNC LOCAL DEFAULT 1 AFPQyOcF
7: 00000000 0 SECTION LOCAL DEFAULT 8
8: 00000000 0 SECTION LOCAL DEFAULT 9
9: 00000000 0 SECTION LOCAL DEFAULT 7
10: 00000000 4 OBJECT GLOBAL DEFAULT 3 phase_id
11: 00000000 160 FUNC GLOBAL DEFAULT 1 nndZqWCYPw
12: 00000000 0 NOTYPE GLOBAL DEFAULT UND strlen
13: 00000000 0 NOTYPE GLOBAL DEFAULT UND strcmp
14: 00000000 0 NOTYPE GLOBAL DEFAULT UND puts
15: 000000d0 70 FUNC GLOBAL DEFAULT 1 do_phase
16: 00000004 4 OBJECT GLOBAL DEFAULT 3 phase
No version information found in this file.

objdump

phase2.o: file format elf32-i386
Disassembly of section .text:
00000000 <nndZqWCYPw>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 48 sub $0x48,%esp
6: c7 45 bb 70 76 78 32 movl $0x32787670,-0x45(%ebp)
d: c7 45 bf 55 37 6b 78 movl $0x786b3755,-0x41(%ebp)
14: c7 45 c3 6b 4a 37 54 movl $0x54374a6b,-0x3d(%ebp)
1b: c7 45 c7 51 20 45 64 movl $0x64452051,-0x39(%ebp)
22: c7 45 cb 79 59 45 6e movl $0x6e455979,-0x35(%ebp)
29: c7 45 cf 49 72 73 61 movl $0x61737249,-0x31(%ebp)
30: c7 45 d3 62 45 4a 78 movl $0x784a4562,-0x2d(%ebp)
37: c7 45 d7 4d 5a 52 4c movl $0x4c525a4d,-0x29(%ebp)
3e: c7 45 db 74 79 4f 4c movl $0x4c4f7974,-0x25(%ebp)
45: c7 45 df 61 57 6f 20 movl $0x206f5761,-0x21(%ebp)
4c: c7 45 e3 73 72 35 68 movl $0x68357273,-0x1d(%ebp)
53: c7 45 e7 20 7a 65 46 movl $0x46657a20,-0x19(%ebp)
5a: c7 45 eb 54 50 37 54 movl $0x54375054,-0x15(%ebp)
61: c7 45 ef 09 5a 73 4c movl $0x4c735a09,-0x11(%ebp)
68: c6 45 f3 00 movb $0x0,-0xd(%ebp)
6c: 83 ec 0c sub $0xc,%esp
6f: 8d 45 bb lea -0x45(%ebp),%eax
72: 50 push %eax
73: e8 fc ff ff ff call 74 <nndZqWCYPw+0x74>
78: 83 c4 10 add $0x10,%esp
7b: 89 45 f4 mov %eax,-0xc(%ebp)
7e: 83 7d 08 00 cmpl $0x0,0x8(%ebp)
82: 78 15 js 99 <nndZqWCYPw+0x99>
84: 8b 45 08 mov 0x8(%ebp),%eax
87: 3b 45 f4 cmp -0xc(%ebp),%eax
8a: 7d 0d jge 99 <nndZqWCYPw+0x99>
8c: 8d 55 bb lea -0x45(%ebp),%edx
8f: 8b 45 08 mov 0x8(%ebp),%eax
92: 01 d0 add %edx,%eax
94: 0f b6 00 movzbl (%eax),%eax
97: eb 05 jmp 9e <nndZqWCYPw+0x9e>
99: b8 00 00 00 00 mov $0x0,%eax
9e: c9 leave
9f: c3 ret
000000a0 <AFPQyOcF>:
a0: 55 push %ebp
a1: 89 e5 mov %esp,%ebp
a3: 83 ec 08 sub $0x8,%esp
a6: 83 ec 08 sub $0x8,%esp
a9: 68 02 00 00 00 push $0x2
ae: ff 75 08 push 0x8(%ebp)
b1: e8 fc ff ff ff call b2 <AFPQyOcF+0x12>
b6: 83 c4 10 add $0x10,%esp
b9: 85 c0 test %eax,%eax
bb: 75 10 jne cd <AFPQyOcF+0x2d>
bd: 83 ec 0c sub $0xc,%esp
c0: ff 75 0c push 0xc(%ebp)
c3: e8 fc ff ff ff call c4 <AFPQyOcF+0x24>
c8: 83 c4 10 add $0x10,%esp
cb: eb 01 jmp ce <AFPQyOcF+0x2e>
cd: 90 nop
ce: c9 leave
cf: c3 ret
000000d0 <do_phase>:
d0: 55 push %ebp
d1: 89 e5 mov %esp,%ebp
d3: 90 nop
d4: 90 nop
d5: 90 nop
d6: 90 nop
d7: 90 nop
d8: 90 nop
d9: 90 nop
da: 90 nop
db: 90 nop
dc: 90 nop
dd: 90 nop
de: 90 nop
df: 90 nop
e0: 90 nop
e1: 90 nop
e2: 90 nop
e3: 90 nop
e4: 90 nop
e5: 90 nop
e6: 90 nop
e7: 90 nop
e8: 90 nop
e9: 90 nop
ea: 90 nop
eb: 90 nop
ec: 90 nop
ed: 90 nop
ee: 90 nop
ef: 90 nop
f0: 90 nop
f1: 90 nop
f2: 90 nop
f3: 90 nop
f4: 90 nop
f5: 90 nop
f6: 90 nop
f7: 90 nop
f8: 90 nop
f9: 90 nop
fa: 90 nop
fb: 90 nop
fc: 90 nop
fd: 90 nop
fe: 90 nop
ff: 90 nop
100: 90 nop
101: 90 nop
102: 90 nop
103: 90 nop
104: 90 nop
105: 90 nop
106: 90 nop
107: 90 nop
108: 90 nop
109: 90 nop
10a: 90 nop
10b: 90 nop
10c: 90 nop
10d: 90 nop
10e: 90 nop
10f: 90 nop
110: 90 nop
111: 90 nop
112: 90 nop
113: 90 nop
114: 5d pop %ebp
115: c3 ret

我们需要在 do_phase 中填充一些指令,使其调用 AFPQyOcF 函数

nndZqWCYPw 函数与本阶段无关

通过对照 .rel.text 或反汇编可执行文件,可知 AFPQyOcF 函数的行为如下:

void AFPQyOcF(const char* first, const char* second) {
if (strcmp(first, "yKSPHJa") == 0) {
puts(second);
}
}

其中字符串 yKSPHJa 通过下面三条指令可以推断出来:

a9: 68 02 00 00 00 push $0x2
ae: ff 75 08 push 0x8(%ebp)
b1: e8 fc ff ff ff call b2 <AFPQyOcF+0x12>

同样是对照 .rel.text 或反汇编可执行文件,可知这里 call 的是 strcmp,第一个参数为调用 AFPQyOcF 的第一个参数,第二个参数对照 .rel.text 可知在 .rodata 中,偏移为 0x2,我们查看 .rodata 的开头:

3200 794b 5350 484a 6100 0047

可知为 79 4b 53 50 48 4a 61 00,即 yKSPHJa

或者通过 gdbgui 直接调试可执行文件也可知字符串地址在 0x804a0e6 处,为 yKSPHJa

同样可以分析出打印的字符串为调用 AFPQyOcF 的第二个参数

c0: ff 75 0c push 0xc(%ebp)
c3: e8 fc ff ff ff call c4 <AFPQyOcF+0x24>

我们来复习一下 IA-32 的过程调用:

e30ef9b1f3ef4fa59557b906d6b8b30e.png

在被调用过程中,调用过程的第一个参数在 0x8(%ebp),第二个参数在 0xc(%ebp) 以此类推

为此我们需要构造如下的函数调用:

void do_phase() {
AFPQyOcF("yKSPHJa", "0809NJU064")
}

也就需要构造 do_phase 的栈帧,如图所示:

b81cb38be9464845aa0d65f703269217.png

我们编写汇编代码:

temp.S
do_phase:
push %ebp
movl %esp, %ebp
subl $0x1c, %esp
movl $0x00003436, -4(%ebp)
movl $0x30554a4e, -8(%ebp)
movl $0x39303830, -12(%ebp)
movl $0x00614a48, -16(%ebp)
movl $0x50534b79, -20(%ebp)
leal -20(%ebp), %eax
movl %eax, (%esp)
leal -12(%ebp), %eax
movl %eax, 4(%esp)
call AFPQyOcF
addl $0x1c, %esp

注意构造参数时为 leal 而非 movl,因为是地址

通过 gcc -m32 -c temp.S 可得:

Disassembly of section .text:
00000000 <do_phase>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 1c sub $0x1c,%esp
6: c7 45 fc 36 34 00 00 movl $0x3436,-0x4(%ebp)
d: c7 45 f8 4e 4a 55 30 movl $0x30554a4e,-0x8(%ebp)
14: c7 45 f4 30 38 30 39 movl $0x39303830,-0xc(%ebp)
1b: c7 45 f0 48 4a 61 00 movl $0x614a48,-0x10(%ebp)
22: c7 45 ec 79 4b 53 50 movl $0x50534b79,-0x14(%ebp)
29: 8d 45 ec lea -0x14(%ebp),%eax
2c: 89 04 24 mov %eax,(%esp)
2f: 8d 45 f4 lea -0xc(%ebp),%eax
32: 89 44 24 04 mov %eax,0x4(%esp)
36: e8 fc ff ff ff call 37 <do_phase+0x37>
3b: 83 c4 1c add $0x1c,%esp

注意到偏移为 -(0xd0 - 0xa0 + 3b) = 0xffffff95,对应修改 phase.o 即可

最终 phase.o 的 do_phase 反汇编如下:

000000d0 <do_phase>:
d0: 55 push %ebp
d1: 89 e5 mov %esp,%ebp
d3: 83 ec 1c sub $0x1c,%esp
d6: c7 45 fc 36 34 00 00 movl $0x3436,-0x4(%ebp)
dd: c7 45 f8 4e 4a 55 30 movl $0x30554a4e,-0x8(%ebp)
e4: c7 45 f4 30 38 30 39 movl $0x39303830,-0xc(%ebp)
eb: c7 45 f0 48 4a 61 00 movl $0x614a48,-0x10(%ebp)
f2: c7 45 ec 79 4b 53 50 movl $0x50534b79,-0x14(%ebp)
f9: 8d 45 ec lea -0x14(%ebp),%eax
fc: 89 04 24 mov %eax,(%esp)
ff: 8d 45 f4 lea -0xc(%ebp),%eax
102: 89 44 24 04 mov %eax,0x4(%esp)
106: e8 95 ff ff ff call a0 <AFPQyOcF>
10b: 83 c4 1c add $0x1c,%esp
10e: 90 nop
10f: 90 nop
110: 90 nop
111: 90 nop
112: 90 nop
113: 90 nop
114: 5d pop %ebp
115: c3 ret

phase3 - switch 语句与重定位

不允许修改 .text section 和 relocation section 的内容

readelf

Relocation section

Relocation section '.rel.text' at offset 0x4a4 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
00000075 00000701 R_386_32 00000000 .rodata
00000153 00000d02 R_386_PC32 00000000 puts
Relocation section '.rel.data' at offset 0x4b4 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
000000f4 00000701 R_386_32 00000000 .rodata
000000f8 00000c01 R_386_32 0000002a do_phase
Relocation section '.rel.rodata' at offset 0x4c4 contains 26 entries:
Offset Info Type Sym.Value Sym. Name
00000004 00000201 R_386_32 00000000 .text
00000008 00000201 R_386_32 00000000 .text
0000000c 00000201 R_386_32 00000000 .text
00000010 00000201 R_386_32 00000000 .text
00000014 00000201 R_386_32 00000000 .text
00000018 00000201 R_386_32 00000000 .text
0000001c 00000201 R_386_32 00000000 .text
00000020 00000201 R_386_32 00000000 .text
00000024 00000201 R_386_32 00000000 .text
00000028 00000201 R_386_32 00000000 .text
0000002c 00000201 R_386_32 00000000 .text
00000030 00000201 R_386_32 00000000 .text
00000034 00000201 R_386_32 00000000 .text
00000038 00000201 R_386_32 00000000 .text
0000003c 00000201 R_386_32 00000000 .text
00000040 00000201 R_386_32 00000000 .text
00000044 00000201 R_386_32 00000000 .text
00000048 00000201 R_386_32 00000000 .text
0000004c 00000201 R_386_32 00000000 .text
00000050 00000201 R_386_32 00000000 .text
00000054 00000201 R_386_32 00000000 .text
00000058 00000201 R_386_32 00000000 .text
0000005c 00000201 R_386_32 00000000 .text
00000060 00000201 R_386_32 00000000 .text
00000064 00000201 R_386_32 00000000 .text
00000068 00000201 R_386_32 00000000 .text

objdump

0000002a <do_phase>:
2a: 55 push %ebp
2b: 89 e5 mov %esp,%ebp
2d: 83 ec 28 sub $0x28,%esp
30: c7 45 e5 54 50 44 46 movl $0x46445054,-0x1b(%ebp)
37: c7 45 e9 4f 43 59 41 movl $0x4159434f,-0x17(%ebp)
3e: 66 c7 45 ed 5a 53 movw $0x535a,-0x13(%ebp)
44: c6 45 ef 00 movb $0x0,-0x11(%ebp)
48: c7 45 f0 00 00 00 00 movl $0x0,-0x10(%ebp)
4f: e9 e0 00 00 00 jmp 134 <do_phase+0x10a>
54: 8d 55 e5 lea -0x1b(%ebp),%edx
57: 8b 45 f0 mov -0x10(%ebp),%eax
5a: 01 d0 add %edx,%eax
5c: 0f b6 00 movzbl (%eax),%eax
5f: 88 45 f7 mov %al,-0x9(%ebp)
62: 0f be 45 f7 movsbl -0x9(%ebp),%eax
66: 83 e8 41 sub $0x41,%eax
69: 83 f8 19 cmp $0x19,%eax
6c: 0f 87 b0 00 00 00 ja 122 <do_phase+0xf8>
72: 8b 04 85 04 00 00 00 mov 0x4(,%eax,4),%eax
79: ff e0 jmp *%eax
7b: c6 45 f7 36 movb $0x36,-0x9(%ebp)
7f: e9 9e 00 00 00 jmp 122 <do_phase+0xf8>
84: c6 45 f7 22 movb $0x22,-0x9(%ebp)
88: e9 95 00 00 00 jmp 122 <do_phase+0xf8>
8d: c6 45 f7 29 movb $0x29,-0x9(%ebp)
91: e9 8c 00 00 00 jmp 122 <do_phase+0xf8>
96: c6 45 f7 30 movb $0x30,-0x9(%ebp)
9a: e9 83 00 00 00 jmp 122 <do_phase+0xf8>
9f: c6 45 f7 23 movb $0x23,-0x9(%ebp)
a3: eb 7d jmp 122 <do_phase+0xf8>
a5: c6 45 f7 38 movb $0x38,-0x9(%ebp)
a9: eb 77 jmp 122 <do_phase+0xf8>
ab: c6 45 f7 64 movb $0x64,-0x9(%ebp)
af: eb 71 jmp 122 <do_phase+0xf8>
b1: c6 45 f7 5a movb $0x5a,-0x9(%ebp)
b5: eb 6b jmp 122 <do_phase+0xf8>
b7: c6 45 f7 4a movb $0x4a,-0x9(%ebp)
bb: eb 65 jmp 122 <do_phase+0xf8>
bd: c6 45 f7 38 movb $0x38,-0x9(%ebp)
c1: eb 5f jmp 122 <do_phase+0xf8>
c3: c6 45 f7 4e movb $0x4e,-0x9(%ebp)
c7: eb 59 jmp 122 <do_phase+0xf8>
c9: c6 45 f7 34 movb $0x34,-0x9(%ebp)
cd: eb 53 jmp 122 <do_phase+0xf8>
cf: c6 45 f7 69 movb $0x69,-0x9(%ebp)
d3: eb 4d jmp 122 <do_phase+0xf8>
d5: c6 45 f7 72 movb $0x72,-0x9(%ebp)
d9: eb 47 jmp 122 <do_phase+0xf8>
db: c6 45 f7 77 movb $0x77,-0x9(%ebp)
df: eb 41 jmp 122 <do_phase+0xf8>
e1: c6 45 f7 37 movb $0x37,-0x9(%ebp)
e5: eb 3b jmp 122 <do_phase+0xf8>
e7: c6 45 f7 2d movb $0x2d,-0x9(%ebp)
eb: eb 35 jmp 122 <do_phase+0xf8>
ed: c6 45 f7 61 movb $0x61,-0x9(%ebp)
f1: eb 2f jmp 122 <do_phase+0xf8>
f3: c6 45 f7 38 movb $0x38,-0x9(%ebp)
f7: eb 29 jmp 122 <do_phase+0xf8>
f9: c6 45 f7 71 movb $0x71,-0x9(%ebp)
fd: eb 23 jmp 122 <do_phase+0xf8>
ff: c6 45 f7 39 movb $0x39,-0x9(%ebp)
103: eb 1d jmp 122 <do_phase+0xf8>
105: c6 45 f7 50 movb $0x50,-0x9(%ebp)
109: eb 17 jmp 122 <do_phase+0xf8>
10b: c6 45 f7 67 movb $0x67,-0x9(%ebp)
10f: eb 11 jmp 122 <do_phase+0xf8>
111: c6 45 f7 55 movb $0x55,-0x9(%ebp)
115: eb 0b jmp 122 <do_phase+0xf8>
117: c6 45 f7 68 movb $0x68,-0x9(%ebp)
11b: eb 05 jmp 122 <do_phase+0xf8>
11d: c6 45 f7 63 movb $0x63,-0x9(%ebp)
121: 90 nop
122: 8d 55 da lea -0x26(%ebp),%edx
125: 8b 45 f0 mov -0x10(%ebp),%eax
128: 01 c2 add %eax,%edx
12a: 0f b6 45 f7 movzbl -0x9(%ebp),%eax
12e: 88 02 mov %al,(%edx)
130: 83 45 f0 01 addl $0x1,-0x10(%ebp)
134: 8b 45 f0 mov -0x10(%ebp),%eax
137: 83 f8 09 cmp $0x9,%eax
13a: 0f 86 14 ff ff ff jbe 54 <do_phase+0x2a>
140: 8d 55 da lea -0x26(%ebp),%edx
143: 8b 45 f0 mov -0x10(%ebp),%eax
146: 01 d0 add %edx,%eax
148: c6 00 00 movb $0x0,(%eax)
14b: 83 ec 0c sub $0xc,%esp
14e: 8d 45 da lea -0x26(%ebp),%eax
151: 50 push %eax
152: e8 fc ff ff ff call 153 <do_phase+0x129>
157: 83 c4 10 add $0x10,%esp
15a: 90 nop
15b: c9 leave
15c: c3 ret

call 的函数为 puts

经过调试可知 COOKIE 字符串为 TPDFOCYAZS,进行的变换如下

对目标字符串下标为 i 的字符,在下面的地址处

addr(table)+(ascii(cookie[i])0x41)×4addr(table) + (ascii(cookie[i])-0x41) × 4

会有一个地址,该地址处会有一条 movb 语句,其操作数即为该字符

注意到 0x41 即为 A,为此,我们需要修改跳转表

vgalaxy@vgalaxy-VirtualBox:~/Lab/linklab$ hexdump -s 0x29c -n 0x6c phase3.o
000029c 0033 0000 00b7 0000 00c9 0000 00db 0000
00002ac 00ff 0000 00c3 0000 00d5 0000 008d 0000
00002bc 00f9 0000 009f 0000 007b 0000 0117 0000
00002cc 0084 0000 011d 0000 00e7 0000 00ed 0000
00002dc 0096 0000 00e1 0000 00a5 0000 00b1 0000
00002ec 00bd 0000 0111 0000 00f3 0000 00ab 0000
00002fc 010b 0000 0105 0000 00cf 0000
0000308

注意到 .rel.rodata 的存在,且从第 1 个表项开始(从 0 计数),反映了这种间接寻址

调试可知第 1 个表项 b7 对应实际地址 0x804926d,即 movb $0x4a,-0x9(%ebp)

发现 b7 就是在 .text 中的偏移

找到一个对应关系,我们就能推导出所有的映射

cookieoffsetitemaddrstring
T19bd → 96300
P1596 → bd388
D3ff → 96300
F5d5 → ff399
O14ed → c34eN
C2db → b74aJ
Y24105 → 11155U
A0b7 → 96300
Z25cf → 7b366
S18b1 → c9344

参考 1

vgalaxy@vgalaxy-VirtualBox:~/Lab/linklab$ hexdump -s 0x2a0 -n 0x6c phase3.o
00002a0 00b7 0000 00c9 0000 00db 0000 00ff 0000
00002b0 00c3 0000 00d5 0000 008d 0000 00f9 0000
00002c0 009f 0000 007b 0000 0117 0000 0084 0000
00002d0 011d 0000 00e7 0000 00ed 0000 0096 0000
00002e0 00e1 0000 00a5 0000 00b1 0000 00bd 0000
00002f0 0111 0000 00f3 0000 00ab 0000 010b 0000
0000300 0105 0000 00cf 0000 4700 4343
000030c

参考 2

7b: c6 45 f7 36 movb $0x36,-0x9(%ebp)
84: c6 45 f7 22 movb $0x22,-0x9(%ebp)
8d: c6 45 f7 29 movb $0x29,-0x9(%ebp)
96: c6 45 f7 30 movb $0x30,-0x9(%ebp)
9f: c6 45 f7 23 movb $0x23,-0x9(%ebp)
a5: c6 45 f7 38 movb $0x38,-0x9(%ebp)
ab: c6 45 f7 64 movb $0x64,-0x9(%ebp)
b1: c6 45 f7 5a movb $0x5a,-0x9(%ebp)
b7: c6 45 f7 4a movb $0x4a,-0x9(%ebp)
bd: c6 45 f7 38 movb $0x38,-0x9(%ebp)
c3: c6 45 f7 4e movb $0x4e,-0x9(%ebp)
c9: c6 45 f7 34 movb $0x34,-0x9(%ebp)
cf: c6 45 f7 69 movb $0x69,-0x9(%ebp)
d5: c6 45 f7 72 movb $0x72,-0x9(%ebp)
db: c6 45 f7 77 movb $0x77,-0x9(%ebp)
e1: c6 45 f7 37 movb $0x37,-0x9(%ebp)
e7: c6 45 f7 2d movb $0x2d,-0x9(%ebp)
ed: c6 45 f7 61 movb $0x61,-0x9(%ebp)
f3: c6 45 f7 38 movb $0x38,-0x9(%ebp)
f9: c6 45 f7 71 movb $0x71,-0x9(%ebp)
ff: c6 45 f7 39 movb $0x39,-0x9(%ebp)
105: c6 45 f7 50 movb $0x50,-0x9(%ebp)
10b: c6 45 f7 67 movb $0x67,-0x9(%ebp)
111: c6 45 f7 55 movb $0x55,-0x9(%ebp)
117: c6 45 f7 68 movb $0x68,-0x9(%ebp)
11d: c6 45 f7 63 movb $0x63,-0x9(%ebp)

对应修改即可

phase4 - 可重定位目标文件

修改 relocation section 的内容

readelf

Section Headers

Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 00027c 00 AX 0 0 1
[ 2] .rel.text REL 00000000 000738 0000b8 08 I 12 1 4
[ 3] .data PROGBITS 00000000 0002c0 000048 00 WA 0 0 32
[ 4] .rel.data REL 00000000 0007f0 000020 08 I 12 3 4
[ 5] .bss NOBITS 00000000 000308 000000 00 WA 0 0 1
[ 6] .rodata PROGBITS 00000000 000320 000100 00 A 0 0 32
[ 7] .rel.rodata REL 00000000 000810 000040 08 I 12 6 4
[ 8] .comment PROGBITS 00000000 000420 00001d 01 MS 0 0 1
[ 9] .note.GNU-stack PROGBITS 00000000 00043d 000000 00 0 0 1
[10] .eh_frame PROGBITS 00000000 000440 0000d8 00 A 0 0 4
[11] .rel.eh_frame REL 00000000 000850 000030 08 I 12 10 4
[12] .symtab SYMTAB 00000000 000518 000190 10 13 9 4
[13] .strtab STRTAB 00000000 0006a8 00008f 00 0 0 1
[14] .shstrtab STRTAB 00000000 000880 000067 00 0 0 1

Relocation section

Relocation section '.rel.text' at offset 0x738 contains 23 entries:
Offset Info Type Sym.Value Sym. Name
00000000 00000000 R_386_NONE
0000007f 00000501 R_386_32 00000000 .rodata
00000000 00000000 R_386_NONE
00000000 00000000 R_386_NONE
000000b5 00000d01 R_386_32 00000020 CMKbeL
000000c7 00000d01 R_386_32 00000020 CMKbeL
000000d6 00000d01 R_386_32 00000020 CMKbeL
000000e7 00000d01 R_386_32 00000020 CMKbeL
00000103 00000e01 R_386_32 00000038 vvWaVk
00000000 00000000 R_386_NONE
00000000 00000000 R_386_NONE
00000122 00000e01 R_386_32 00000038 vvWaVk
00000142 00001302 R_386_PC32 00000000 strlen
00000166 00001101 R_386_32 00000080 KvXOBb
0000016c 00000e01 R_386_32 00000038 vvWaVk
000001ca 00001302 R_386_PC32 00000000 strlen
000001ee 00001101 R_386_32 00000080 KvXOBb
000001f4 00000e01 R_386_32 00000038 vvWaVk
00000000 00000000 R_386_NONE
00000258 00001501 R_386_32 0000003c encoder
00000260 00000c01 R_386_32 0000002c OdZAJybs
0000026d 00000c01 R_386_32 0000002c OdZAJybs
00000272 00001702 R_386_PC32 00000000 puts
Relocation section '.rel.data' at offset 0x7f0 contains 4 entries:
Offset Info Type Sym.Value Sym. Name
00000028 00000501 R_386_32 00000000 .rodata
00000000 00000000 R_386_NONE
00000040 00001401 R_386_32 000001bd encode_2
00000044 00001601 R_386_32 00000244 do_phase
Relocation section '.rel.rodata' at offset 0x810 contains 8 entries:
Offset Info Type Sym.Value Sym. Name
00000060 00000201 R_386_32 00000000 .text
00000064 00000201 R_386_32 00000000 .text
00000068 00000201 R_386_32 00000000 .text
0000006c 00000201 R_386_32 00000000 .text
00000070 00000201 R_386_32 00000000 .text
00000074 00000201 R_386_32 00000000 .text
00000078 00000201 R_386_32 00000000 .text
0000007c 00000201 R_386_32 00000000 .text

代码框架

/* NOTE: Those capitalized variable names in following code will be substituted by different actual names in the module. */
char BUFFER[] = ......;
const int CODE_TRAN_ARRAY[] = ......;
int CODE = ......;
const char DICT[] = ......;
...... // Definitions of other variables
int transform_code( int code, int mode ) {
switch ( CODE_TRAN_ARRAY[mode] ... )
{
case 0: ......
case 1: ......
......
default: ......
}
return code;
}
void generate_code( int cookie ) {
... = cookie;
for ( i = 0; i < ...; i++ ) {
... = transform_code( ..., i );
}
}
int encode_1( char* str ) {
......
for (i = 0; i < n; i++) {
str[i] = DICT[str[i]] ...;
if (str[i] < 0x20 || str[i] > 0x7E)
str[i] = ...;
}
......
}
int encode_2( char* str ) {
......
// Similar to encode_1
......
}
typedef int (*CODER)(char*);
CODER encoder[] = { ...... };
void do_phase() {
generate_code(...);
......; // Call one encoder here
printf("%s\n", ...);
}
......

.rel.text 缺失 6 个,.rel.data 缺失 1 个

CMKbeL 对应 CODE_TRAN_ARRAY

6d: 8b 04 85 00 00 00 00 mov 0x0(,%eax,4),%eax
8d: 8b 04 85 00 00 00 00 mov 0x0(,%eax,4),%eax
a1: 8b 04 85 00 00 00 00 mov 0x0(,%eax,4),%eax
b2: 8b 04 85 00 00 00 00 mov 0x0(,%eax,4),%eax
c4: 8b 04 85 00 00 00 00 mov 0x0(,%eax,4),%eax
d3: 8b 04 85 00 00 00 00 mov 0x0(,%eax,4),%eax
e4: 8b 04 85 00 00 00 00 mov 0x0(,%eax,4),%eax

未缺失

000000b5 00000d01 R_386_32 00000020 CMKbeL
000000c7 00000d01 R_386_32 00000020 CMKbeL
000000d6 00000d01 R_386_32 00000020 CMKbeL
000000e7 00000d01 R_386_32 00000020 CMKbeL

缺失 70 / 90 / a4

vvWaVk 对应 CODE

00000103 00000e01 R_386_32 00000038 vvWaVk
00000122 00000e01 R_386_32 00000038 vvWaVk
0000016c 00000e01 R_386_32 00000038 vvWaVk
000001f4 00000e01 R_386_32 00000038 vvWaVk

未缺失

000000f9 <generate_code>:
102: a3 00 00 00 00 mov %eax,0x0
121: a3 00 00 00 00 mov %eax,0x0
00000135 <encode_1>:
16a: 8b 15 00 00 00 00 mov 0x0,%edx
000001bd <encode_2>:
1f2: 8b 15 00 00 00 00 mov 0x0,%edx

KvXOBb 对应 DICT

00000166 00001101 R_386_32 00000080 KvXOBb
000001ee 00001101 R_386_32 00000080 KvXOBb

未缺失

00000135 <encode_1>:
163: 0f b6 80 00 00 00 00 movzbl 0x0(%eax),%eax
000001bd <encode_2>:
1eb: 0f b6 80 00 00 00 00 movzbl 0x0(%eax),%eax

OdZAJybs 对应 BUFFER

00000260 00000c01 R_386_32 0000002c OdZAJybs
0000026d 00000c01 R_386_32 0000002c OdZAJybs

未缺失

00000244 <do_phase>:
25f: 68 00 00 00 00 push $0x0
26c: 68 00 00 00 00 push $0x0

puts

00000272 00001702 R_386_PC32 00000000 puts

对应

00000244 <do_phase>:
271: e8 fc ff ff ff call 272 <do_phase+0x2e>

encoder

00000258 00001501 R_386_32 0000003c encoder

对应

00000244 <do_phase>:
257: a1 00 00 00 00 mov 0x0,%eax

strlen

00000142 00001302 R_386_PC32 00000000 strlen
000001ca 00001302 R_386_PC32 00000000 strlen

对应

00000135 <encode_1>:
141: e8 fc ff ff ff call 142 <encode_1+0xd>
000001bd <encode_2>:
1c9: e8 fc ff ff ff call 1ca <encode_2+0xd>

注意下面两个没有出现在 relocation section 中,可以通过范围来判断:

00000135 <encode_1>:
14c: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp)
000001bd <encode_2>:
1d4: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp)

还有

000000f9 <generate_code>:
107: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp)

这是 for 循环初始化循环变量

不要以为操作数是 00 00 00 00 就需要重定位

综上,.rel.text 剩下的缺失如下:

000000f9 <generate_code>:
110: a1 00 00 00 00 mov 0x0,%eax
119: e8 fc ff ff ff call 11a <generate_code+0x21>
00000244 <do_phase>:
24f: e8 fc ff ff ff call 250 <do_phase+0xc>

这里应该对应 CODE,即 vvWaVk,为调用 transform_code 准备第一个参数

110: a1 00 00 00 00 mov 0x0,%eax

这里则是调用 transform_code

119: e8 fc ff ff ff call 11a <generate_code+0x21>

这里则是调用 generate_code

24f: e8 fc ff ff ff call 250 <do_phase+0xc>

分析完 .rel.text 后,我们研究一下重定位表项的数据结构

typedef struct
{
Elf32_Addr r_offset; /* Address */
Elf32_Word r_info; /* Relocation type and symbol index */
} Elf32_Rel;
#define ELF32_R_SYM(val) ((val) >> 8)
#define ELF32_R_TYPE(val) ((val) & 0xff)
#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))

/usr/include/elf.h

定位 .rel.text 的二进制表示

vgalaxy@vgalaxy-VirtualBox:~/Lab/linklab$ hexdump -s 0x738 -n 0xb8 phase4.o
0000738 0000 0000 0000 0000 007f 0000 0501 0000
0000748 0000 0000 0000 0000 0000 0000 0000 0000
0000758 00b5 0000 0d01 0000 00c7 0000 0d01 0000
0000768 00d6 0000 0d01 0000 00e7 0000 0d01 0000
0000778 0103 0000 0e01 0000 0000 0000 0000 0000
0000788 0000 0000 0000 0000 0122 0000 0e01 0000
0000798 0142 0000 1302 0000 0166 0000 1101 0000
00007a8 016c 0000 0e01 0000 01ca 0000 1302 0000
00007b8 01ee 0000 1101 0000 01f4 0000 0e01 0000
00007c8 0000 0000 0000 0000 0258 0000 1501 0000
00007d8 0260 0000 0c01 0000 026d 0000 0c01 0000
00007e8 0272 0000 1702 0000
00007f0

先补充前三个缺失 70 / 90 / a4

00000070 00000d01 R_386_32 00000020 CMKbeL
00000090 00000d01 R_386_32 00000020 CMKbeL
000000a4 00000d01 R_386_32 00000020 CMKbeL
000000b5 00000d01 R_386_32 00000020 CMKbeL
000000c7 00000d01 R_386_32 00000020 CMKbeL
000000d6 00000d01 R_386_32 00000020 CMKbeL
000000e7 00000d01 R_386_32 00000020 CMKbeL

第四个

00000111 00000e01 R_386_32 00000038 vvWaVk

下面两个是 PC 相对寻址,r_info 部分高 24 位是符号索引,低 8 位是重定位类型

看一看符号表

Symbol table '.symtab' contains 25 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS phase4.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 5
5: 00000000 0 SECTION LOCAL DEFAULT 6
6: 00000000 0 SECTION LOCAL DEFAULT 9
7: 00000000 0 SECTION LOCAL DEFAULT 10
8: 00000000 0 SECTION LOCAL DEFAULT 8
9: 00000000 38 OBJECT GLOBAL DEFAULT 3 BvuGmt
10: 00000000 103 FUNC GLOBAL DEFAULT 1 nndZqWCYPw
11: 00000028 4 OBJECT GLOBAL DEFAULT 3 phase_id
12: 0000002c 11 OBJECT GLOBAL DEFAULT 3 OdZAJybs
13: 00000020 64 OBJECT GLOBAL DEFAULT 6 CMKbeL
14: 00000038 4 OBJECT GLOBAL DEFAULT 3 vvWaVk
15: 00000067 146 FUNC GLOBAL DEFAULT 1 transform_code
16: 000000f9 60 FUNC GLOBAL DEFAULT 1 generate_code
17: 00000080 128 OBJECT GLOBAL DEFAULT 6 KvXOBb
18: 00000135 136 FUNC GLOBAL DEFAULT 1 encode_1
19: 00000000 0 NOTYPE GLOBAL DEFAULT UND strlen
20: 000001bd 135 FUNC GLOBAL DEFAULT 1 encode_2
21: 0000003c 8 OBJECT GLOBAL DEFAULT 3 encoder
22: 00000244 56 FUNC GLOBAL DEFAULT 1 do_phase
23: 00000000 0 NOTYPE GLOBAL DEFAULT UND puts
24: 00000044 4 OBJECT GLOBAL DEFAULT 3 phase

举个例子:

00000142 00001302 R_386_PC32 00000000 strlen

0x13 → 19 → strlen

所以第五个为 11a 0f02,第六个为 250 1002

0000011a 00000f02 R_386_PC32 00000067 transform_code
00000250 00001002 R_386_PC32 000000f9 generate_code

最后一个在 .rel.data

Relocation section '.rel.data' at offset 0x7f0 contains 4 entries:
Offset Info Type Sym.Value Sym. Name
00000028 00000501 R_386_32 00000000 .rodata
00000000 00000000 R_386_NONE
00000040 00001401 R_386_32 000001bd encode_2
00000044 00001601 R_386_32 00000244 do_phase

看一下 .data

vgalaxy@vgalaxy-VirtualBox:~/Lab/linklab$ hexdump -s 0x2c0 -n 0x48 phase4.o
00002c0 acd0 3cd3 36b1 659e e49b 4e58 fe3d d31a
00002d0 47a0 c1b4 a3b9 e15a eb1d c783 6cf0 26a2
00002e0 1d2a 8b39 04ec 0000 0000 0000 3830 3930
00002f0 4a4e 3055 3436 0000 ffff ffff 0000 0000
0000300 0000 0000 0000 0000
0000308

猜测在偏移 0x3c 处为 encode_1,即 3c 1201

0000003c 00001201 R_386_32 00000135 encode_1

但是最后的输出似乎和实验指南中不一致:

vgalaxy@vgalaxy-VirtualBox:~/Lab/linklab$ make phase4
gcc -m32 -no-pie -o linkbomb main.o phase4.o
./linkbomb
UWU??$]UA8

算了,不想再看了……

_end