# TOPKEK (50 p)
```A CNN reporter had only one question that she couldn't get off her mind
Do we even know, who is this 4 CHAN???
So she set out to find who this 400lb hacker is. During her investigation, she came across this cryptic message on some politically incorrect forum online, can you figure out what it means?```
There is a ciphertext attached to this challenge, which contains the following:
```KEK! TOP!! KEK!! TOP!! KEK!! TOP!! KEK! TOP!! KEK!!! TOP!! KEK!!!! TOP! KEK! TOP!! KEK!! TOP!!! KEK! TOP!!!! KEK! TOP!! KEK! TOP! KEK! TOP! KEK! TOP! KEK!!!! TOP!! KEK!!!!! TOP!! KEK! TOP!!!! KEK!! TOP!! KEK!!!!! TOP!! KEK! TOP!!!! KEK!! TOP!! KEK!!!!! TOP!! KEK! TOP!!!! KEK!! TOP!! KEK!!!!! TOP!! KEK! TOP!!!! KEK!! TOP!! KEK!!!!! TOP! KEK! TOP! KEK!!!!! TOP! KEK! TOP!!!!! KEK! TOP! KEK! TOP!!!!! KEK! TOP! KEK! TOP!!!!! KEK! TOP! KEK! TOP!!!!! KEK! TOP! KEK! TOP!!!!! KEK! TOP! KEK! TOP!!!!! KEK!! TOP!! KEK!!! TOP! KEK! TOP!! KEK! TOP!! KEK! TOP! KEK! TOP! KEK! TOP!!!!! KEK! TOP!! KEK! TOP! KEK!!!!! TOP!! KEK! TOP! KEK!!! TOP! KEK! TOP! KEK! TOP!! KEK!!! TOP!! KEK!!! TOP! KEK! TOP!! KEK! TOP!!! KEK!! TOP! KEK!!! TOP!!! KEK! TOP! KEK! TOP!!!!! KEK! TOP! KEK!!! TOP!! KEK!! TOP!!! KEK! TOP! KEK! TOP! KEK! TOP! KEK!! TOP!!! KEK!! TOP! KEK! TOP!!!!! KEK! TOP!!! KEK!! TOP! KEK!!! TOP!! KEK!!! TOP! KEK! TOP!! KEK!! TOP!!! KEK! TOP! KEK!! TOP! KEK!!!! TOP!!! KEK! TOP! KEK!!! TOP! KEK! TOP!!!!! KEK! TOP!! KEK! TOP!!! KEK!!! TOP!! KEK!!!!! TOP! KEK! TOP! KEK! TOP!!! KEK! TOP! KEK! TOP!!!!! KEK!! TOP!! KEK! TOP! KEK!!! TOP! KEK! TOP! KEK!! TOP! KEK!!! TOP!! KEK!! TOP!! KEK! TOP! KEK! TOP!!!!! KEK! TOP!!!! KEK!! TOP! KEK!! TOP!! KEK!!!!! TOP!!! KEK! TOP! KEK! TOP! KEK! TOP! KEK! TOP!!!!! KEK! TOP!! KEK! TOP! KEK!!!!! TOP!! KEK! TOP! KEK!!! TOP!!! KEK! TOP!! KEK!!! TOP!! KEK!!! TOP! KEK! TOP!! KEK! TOP!!! KEK!! TOP!! KEK!! TOP!!! KEK! TOP! KEK! TOP!!!!! KEK! TOP!! KEK!! TOP!! KEK!! TOP!!! KEK! TOP! KEK! TOP! KEK! TOP!! KEK! TOP!!! KEK!! TOP! KEK! TOP!!!!! KEK! TOP! KEK! TOP!!!!! KEK! TOP! KEK! TOP!!!!! KEK! TOP! KEK! TOP!!!!! KEK! TOP! KEK! TOP!!!!! KEK! TOP! KEK! TOP!!!!! KEK! TOP! KEK!! TOP! KEK! TOP!! KEK!! TOP!! KEK!! TOP!! KEK! TOP! KEK!! TOP! KEK! TOP!! KEK!! TOP! KEK!!!! TOP! KEK!! TOP! KEK!!!! TOP! KEK!! TOP! KEK!!!! TOP! KEK! TOP!!!!! KEK! TOP!```
First guess is a binary, and judging from the amount of points given for this challenge, that is probably no more complicated than that. `TOP` is either `0` or `1` and the number of `!` denotes the number of each symbol. We try both and find that `TOP` maps to `1`, so `KEK` is `0`. The following code decodes the ciphertext.
```pythonsplit_cipher = ciphertext.split()decrypted = ''for block in split_cipher:    if block.startswith('KEK'):        decrypted += '0' * (len(block) - 3)    else:        decrypted += '1' * (len(block) - 3)
decrypted = int(decrypted, 2)print libnum.n2s(decrypted)```
This gives
```flag{T0o0o0o0o0P______1m_h4V1nG_FuN_r1gHt_n0W_4R3_y0u_h4v1ng_fun______K3K!!!}```# Trump Trump (100 p)
```With Trump about to be in office, autographed photos of him are selling like wildfire. The only problem is:Trump makes it a point to never sign a photo of himself. If you could get a signed picture, you could stand to make DOZENS of dollars.
nc trumptrump.pwn.republican 3609```
We get the following parameters
```pythone = 65537N = 23377710160585068929761618506991996226542827370307182169629858568023543788780175313008507293451307895240053109844393208095341963888750810795999334637219913785780317641204067199776554612826093939173529500677723999107174626333341127815073405082534438012567142969114708624398382362018792541727467478404573610869661887188854467262618007499261337953423761782551432338613283104868149867800953840280656722019640237553189669977426208944252707288724850642450845754249981895191279748269118285047312864220756292406661460782844868432184013840652299561380626402855579897282032613371294445650368096906572685254142278651577097577263```Converting the image to a number
```pythonf = open('trump.jpg', 'r')data = libnum.s2n(f.read()) % N```
we try to submit it, which incidentially fails. We can exploit that sign(a) × sign(b) = sign(a × b). Since the image is divisible by for instance 5, we can factor out this and sign the two parts separately.
```sign(data / 5) = 15742105247958736958004859844860106392650529642491444791655288653059139800053206167023792876159338330811553994563264038797209523053486931817881299156223450837206775783069574776254654197337314541494064874054449749920216258529257414289049794126137529358458843274774718683434637726891822317083908587215429977340799931758155377373656742947190372216055450421108566287038161365843817023142180328035768992726841684537565155117632165969899505426984495819465218509929865350057283134017766501372618581237936784285588661088765130624093014320161531747074858737002260566015050922492437422682387506583350890218827504186050632600504sign(5) = 18938431620064949405099081881389422411569506620645684785718437650149907701313939238017399264771270907473551575023831816899182480214946633959498312433619616816861526269114681215528914329791099013891595131862543300865871379621247867883669403120593815746911158013483346808195756730946735362037791985948842449343328484149265803462983935765047801620079220588638013959948297979415581591179722303271496129424130559547762467547913292325129340535450673107267746074776721093375970510983576513946461957148135755448610570645462794635156136176208419134557678284424568016798221633694322809374691561612990098051154456165773266086828```so,
```sign(data) = 7240527260044126899075832339973255923943354335060037001558105343295495841635843603507411996488568977206115374657942401805673165802944813082589201103827861325639581582005106924492724100812077464571265915352012064311221086996199961637876724784326540728342282620427706011099830010859187486529928704673604893811823836195858916605646466850177580221970723526928598144155086898666864544017092301766812496415256830844105167571316067435310083881243302996555421199570092966497927454347195963984192282682803663188954259681974561132158520131591167970511602803401392202553720288822909116428852233039667283953852194960467196349739```
Sending this to the service, we get
```Duneld Trump: Well, I already met my quota for Guantanimo Bay inmates today, so okay.Trump looks shocked, appalled by the fact that he'd sign a picture of himself for such a not-billionaire.Trump sprints away at a blinding 2mph, dropping what he was carrying.It's a stack of photos, you pick one up and look at it.ffd8ffe000104a46494600010101006000600000ffdb0043000302020302020303030304030304050805050404050a070706080c0a0c0c0b0a0b0b0d0e12100d0e110e0b0b1016101113141515150c0f171816141812141514ffdb00430103040405040509050509140d0b0d1414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414ffc20011080173029403011100021101031101ffc4001d000002020301010100000000000000000003040102000506070809ffc4001b01000301010101010000000000000000000002030104050607ffda000c03010002100310000001f9904c0c090837024303025896590c36431480cc202776420c90c0c08090c090c090c3242c6f5136f41853dd38e9d0ab557756b58562b284099bb4657767675d55339066f27e8978ef673ebc3030dc08090c330303021770302ccb3b9218658622e955ec8d20...```
Let us write code to make it viewable:
```pythonimport libnumfrom pwn import *
v = remote('trumptrump.pwn.republican', 3609)v.recv(1024)v.send(str(s) + '\r\n')
for i in range(4): v.recvline()data = v.recvline()open('trump1.jpg','w').write(libnum.n2s(int(data, 16)))```
![flag](trump1.jpg)
# Vermatrix Supreme (100 p)
```Working in IT for a campaign is rough; especially when your candidate uses his password as the IV for your campaign's proprietary encryption scheme, then subsequently forgets it. See if you can get it back for him.The only hard part is, he changes it whenever he feels like it.
nc vermatrix.pwn.democrat 4201```
Along this, we get the code for the encryption scheme.
```pythonimport sys, random, time
flag = "flag{1_sw34r_1F_p30Pl3_4cTu4lLy_TrY_Th1s}"
def printmat(matrix):	for row in matrix:		for value in row:			print value,		print ""	print ""
def pad(s):	if len(s)%9 == 0:		return s	for i in xrange((9-(len(s)%9))):		s.append(0)	return s
def genBlockMatrix(s):	outm = [[[7 for x in xrange(3)] for x in xrange(3)] for x in xrange(len(s)/9)]	for matnum in xrange(0,len(s)/9):		for y in xrange(0,3):			for x in xrange(0,3):				outm[matnum][y][x] = s[(matnum*9)+x+(y*3)]	return outm
def fixmatrix(matrixa, matrixb):	out = [[0 for x in xrange(3)] for x in xrange(3)]		for rn in xrange(3):		for cn in xrange(3):			out[cn][rn] = (int(matrixa[rn][cn])|int(matrixb[cn][rn]))&~(int(matrixa[rn][cn])&int(matrixb[cn][rn]))	return out
def chall():	IV = [c for c in '?????????']	seed = "??????????????????"
	blocks = genBlockMatrix(pad(IV + [ord(c) for c in seed]))
	res = [[0 for i in xrange(3)] for i in xrange(3)]	for i in xrange(len(blocks)):		res = fixmatrix(res, blocks[i])
	print "SEED: " + str(seed)	printmat(res)
	data = raw_input("")
	data = data.replace(' ', '').strip().split(',')
	if len(data) != 9:		return False
	for i in xrange(len(IV)):		if str(IV[i]) != str(data[i]):			return False
	return True
if chall():	print flag```
The `IV` is a series of 9 numbers in some undefined range. Instead of spending a bunch of time to find some algebraic relations that we can exploit, we can use Z3. We define a set of variables (BitVec) for Z3, representing the unknown `IV`.  Since the matrix we receive should contain the same values as the computed one, given `seed` and the correct `IV`, we set up equality relations.
```pythonfrom z3 import *from pwn import *from vermatrix import *
def find_iv(seed, target):    s = Solver()    IV = [BitVec('%d' % i, 32) for i in range(1,10)]      blocks = genBlockMatrix(pad(IV + [ord(c) for c in seed]))    res = [[0 for i in xrange(3)] for i in xrange(3)]     for i in xrange(len(blocks)):        res = fixmatrix(res, blocks[i])
    for y1, y2 in zip(res, target):         for x1, x2 in zip(y1, y2):             s.add(x1 == x2) # they should be equal!     return s```
Now, we can use this routine in connecting to the server as follows:
```pythoncontext.log_level = 'error'v = remote('vermatrix.pwn.democrat', 4201)
seed = v.recvline().split()[1]target_matrix = [[int(x) for x in v.recvline().split()] for i in range(0, 3)]s = find_iv(seed, target_matrix)
if s.check() == sat:    m = s.model()    out = [0]*9    for x in m:        out[int(str(x))-1] = m[x]    v.send(str(out)[1:-1] + '\n')    print 'FLAG: {0}'.format(v.recvline())```
Running the whole code, we obtain
```flag{IV_wh4t_y0u_DiD_Th3r3}```
# Boxes of Ballots (200 p)
```Privjet Komrade!
While doing observing of Amerikanski's voting infrascture we find interesting box. We send operative to investigate. He return with partial input like showing below.He say box very buggy but return encrypted data sometimes. Figure out what box isdo; maybe we finding embarass material to include in next week bitcoin auction, yes?
ebug": true, "data": "BBBBBBBBBBBBBBBB", "op": "enc"}
nc boxesofballots.pwn.republican 9001```
This challenge is very similar to [this](https://github.com/grocid/CTF/tree/master/IceCTF/2016#l33tcrypt-90-p)). We can solve it as follows:
```pythonfrom pwn import *import jsonimport string
def getdata(res):    for l in res.split('\n'):        if l.startswith('{"Status"'):            return json.loads(l)['data']
def getreference(buflen, v):    data = {"debug": False, "data": 'x'*buflen , "op": "enc"}    payload = json.dumps(data).replace('False', 'false')    v.send(payload + '\n')    response = v.recv(1024)    ref = getdata(response)[:64]    return ref
context.log_level = 'error'v = remote('boxesofballots.pwn.republican', 9001)result = ""buflen = 31
while buflen:    ref = getreference(buflen, v)
    for i in string.printable:        data = {"debug": False, "data": 'x'*buflen + result + i, "op": "enc"}        payload = json.dumps(data).replace('False', 'false')
        v.send(payload + '\n')        response = v.recv(1024)        res = getdata(response)        if res[:64] == ref:            result += i            buflen -= 1            print result            break    else:        print "[-] Error"        exit(-1)```
gives
```flag{Source_iz_4_noobs}```
Michał Żuberek ([Z](http://z.bigi.pl)) of my team Snatch the Root solved this one.
# The Best RSA (250 p)
```At his last rally, Trump made an interesting statement:
I know RSA, I have the best RSAThe more bits I have, the more secure my cyber, and my modulus is YUUUUUUUUUUUUUGEWe don't believe his cyber is as secure as he says it is. See if you can break it for us```
We get a file with a public exponent `e = 65537` and a massive public modulus `N`. Clearly, there is something strange with this modulus. The first obvious move is to check for small factors, and in fact, we find that 3 is a factor. Not once, but several times. The whole modulus consist of very small prime factors. Let us write some code to factor it!
```pythonimport libnum, grocid, challenge
def get_private_exponent(phi, e):    return libnum.modular.invmod(e, phi)
def find_factors(n, h):    primes = grocid.sieve(h)    factors = {}    for p in primes:        while n % p == 0:            n = n / p            if p in factors:                factors[p] +=1            else:                factors[p] = 1    return factors
print '[+] Factoring n...'single_factors = find_factors(challenge.n, 10000)```
OK, so we got a dictionary containing each prime factor and its corresponding exponent. It looks like this:
```python{3: 1545, 5: 1650, 7: 1581, 137: 1547, 11: 1588, 13: 1595, 17: 1596, 19: 1553, 149: 1572, 23: 1579, 29: 1549, 31: 1613, 163: 1589, 37: 1594, 167: 1578, 41: 1524, 43: 1538, 173: 1617, 47: 1571, 229: 1610, 179: 1556, 53: 1635, 59: 1556, 151: 1549, 61: 1605, 181: 1582, 193: 1549, 67: 1606, 197: 1520, 71: 1589, 73: 1571, 241: 1564, 79: 1548, 83: 1630, 139: 1638, 89: 1535, 199: 1574, 223: 1610, 97: 1456, 227: 1600, 131: 1540, 101: 1514, 103: 1583, 233: 1564, 107: 1591, 109: 1529, 239: 1556, 157: 1600, 113: 1601, 211: 1544, 251: 1493, 191: 1564, 127: 1565}```
So, we can compute ϕ and the corresponding private exponent:
```pythonphi = challenge.nprint '[+] Computing phi...'for p in single_factors:    phi = phi / p * (p - 1)
print '[+] Computing private exponent'd = get_private_exponent(phi, 65537)```
This enables us to decrypt! However, if you try it, you will probably notice that it takes quite some time and memory to compute cᵈ (mod n). Now, we can speed this a bit using CRT. So, we compute cᵈ (mod 3¹⁵⁴⁵) and so on separately, for each prime factor and then use CRT to reconstruct the whole message:
```pythonremainders = []moduli = []
for p in single_factors:    modulus = pow(p, single_factors[p])    moduli.append(modulus)    remainder = pow(challenge.c, d, modulus)    remainders.append(remainder)
plaintext = libnum.modular.solve_crt(remainders, moduli)print 'Message: {0}'.format(libnum.n2s(plaintext))```
It still takes some time to complete, but it is managable (left it running while doing other stuff so...). It could possibly be made faster by Hensel lifting, but I decided not to try it. When done, we get a message which is a image file.:
![Decrypted](decrypted.gif)
# Baby's hands (300 p)```We think that Trump's right hand man has been sending out flags from his personal computer, but we need to be sure. See if you can make anything out of the trafficwe intercepted.```
The initial two lines are
```python{d:n:c}{64193765095472280945778947695026260940793161700792092928929371930940586875921621250436677664062645637750266086941620369817913432656342447118119648040487568561166129534408858429501807430550886328164336961068507005046531729954378900389289038547121166749974617776234380115780563231906876010653549490718147637109:162375468556255342840184380017752307049575955143811124651668179546999144455415632265862602514386409412258772643790637233144774447636694664087397175482938958661142022166864007317692608104513835959387316735889741416403005613839667775733147723497537341613995375357897642024075069112712472560335406551536669543677:161368580245997137625438248139098888389801359838792140099794084052829279383422322670122662786704858201672541232233171127388341066584896672407182421832728901923771676356720611937864219195771372253188974650818854505110963737925290199983571032857746780899310446337006151661497839040062867489758146326490061720009}```
OK, so the private exponent `d` is published. We try to compute cᵈ (mod n) and look at the binary data with binwalk. No results. Hm... so, what if we need the public exponent `e` to compute the plaintext? We can probably find this with Wieners attack! Let us try it!
```pythonimport libnum, grocid
f = open('intercepted', 'r')
data = f.read()data = data.split('\n')
for line in data[1:]:    d, n, c = [int(x) for x in line[1:-1].split(':')]    e = grocid.wiener.attack(d, n)```
This yields
```flag{G3t_1t?_1t_h4s_4_sm4ll_d}```
# SMTPresident (400 p)
```The FBI reopened their investigation of Hillary Clinton after they recovered some interesting files from her personal email server.
emailspubkeysflag```
The file `pubkeys` contains a set of public keys with very small public exponent (e = 17). Assuming that every message sent on the same date is identical, we can use Håstad's broadcast attack. Incidentially, we have 17 of each every date. The following Python code will do just fine:
```pythonfrom os import listdirfrom os.path import isfile, joinfrom Crypto.PublicKey import RSAfrom base64 import b64decodeimport re, libnum, gmpy
def get_files(path):     return [f for f in listdir(path) if isfile(join(path, f))] pubkeysfiles = get_files('./pubkeys')emailfiles = get_files('./emails')pubkeys = {}encrypted_emails = {}
for pubkeyfile in pubkeysfiles:    f = open('./pubkeys/' + pubkeyfile, 'r')    data = f.read().replace('-----BEGIN RSA PUBLIC KEY-----', '').replace('-----END RSA PUBLIC KEY-----', '')    data = b64decode(data)    pubkeys[pubkeyfile] = RSA.importKey(data)    f.close()
for emailfile in emailfiles:    f = open('./emails/' + emailfile, 'r')    data = f.read()    sender = re.findall('To: (.*)@dnc', data)[0]    date = re.findall('Date: (.*)\n', data)[0]    content = re.findall('Content: (.*)', data)[0]    if not date in encrypted_emails:        encrypted_emails[date] = {}    encrypted_emails[date][sender] = int(content, 16)
message_content = Falsefor date in encrypted_emails:    moduli = []    remainders = []     for x in encrypted_emails[date]:        moduli.append(pubkeys[x].n)        remainders.append(encrypted_emails[date][x])
    x = libnum.modular.solve_crt(remainders, moduli)    x0 = gmpy.mpz(x)    xr = x0.root(17)    message = libnum.n2s(int(xr[0]))     if not message_content:        message_content = ['?'] * len(message)     for i, c in enumerate(message):        if c != '#':            message_content[i] = c
print ''.join(message_content)```
which outputs
```Subject: My Fellow DNC MembersContent: Keep this safe <MISSING>1862866103431083493477241717117566609979097064670248011800478128293487053500169824960133057115553, that's the key we agreed on.```
OK, so let us assume that the key mentioned in the message is the lower bits of the private exponent. There is a method to solve this problem. A script which implements this method can be found [here](https://github.com/grocid/CTF/tree/master/CSAW/2016#still-broken-box-400-p) and [here](https://grocid.net/2016/03/14/0ctf-equation/).
Unfortunately, the computation did not finish (e = 65537 takes some time to run, even multithreaded). Pity.