--------------------------------------------------------------------------------
author: hjjdebug
date: 2023年 10月 10日 星期二 15:11:53 CST
description: elf 文件信息,
--------------------------------------------------------------------------------
目录:
1. 检查程序头, 判定重定位信息是否是只读的.
$readelf -l ${1} | grep 'GNU_RELRO'
2. 检查是否存在符号表
$readelf -s ${1} |grep '.symtab'
3. canary 检测(金丝雀检测), 检查符号表中是否存在__stack_chk_fail函数调用
$readelf -s ${1} | grep '__stack_chk_fail'
4. 查看执行文件中有多少个函数调用了libc中的函数
参考下面详述.
1. 检查程序头, 判定重定位信息是否是只读的.
Program headers 信息
readelf -l ${1} | grep 'GNU_RELRO' // 重定位信息只读后要继续查询:
readelf -d ${1} | grep 'BIND_NOW' // 动态节中有'BIND_NOW'字符串 为"Full RELRO", 无该字串为"Partial RELRO"
readelf -l ${1} | grep 'GNU_STACK' |grep 'RWE' //存在RWE 表示堆栈上有可执行权限
2. 检查是否存在符号表
readelf -s ${1} |grep '.symtab'
存在就是没有去除, 不存在就是去除了. 例如:
$readelf -s /bin/ls |grep '.symtab' 确认其没有符号表, /bin/ls 只有'.dynsym'
而我自己的一个程序, 则有符号表
$readelf -s multiview |grep '.symtab' |cut -d' ' -f5 可以获取符号个数.
$readelf -s multiview 输出详细的符号信息
$readelf -s multiview | grep '.symtab' 输出一行信息,如下:
Symbol table '.symtab' contains 28697 entries:
$readelf -s multiview |grep '.symtab' |cut -d' ' -f5 输出符号个数,如下:
28697
3. canary 检测(金丝雀检测), 检查符号表中是否存在__stack_chk_fail函数调用
$readelf -s "${1}" | grep '__stack_chk_fail' // 符号表中存在__stack_chk_fail函数,表示有canary 保护,该函数是动态符号表中函数
综合测试:
4. 查看执行文件中有多少个函数调用了libc中的函数
步骤:
4.1. 查看执行文件的对外连接符号(动态连接符号), 用--dyn-syms
$readelf --dyn-syms multiview
4.2. 将输出净化, 只保留外部调用的函数名称
$readelf --dyn-syms multiview | awk '{ print $8 }' | sed -e 's/_*//' -e 's/@.*//' -e '/^$/d'
查看libc 对外提供的函数
4.3. libc 中的符号信息, 以i386-linux-gnu 目录下libc 为例
$ readelf -s /usr/lib/i386-linux-gnu/libc.so.6
4.4. libc对外提供的函数名称一类是带 _chk 字符串的, 我们去掉修饰,只打印名称
$ readelf -s /usr/lib/i386-linux-gnu/libc.so.6 | sed -ne 's/.*__\(.*_chk\)@@.*/\1/p
另一类是不带_chk字符串的. 见后边sprintf 举例
把_chk去掉就是不带_chk 的函数名
用脚本可以这样写: 把输出送给变量保存
FS_chk_func_libc="$(${readelf} -s $FS_libc 2>/dev/null | sed -ne 's/.*__\(.*_chk\)@@.*/\1/p')"
FS_func_libc="$(echo "${FS_chk_func_libc}" | sed 's/_chk$//')"
举例, 以sprintf 为例, 去掉无关输出, 发现有sprintf(GLIBC_2.0引入), 同时也有 __sprintf_chk(GLIBC_2.3.4引入)
$ readelf -s /usr/lib/i386-linux-gnu/libc.so.6 | grep sprintf
178: 00050300 36 FUNC GLOBAL DEFAULT 15 sprintf@@GLIBC_2.0
2187: 00112b80 63 FUNC GLOBAL DEFAULT 15 __sprintf_chk@@GLIBC_2.3.4
4.5. 外部调用函数列表以及libc函数列表都已经准备好了, 现在我们来查询一下: 外部调用函数表中有多少个是libc的
fgrep -xf <libc_file> f_file
其中fgrep 就是 grep -F 的意思, 就是搜索固定的字符串
-x 需要匹配整行才输出
-f 指明后边的参数是一个文件,文件中包含了要搜索的字符串
参考:
以上知识来源于对 checksec "检查安全性"的shell源码分析, 确实有收获!
要想脚本过硬, bash下的命令含义也要过硬!