Implemented chaining multiple encoding techniques for data transformation.
This commit is contained in:
@@ -44,9 +44,12 @@ suffix = ".######################################-####"
|
||||
# placement = { type = "query", name = "id" }
|
||||
# encoding = { type = "hex" }
|
||||
|
||||
# Example: Raw data in GET request body
|
||||
# Example: Data encoded with multiple techniques in GET request body
|
||||
# placement = { type = "body" }
|
||||
# encoding = { "none" }
|
||||
# encoding = [
|
||||
# { type = "rot", key = 5 },
|
||||
# { type = "base64" }
|
||||
# ]
|
||||
|
||||
# Defines arbitrary URI parameters that are added to the request
|
||||
[http-get.agent.parameters]
|
||||
|
||||
@@ -80,8 +80,23 @@ suffix = ".######################################-####"
|
||||
|
||||

|
||||
|
||||
Multiple encodings can be applied to a packet by defining them in an array of inline-tables, as seen in the example below. The encodings are applied in the order they are defined in the profile. During the decoding of the data transformation, this order is reversed. Hence, the example below first applies the ROT encoding with the key 5 on the data and later base64-encodes it. The reversal starts with the base64-decoding and a rotation in the opposite direction.
|
||||
|
||||
```toml
|
||||
placement = { type = "body" }
|
||||
encoding = [
|
||||
{ type = "rot", key = 5 },
|
||||
{ type = "base64" }
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
|
||||
Check the [default profile](../data/profile.toml) for more examples.
|
||||
|
||||
Other example profiles:
|
||||
- [youtube.profile](../data/youtube.toml): Traffic that resembles watching and interacting with Youtube videos.
|
||||
|
||||
### Request options
|
||||
|
||||
The profile language makes is further possible to add parameters and headers. When arrays are passed to these settings instead of strings, a random member of the array is chosen. Again, character randomization can be used to break up repeating patterns.
|
||||
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
import strutils, sequtils, random, base64
|
||||
import strutils, sequtils, random, base64, algorithm
|
||||
import ./[types, utils]
|
||||
import ./toml/toml
|
||||
export parseFile, parseString, free, getTableKeys, getRandom
|
||||
@@ -74,18 +74,28 @@ proc isArray*(profile: Profile, path: string): bool =
|
||||
]#
|
||||
proc applyDataTransformation*(profile: Profile, path: string, data: seq[byte]): string =
|
||||
# 1. Encoding
|
||||
var dataString: string
|
||||
case profile.getString(path & protect(".encoding.type"), default = protect("none"))
|
||||
of protect("base64"):
|
||||
dataString = encode(data, safe = profile.getBool(path & protect(".encoding.url-safe"))).replace("=", "")
|
||||
of protect("hex"):
|
||||
dataString = Bytes.toString(data).toHex().toLowerAscii()
|
||||
of protect("rot"):
|
||||
dataString = Bytes.toString(encodeRot(data, profile.getInt(path & ".encoding.key", default = 13)))
|
||||
of protect("xor"):
|
||||
dataString = Bytes.toString(xorBytes(data, profile.getInt(path & ".encoding.key", default = 1)))
|
||||
of protect("none"):
|
||||
dataString = Bytes.toString(data)
|
||||
var steps: seq[TomlTableRef] = @[]
|
||||
|
||||
# Apply all encoding techniques in the order specified in the profile
|
||||
if profile.isArray(path & protect(".encoding")):
|
||||
for encoding in profile.getArray(path & protect(".encoding")):
|
||||
steps.add(encoding.getTable())
|
||||
else:
|
||||
steps = @[profile.getTable(path & protect(".encoding"))]
|
||||
|
||||
var dataString: string = Bytes.toString(data)
|
||||
for step in steps:
|
||||
case step.getTableValue(protect("type")).getStr(default = "none")
|
||||
of protect("base64"):
|
||||
dataString = encode(dataString, safe = step.getTableValue(protect("url-safe")).getBool()).replace("=", "")
|
||||
of protect("hex"):
|
||||
dataString = dataString.toHex().toLowerAscii()
|
||||
of protect("rot"):
|
||||
dataString = Bytes.toString(encodeRot(string.toBytes(dataString), step.getTableValue(protect("key")).getInt(default = 13)))
|
||||
of protect("xor"):
|
||||
dataString = Bytes.toString(xorBytes(string.toBytes(dataString), step.getTableValue(protect("key")).getInt(default = 1)))
|
||||
of protect("none"):
|
||||
discard
|
||||
|
||||
# 2. Add prefix & suffix
|
||||
let prefix = profile.getString(path & protect(".prefix"))
|
||||
@@ -98,17 +108,29 @@ proc reverseDataTransformation*(profile: Profile, path: string, data: string): s
|
||||
let
|
||||
prefix = profile.getString(path & protect(".prefix"))
|
||||
suffix = profile.getString(path & protect(".suffix"))
|
||||
dataString = data[len(prefix) ..^ len(suffix) + 1]
|
||||
var dataString = data[len(prefix) ..^ len(suffix) + 1]
|
||||
|
||||
# 2. Decoding
|
||||
case profile.getString(path & protect(".encoding.type"), default = protect("none")):
|
||||
var steps: seq[TomlTableRef] = @[]
|
||||
|
||||
# Apply all encoding techniques in reverse order
|
||||
if profile.isArray(path & protect(".encoding")):
|
||||
for encoding in profile.getArray(path & protect(".encoding")):
|
||||
steps.add(encoding.getTable())
|
||||
else:
|
||||
steps = @[profile.getTable(path & protect(".encoding"))]
|
||||
|
||||
for step in steps.reversed():
|
||||
case step.getTableValue(protect("type")).getStr(default = "none")
|
||||
of protect("base64"):
|
||||
result = string.toBytes(decode(dataString))
|
||||
dataString = decode(dataString)
|
||||
of protect("hex"):
|
||||
result = string.toBytes(parseHexStr(dataString))
|
||||
of protect("rot"):
|
||||
result = decodeRot(string.toBytes(dataString), profile.getInt(path & ".encoding.key", default = 13))
|
||||
dataString = parseHexStr(dataString)
|
||||
of protect("rot"):
|
||||
dataString = Bytes.toString(decodeRot(string.toBytes(dataString), step.getTableValue(protect("key")).getInt(default = 13)))
|
||||
of protect("xor"):
|
||||
result = xorBytes(string.toBytes(dataString), profile.getInt(path & ".encoding.key", default = 1))
|
||||
of protect("none"):
|
||||
result = string.toBytes(dataString)
|
||||
dataString = Bytes.toString(xorBytes(string.toBytes(dataString), step.getTableValue(protect("key")).getInt(default = 1)))
|
||||
of protect("none"):
|
||||
discard
|
||||
|
||||
return string.toBytes(dataString)
|
||||
Reference in New Issue
Block a user