Problem

Solution

Let’s start by taking a look at chall.py:

flag = "lactf{REDACTED}"  
extended_flag = ""  
  
for c in flag:  
	o = bin(ord(c))[2:].zfill(8)  
	
	# Replace the first 0 with a 1  
	for i in range(8):  
		if o[i] == "0":  
			o = o[:i] + "1" + o[i + 1 :]  
			break  
	
	extended_flag += chr(int(o, 2))  
	
print(extended_flag)  
 
with open("chall.txt", "wb") as f:  
	f.write(extended_flag.encode("iso8859-1"))

Something that stands out is this section here:

# Replace the first 0 with a 1  
for i in range(8):  
	if o[i] == "0":  
		o = o[:i] + "1" + o[i + 1 :]  
		break  

The keen eye will notice that nothing is replaced at all! In Python’s slice and range notation, start is inclusive but stop is not; that is, the range is .So the line o = o[:i] + "1" + o[i + 1 :] merely inserts a “1” before the first zero, but does not replace it. With this in mind, reversing the “extended” charset is quite simple.

Script

with open("chall.txt", "rb") as f:  
	c = f.read().decode("iso8859-1")  
 
flag = "" 
 
for i in c:  
	binstring = bin(ord(i))[2:]  
	
	for j in range(len(binstring)):  
		if binstring[j] == "0":
			binstring = binstring[:j-1] + binstring[j:]  
			break 
	
	flag += chr(int(binstring, 2))  
 
print(flag)