越後面的主題越難寫啊 QQ,今天開始逆向的主題,希望我可以繼續撐下去 😵💫
這邊我們需要複習一下一支程式是怎麼從高階語言變成一個執行檔的,也就是編譯的流程:
編譯器 (compiler)
➡️ 組合語言 (assembly)組譯器 (assembler)
➡️ 目的碼 (object code)連結器 (linker)
➡️ 執行檔 (e.g. .exe 檔案)中間還有一些預處理之類的我們先不管它們
而逆向工程就是反過來將執行檔變回容易理解的高階語言,雖然沒辦法和原先的程式碼一模一樣,但基本上邏輯都可以還原出來。
在開始逆向之前,我們先來操作一次編譯一支程式的過程!
須先安裝 gcc
首先我們有一個簡單的 C 語言程式 hello.c
如下:
#include <stdio.h>
int main(void) {
printf("Hello world!\n");
}
使用 gcc 將高階語言編譯成組合語言:
> gcc -o asm.s -S hello.c
其中 -o
是指定輸出的檔案名稱,-S
則是產生組合語言程式碼
這時的 asm.s
就是編譯過後的組合語言:
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 13, 0 sdk_version 13, 3
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
.cfi_def_cfa_offset 16
mov x29, sp
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
adrp x0, l_.str@PAGE
add x0, x0, l_.str@PAGEOFF
bl _printf
mov w0, #0
ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
ret
.cfi_endproc
; -- End function
.section __TEXT,__cstring,cstring_literals
l_.str: ; @.str
.asciz "Hello world!\n"
.subsections_via_symbols
我們繼續將組合語言組譯成 obj code:
> gcc -o obj.o -c asm.s
-c
就是產生 obj code 的參數
再來是把 obj code 連結起來,但因為我們只有一個 obj file,因此只需要帶 obj.o
這個檔案就好:
> gcc -o hello.out obj.o
最後我們就得到了從 hello.c
編譯而來的 hello.out
,我們執行它就可以看到 Hello world!
的輸出:
> ./hello.out
Hello world!
不意外的話,明天應該會使用 Ghidra 將今天這支 hello.out
的執行檔逆向回去,想跟著文章一起操作的話可以先把 Ghidra 安裝起來!