Writeup from Junior 35c3CTF’18
Junior 35c3CTF 2018: pretty-linear Category:  CryptoChallenge Points:  158Solves:  28
Description: 
1 2 3 4 5 The NSA gave us these packets, they said it should be just enough to break this crypto. surveillance.pcap server.py Difficulty estimate: Medium-Hard 
 
 
This challenge objective was pretty clear - Solve Linear Equation with 40 unknowns 
Now starting with  *server.py*, we have three sets of variables, 
1 2 3 4 5 6 7 8 if  __name__ == '__main__' :           challenge = keygen()      print(' ' .join(map(str, challenge)))      response = int(input())      if  response != sum(x*y%p for  x, y in  zip(challenge, key)):          print('ACCESS DENIED' )          exit(1 ) 
 
key 
 
unknown, find 40 of them to get flag 
 
challenge 
 
40 integers per stream, we have 40 of them 
 
response 
 
1 response per stream, again 40 of them 
 
 
 
Analysing surveilance.pcap  with Wireshark Open the packet capture file with Wireshark. We see mostly TCP packets, and to analyse the TCP packets, click 
Analyse > Follow > TCP stream
 
 
We have 40 such streams of which, the blue  ones are the challenge, and the red  ones are response.
The following bash script will extract the data from surveilance.pcap 
extract.sh
 
1 2 3 4 5 6 7 8 infile=surveilance.pcap outfile=out ext=txt for  stream in  $(tshark -nlr $infile  -Y tcp.flags.syn==1 -T fields -e tcp.stream | sort -n | uniq | sed 's/\r//' )do         echo  "Processing stream $stream : ${outfile} _${stream} .${ext} "              tshark -nlr $infile  -qz "follow,tcp,raw,$stream "  | tail -n +7 | sed 's/^\s\+//g'  | xxd -r -p > ${outfile} _${stream} .${ext}          done  
 
Solving Linear Equations using Matrices Again, from *server.py*, we get
response = sum(x*y%p for x, y in zip(challenge, key))
 
So, finally with all the 40 files, we get 40 such equations (where i=range(40) )
response[i] = sum(x*y%p for x, y in zip(challenge[i], key))
 
Solving linear equation of 40 unknowns can be done easily with Matrices.,reference 
Thus, the key will be 
1 2 challenge * key = response key = challenge_inv * response 
 
Solving for key using Sage To calculate the InverseMod(p) of the Matrix challenge, sage  provides an easy way to this:
challenge_inv = Matrix(IntegerModRing(p),challenge).inverse()
 
Matrix multiplication of challenge_inv and response yeilds the key
key = challenge_inv * response
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 key = [151166356399959194245460055888166966126L ,  23349654305343746371904146512921179610L ,  303231127335861985008837572586617401477L ,  52564325979162295713031020943288299431L ,  318561098467762156502271721157519784045L ,  263049694618319332492436935081367988962L ,  151925705582116739255625584197651639678L ,  46319333286788790879399387215584902926L ,  144250191566113115015826218788418570765L ,  95097625879948609497612754022619234195L ,  40890527924981050968775993543458295905L ,  73015657936779070795829412187806965634L ,  17764129701686300306686689106838999642L ,  325835500394544926294581718484613749556L ,  71443020776832402486826429105359001130L ,  328905290970722092344104084599942510400L ,  246319993494260311894585740502008352891L ,  339251916682414225894494357646852524504L ,  270753355547506496805860877660621175158L ,  266604583518913012106937436764867155955L ,  132952188910249324219774647464400732439L ,  229485064954594431373138165566214808548L ,  273124499649767430591820642695664426994L ,  161206428662237066098654588615704724656L ,  191676246712534509807283243359699775780L ,  110791878778380133926865862999743362183L ,  121869512181659437298676494294916884080L ,  81324902884339942138294016318959955113L ,  219404824444265280645688236691554688702L ,  169041597038940530794876375975659802012L ,  131851490945732599957487956170326572223L ,  337190018815691236060142455413012785269L ,  215436829468576180414177636304832181536L ,  174614268507338543165725749934608091983L ,  316523955444804263394840392424504742312L ,  215434679427738924369625297037020081680L ,  103769840624100781721896803697739863413L ,  302813910848119681638497129402557822574L ,  104414047167186149419822776294661649936L ,  124689157029586638342169541932443340723L ] 
 
All we have to do next is, create the AES instance using the AES_key = sha256(key)  
1 2 3 4 5 6 cipher = AES.new(             sha256(' ' .join(map(str, key)).encode('utf-8' )).digest(),             AES.MODE_CFB,             b'\0' *16          ) print  cipher.decrypt(ct.decode('hex' ))
 
FLAG 
35C3_G4uss_w0uld_b3_so_pr0ud_of_y0u_r1ght_n0w  
 
Complete Script P.S you need to install sage to run the script 
$sage exploit.sage
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 from  hashlib import  sha256from  Crypto.Cipher import  AESimport  osp = 340282366920938463463374607431768211297  challenge=[]     response=[]      key=[]           ct = "923fa1835d8dbdcd9f9b0e6658b24fce54512fbba71d7a0012c37d2c9dd094a6278593d8d9f7a4aa9fecb66042"  os.system("./extract.sh" )  for  i in  range(40 ):    f = open("out/out_" +str(i)+".txt" ).read().split('\n' )     challenge+=[map(int,f[0 ].split(' ' ))]     response+=[int(f[1 ])] challenge_inv = Matrix(IntegerModRing(p),challenge).inverse() rl=[] for  i in  response: rl+=[[i]]response_mat = Matrix(rl) y = challenge_inv*response_mat key = eval(y.str().strip().replace("]\n[" ,"," )) print  keycipher = AES.new(             sha256(' ' .join(map(str, key)).encode('utf-8' )).digest(),             AES.MODE_CFB,             b'\0' *16          ) print  cipher.decrypt(ct.decode('hex' ))