Skip to content

Commit

Permalink
Add New Thens: Extract, Generate, Transform. Add generator variable t…
Browse files Browse the repository at this point in the history
…ag. Support quoted values in variable tags. Add custom pseudo selector ::innerHTML to HTML value path/CSS Selector support. Misc. small UI improvements for performance and usability. Add settings option to hide features.
  • Loading branch information
ddwightx committed May 26, 2024
1 parent 7d2fb61 commit 9e99ec6
Show file tree
Hide file tree
Showing 223 changed files with 6,244 additions and 801 deletions.
26 changes: 16 additions & 10 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Proxy Name - If received by a certain Burp proxy listener

Repeat - Repeat a group of When constraints for each item in a list

[More](https://synfron.github.io/ReshaperForBurp/Rules.html#whens)
[More](https://synfron.github.io/ReshaperForBurp/Whens.html)

### Thens

Expand All @@ -54,6 +54,10 @@ Drop - Have Burp drop the connection

Evaluate - Perform operations on values

Extract - Extract values into lists

Generate - Generate a value

Highlight - Highlight the line item in the HTTP/WebSocket history

Intercept - Intercept the message in the Proxy interceptor
Expand All @@ -76,21 +80,23 @@ Run Script - Execute a JavaScript script

Save File - Save text to a file

Set Encoding - Set the encoding used to read and write bytes of the HTTP request or response body, or WebSocket message
Send Message - Send a separate WebSocket message

Send Request - Send a separate HTTP request

Send To - Send data to other Burp tools or the system's default browser

Set Encoding - Set the encoding used to read and write bytes of the HTTP request or response body, or WebSocket message

Set Event Direction - Change whether to send a request or to send a response at the end of processing

Set Value - Set the value of an HTTP/WebSocket event using another value (text, variable, or HTTP/WebSocket event entity)

Set Variable - Set a variable using another value (text, variable, or HTTP/WebSocket event entity)

Send Message - Send a separate WebSocket message

Send Request - Send a separate HTTP request

Send To - Send data to other Burp tools or the system's default browser
Transform - Transform/convert a value

[More](https://synfron.github.io/ReshaperForBurp/Rules.html#thens)
[More](https://synfron.github.io/ReshaperForBurp/Thens.html)

## Variables

Expand All @@ -109,8 +115,8 @@ Share values across different Rules while processing the same event or all event

### Build JAR with CLI

1. Install Java 18.
2. Install Gradle v8.5.
1. Install Java 21.
2. Install Gradle v8.6.
3. Open a terminal into the `extension` directory of the project.
4. Run the `gradle --refresh-dependencies build jar` command.
5. The JAR will be placed in the `extension/build/libs` directory.
Expand Down
2 changes: 1 addition & 1 deletion docs
Submodule docs updated 6 files
+21 −9 Readme.md
+3 −648 Rules.md
+168 −13 ScriptingLibrary.md
+807 −0 Thens.md
+45 −13 Variables.md
+149 −0 Whens.md
5 changes: 3 additions & 2 deletions extension/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {

group 'com.synfron.reshaper.burp'
archivesBaseName = 'reshaper-for-burp'
version '2.3.3'
version '2.4.0'

targetCompatibility = '21'
sourceCompatibility = '21'
Expand Down Expand Up @@ -35,7 +35,8 @@ dependencies {
'org.jsoup:jsoup:1.15.3',
'com.fasterxml.jackson.core:jackson-databind:2.14.0',
'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.14.0',
'org.apache.commons:commons-text:1.10.0'
'org.apache.commons:commons-text:1.10.0',
'com.fasterxml.uuid:java-uuid-generator:5.0.0'
)

compileOnly (
Expand Down
32 changes: 32 additions & 0 deletions extension/src/main/java/synfron/reshaper/burp/core/Tab.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package synfron.reshaper.burp.core;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.Arrays;

@Getter
@AllArgsConstructor
public enum Tab {
HttpRules("HTTP Rules"),
WebSocketRules ("WebSocket Rules"),
GlobalVariables("Global Variables"),
Logs("Logs"),
Settings("Settings", false);

private String name;
private boolean hideable = true;

Tab(String name) {
this.name = name;
}

@Override
public String toString() {
return name;
}

public static Tab byName(String name) {
return Arrays.stream(Tab.values()).filter(tab -> tab.name.equals(name)).findFirst().orElse(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public synchronized void clearListeners() {
public synchronized void remove(IEventListener<A> listener) {
if (listeners != null) {
listeners.removeIf(listenerReference -> listenerReference.get() == null || listenerReference.get().equals(listener));
if (listeners.size() == 0) {
if (listeners.isEmpty()) {
listeners = null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@

@EqualsAndHashCode
public class ContentType {
public static final ContentType None = new ContentType("None", 0, 1);
public static final ContentType UrlEncoded = new ContentType("URL Encoded", 1, 2);
public static final ContentType MultiPart = new ContentType("Multi-Part", 2, 4);
public static final ContentType Xml = new ContentType("XML", 3, 8);
public static final ContentType Json = new ContentType("JSON", 4, 16);
public static final ContentType Amf = new ContentType("AMF", 5, 32);
public static final ContentType Unknown = new ContentType("Unknown", -1, 64);
public static final ContentType None = new ContentType("None", 1);
public static final ContentType UrlEncoded = new ContentType("URL Encoded", 2);
public static final ContentType MultiPart = new ContentType("Multi-Part", 4);
public static final ContentType Xml = new ContentType("XML", 8);
public static final ContentType Json = new ContentType("JSON", 16);
public static final ContentType Amf = new ContentType("AMF", 32);
public static final ContentType Unknown = new ContentType("Unknown", 64);

@Getter
private static final List<ContentType> values = List.of(
None,
UrlEncoded,
Expand All @@ -28,37 +29,30 @@ public class ContentType {

@Getter
private final String[] names;
private final int[] ids;
private final int flags;

private ContentType() {
this(None.names[0], None.ids[0], None.flags);
this(None.names[0], None.flags);
}

private ContentType(String name, int id, int flags) {
private ContentType(String name, int flags) {
this.names = new String[] { name };
this.ids = new int[] { id };
this.flags = flags;
}

private ContentType(int flags) {
List<ContentType> contentTypes = getValues().stream()
.filter(contentType -> contentType.hasFlags(flags))
.collect(Collectors.toList());
.toList();
this.names = contentTypes.stream()
.map(ContentType::getName).toArray(String[]::new);
this.ids = contentTypes.stream().mapToInt(ContentType::getId).toArray();
this.flags = flags;
}

public String getName() {
return String.join(", ", names);
}

private int getId() {
return ids.length == 1 ? ids[0] : Unknown.getId();
}

public static ContentType get(burp.api.montoya.http.message.ContentType contentType) {
return switch (contentType) {
case AMF -> Amf;
Expand All @@ -71,21 +65,10 @@ public static ContentType get(burp.api.montoya.http.message.ContentType contentT
};
}

public static ContentType get(int id) {
return getValues().stream()
.filter(contentType -> contentType.getId() == id)
.findFirst()
.orElse(Unknown);
}

public boolean isTextBased() {
return flags != 0 && (flags & ~(Json.flags | UrlEncoded.flags | Xml.flags)) == 0;
}

public static List<ContentType> getValues() {
return values;
}

public boolean hasFlags(ContentType contentType) {
return hasFlags(contentType.flags);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,9 @@ public static String getResponseValue(EventInfo eventInfo, HttpResponseMessage r


public static void setValue(EventInfo eventInfo, MessageValue messageValue, VariableString identifier, SetItemPlacement itemPlacement, String replacementText) {
if (eventInfo instanceof HttpEventInfo) {
HttpEventInfo httpEventInfo = (HttpEventInfo)eventInfo;
if (eventInfo instanceof HttpEventInfo httpEventInfo) {
setValue(httpEventInfo, messageValue, identifier, itemPlacement, replacementText);
} else if (eventInfo instanceof WebSocketEventInfo<?>) {
WebSocketEventInfo<?> webSocketEventInfo = (WebSocketEventInfo<?>)eventInfo;
} else if (eventInfo instanceof WebSocketEventInfo<?> webSocketEventInfo) {
setValue(webSocketEventInfo, messageValue, replacementText);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ public enum MatchType {
Contains("Contains"),
BeginsWith("Begins With"),
EndsWith("Ends With"),
Regex("Regex");
Regex("Regex"),
LessThan("Less Than"),
LessThanOrEqual("Less Than Or Equal"),
GreaterThan("Greater Than"),
GreaterThanOrEqual("Greater Than Or Equal");

@Getter
private final String name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public void logProperties(When<?> when, boolean result, List<? extends Pair<Stri

private boolean isLast(DiagnosticEntityType entityType) {
List<DiagnosticRecord> records = getRecords();
return records.size() > 0 && records.get(records.size() - 1).getEntityType() == entityType;
return !records.isEmpty() && records.get(records.size() - 1).getEntityType() == entityType;
}

@Override
Expand Down Expand Up @@ -167,22 +167,18 @@ public void logGroupEnd(String name) {

@Override
public void logStart(EventInfo eventInfo) {
if (eventInfo instanceof HttpEventInfo) {
HttpEventInfo httpEventInfo = (HttpEventInfo)eventInfo;
if (eventInfo instanceof HttpEventInfo httpEventInfo) {
logStart(httpEventInfo);
} else if (eventInfo instanceof WebSocketEventInfo<?>) {
WebSocketEventInfo<?> webSocketEventInfo = (WebSocketEventInfo<?>)eventInfo;
} else if (eventInfo instanceof WebSocketEventInfo<?> webSocketEventInfo) {
logStart(webSocketEventInfo);
}
}

@Override
public void logEnd(EventInfo eventInfo) {
if (eventInfo instanceof HttpEventInfo) {
HttpEventInfo httpEventInfo = (HttpEventInfo)eventInfo;
if (eventInfo instanceof HttpEventInfo httpEventInfo) {
logEnd(httpEventInfo);
} else if (eventInfo instanceof WebSocketEventInfo<?>) {
WebSocketEventInfo<?> webSocketEventInfo = (WebSocketEventInfo<?>)eventInfo;
} else if (eventInfo instanceof WebSocketEventInfo<?> webSocketEventInfo) {
logEnd(webSocketEventInfo);
}
}
Expand Down Expand Up @@ -268,6 +264,10 @@ private String toMatchPhrase(MatchType matchType, boolean negated) {
case EndsWith -> "ends with";
case BeginsWith -> "begins with";
case Regex -> "is matched by";
case LessThan -> "is less than";
case GreaterThan -> "is greater than";
case LessThanOrEqual -> "is less than or equals";
case GreaterThanOrEqual -> "is greater than or equals";
};
} else {
return switch (matchType) {
Expand All @@ -276,6 +276,10 @@ private String toMatchPhrase(MatchType matchType, boolean negated) {
case EndsWith -> "does not end with";
case BeginsWith -> "does not begin with";
case Regex -> "is not matched by";
case LessThan -> "is not less than";
case GreaterThan -> "is not greater than";
case LessThanOrEqual -> "is not less than or equal to";
case GreaterThanOrEqual -> "is not greater than or equal to";
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@
@JsonSubTypes.Type(value = ThenSendRequest.class),
@JsonSubTypes.Type(value = ThenSendMessage.class),
@JsonSubTypes.Type(value = ThenRepeat.class),
@JsonSubTypes.Type(value = ThenReadFile.class)
@JsonSubTypes.Type(value = ThenReadFile.class),
@JsonSubTypes.Type(value = ThenExtract.class),
@JsonSubTypes.Type(value = ThenGenerate.class),
@JsonSubTypes.Type(value = ThenTransform.class)
})
public abstract class Then<T extends Then<T>> implements IRuleOperation<T> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public RuleResponse perform(EventInfo eventInfo) {
Pair.of("index", destinationVariableSource.isList() && itemPlacement.isHasIndexSetter() ? VariableString.getTextOrDefault(eventInfo, index, null) : null)
),
messageValueSetters.stream().map(messageValueSetter -> Pair.of(
VariableSourceEntry.getTag(
VariableTag.getTag(
VariableSource.Message,
messageValueSetter.getDestinationMessageValue().name().toLowerCase(),
messageValueSetter.getDestinationMessageValue().isIdentifierRequired() ? VariableString.getTextOrDefault(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import synfron.reshaper.burp.core.vars.VariableString;

import java.util.Arrays;
import java.util.List;

public class ThenDelay extends Then<ThenDelay> implements IHttpRuleOperation, IWebSocketRuleOperation {
@Getter
Expand All @@ -33,7 +34,7 @@ public RuleResponse perform(EventInfo eventInfo) {
hasError = true;
throw e;
} finally {
if (eventInfo.getDiagnostics().isEnabled()) eventInfo.getDiagnostics().logProperties(this, hasError, Arrays.asList(Pair.of("millis", VariableString.getTextOrDefault(eventInfo, delay, "0"))));
if (eventInfo.getDiagnostics().isEnabled()) eventInfo.getDiagnostics().logProperties(this, hasError, List.of(Pair.of("millis", VariableString.getTextOrDefault(eventInfo, delay, "0"))));
}
return RuleResponse.Continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public RuleResponse perform(EventInfo eventInfo) {
if (eventInfo.getDiagnostics().isEnabled()) eventInfo.getDiagnostics().logValue(
this,
hasError,
VariableSourceEntry.getTag(
VariableTag.getTag(
targetSource,
variableName.getText(eventInfo),
IListItemPlacement.toGet(itemPlacement),
Expand Down
Loading

0 comments on commit 9e99ec6

Please sign in to comment.