Skip to content

Instantly share code, notes, and snippets.

@earthnuker
Last active November 25, 2017 17:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save earthnuker/4b0cd77a162d25dd5472883a411c056c to your computer and use it in GitHub Desktop.
Save earthnuker/4b0cd77a162d25dd5472883a411c056c to your computer and use it in GitHub Desktop.
IMG_Glitch
[DEFAULT]
reload=0
header_size=1024
iter_cnt=16
file_cnt=1
quiet=1
join=0
mode=reverse:1024
[raw]
header_size=0
file_cnt=1024
;iter_cnt=64
#1024
#65536
;256
;1024
;131072
;65536
;8388608
;4096
;1024
quiet=1
reload=1
join=0
;mode=copy:int(divmod(1.5**n//5,len(data))[1])|remove:int(divmod(1.5**n//5,len(data))[1])
iter_cnt=128
mode=copy:256|remove:256
;mode=copy:4096
;mode=add:1024|remove:1024
;mode=copy:1|remove:1
[wav]
header_size=1024
iter_cnt=1024
file_cnt=100
reload=0
quiet=0
mode=reverse:65536
[bmp]
file_cnt=1
header_size=4096
iter_cnt=512
reload=1
quiet=1
mode=copy:16|remove:16
#invert:777777
[gif]
reload=0
header_size=1024
iter_cnt=n
file_cnt=1024
mode=flip
[jpg]
iter_cnt=1
reload=1
header_size=1024
file_cnt=1024
mode=flip
[png]
file_cnt=1024
header_size=8
iter_cnt=1
reload=1
mode=flip
[mp3]
iter_cnt=65536
reload=0
mode=replace
[avi]
iter_cnt=512
#65536
#8388608
header_size=65536
reload=0
mode=randomize:1024
#1024
[bin]
iter_cnt=65536
#8388608
#65536
#8388608
header_size=0
mode=copy:128
#536870912
[wmv]
reload=0
header_size=65536
iter_cnt=4096
#65536
#4096
#1024
mode=flip
[m4v]
iter_cnt=4096
#65536
#8388608
header_size=65536
reload=0
mode=copy:2|remove:2
#1024
[smc]
iter_cnt=1
header_size=1024
reload=0
mode=flip
file_cnt=4096
[nes]
iter_cnt=128
header_size=1024
reload=0
mode=flip
file_cnt=128
import random,os,sys,configparser,glob,time,datetime,argparse,mmap,io,re
from zlib import crc32
if len(sys.argv)<2:
print(sys.argv[0],"<input file>")
exit(-1)
t_s=time.time()
dt=lambda :datetime.timedelta(seconds=time.time()-t_s)
def fixpng(data):
data_handle=io.BytesIO(data)
ret=bytearray()
pngsig=bytes([ 0x89, 0x50 , 0x4e , 0x47 , 0x0d , 0x0a , 0x1a , 0x0a ])
sig=data_handle.read(8)
if sig!=pngsig:
return
ret+=sig
fix=0
while 1:
csize=int.from_bytes(data_handle.read(4),'big')
cn=data_handle.read(4)
data=data_handle.read(csize)
cs=int.from_bytes(data_handle.read(4),'big')
ncs=crc32(cn)
ncs=crc32(data,ncs)&((1<<32)-1)
if cs!=ncs:
fix+=1
ncs=ncs.to_bytes(4,'big')
chunk=csize.to_bytes(4,'big')+cn+data+ncs
ret+=chunk
if cn==b'IEND':
break
if data_handle.tell()==len(data_handle.getbuffer()):
break
ret+=data_handle.read()
print("Fixed {} checksums".format(fix))
return ret
def flipbit(data):
offset=random.randint(headersize,bs)
byte=offset//8
bit=7-(offset%8)
try:
data[byte-1]^=1<<bit
except:
print(byte,len(data))
raise
return data
def swap_data(data,size=1024):
if extra!=None:
size=extra
o1=random.randint(headersize,(len(data)-size)-1)
o2=random.randint(headersize,(len(data)-size)-1)
data[o2:o2+size],data[o1:o1+size]=data[o1:o1+size],data[o2:o2+size]
return data
def replace_data(data,size=1024):
if extra!=None:
size=extra
o=random.randint(headersize,(len(data)-size)-1)
toadd=data[o:o+size]
o=random.randint(headersize,(len(data)-len(toadd)-1))
data[o:o+len(toadd)]=toadd
return data
def randomize_data(data,size=1024):
if extra!=None:
size=extra
toadd=bytes(random.randint(0,255) for x in range(size))
o=random.randint(headersize,(len(data)-len(toadd)-1))
data[o:o+len(toadd)]=toadd
return data
def add_data(data,size=1024):
if extra!=None:
size=extra
toadd=bytes(random.randint(0,255) for x in range(size))
o=random.randint(headersize,(len(data)-len(toadd)-1))
data=data[:o]+toadd+data[o:]
return data
def copy_data(data,scs=1024):
if extra!=None:
scs=extra
o=random.randint(headersize,(len(data)-scs)-1)
toadd=data[o:o+scs]
data=data[:o]+toadd+data[o:]
return data
def clone_data(data,scs=1024):
if extra!=None:
scs=extra
o=random.randint(headersize,(len(data)-scs)-1)
toadd=data[o:o+scs]
for _ in range(8):
data=data[:o]+toadd+data[o:]
return data
def remove_data(data,scs=1024):
if extra!=None:
scs=extra
o=random.randint(headersize,(len(data)-scs)-1)
del data[o:o+scs]
return data
def reverse_data(data,scs=1024):
if extra!=None:
scs=extra
o=random.randint(headersize,(len(data)-scs)-1)
data[o:o+scs]=data[o:o+scs][::-1]
return data
def invert_data(data,scs=1024):
if extra!=None:
scs=extra
o=random.randint(headersize,(len(data)-1))
data[o:o+scs]=bytearray(map(lambda x:x^0xff,data[o:o+scs]))
return data
def wordpad(data):
repls={
b"\x07":b"\x20",
b"\x0a":b"\x0d\x0a",
b"\x0d":b"\x0d\x0a",
b"\x0b":b"\x0d\x0a",
}
return re.sub(b'|'.join(re.escape(key) for key in repls.keys()),lambda k: repls[k.group(0)], data)
config=configparser.ConfigParser()
config.read("glitch.ini")
fn=sys.argv[1]
files=glob.glob(fn)
if not os.path.isdir("glitch_out"):
os.mkdir("glitch_out")
for fn in files:
n=0
fmt=fn.split(".")[-1]
if fmt=="jpeg":
fmt="jpg"
try:
configd=dict(config[fmt])
except KeyError:
configd=dict(config['DEFAULT'])
do_mmap=False
fs=os.stat(fn).st_size
with open(fn,"rb") as f:
if not do_mmap:
data=bytearray(f.read())
else:
data=mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
fs=len(data)
bs=fs*8
while 1:
headersize=eval(configd['header_size'])
end=eval(configd['file_cnt'])
cnt=eval(configd['iter_cnt'])
reload=eval(configd['reload'])
quiet=bool(int(configd['quiet']))
join=bool(int(configd['join']))
chain=configd['mode'].split("|")
try:
extra=eval(configd['extra'])
except KeyError:
extra=None
if reload:
with open(fn,"rb") as f:
if not do_mmap:
data=bytearray(f.read())
else:
data=mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
n+=1
print(dt(),"F:",fn,"OF:",n,"/",end)
for itn in range(1,cnt+1):
for mode in chain:
extra=None
if ":" in mode:
mode,extra=mode.split(":",1)
if ":" in extra:
extra,s=extra.split(":",1)
#if extra=="r":
extra=eval(extra)
if not quiet:
if itn%100==0:
print(dt())
print(mode,extra)
print("F:",fn)
print("OF:",n,"/",end)
print("OFS:",len(data))
print("IT:",itn,"/",cnt)
print("-"*10)
if mode=="flip":
data=flipbit(data)
elif mode=="swap":
data=swap_data(data)
elif mode=="replace":
data=replace_data(data)
elif mode=="add":
data=add_data(data)
elif mode=="wordpad":
data=wordpad(data)
elif mode=="copy":
data=copy_data(data)
elif mode=="remove":
data=remove_data(data)
elif mode=="reverse":
data=reverse_data(data)
elif mode=="clone":
data=clone_data(data)
elif mode=="invert":
data=invert_data(data)
elif mode=="randomize":
data=randomize_data(data)
else:
exit("unknown mode '{}'".format(mode))
dir,fname=os.path.split(fn)
dir=os.path.join(os.getcwd(),"glitch_out")
ext=fname.split(".")[-1]
fname=".".join(fname.split(".")[:-1])
if not join:
ofn="glitched_"+fname+"_"+str(int(n)).zfill(5)+"."+fmt
w_mode="wb"
else:
ofn="glitched_"+fname+"."+fmt
w_mode="ab"
ofn=os.path.join(dir,ofn)
data_fixed=data
if fmt=="png":
data_fixed=fixpng(data)
if data_fixed:
with open(ofn,w_mode) as of:
of.write(data_fixed)
if n==end:
break
print("Done in",dt())
#input("Press enter to exit...")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment