COIN Attacks符号執行SGX_SQLite
從COIN Attack符号執行SGX_SQLite的過程入手分析COIN Attacks。從
run.sh
開始。
第一步 編譯SGX_SQLite
SGX SIM Mode編譯SGX_SQLite。(位于
run.sh
)
第二步 提取EDL資訊
分析EDL檔案并記錄所有會将資料傳入Enclave的E/OCALL函數及對應參數,具體包括OCALL傳回值、
[out]
标記的OCALL參數、
[in]
标記的及其它所有的ECALL參數。這些參數稱為不安全參數。資訊放到
unsafe_input_stat.tmp
和
unsafe_ecall_stat.tmp
檔案。(位于
edlParse.py
)
第三步 提取不安全參數的類型資訊
結合第二步得出的資訊,使用ModulePass讀取(似乎會漏掉SDK的接口)每個不安全參數所包含内容的類型(如pointer所指Reference的類型,struct内的各個成員的類型)。基于LLVM Pass的RTTI能更簡單地擷取類型資訊。資訊放到
unsafe_input_complete.tmp
檔案。(位于
EnclaveSemantics.cpp
)
第四步 符号執行Enclave
加載Enclave.so
load_binary
中,使用
lief.parse
解析
enclave.so
,使用Triton的
setConcreteMemoryAreaValue
将Enclave加載起來。
加載不安全的輸入資訊
load_input_semantics
函數将
unsafe_input_complete.tmp
裡的不安全函數及其參數資訊分别加載到資料結構
interface_hook_fn
和
input_semantics
中。
加載ECALL資訊
load_ECALLs
将
unsafe_ecall_stat.tmp
裡的Ecall資訊加載到資料結構
primary_ECALLs
中。
permutations
建構Ecall函數的各種排列。
為模拟器配置Hooks
config_hook_table
中,利用
lief.ELF.Binary
豐富的資訊,動态設定Unsafe函數pltgot項位址(若其為pltgot符号)。動态更新
dlmalloc
、
dlfree
、
memcpy
函數的位址資訊。動态更新
__stack_chk_fail
tag的位址資訊。
初始化triton上下文
單線程模拟執行(包括亂序執行)
定位
urts
中
sgx_ocall
、
sgx_ocfree
函數位址。Triton具體化所有記憶體、寄存器。擷取所有ECALL的位址。設定棧資訊(RBP和RSP)。選擇需要亂序執行的Ecall,對其參數設定記憶體值。其中比較重要的是模拟執行Ecall。在
MAX_SEED_ATTEMPT
次數内不斷變化seed(即改變記憶體值),然後重新模拟執行Ecall。
"""
run_single_thread_emul(perm_ECALLs_list) prepares and handles single thread mode of emulation
"""
def run_single_thread_emul(perm_ECALLs_list):
...
config_memory_for_param(it_ECALL, param_ECALL, it_ECALL_addr, init_seed_flag, True)
...
res = emulate(it_ECALL_addr, sgx_ocall, sgx_ofree, False)
...
模拟執行
初始化模拟器。擷取Ecall函數的opcode并使用Triton模拟執行。單次模拟執行中,最多從入口指令開始往後執行
MAX_INST_CNT
條指令。檢查目前指令是否符合政策。
檢查目前指令是不是某個hook函數(針對
dlmalloc
的
sgx_malloc_hook
、針對
dlfree
的
sgx_free_hook
、針對
memcpy
的
sgx_memcpy
)或tag(
__stack_chk_fail
),陷入到hook或者tag時也進行政策檢查,若違反政策就建構報告。
政策檢查是這項工作的關鍵所在。
"""
emulate(pc, sgx_ocall, sgx_free, is_threaded) emulates instructions
"""
def emulate(pc, sgx_ocall, sgx_free, is_threaded):
...
ret = Triton.processing(instruction)
...
policies.inspection(instruction)
...
hook_process_inst(instruction)
...
print_report()
...
檢查政策(*)
- 當opcode為
、mov
、movsx
且某個operand為記憶體時(lea
函數中)oob_uaf_policy
- 若記憶體對象尾部跨出了堆配置設定時記錄的Enclave堆對象的尾部,則認為OOB發生。
- 若記憶體對象頭部未指向堆配置設定時記錄的Enclave堆對象内,并且與堆配置設定曆史記錄吻合,則認為UAF發生。
- 當opcode為
,指令被符号化,後20條指令記憶體在操作數是第32位為1的立即數(認為攻擊者控制?)的cmp
指令,再往後10條指令内有mov
指令,則認為Ineffectual Condition發生。(jmp
函數中)test_cmp_sides
- Enclave内調用
函數時,會被memcpy
hook函數攔截,其中會先後檢查棧洩漏、Null Pointer Deference、堆溢出。sgx_memcpy
- 棧洩漏檢測
中是否是棧對象複制到堆對象。(memcpy
函數中)test_stack_leak
- Null Pointer Deference
目标位址是否為Null(memcpy
函數中)is_nd_or_heap_overflow
- 堆溢出檢查目标堆對象有效大小(堆配置設定時會記錄堆對象資訊)是否小于
參數指定的大小。(memcpy
函數中)is_nd_or_heap_overflow
- 棧洩漏檢測