# 编译器堆栈保护技术 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-all") # 开启PIE地址随机化、RELRO重定位保护 set(CMAKE_POSITION_INDEPENDENT_CODE ON) # 链接器:完整RELRO防护 set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,relro,-z,now") # Release优化+符号剥离 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -s -DNDEBUG") # OLLVM混淆参数,Release开启 if(CMAKE_BUILD_TYPE STREQUAL "Release") add_compile_options( -mllvm -fla -mllvm -sub -mllvm -bcf -mllvm -sobf -mllvm -split ) endif()1. 栈保护
#有.cpp文件时需要添加
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-all")
#有.c文件时需要添加
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-all")
解决的漏洞:
依靠栈溢出篡改返回地址
开启之后的效果:
编译器在所有函数栈开头插入随机校验值,函数退出前校验该随机数是否被篡改,如果校验失败程序立刻崩溃终止
-fstack-protector 只给含有字符数组、局部缓冲区的函数开启保护
-fstack-protector-strong 数组、结构体、大局部变量都会开启栈保护
-fstack-protector-all 所有函数全部强制开启栈保护
2. PIE动态地址
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
解决的漏洞:
代码、全局变量、函数地址编译时就固定死, 黑客一旦拿到这个固定地址,就能精准构造栈溢出漏洞、ROP 攻击,直接接管程序。
开启之后的效果:
系统每次启动 APP、加载 SO 库时,都会随机分配一段内存基地址。原本代码内部所有跳转、函数调用、全局变量引用,全部用相对偏移寻址,不依赖绝对地址。
3. GOT 劫持防护
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,relro,-z,now")
GOT 表:Android so 调用系统库函数的地址表
解决的漏洞:
攻击者如果改写 GOT 表里面的函数指针,就能把正常系统调用劫持成恶意代码。
开启之后的效果:
-z relro 程序启动加载阶段:将 GOT 表前半段关键区域 标记为只读
-z now 程序运行前,一次性解析完所有外部函数地址,全部填入 GOT 表,填充完毕后,整张 GOT 表全部设置为只读
设置后可防止GOT 被写入、篡改
4. 混淆,防逆向
1)原生
#有.cpp文件时需要添加
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -s -DNDEBUG")
#有.c文件时需要添加
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -s -DNDEBUG")
2)OLLVM
OLLVM需要额外安装编译,可以参考so基础防护记录-ollvm编译和使用-CSDN博客
if(CMAKE_BUILD_TYPE STREQUAL "Release")
add_compile_options(
-mllvm -fla
-mllvm -sub
-mllvm -bcf
-mllvm -sobf
-mllvm -split
)
endif()
解决的漏洞:
反编译查看源码内容
开启之后的效果:
代码混淆防逆向
1)原生参数
-O2:编译器二级优化,代码精简、常量传播、循环优化、无用代码消除
-s:剔除调试符号、行号信息
-DNDEBUG 关闭 C/C++ 标准 assert 断言
2)OLLVM
-mllvm -fla控制流平坦化
-mllvm -sub指令替换
-mllvm -bcf虚假控制流
-mllvm -sobf 替换式虚假控制流
-mllvm -split 基本块拆分
补一个Hikari分支参数,与经典OLLVM有些区别
-mllvm -hikari 主开关
-mllvm -enable-bcfobf 虚假控制流
-mllvm -enable-subobf 指令替换
-mllvm -enable-cffobf 控制流平坦化
-mllvm -enable-strcry 字符串加密