
戟星安全实验室
本文约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; //用来输出流需要@Overridepublic 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. 获取请求包中的数据例子
@Overridepublic 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.IBurpExtenderCallbacksif (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 StringString 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处的。




