前一阵子看到一篇文章说利用分块传输可以过waf,但是又没找到现成的工具,就只能自己写一个,考虑到抵御此类攻击太容易并且国外有防火墙早在14年就可以识别,所以没必要写的太复杂,加太多功能。
说明:将HTTP数据包变成分块传输包,可分成指定块,仅支持ascii编码和普通数据包。
主程序
import tools.Queue;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.print.DocFlavor.READER;
/**
* @author Elliot
*
*/
public class TransferEncoding {
// 测试用硬编码
private static String FileName = "E:\\sqlmap-dev\\post.txt"; // 要读取的文件名
private static String pathname = "H:\\output.txt"; // 写入的文件名
private static int mod = 13;
/**
* @param FileName
* @param pathname
*/
private TransferEncoding(String FileName, String pathname) {
this.FileName = FileName;
this.pathname = pathname;
}
public static String getFileName() {
return FileName;
}
public static void setFileName(String fileName) {
FileName = fileName;
}
public static String getPathname() {
return pathname;
}
public static void setPathname(String pathname) {
TransferEncoding.pathname = pathname;
}
private static String EncodeString = "";
// 按行读取文件并打印
private static void readUsingBufferedReader(String fileName, String pathname, Charset cs) throws IOException {
/** 准备BufferReader */
File file = new File(fileName); // 准备读取的post包
File writefile = new File(pathname); // 准备写入的post包
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, cs);
BufferedReader br = new BufferedReader(isr); // 缓冲区读取
BufferedWriter out = new BufferedWriter(new FileWriter(writefile)); // 缓冲区写入
/** 准备结束 */
String line;
while ((line = br.readLine()) != null) { // 按行读取
if (line.equals("")) { // 如果是空格分隔符
out.write("Transfer-Encoding: chunked\r\n"); // 写入分块传输头
out.write("\r\n");
while ((line = br.readLine()) != null) { // 读取body
EncodeString += line; // 将body拼接在一起
}
} else
out.write(line + "\r\n"); // 否则按行写入
}
out.flush();
out.close();
br.close();
}
// 十进制整数转化为16进制
public static String convert(int n) {
return Integer.toHexString(n);
}
// 处理有ascii码的程序 按照最少三个字节切分
/*
*
* @mod 为输入的希望切割的分块数,带ascii码的分块值最少为3
*/
public static void EncodingAscii(int mod) throws IOException {
File writefile = new File(pathname); // 准备写入的文件
BufferedWriter out = new BufferedWriter(new FileWriter(writefile, true)); // 写入器
byte[] buffer = EncodeString.getBytes(); // 把字符串转化为字节数组
int i;
for (i = 0; i < buffer.length && buffer.length - i > mod; i++) { // 逐字节读取,确保剩下的字节数大于分块数
int count = i;
int c = 0; // 每个分块数
Queue<Character> queue = new Queue<Character>(); // 队列
for (int j = count; j < count + mod; j++) { // 处理每个分块
if (buffer[j] == 37) { // 如果读到的了%分号
// 强制输出至少三次
queue.enqueue((char) buffer[j++]);
queue.enqueue((char) buffer[j++]);
queue.enqueue((char) buffer[j]);
c += 3;
} else {
queue.enqueue((char) buffer[j]); // 正常加入队列
c++;
}
if (j >= count + mod - 1) {
out.write(convert(c) + "\r\n"); // 写入分块数
while (!queue.isEmpty()) // 将队列清空
out.write(queue.dequeue());
out.write("\r\n");
}
i = j;
}
}
out.write((buffer.length - i) + "\r\n");
while (i < buffer.length) // 打印剩下的元素
out.write((char) buffer[i++]);
out.write("\r\n0\r\n");
out.flush();
out.close();
}
public static void main(String[] args) throws Exception {
// 把FileName和Pathname改成自己想要的的路径,mod为希望切割的份数
TransferEncoding.readUsingBufferedReader(FileName, pathname, StandardCharsets.UTF_8);
TransferEncoding.EncodingAscii(mod);
}
}
import java.util.Iterator;
import java.util.NoSuchElementException;
/*
* 队列类
*/
public class Queue<Item> implements Iterable<Item> {
private Node<Item> first;
private Node<Item> last;
private int n;
private static class Node<Item>{
private Item item;
private Node<Item> next;
}
public Queue() {
first = null;
last = null;
n = 0;
}
public boolean isEmpty() {
return first == null;
}
public int size() {
return n;
}
public Item peek() {
if(isEmpty()) throw new NoSuchElementException("Queue underflow");
return first.item;
}
public void enqueue(Item item) {
Node<Item> oldlast = last;
last = new Node<Item>();
last.item = item;
last.next = null;
if(isEmpty()) first = last;
else oldlast.next = last;
n++;
}
public Item dequeue() {
if(isEmpty()) throw new NoSuchElementException("Queue underflow");
Item item = first.item;
first = first.next;
n--;
if(isEmpty()) last = null;
return item;
}
public String toString() {
StringBuilder s = new StringBuilder();
for (Item item:this) {
s.append(item);
s.append(' ');
}
return s.toString();
}
// 迭代器
public Iterator<Item> iterator(){
return new ListIterator<Item>(first);
}
private class ListIterator<Item> implements Iterator<Item>{
private Node<Item> current;
public ListIterator(Node<Item> first) {
current = first;
}
public boolean hasNext() { return current != null;}
public void remove() { throw new UnsupportedOperationException();}
public Item next() {
if(!hasNext()) throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
}
}