Rating:

# Crypto

# Base646464
```
Encoding something multiple times makes it exponentially more secure!
Files: cipher.txt generate.js
```

In `cipher.txt`, there seems to be a very large base64 message, and in `generate.js`, there is:
``` js
const btoa = str => Buffer.from(str).toString('base64');

const fs = require("fs");
const flag = fs.readFileSync("flag.txt", "utf8").trim();

let ret = flag;
for(let i = 0; i < 25; i++) ret = btoa(ret);

fs.writeFileSync("cipher.txt", ret);
```

`generate.js` encode the flag 25 times in base64, we can reverse what this script do but, i want to use my BaseCracker software (https://github.com/skyf0l/BaseCracker):
```
$ ./basecracker.py `cat ~/Downloads/cipher.txt`
Cipher: [...]

[...]
Apply base64: VjIweE5HRkdiM3BrU0U1T1VrVktlVmw2UlRWak1ERllaRWQ0V1UxcldtMVphMUpEVFVabmVVOVhNVmxsYkd0M1dYcE5kMUJSUFQwPQ==
Apply base64: V20xNGFGb3pkSE5OUkVKeVl6RTVjMDFYZEd4WU1rWm1Za1JDTUZneU9XMVllbGt3WXpNd1BRPT0=
Apply base64: Wm14aFozdHNNREJyYzE5c01XdGxYMkZmYkRCMFgyOW1YelkwYzMwPQ==
Apply base64: ZmxhZ3tsMDBrc19sMWtlX2FfbDB0X29mXzY0c30=
Apply base64: flag{l00ks_l1ke_a_l0t_of_64s}

Decode order: base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64,base64
Plaintext: flag{l00ks_l1ke_a_l0t_of_64s}
```

The flag is: `flag{l00ks_l1ke_a_l0t_of_64s}`

# 4k-rsa
```
Only n00bz use 2048-bit RSA. True gamers use keys that are at least 4k bits long, no matter how many primes it takes...
File: 4k-rsa-public-key.txt
```

In `4k-rsa-public-key.txt`, there is:
```
n: 5028492424316659784848610571868499830635784588253436599431884204425304126574506051458282629520844349077718907065343861952658055912723193332988900049704385076586516440137002407618568563003151764276775720948938528351773075093802636408325577864234115127871390168096496816499360494036227508350983216047669122408034583867561383118909895952974973292619495653073541886055538702432092425858482003930575665792421982301721054750712657799039327522613062264704797422340254020326514065801221180376851065029216809710795296030568379075073865984532498070572310229403940699763425130520414160563102491810814915288755251220179858773367510455580835421154668619370583787024315600566549750956030977653030065606416521363336014610142446739352985652335981500656145027999377047563266566792989553932335258615049158885853966867137798471757467768769820421797075336546511982769835420524203920252434351263053140580327108189404503020910499228438500946012560331269890809392427093030932508389051070445428793625564099729529982492671019322403728879286539821165627370580739998221464217677185178817064155665872550466352067822943073454133105879256544996546945106521271564937390984619840428052621074566596529317714264401833493628083147272364024196348602285804117877
e: 65537
c: 3832859959626457027225709485375429656323178255126603075378663780948519393653566439532625900633433079271626752658882846798954519528892785678004898021308530304423348642816494504358742617536632005629162742485616912893249757928177819654147103963601401967984760746606313579479677305115496544265504651189209247851288266375913337224758155404252271964193376588771249685826128994580590505359435624950249807274946356672459398383788496965366601700031989073183091240557732312196619073008044278694422846488276936308964833729880247375177623028647353720525241938501891398515151145843765402243620785039625653437188509517271172952425644502621053148500664229099057389473617140142440892790010206026311228529465208203622927292280981837484316872937109663262395217006401614037278579063175500228717845448302693565927904414274956989419660185597039288048513697701561336476305496225188756278588808894723873597304279725821713301598203214138796642705887647813388102769640891356064278925539661743499697835930523006188666242622981619269625586780392541257657243483709067962183896469871277059132186393541650668579736405549322908665664807483683884964791989381083279779609467287234180135259393984011170607244611693425554675508988981095977187966503676074747171
```

It's a RSA encryption, we can see all factors of n with http://www.factordb.com:
```
N = 9353689450544968301 * 9431486459129385713 * 9563871376496945939 * 9734621099746950389 * 9736426554597289187 * 10035211751896066517 * 10040518276351167659 * 10181432127731860643 * 10207091564737615283 * 10435329529687076341 * 10498390163702844413 * 10795203922067072869 * 11172074163972443279 * 11177660664692929397 * 11485099149552071347 * 11616532426455948319 * 11964233629849590781 * 11992188644420662609 * 12084363952563914161 * 12264277362666379411 * 12284357139600907033 * 12726850839407946047 * 13115347801685269351 * 13330028326583914849 * 13447718068162387333 * 13554661643603143669 * 13558122110214876367 * 13579057804448354623 * 13716062103239551021 * 13789440402687036193 * 13856162412093479449 * 13857614679626144761 * 14296909550165083981 * 14302754311314161101 * 14636284106789671351 * 14764546515788021591 * 14893589315557698913 * 15067220807972526163 * 15241351646164982941 * 15407706505172751449 * 15524931816063806341 * 15525253577632484267 * 15549005882626828981 * 15687871802768704433 * 15720375559558820789 * 15734713257994215871 * 15742065469952258753 * 15861836139507191959 * 16136191597900016651 * 16154675571631982029 * 16175693991682950929 * 16418126406213832189 * 16568399117655835211 * 16618761350345493811 * 16663643217910267123 * 16750888032920189263 * 16796967566363355967 * 16842398522466619901 * 17472599467110501143 * 17616950931512191043 * 17825248785173311981 * 18268960885156297373 * 18311624754015021467 * 18415126952549973977
```

Now, we can decrypt the cipher:
``` pytyhon
$ python
Python 2.7.18 (default, Apr 21 2020, 18:49:31)
[GCC 9.3.1 20200408 (Red Hat 9.3.1-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> primes = [9353689450544968301, 9431486459129385713, 9563871376496945939, 9734621099746950389, 9736426554597289187, 10035211751896066517, 10040518276351167659, 10181432127731860643, 10207091564737615283, 10435329529687076341, 10498390163702844413, 10795203922067072869, 11172074163972443279, 11177660664692929397, 11485099149552071347, 11616532426455948319, 11964233629849590781, 11992188644420662609, 12084363952563914161, 12264277362666379411, 12284357139600907033, 12726850839407946047, 13115347801685269351, 13330028326583914849, 13447718068162387333, 13554661643603143669, 13558122110214876367, 13579057804448354623, 13716062103239551021, 13789440402687036193, 13856162412093479449, 13857614679626144761, 14296909550165083981, 14302754311314161101, 14636284106789671351, 14764546515788021591, 14893589315557698913, 15067220807972526163, 15241351646164982941, 15407706505172751449, 15524931816063806341, 15525253577632484267, 15549005882626828981, 15687871802768704433, 15720375559558820789, 15734713257994215871, 15742065469952258753, 15861836139507191959, 16136191597900016651, 16154675571631982029, 16175693991682950929, 16418126406213832189, 16568399117655835211, 16618761350345493811, 16663643217910267123, 16750888032920189263, 16796967566363355967, 16842398522466619901, 17472599467110501143, 17616950931512191043, 17825248785173311981, 18268960885156297373, 18311624754015021467, 18415126952549973977]
>>> N = 1
>>> for prime in primes:
... N *= prime
...
>>> N == 5028492424316659784848610571868499830635784588253436599431884204425304126574506051458282629520844349077718907065343861952658055912723193332988900049704385076586516440137002407618568563003151764276775720948938528351773075093802636408325577864234115127871390168096496816499360494036227508350983216047669122408034583867561383118909895952974973292619495653073541886055538702432092425858482003930575665792421982301721054750712657799039327522613062264704797422340254020326514065801221180376851065029216809710795296030568379075073865984532498070572310229403940699763425130520414160563102491810814915288755251220179858773367510455580835421154668619370583787024315600566549750956030977653030065606416521363336014610142446739352985652335981500656145027999377047563266566792989553932335258615049158885853966867137798471757467768769820421797075336546511982769835420524203920252434351263053140580327108189404503020910499228438500946012560331269890809392427093030932508389051070445428793625564099729529982492671019322403728879286539821165627370580739998221464217677185178817064155665872550466352067822943073454133105879256544996546945106521271564937390984619840428052621074566596529317714264401833493628083147272364024196348602285804117877
True
>>> e = 65537
>>> phi = 1
>>> for prime in primes:
... phi *= (prime - 1)
...
>>> from Crypto.Util.number import inverse
>>> d = inverse(e, phi)
>>> cipher = 3832859959626457027225709485375429656323178255126603075378663780948519393653566439532625900633433079271626752658882846798954519528892785678004898021308530304423348642816494504358742617536632005629162742485616912893249757928177819654147103963601401967984760746606313579479677305115496544265504651189209247851288266375913337224758155404252271964193376588771249685826128994580590505359435624950249807274946356672459398383788496965366601700031989073183091240557732312196619073008044278694422846488276936308964833729880247375177623028647353720525241938501891398515151145843765402243620785039625653437188509517271172952425644502621053148500664229099057389473617140142440892790010206026311228529465208203622927292280981837484316872937109663262395217006401614037278579063175500228717845448302693565927904414274956989419660185597039288048513697701561336476305496225188756278588808894723873597304279725821713301598203214138796642705887647813388102769640891356064278925539661743499697835930523006188666242622981619269625586780392541257657243483709067962183896469871277059132186393541650668579736405549322908665664807483683884964791989381083279779609467287234180135259393984011170607244611693425554675508988981095977187966503676074747171
>>> plaintext = pow(cipher, d, N)
>>> print plaintext
706900059475106681301586714568958471062774799484906508017771377121899901
>>> print hex(plaintext)[2:-1].decode('hex')
flag{t0000_m4nyyyy_pr1m355555}
```

The flag is: `flag{t0000_m4nyyyy_pr1m355555}`

## Itsy-bitsy
```
The itsy-bitsy spider climbed up the water spout...

nc 2020.redpwnc.tf 31284
File: itsy-bitsy.py
```

We have the script running on netcat in `itsy-bitsy.py`:
``` python
#!/usr/bin/env python3

from Crypto.Random.random import randint

def str_to_bits(s):
bit_str = ''
for c in s:
i = ord(c)
bit_str += bin(i)[2:]
return bit_str

def recv_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)
if i <= 0 or j <= i:
raise Exception
except:
print('Error! You must adhere to the restrictions!')
exit()
return i,j

def generate_random_bits(lower_bound, upper_bound, number_of_bits):
bit_str = ''
while len(bit_str) < number_of_bits:
r = randint(lower_bound, upper_bound)
bit_str += bin(r)[2:]
return bit_str[:number_of_bits]

def bit_str_xor(bit_str_1, bit_str_2):
xor_res = ''
for i in range(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))
return xor_res

def main():
with open('flag.txt','r') as f:
flag = f.read()
for c in flag:
i = ord(c)
assert i in range(2**6,2**7)
flag_bits = str_to_bits(flag)
i,j = recv_input()
lb = 2**i
ub = 2**j - 1
n = 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()
```

For exemple:
```
$ nc 2020.redpwnc.tf 31284
Enter an integer i such that i > 0: 5
Enter an integer j such that j > i > 0: 12
Ciphertext: 0001111101011111100111111010110001100100000011011001110000101100100100010011110100000101010101111110101101000110100000110001110000100100100001011111100100001001010101000101100100101111100010101010010001100011000100000000001101101101001000100111000000110101000010111110000010011110000001000110001011111
```

The flag is xored with a key generated with random numbers between `2**i` (`2**5 = 32`) and `2**j - 1` (`2**12 - 1 = 4095`) but we can't guess them

In fact, we can guess a few bits at a time

For exemple, with i = 2 and j = 3, random numbers can be from 4 to 7 and their binary values are:
``` python
>>> bin(4)[2:]
'100'
>>> bin(5)[2:]
'101'
>>> bin(6)[2:]
'110'
>>> bin(7)[2:]
'111'
```
Then, the key is composed by packs of 3 bits and the first bit af all packs is `1`, so all bits at positions multiple of 3 are xored by one

In general, for `i = n` and `j = n + 1`, all bits at positions multiple of n are xored by one

We can make a script to solve it:
``` python
#!/usr/bin/python2
import socket
import random

TCP_IP = '2020.redpwnc.tf'
TCP_PORT = 31284
BUFFER_SIZE = 1024

'''
bin(1)[2:] == 10
bin(2)[2:] == 11
-> all 2n bit is cipher_bit ^ 1
'''

res = ['_'] * 301

size = 2

while '_' in res[2:]:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))

s.recv(BUFFER_SIZE)
s.send(str(size - 1) + '\n')
s.recv(BUFFER_SIZE)
s.send(str(size) + '\n')
data = s.recv(BUFFER_SIZE)

cipher = data[len('Ciphertext: '):][:-1]

for k in range(0, len(cipher), size):
res[k] = str(int(cipher[k]) ^ 1)
print(''.join(res))
size += 1
```

Execute it and we get `1_00110110110011000011100111111101111000101101001111010011100111011111110110011001011100001110101111010011101110110011110111111101111111010111101001011111110010011011111110111110111010111111110100110100011001011011111111011111000011110100110010111100101011111111001111100001101111111010111101001111101`, but we can't find the second char with this technique

No problems, because with `1`, it's `Flag{bits_leaking_out_down_the_water_spout}` and with 1 is `flag{bits_leaking_out_down_the_water_spout}`

The flag is: `flag{bits_leaking_out_down_the_water_spout}`

Original writeup (https://github.com/skyf0l/CTF/blob/master/RedPwnCTF_2_2020/Crypto.md#4k-rsa).