破军安全实验室
本文约4500字,阅读约需12分钟。
0x00 前言
扩展burp功能的程序,依赖burp提供的API,让使用者可以开发一些自己想要的功能。
0x01 api文档
https://gitee.com/stemmm/burp-api-drops#burp-api-drops
0x02 burp插件hello world
下载开发模板,导入到idea中
或者新建maven项目,导入maven依赖也可以。(建议)
导入依赖
开始写代码:
新建一个burp的包
写个BurpExtender类,一定要放在burp包下
package burp;
import java.io.PrintWriter;
public class BurpExtender implements IBurpExtender{
private IBurpExtenderCallbackscallbacks; //声明回调对象
private IExtensionHelpershelpers; //辅助类,小工具箱,各种类型的转换等
private PrintWriter stdout; //用来输出流需要
@Override
public voidregisterExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
this.callbacks=callbacks;
this.helpers =callbacks.getHelpers(); //通过回调获取辅助对象
this.stdout = newPrintWriter(callbacks.getStdout(),true); //输出流
callbacks.setExtensionName("burp_hello"); //给插件命名
stdout.println("burptest !!!"); //输出内容
}
}
点击maven的package,打包项目成jar包
Jar包在target目录下
打成jar包后,到入burp之后会自动调用burp包中的BurpExtender类中的类的registerExtenderCallbacks方法
导入burp后,就成功了。第一个burp插件完成。
0x03 HTTP数据包的处理
主要是processHttpMessage这个函数。
callbacks.registerHttpListener(this);//如果没有注册,下面的processHttpMessage方法是不会生效的。处理请求和响应包的插件,这个应该是必要的
1. 获取请求包中的数据例子
@Override
public void processHttpMessage(int toolFlag,boolean messageIsRequest,IHttpRequestResponse messageInfo)
{
if (toolFlag == IBurpExtenderCallbacks.TOOL_PROXY){
//不同的toolFlag代表了不同的burp组件 https://portswigger.net/burp/extender/api/constant-values.html#burp.IBurpExtenderCallbacks
if (messageIsRequest){ //对请求包进行处理
IRequestInfo analyzeRequest = helpers.analyzeRequest(messageInfo);
//对消息体进行解析,messageInfo是整个HTTP请求和响应消息体的总和,各种HTTP相关信息的获取都来自于它,HTTP流量的修改都是围绕它进行的。
/*****************获取参数**********************/
List<IParameter> paraList = analyzeRequest.getParameters();
//获取参数的方法
//当body是json格式的时候,这个方法也可以正常获取到键值对;但是PARAM_JSON等格式不能通过updateParameter方法来更新。
//如果在url中的参数的值是 key=json格式的字符串 这种形式的时候,getParameters应该是无法获取到最底层的键值对的。
for (IParameter para : paraList){// 循环获取参数,判断类型,进行加密处理后,再构造新的参数,合并到新的请求包中。
String key = para.getName(); //获取参数的名称
String value = para.getValue(); //获取参数的值
int type = para.getType();
stdout.println("参数 key value type: "+key+" "+value+" "+type);
}
}
效果
2.更新和删除数据等其他操作。
/*****************修改并更新参数**********************/
IParameter newPara = helpers.buildParameter("testKey", "testValue", IParameter.PARAM_BODY); //构造新的参数
byte[] new_Request = messageInfo.getRequest();
new_Request = helpers.updateParameter(new_Request, newPara); //构造新的请求包
messageInfo.setRequest(new_Request);//设置最终新的请求包
/*****************删除参数**********************/
for (IParameter para : paraList){// 循环获取参数,判断类型,进行加密处理后,再构造新的参数,合并到新的请求包中。
String key = para.getName(); //获取参数的名称
if (key.equals("aaa")) {
new_Request = helpers.removeParameter(new_Request, para); //构造新的请求包
}
}
/*****************获取header**********************/
List<String> headers = analyzeRequest.getHeaders();
for (String header : headers){// 循环获取参数,判断类型,进行加密处理后,再构造新的参数,合并到新的请求包中。
stdout.println("header "+header);
if (header.startsWith("referer")) {
/*****************删除header**********************/
headers.remove(header);
}
}
/*****************新增header**********************/
headers.add("myheader: balalbala");
/*****************获取body 方法一**********************/
int bodyOffset = analyzeRequest.getBodyOffset();
byte[] byte_Request = messageInfo.getRequest();
String request = new String(byte_Request); //byte[] to String
String body = request.substring(bodyOffset);
byte[] byte_body = body.getBytes(); //String to byte[]
/*****************获取body 方法二**********************/
int len = byte_Request.length;
byte[] byte_body1 = Arrays.copyOfRange(byte_Request, bodyOffset, len);
new_Request = helpers.buildHttpMessage(headers, byte_body);
//如果修改了header或者数修改了body,不能通过updateParameter,使用这个方法。
messageInfo.setRequest(new_Request);//设置最终新的请求包
}
}
else{//处理响应包
IResponseInfo analyzedResponse = helpers.analyzeResponse(messageInfo.getResponse()); //getResponse获得的是字节序列
short statusCode = analyzedResponse.getStatusCode();
List<String> headers = analyzedResponse.getHeaders();
String resp = new String(messageInfo.getResponse());
int bodyOffset = analyzedResponse.getBodyOffset();//响应包是没有参数的概念的,大多需要修改的内容都在body中
String body = resp.substring(bodyOffset);
if (statusCode==200){
String newBody= body+"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&";
byte[] bodybyte = newBody.getBytes();
messageInfo.setResponse(helpers.buildHttpMessage(headers, bodybyte));
}
}
}
}
for (IParameter para : paraList){// 循环获取参数,判断类型,进行加密处理后,再构造新的参数,合并到新的请求包中。
String key = para.getName(); //获取参数的名称
String value = para.getValue(); //获取参数的值
int type = para.getType();
stdout.println("参数 key value type: "+key+" "+value+" "+type);
}
para.getType()
0代表的是URL。
1代表的是Body处的。
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,破军安全实验室及文章作者不为此承担任何责任。
破军安全实验室拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经破军安全实验室允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
破军安全实验室
# 长按二维码 关注我们 #
原文始发于微信公众号(戟星安全实验室):从零开始Burpsuite 插件开发
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论