New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TLV traffic obfuscation with 4-non-null-byte XOR #6480
Changes from all commits
c747ffc
ed49a67
18fe9bd
d92ca8f
6c2391e
ac0b489
0134161
44eb2d6
4ac7c5e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -665,6 +665,44 @@ def initialize(type = nil, method = nil) | |
end | ||
end | ||
|
||
# | ||
# Override the function that creates the raw byte stream for | ||
# sending so that it generates an XOR key, uses it to scramble | ||
# the serialized TLV content, and then returns the key plus the | ||
# scrambled data as the payload. | ||
# | ||
def to_r | ||
raw = super | ||
xor_key = rand(254) + 1 | ||
xor_key |= (rand(254) + 1) << 8 | ||
xor_key |= (rand(254) + 1) << 16 | ||
xor_key |= (rand(254) + 1) << 24 | ||
result = [xor_key].pack('N') + xor_bytes(xor_key, raw) | ||
result | ||
end | ||
|
||
# | ||
# Override the function that reads from a raw byte stream so | ||
# that the XORing of data is included in the process prior to | ||
# passing it on to the default functionality that can parse | ||
# the TLV values. | ||
# | ||
def from_r(bytes) | ||
xor_key = bytes[0,4].unpack('N')[0] | ||
super(xor_bytes(xor_key, bytes[4, bytes.length])) | ||
end | ||
|
||
# | ||
# Xor a set of bytes with a given DWORD xor key. | ||
# | ||
def xor_bytes(xor_key, bytes) | ||
result = '' | ||
bytes.bytes.zip([xor_key].pack('V').bytes.cycle).each do |b| | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems overcomplex, why not something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because I'm stupid? :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LOL. This is post-merge, I'll PR something back if there is time. |
||
result << (b[0].ord ^ b[1].ord).chr | ||
end | ||
result | ||
end | ||
|
||
## | ||
# | ||
# Conditionals | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mainly a style nitpick, but this could be cleaner:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn't guarantee non-null bytes in all 4 positions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would something like
xor_key = rand(0xffffffff) +1
be better?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is avoiding any single byte good or bad for heuristic detection? Would the chance of the first byte never being an 'R' be more of a tell than it being an 'R' in rare cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that as long as not all of the bytes are 0, nothing else really makes a difference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may just be overly paranoid, but I felt like it was a good thing to guarantee that every byte changed. That's really the only reasoning.