2022年5月27日 星期五

gcc’s enable “–enable-default-pie” option

the 1st edition: 20220329
gcc 從某個版本之後預設開啟了 –enable-default-pie, 從那一版開始我不知道, 但是 gcc 5 沒有開啟這功能。可以用 gcc -v 來查看有沒開啟這功能。

gcc’s enable “–enable-default-pie” option make you stuck at “relocation R_X86_64_32S against …” error

這個參數主要影響是編譯之後的組合語言是不是和位址有關, 也就是這個變數的位址不是寫死, 是透過一些方法去取得, 所以這個執行檔不管被載入到哪裡, 裡頭的變數都可以正常取得, 如果是寫死這個變數的位址, 那這個執行檔被載入到不同位址時, 這個寫死的變數位址就不見得正確。

這會影響什麼呢? 如果你是單純的使用者就沒什麼差異 (程式執行慢了一點), 我的話有時候要看反組譯的組合語言, 有著 pie 的組合語言會比較難看懂, 所以我一般都會下 -fno-pic, -no-pie 來觀察 objdump 之後的組合語言。

通常會影響到全域變數的觀察。我是透過 bare-metal 程式來觀察 elf, bare-metal 的程式很簡潔, 所以很好觀察 elf 所有欄位。 cb.c L10 定義了一個 bbb 全域變數, L42 ++ 它。

cb.c
 1 __asm__(".code16gcc\n");
 2 /*
 3  * c bootloader
 4  */
 5 
 7 
 8 void main(const char   *s);
 9 
10 int bbb=0; // test bss section
11 
34   while(1);
35 }
36 
37 #ifndef POINTER_TEST
38 void main(const char   *s)
39 {
40   while(*s)
41   {
42     ++bbb;
43     __asm__ __volatile__ ("int  $0x10" : : "a"(0x0E00 | *s), "b"(7));
44     s++;
45   }
46 }
47 #endif

先觀察使用 -fno-pic 編譯出來的版本。

list 1 objdump -m i8086 -dS cb.elf -fno-pic
 1 
 2 cb.elf:     file format elf32-i386
 3 
 4 
 5 Disassembly of section .text:
 6 
 7 00007c00 <WinMain>:
 8 void main(const char   *s);
 9 
10 int bbb=0; // test bss section
11 
12 #ifndef POINTER_TEST
13 void main(const char   *s)
14 {
15     7c6c:	66 55                	push   %ebp
16     7c6e:	66 89 e5             	mov    %esp,%ebp
17     7c71:	66 53                	push   %ebx
18   while(*s)
19     7c73:	eb 2e                	jmp    7ca3 <main+0x37>
20   {
21     ++bbb;
22     7c75:	66 a1 10 7d          	mov    0x7d10,%eax
23     7c79:	66 83 c0 01          	add    $0x1,%eax

24     7c7d:	66 a3 10 7d          	mov    %eax,0x7d10
25     __asm__ __volatile__ ("int  $0x10" : : "a"(0x0E00 | *s), "b"(7));
26     7c81:	67 66 8b 45 08       	mov    0x8(%ebp),%eax
27     7c86:	67 66 0f b6 00       	movzbl (%eax),%eax
28     7c8b:	66 0f be c0          	movsbl %al,%eax
29     7c8f:	80 cc 0e             	or     $0xe,%ah
30     7c92:	66 ba 07 00 00 00    	mov    $0x7,%edx
31     7c98:	66 89 d3             	mov    %edx,%ebx
32     7c9b:	cd 10                	int    $0x10
33     s++;
34     7c9d:	67 66 83 45 08 01    	addl   $0x1,0x8(%ebp)
35   while(*s)
36     7ca3:	67 66 8b 45 08       	mov    0x8(%ebp),%eax
37     7ca8:	67 66 0f b6 00       	movzbl (%eax),%eax
38     7cad:	84 c0                	test   %al,%al
39     7caf:	75 c4                	jne    7c75 <main+0x9>
40   }
41 }
42     7cb1:	90                   	nop
43     7cb2:	66 5b                	pop    %ebx
44     7cb4:	66 5d                	pop    %ebp
45     7cb6:	66 c3                	retl   


可以從 list 2 L82 看到 bbb 的位址是 0x7d10, 對照 list 1 L22, L23, 可以看到就是把 bbb 做 +1 的動作。

list 2 cb.elf -fno-pic
 1 ELF Header:
 2   Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
 3   Class:                             ELF32
 4   Data:                              2's complement, little endian
 5   Version:                           1 (current)
 6   OS/ABI:                            UNIX - System V
 7   ABI Version:                       0
 8   Type:                              EXEC (Executable file)
 9   Machine:                           Intel 80386
10   Version:                           0x1
11   Entry point address:               0x7c00
12   Start of program headers:          52 (bytes into file)
13   Start of section headers:          4428 (bytes into file)
14   Flags:                             0x0
15   Size of this header:               52 (bytes)
16   Size of program headers:           32 (bytes)
17   Number of program headers:         3
18   Size of section headers:           40 (bytes)
19   Number of section headers:         13
20   Section header string table index: 12
21 

44 
45 Program Headers:
46   Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
47   LOAD           0x000000 0x00007000 0x00007000 0x00d1d 0x00d1d RWE 0x1000
48   LOAD           0x000d1d 0x00007d1d 0x00007dfe 0x00002 0x00002 RW  0x1000
49   GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
50 
51  Section to Segment mapping:
52   Segment Sections...
53    00     .text .eh_frame .data 
54    01     .sig 
55    02     
56 
57 There is no dynamic section in this file.
58 
59 There are no relocations in this file.
60 
61 The decoding of unwind sections for machine type Intel 80386 is not currently supported.
62 
63 Symbol table '.symtab' contains 18 entries:
64    Num:    Value  Size Type    Bind   Vis      Ndx Name
65      0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
66      1: 00007c00     0 SECTION LOCAL  DEFAULT    1 
67      2: 00007cb8     0 SECTION LOCAL  DEFAULT    2 
68      3: 00007d10     0 SECTION LOCAL  DEFAULT    3 
69      4: 00007d1d     0 SECTION LOCAL  DEFAULT    4 
70      5: 00000000     0 SECTION LOCAL  DEFAULT    5 
71      6: 00000000     0 SECTION LOCAL  DEFAULT    6 
72      7: 00000000     0 SECTION LOCAL  DEFAULT    7 
73      8: 00000000     0 SECTION LOCAL  DEFAULT    8 
74      9: 00000000     0 SECTION LOCAL  DEFAULT    9 
75     10: 00000000     0 FILE    LOCAL  DEFAULT  ABS cb.c
76     11: 00007cb8     0 NOTYPE  GLOBAL DEFAULT    1 _text_end
77     12: 00007d1d     0 NOTYPE  GLOBAL DEFAULT    3 _data_end
78     13: 00007c00     0 NOTYPE  GLOBAL DEFAULT    1 _text
79     14: 00007c6c    76 FUNC    GLOBAL DEFAULT    1 main
80     15: 00007c00   108 FUNC    GLOBAL DEFAULT    1 WinMain
81     16: 00007d10     0 NOTYPE  GLOBAL DEFAULT    3 _data
82     17: 00007d10     4 OBJECT  GLOBAL DEFAULT    3 bbb


再來看看 list 3, list 4 使用了 -fpic 的版本, bbb 位址在 0x7d6c, 但是在 list 3 卻看不到存取這個位址的程式碼。 list 3 L24 ~ 26 一樣做 bbb +1 的動作, 但用到 edx 是從 L18 來的, 一個很特別的 function - _x86.get_pc_thunk.dx, 細節就不說了, 反正就是運用這個 fuction 間接取得 bbb 的位址。

list 3. ojdump -m i8086 -dS cb.elf cb pic
 1 
 2 cb.elf:     file format elf32-i386
 3 
 4 
 5 Disassembly of section .text:
 6 
 7 00007c00 <WinMain>:
 8 void main(const char   *s);
 9 
10 int bbb=0; // test bss section
11 
12 #ifndef POINTER_TEST
13 void main(const char   *s)
14 {
15     7c7c:	66 55                	push   %ebp
16     7c7e:	66 89 e5             	mov    %esp,%ebp
17     7c81:	66 53                	push   %ebx
18     7c83:	66 e8 5b 00 00 00    	calll  7ce4 <__x86.get_pc_thunk.dx>
19     7c89:	66 81 c2 f3 00 00 00 	add    $0xf3,%edx
20   while(*s)
21     7c90:	eb 36                	jmp    7cc8 <main+0x4c>
22   {
23     ++bbb;
24     7c92:	67 66 8b 82 f0 ff ff 	mov    -0x10(%edx),%eax
25     7c99:	ff 
26     7c9a:	66 83 c0 01          	add    $0x1,%eax
27     7c9e:	67 66 89 82 f0 ff ff 	mov    %eax,-0x10(%edx)
28     7ca5:	ff 
29     __asm__ __volatile__ ("int  $0x10" : : "a"(0x0E00 | *s), "b"(7));
30     7ca6:	67 66 8b 45 08       	mov    0x8(%ebp),%eax
31     7cab:	67 66 0f b6 00       	movzbl (%eax),%eax
32     7cb0:	66 0f be c0          	movsbl %al,%eax
33     7cb4:	80 cc 0e             	or     $0xe,%ah
34     7cb7:	66 b9 07 00 00 00    	mov    $0x7,%ecx
35     7cbd:	66 89 cb             	mov    %ecx,%ebx
36     7cc0:	cd 10                	int    $0x10
37     s++;
38     7cc2:	67 66 83 45 08 01    	addl   $0x1,0x8(%ebp)
39   while(*s)
40     7cc8:	67 66 8b 45 08       	mov    0x8(%ebp),%eax
41     7ccd:	67 66 0f b6 00       	movzbl (%eax),%eax
42     7cd2:	84 c0                	test   %al,%al
43     7cd4:	75 bc                	jne    7c92 <main+0x16>
44   }
45 }
46     7cd6:	90                   	nop
47     7cd7:	66 5b                	pop    %ebx
48     7cd9:	66 5d                	pop    %ebp
49     7cdb:	66 c3                	retl   
50 
51 Disassembly of section .text.__x86.get_pc_thunk.ax:
52 
53 00007cdd <__x86.get_pc_thunk.ax>:
54     7cdd:	67 66 8b 04 24       	mov    (%esp),%eax
55     7ce2:	66 c3                	retl   
56 
57 Disassembly of section .text.__x86.get_pc_thunk.dx:
58 
59 00007ce4 <__x86.get_pc_thunk.dx>:
60     7ce4:	67 66 8b 14 24       	mov    (%esp),%edx
61     7ce9:	66 c3                	retl   


list 5. cb.elf pic
 1 ELF Header:
 2   Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
 3   Class:                             ELF32
 4   Data:                              2's complement, little endian
 5   Version:                           1 (current)
 6   OS/ABI:                            UNIX - System V
 7   ABI Version:                       0
 8   Type:                              EXEC (Executable file)
 9   Machine:                           Intel 80386
10   Version:                           0x1
11   Entry point address:               0x7c00
12   Start of program headers:          52 (bytes into file)
13   Start of section headers:          4772 (bytes into file)
14   Flags:                             0x0
15   Size of this header:               52 (bytes)
16   Size of program headers:           32 (bytes)
17   Number of program headers:         3
18   Size of section headers:           40 (bytes)
19   Number of section headers:         16
20   Section header string table index: 15
21 
65 
66 Symbol table '.symtab' contains 25 entries:
67    Num:    Value  Size Type    Bind   Vis      Ndx Name
68      0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
69      1: 00007c00     0 SECTION LOCAL  DEFAULT    1 
70      2: 00007cdd     0 SECTION LOCAL  DEFAULT    2 
71      3: 00007ce4     0 SECTION LOCAL  DEFAULT    3 
72      4: 00007cec     0 SECTION LOCAL  DEFAULT    4 
73      5: 00007d6c     0 SECTION LOCAL  DEFAULT    5 
74      6: 00007d7c     0 SECTION LOCAL  DEFAULT    6 
75      7: 00007d88     0 SECTION LOCAL  DEFAULT    7 
76      8: 00000000     0 SECTION LOCAL  DEFAULT    8 
77      9: 00000000     0 SECTION LOCAL  DEFAULT    9 
78     10: 00000000     0 SECTION LOCAL  DEFAULT   10 
79     11: 00000000     0 SECTION LOCAL  DEFAULT   11 
80     12: 00000000     0 SECTION LOCAL  DEFAULT   12 
81     13: 00000000     0 FILE    LOCAL  DEFAULT  ABS cb.c
82     14: 00000000     0 FILE    LOCAL  DEFAULT  ABS 
83     15: 00007d7c     0 OBJECT  LOCAL  DEFAULT    6 _GLOBAL_OFFSET_TABLE_
84     16: 00007cdd     0 NOTYPE  GLOBAL DEFAULT    1 _text_end
85     17: 00007cdd     0 FUNC    GLOBAL HIDDEN     2 __x86.get_pc_thunk.ax
86     18: 00007ce4     0 FUNC    GLOBAL HIDDEN     3 __x86.get_pc_thunk.dx
87     19: 00007d79     0 NOTYPE  GLOBAL DEFAULT    5 _data_end
88     20: 00007c00     0 NOTYPE  GLOBAL DEFAULT    1 _text
89     21: 00007c7c    97 FUNC    GLOBAL DEFAULT    1 main
90     22: 00007c00   124 FUNC    GLOBAL DEFAULT    1 WinMain
91     23: 00007d6c     0 NOTYPE  GLOBAL DEFAULT    5 _data
92     24: 00007d6c     4 OBJECT  GLOBAL DEFAULT    5 bbb

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。