144 lines
3.7 KiB
Python
144 lines
3.7 KiB
Python
"""
|
|
Stegano.py
|
|
https://github.com/MatMasIt/steganoCode
|
|
|
|
2021, Mattia Mascarello
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import sys
|
|
import re
|
|
|
|
def unicodeToBin(text):
|
|
return ''.join('{:08b}'.format(b) for b in text.encode('utf8'))
|
|
def binToUnicode(binI):
|
|
return bytes(int(b, 2) for b in re.split('(........)', binI) if b).decode('utf8')
|
|
def binToRTLLTR(binI):
|
|
final = ""
|
|
for b in list(binI):
|
|
if b == "1":
|
|
final += "\u200f" # RTL
|
|
else:
|
|
final += "\u200e" # LTR
|
|
if final[-1] == "\u200f":
|
|
final += "\u200e"
|
|
else:
|
|
final += "\u200f"
|
|
return final
|
|
def RTLLTRToBin(rtlltr):
|
|
final = ""
|
|
for c in list(rtlltr):
|
|
if c == "\u200f":
|
|
final+="1"
|
|
else:
|
|
final+="0"
|
|
final= final [:-1]
|
|
return final
|
|
|
|
|
|
def enc(message):
|
|
return binToRTLLTR(unicodeToBin(message))
|
|
|
|
def dec(encoded):
|
|
return binToUnicode(RTLLTRToBin(encoded))
|
|
|
|
def multilineComment(message,comment,begin="\n/*\n",end="\n*/\n"):
|
|
final = begin
|
|
final += enc(message)
|
|
final += "\n"+comment+"\n"
|
|
final += end
|
|
return final
|
|
|
|
def srcEnc(src,lang,message,comment):
|
|
if lang == "py":
|
|
comm = multilineComment(message,comment,'\n"""\n','\n"""\n')+"\n"+src
|
|
else:
|
|
comm = multilineComment(message,comment)+"\n"+src
|
|
return comm
|
|
|
|
def srcDec(src):
|
|
found=[]
|
|
accumulator=""
|
|
srcPrev=""
|
|
for char in list(src):
|
|
if char == "\u200f" or char == "\u200e":
|
|
accumulator+=char
|
|
elif len(accumulator):
|
|
accumulator=dec(accumulator)
|
|
srcPrev+=accumulator
|
|
srcPrev+=char
|
|
found.append(accumulator)
|
|
accumulator=""
|
|
else:
|
|
srcPrev+=char
|
|
res={"found":found,"cleanedSrc":srcPrev}
|
|
return res
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--input", help="Input file")
|
|
parser.add_argument("--output", help="Output file")
|
|
parser.add_argument("--stdin", action='store_true', help="Read from stdin")
|
|
parser.add_argument("--stdout", action='store_true', help="Output to stdout")
|
|
parser.add_argument("--hide", action='store_true', help="Hide Mode")
|
|
parser.add_argument("--showSource", action='store_true', help="Show clean source")
|
|
parser.add_argument("--showFound", action='store_true', help="Show Matches")
|
|
parser.add_argument("--lang", help="Programming Language")
|
|
parser.add_argument("--message", help="Hidden message")
|
|
parser.add_argument("--comment", help="Comment")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.input:
|
|
if not os.path.isfile(args.input):
|
|
sys.exit("You must specify a valid input file")
|
|
try:
|
|
data=open(args.input,"r").read()
|
|
except:
|
|
sys.exit("Could not read file")
|
|
elif args.stdin:
|
|
data = ""
|
|
for line in sys.stdin:
|
|
data+=line
|
|
else:
|
|
sys.exit("No input method")
|
|
|
|
if not args.output and not args.stdout:
|
|
sys.exit("No output method")
|
|
|
|
|
|
if args.hide:
|
|
if args.message and len(args.message):
|
|
if args.lang:
|
|
if args.comment:
|
|
comment=args.comment
|
|
else:
|
|
comment=""
|
|
res=srcEnc(data,args.lang,args.message,comment)
|
|
if args.output:
|
|
out=open(args.output,"w+")
|
|
out.write(res)
|
|
out.close()
|
|
if args.stdout:
|
|
print(res)
|
|
else:
|
|
sys.exit("Specify a language")
|
|
else:
|
|
sys.exit("Specifify a message")
|
|
elif args.showSource or args.showFound:
|
|
res=srcDec(data)
|
|
if args.showSource:
|
|
r=res["cleanedSrc"]
|
|
else:
|
|
r="\n".join(res["found"])
|
|
if args.output:
|
|
out=open(args.output,"w+")
|
|
out.write(r)
|
|
out.close()
|
|
if args.stdout:
|
|
print(r)
|
|
else:
|
|
sys.exit("No action specified")
|