g++/gcc編譯器——常用知識(一)


基本的命令

把一個源文件,編譯成可執行文件,經過了預處理、匯編、編譯與鏈接。

-E: 對目標文件只進行預處理,生成的還是源碼。

例如:g++ -E 1.cpp -o 1.i

-S: 對目標文件進行預處理、編譯操作,生成匯編代碼。

例如:g++ -S 1.cpp -o 1.s

-o: 對目標文件進行預處理、編譯和匯編操作,生效obj文件。

例如:g++ -c 1.cpp -o 1.o

-fsyntax-only : 對代碼只進行語法檢查,不做其它任何動作。

常用安全編譯選項

ALSR 地址隨機化處理

系統級的配置,不屬於gcc編譯器的范疇。

棧保護

棧保護在編譯階段進行,所以下面的參數是傳給編譯器的。

直接上英文, 更容易明白。

  • -fstack-protector:

    Emit extra code to check for buffer overflows, such as stack smashing attacks.
    This is done by adding a guard variable to functions with vulnerable objects.
    This includes functions that call alloca, and functions with buffers larger than
    or equal to 8 bytes. The guards are initialized when a function is entered and
    then checked when the function exits. If a guard check fails, an error message
    is printed and the program exits. Only variables that are actually allocated
    on the stack are considered, optimized away variables or variables allocated in
    registers don’t count.

  • -fstack-protector-all:

    Like ‘-fstack-protector’ except that all functions are protected.

  • -fstack-protector-strong:

    Like ‘-fstack-protector’ but includes additional functions to be protected —
    those that have local array definitions, or have references to local frame addresses. Only variables that are actually allocated on the stack are considered,
    optimized away variables or variables allocated in registers don’t count.

  • -fstack-protector-explicit:

    Like ‘-fstack-protector’ but only protects those functions which have the
    stack_protect attribute.

說明:

  1. 原理就是在緩沖區與函數返回控制信息之間插入一個哨兵變量, 當緩沖區溢出時, 哨兵變量的值會首先被覆蓋掉, 這樣就能判斷發生了溢出攻擊。
  2. 使用堆棧保護選項在對字符數組進行溢出防護的同時,還有意將局部變量中的數組放到函數棧的高地址,而將其它變量放在低地址。
  3. 性能損失度:fstack-protector-all > fstack-protector-strong > fstack-protector.

堆棧不可執行保護

該保護作用於鏈接階段,所以需要把參數傳遞給鏈接器。 使用-Wl,<optional>的格式傳遞給鏈接器。

使用格式為:-Wl, -z noexecstack 選項。可用於動態庫、ELF格式的可執行文件。

作用原理:首先,緩沖區溢出成功后都是通過執行shellcode來達到攻擊目的的, 而shellcode基本都是放到緩沖區中,只要操作系統限制了堆棧內存區域不可執行狀態就可以,一旦被攻擊就報錯並返回。

GOT表的保護

該保護作用於鏈接階段, 同樣把參數傳遞給鏈接器。

使用格式:

  • -Wl, -z relro: Create RELRO program header, RELRO表示 relocation read only, 重定位段為只讀。 GOT表就是用於重定位的。
  • -Wl, -z now: Mark object non-lazy runtime binding

作用原理:動態鏈的ELF二進制程序使用稱為全局偏移表(GOT)的的查找表去動態解析位於共享庫的函數。攻擊者通過緩沖區溢出修改GOT表項的函數地址來達到攻擊目的。通過增加RELRO選項可以防止GOT表被惡意重寫。 另外,GOT表的保護會影響到程序的加載速度。

地址無關的代碼 -fPIC

作用階段為編譯器,參數格式為:-fPIC 或者 -fpic.

  • -fpic: Generate position-independent code (PIC) suitable for use in a shared library,
    if supported for the target machine. Such code accesses all constant addresses
    through a global offset table (GOT). The dynamic loader resolves the GOT
    entries when the program starts (the dynamic loader is not part of GCC; it
    is part of the operating system). If the GOT size for the linked executable
    exceeds a machine-specific maximum size, you get an error message from the
    linker indicating that ‘-fpic’ does not work; in that case, recompile with ‘-fPIC’
    instead. (These maximums are 8k on the SPARC, 28k on AArch64 and 32k on
    the m68k and RS/6000. The x86 has no such limit.)
    Position-independent code requires special support, and therefore works only on
    certain machines. For the x86, GCC supports PIC for System V but not for the
    Sun 386i. Code generated for the IBM RS/6000 is always position-independent.
    When this flag is set, the macros pic and PIC are defined to 1.

  • -fPIC: If supported for the target machine, emit position-independent code, suitable
    for dynamic linking and avoiding any limit on the size of the global offset table.
    This option makes a difference on AArch64, m68k, PowerPC and SPARC.
    Position-independent code requires special support, and therefore works only
    on certain machines

地址無關可執行 -fPIE

作用於編譯器, 參數格式為:-fPIE 或者 -fPIC, 與fPIC非常類似。

These options are similar to ‘-fpic’ and ‘-fPIC’, but the generated positionindependent code can be
only linked into executables. Usually these options are used to compile code that will be linked using
the ‘-pie’ GCC option.

說明: PIE是GCC與操作系統的產物,提供了地址無關的功能。 ASLR是基礎,只有操作系統開啟了ASLR功能時,-fpie選項添加的隨機化特征才會在程序加載和運行時展現。

棧檢查 -fstack-check

stack-check選項作用於編譯器。它會在每個棧空間最低層部分設置一個安全緩沖區,如果函數中申請的棧空間進入了該區域,就會觸發異常。對應的英文資料如下:

Generate code to verify that you do not go beyond the boundary of the stack. You should specify this flag if you are running in an environment with multiple threads, but you only rarely need to specify it in a single-threaded environment since stack overflow is automatically detected on nearly all systems if there is only one stack.
Note that this switch does not actually cause checking to be done; the operating system or the language runtime must do that. The switch causes generation of code to ensure that they see the stack being extended.

整數溢出檢查 -ftrapv

編譯選項,使用了它之后,在執行有符號整數間的加減乘運算時,不是通過CPU的指令,而是用包含了GCC附屬庫的libgcc.c里面的函數來實現。對性能影響比較大。

常用告警選項

-w 選項:

禁止了所有的告警(完全不推薦使用)

-Werror選項:

把所有的警告標識為錯誤。

-Werror= ** 選項:

把指定的警告標識為錯誤。

- Wno-error= **選項:

取消指定的警告為錯誤。

- Wchar-subscripts 選項:

對數組下標為char類型給出警告。這是一個常見的錯誤。因為大多數char類型為有符號數。

- Wfatal-errors 選項:

編譯器遇到第一個錯誤時,就停止下來,不繼續檢查更多錯誤。
我不建議使用, 每次編譯就出一個錯誤,多浪費時間。

-Wreturn-type 選項:

Warn whenever a function is defined with a return type that defaults to int.
當函數定義了非void類型的返回值類型但是沒有return時,給出警告。
當函數定義中,沒有控制所有的返回值路徑時,也會給出警告。

-Wunused選項:

定義了變量不使用,一個函數聲明為靜態但不定義,函數有返回值,調用了函數不使用(想要避免,加void強轉一下), 等等等等, 都會給警告。具體包含了以下這些:

-Wunused-but-set-parameter
-Wunused-but-set-variable
-Wunused-const-variable
-Wunused-const-variable=
-Wunused-dummy-argument
-Wunused-function
-Wunused-label
-Wunused-local-typedefs
-Wunused-macros
-Wunused-parameter
-Wunused-result
-Wunused-value
-Wunused-variable

-Wuninitialized 選項:

變量不初始化就使用, 給警告。
c++類的能成員變量為非靜態的引用或者const變量, 如果不使用構造函數進行初始化, 給警告。

Warn if an automatic variable is used without first being initialized. In C++,
warn if a non-static reference or non-static const member appears in a class
without constructors.

Wsign-compare 選項:

對有符號數與無符號數的比較,給出警告。

-Wall 選項:

它打開了一大堆常用的編譯告警選項,能覆蓋大部分的需求了。

-Waddress
-Warray-bounds=1 (only with ‘-O2’)
-Wbool-compare
-Wbool-operation
-Wc++11-compat -Wc++14-compat
-Wcatch-value (C++ and Objective-C++ only)
-Wchar-subscripts
-Wcomment
-Wduplicate-decl-specifier (C and Objective-C only)
-Wenum-compare (in C/ObjC; this is on by default in C++)
-Wenum-conversion in C/ObjC;
-Wformat
-Wformat-overflow
-Wformat-truncation
-Wint-in-bool-context
-Wimplicit (C and Objective-C only)
-Wimplicit-int (C and Objective-C only)
-Wimplicit-function-declaration (C and Objective-C only)
-Winit-self (only for C++)
-Wlogical-not-parentheses
-Wmain (only for C/ObjC and unless ‘-ffreestanding’)
-Wmaybe-uninitialized
-Wmemset-elt-size
-Wmemset-transposed-args
-Wmisleading-indentation (only for C/C++)
-Wmissing-attributes
-Wmissing-braces (only for C/ObjC)
-Wmultistatement-macros
-Wnarrowing (only for C++)
-Wnonnull
-Wnonnull-compare
-Wopenmp-simd
-Wparentheses
-Wpessimizing-move (only for C++)
-Wpointer-sign
-Wreorder
-Wrestrict
-Wreturn-type
-Wsequence-point
-Wsign-compare (only in C++)
-Wsizeof-pointer-div
-Wsizeof-pointer-memaccess
-Wstrict-aliasing
-Wstrict-overflow=1
-Wswitch
-Wtautological-compare
-Wtrigraphs
-Wuninitialized
-Wunknown-pragmas
-Wunused-function
-Wunused-label
-Wunused-value
-Wunused-variable
-Wvolatile-register-var
-Wzero-length-bounds

-Wextra選項(原為-W, 已經棄用了):

它會打開-Wall選項沒有打開的一些編譯警告,包括:

-Wclobbered
-Wcast-function-type
-Wdeprecated-copy (C++ only)
-Wempty-body
-Wignored-qualifiers
-Wimplicit-fallthrough=3
-Wmissing-field-initializers
-Wmissing-parameter-type (C only)
-Wold-style-declaration (C only)
-Woverride-init
-Wsign-compare (C only)
-Wstring-compare
-Wredundant-move (only for C++)
-Wtype-limits
-Wuninitialized
-Wshift-negative-value (in C++03 and in C99 and newer)
-Wunused-parameter (only with ‘-Wunused’ or ‘-Wall’)
-Wunused-but-set-parameter (only with ‘-Wunused’ or ‘-Wall’)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM