Lets quickly take a look at now the connection works
Bash
1
2
3
4
5
nc 2020.redpwnc.tf 31284
Enter an integer i such that i > 0: 1
Enter an integer j such that j > i > 0: 2
Ciphertext: 0010001001011101111000001100000010000011000111100100111100011000100001001001100111110011100100000001101101010101001100001100010010000001111000000010100001001100100001000000010101000101010101011010011011100110100000010001110000101000011011001001010110010101000000100001011110000100010100010010110100000
Let us quickly go through the required functions of the source
#!/usr/bin/env python3
fromCrypto.Random.randomimportrandintdefstr_to_bits(s):bit_str=''forcins:i=ord(c)bit_str+=bin(i)[2:]returnbit_strdefrecv_input():i=input('Enter an integer i such that i > 0: ')j=input('Enter an integer j such that j > i > 0: ')try:i=int(i)j=int(j)ifi<=0orj<=i:raiseExceptionexcept:print('Error! You must adhere to the restrictions!')exit()returni,jdefgenerate_random_bits(lower_bound,upper_bound,number_of_bits):bit_str=''whilelen(bit_str)<number_of_bits:r=randint(lower_bound,upper_bound)bit_str+=bin(r)[2:]returnbit_str[:number_of_bits]defbit_str_xor(bit_str_1,bit_str_2):xor_res=''foriinrange(len(bit_str_1)):bit_1=bit_str_1[i]bit_2=bit_str_2[i]xor_res+=str(int(bit_1)^int(bit_2))returnxor_resdefmain():withopen('flag.txt','r')asf:flag=f.read()forcinflag:i=ord(c)assertiinrange(2**6,2**7)flag_bits=str_to_bits(flag)i,j=recv_input()lb=2**iub=2**j-1n=len(flag_bits)random_bits=generate_random_bits(lb,ub,n)encrypted_bits=bit_str_xor(flag_bits,random_bits)print(f'Ciphertext: {encrypted_bits}')if__name__=='__main__':main()
It will generate a random bitstring of length number_of_bits from lower_bound to upper_bound and if the lower_bound itself is greater than the requirement, it will truncate it.
We are asked for input for i and j which are converted to lower and upper bounds as 2**i to 2**j - 1.
The generated bitstream is xored (bit-wise) with the flag and returned
Observation
If one sets i and j to i and i+1, the bounds are 2**i and 2**(i+1) - 1, which are both i bits in length.
The pecularity being the first bit would always be 1 because of 2**i and all the bits at positions multiples of i would be 1
Notice the 0th, 2nd, 4th index and so on is always 1
My unoptimized script solve.py which just concerns about knowing the bit at position i by sending the index i-1 and i.
frompwnimportremoteHOST,PORT="2020.redpwnc.tf",31284defget_ct(num_bits):REM=remote(HOST,PORT)REM.sendline(str(num_bits-1).encode())REM.sendline(str(num_bits).encode())data=REM.recvline()ciphertext=data.split(b':')[-1].strip()#print(data)
REM.close()returnciphertextflag_bits=bytearray(301)#flag size known
flag_bits[0]=49# ord('1') known from the first character 'f' of flag
flag_bits[1]=49# ord('1')
fornum_bitsinrange(2,301):ct=get_ct(num_bits)flag_bits[num_bits]=48ifct[num_bits]==49else49print(bits_to_str(flag_bits))
This can be improved just by noting the fact we knew most of the bits i before reaching the index i, we will only make a request if bit i is not known