各位抱歉阿~~因為這個比賽影響到了我的學業了,經過再三的考量後,又不想放棄比賽😭😭
所以目前決定的是把解題變為理論的部分,會把以前運用到的一些知識,但因時間或篇幅而未詳談的
都會在接下來的幾天內做補充,希望可以苟延殘喘下去🫠🫠
收先來介紹在reverse中,最常遇到的ELF格式
ELF 檔案是一種在 Linux 和其他類 Unix 系統上使用的標準格式,它能夠儲存可執行檔、共享庫、以及目標檔案(Object Files)。這種格式的設計目的是允許不同模組和程式碼段在編譯和連結過程中進行互操作,進而形成一個可執行的程式。
高階語言 (Source Code):
編譯 (Compilation):
彙編 (Assembly):
連結 (Linking):
ELF 檔案的主要段 (Section)
ELF 檔案包含了多個段(section),分別儲存各類資料:
.bss 段 (Block Started by Symbol):
這個段用來存放未初始化的全域變數或靜態變數。這些變數在程式開始執行時會被自動初始化為零,但 .bss 本身不佔用檔案大小,它只是記錄了需要初始化的變數數量。
.data 段:
這個段存放已經初始化的全域變數和靜態變數。當程式啟動時,這些變數的初始值會直接從 .data 段中載入記憶體。
.rodata 段 (Read-Only Data):
存放程式中的只讀資料,通常是常數值(如字串字面值、常數變數)。這些資料是不可修改的,防止在程式執行過程中被意外改動。
.text 段:
這個段儲存程式的可執行程式碼。所有的函式和執行邏輯都位於 .text 段中,它通常是唯讀的,這樣可以防止惡意程式修改程式碼段。
區域變數的存放位置
當函式被呼叫時,區域變數會被推入堆疊區(stack)並不會存放在 .bss 或 .data 段中,且當函式執行結束時,就會釋放堆疊。
連結器 (Linker) 的角色
連結器的主要任務是將不同的目標檔案(可能是由不同的源碼檔案編譯而成的)與所需的函式庫連結起來。它解決了程式中所有的符號定義與使用之間的依賴關係,確保最終的可執行檔案中的每一個符號都能正確引用到相應的程式碼或資料。連結器將這些段組織成一個整體,形成一個可執行的 ELF 檔案。
以下為白話文:
ELF:Executable and Linkable Format
我們平常在寫的叫做高階語言(python、C、c++、JAVA之類的),
他會經過compiler(中文叫編譯器) 進行 compile (中文叫編譯),
變成組合語言,組合語言是一種介於人類語言與機械語言(二進位的檔(0,1)),
再經過組合語言器變為一個目標檔案(Object file),一個目標檔案裡面會包含以下部分(section)
這裡我有寫一個範例各位可以寫寫看
題目:
#include <stdio.h>
#include <iostream>
int a;
int b = 3;
int main()
{
int b = 3;
std::cout << "test text";
return 0;
}
解答:
#include <stdio.h>
#include <iostream>
/*
標頭檔會在compile的時候,
會將所有用到的函式的符號放入目標檔案中,
接下來,連結器會將這些符號與相應的標準庫進行連結
*/
int a; //存到.bss
int b = 3; //b存到.data,3存到.rodata
int main()
{
int b = 3; //放到堆疊(stack)裡,注意這是區域變數喔
std::cout << "test text"; //"test text"存到.rodata
return 0; //釋放堆疊 b、"test text"
}
//整個main會存到.text裡面
後記:
怎麼感覺這個更累🫠🫠