Created
October 16, 2013 08:43
-
-
Save hellman/7004616 to your computer and use it in GitHub Desktop.
xor script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
#-*- coding:utf-8 -*- | |
""" | |
xor strings | |
options: | |
-s - string with \\xAF escapes | |
-r - raw string | |
-h - hex-encoded string (non-letterdigit chars are stripped) | |
-f - read data from file (- for stdin) | |
-n - no newline at the end | |
--no-cycle / --nc - pad smaller strings with null bytes | |
example: xor -s lol -h 414243 -f /etc/passwd | |
author: hellman ( [email protected] ) | |
""" | |
import sys | |
import string | |
import getopt | |
DATA_OPTS = "s:r:h:f:" | |
HEXES = set("0123456789abcdefABCDEF") | |
def main(): | |
nocycle = False | |
nonewline = False | |
try: | |
opts, args = getopt.getopt(sys.argv[1:], "n" + DATA_OPTS, ["no-cycle", "nc"]) | |
datas = [] | |
for c, val in opts: | |
if c in ("--no-cycle", "--nc"): | |
nocycle = True | |
elif c == "-n": | |
nonewline = True | |
else: | |
v = arg_data(c, val) | |
if v is None: | |
raise getopt.GetoptError("unknown option %s" % c) | |
datas.append(v) | |
if not datas: | |
raise getopt.GetoptError("no data given") | |
except getopt.GetoptError as e: | |
print >>sys.stderr, "error:", e | |
print >>sys.stderr, __doc__ | |
quit() | |
sys.stdout.write(xor(datas, nocycle=nocycle)) | |
if not nonewline: | |
sys.stdout.write("\n") | |
def xor(args, nocycle=False): | |
maxlen = max(map(len, args)) | |
res = [0] * maxlen | |
if nocycle: | |
for s in args: | |
for i in xrange(len(s)): | |
res[i] ^= ord(s[i]) | |
else: | |
for s in args: | |
slen = len(s) | |
for i in xrange(maxlen): | |
res[i] ^= ord(s[i % slen]) | |
return "".join(map(chr, res)) | |
def from_str(s): | |
res = "" | |
i = 0 | |
while True: | |
if i + 4 > len(s): | |
break | |
if s[i+1] == "x" and s[i+2] in HEXES and s[i+3] in HEXES: | |
res += chr(int(s[i+2:i+4], 16)) | |
i += 4 | |
else: | |
res += s[i] | |
i += 1 | |
res += s[i:] | |
return res | |
def from_hex(s): | |
res = "" | |
for c in s: | |
if c in HEXES: | |
res += c | |
elif c in string.ascii_letters: | |
raise ValueError("Bad splitters (alphanum)") | |
return res.decode("hex") | |
def from_file(s): | |
if s == "-": | |
return sys.stdin.read() | |
return open(s, "rb").read() | |
def arg_data(opt, s): | |
if opt == "-s": | |
return from_str(s) | |
elif opt == "-r": | |
return s | |
elif opt == "-h": | |
return from_hex(s) | |
elif opt == "-f": | |
return from_file(s) | |
return None | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment