Write up - SHACTF 2017 ( 2For100 + Cryp100 + Network100 + Crypt200)

1. Crypt100 : Stackoverflow



I had some issues implementing strong encryption, luckily I was able to find a nice example on stackoverflow that showed me how to do it.
Challenge: stackoverflow.tgz
File contains:
At first, when we check the given site above, we know that this pdf was encrypted with AES-CTR mode, and more interesting, we can see that they reuse the Counter -> that make AES-CTR vulnarable to Known-Plaintext attack
crypto = AES.new(os.urandom(32), AES.MODE_CTR, counter=lambda: secret)
with secret = os.urandom(16)
Okay, let take look at the AES-CTR , let see the reason why they are vulnerable to Known-Plaintext attack:
107.50 KB
Normally Counter must be UNIQUE , so that the keystream will be different every step. It is more secured than reused , it will make AES-CTR encryption become: 
E(m[i]) = message[i] ^ keystream = cipher[i]
and when we know the plaintext message[i] and the cipher[i] , we will get the keystream then decrypt the whole cipher to get the message
And in the code above, we can see that they reuse key and counter every step , so counter[16bytes] and key[32 bytes] give us keystream[16bytes]
and the encryption become 
cipher[i] = keystream ^ message[i]
so now we just need to guess the message[i] to recover the keystream, then decrypt the whole cipher
 message[i] = keystream ^ cipher[i]
- The encrypted file: Flag.pdf.enc
Okay so it should be pdf file, and we can know for sure their first 7 bytes must be 255044462d312e  ( %PDF-.1 )
and which version (0 -> 7 ) is unknown yet
and because the keystream is 16 bytes, and when xor-ing, message and cipher must be at the same length with keystream, so now we can get the first 7 bytes of keystream by xor-ing the first 7 bytes above with the first 7 bytes of flag.pdf.enc. Now we have to guess they last 9 bytes
and i found a page that contains pdf file structure and it really useful
Why do i say that? let see
i used a script from github to recover the keystream
Now let start our guessing game :D 
i assume our first 8 bytes is %PDF-1.3
let xor with the first 8 bytes in cipher to recover the first 8 bytes of keystream
okay we got the first 8 bytes of keystream because it recover our first 8 bytes in plaintext,  or let xor with the 16th to 24 bytes from flag.pdf.enc ( 24 % 16 = 8 because it is repeating xor ) to see if we can get a nice plaintext
yes, really nice, and from the page above, with /Pa  , it can be /Pages or /Parent or /PageModes
so we dont have to risk trying to guess this one, let start with the  32th -> 40th bytes or with any bytes from 16*i to 16*i + 8 bytes.
  like this one, we can get the 9th -> 11th bytes of keystream , /T should be /Type
 now our cipher: 91D0F70F21226BFC5C50BB
our plaintext predicted: 626a0a3c3c0a2f54 adding ype :  626a0a3c3c0a2f54797065
-> we xor cipher and plaintnext then we will get the 11bytes keystream in hex : f3bafd331d2844a82520de 
okay, we need to find the last 5 bytes, just repeating finding like that and then we get keystream:
keystream = [243, 186, 253, 51, 29, 40, 68, 168, 37, 32, 222, 183, 222, 12, 111, 185]   
now let xor the whole flag.pdf.enc with keystream to get our pdf file
Flag: FLAG{15AD69452103C5DF1CF61E9D98893492}
Forensic100: Compromised
We given a scap file,
use: gzip -d compromised to extract data
after check with wire shark, i found this script:
  1. ciphertext = sys.argv[1]
So now we should find the that sys.argv[1]
So when i was planning to check the read protocal or revmsg protocol , i received a hint from a pro that they should be in /tmp, so i should use the super-unstopable-Extremely-Best-One of a kind STRINGS to find them :v use command : strings FOR100.scap | grep '/tmp'
okay :v now just decode and we get the flag
 For100: Wannafly
 My daughter Kimberly her computer got hacked. Now she lost all her favorite images. Can you please help me recover those images?

From this challenge, we received a .img file, and after checking header, i realize that there are a script and some picture ( %PNG ) in this .img, so i use FKT Imager to see what inside this .img 
as u can see there are a lot of picture, and ... file is a python script

if __name__ == '__main__':
    if len(sys.argv) != 2:
        print "Usage: %s <pass>" % sys.argv[0]
    else:
        encrypt_images()
and the  .bash_history

 so the key will be inputed from the command line, so the .bash_history should have the pass inside
and we check and get the pass: Hb8jnSKzaNQr5f7p

one more thing we should care is: 

  1. def get_iv():
  2.     iv = ""
  3.     random.seed(int(time()))
  4.     for i in range(0,16):
  5.         iv += random.choice(string.letters + string.digits)
  6.     return iv

great, random.seed(int(time())) it mean that they will use the seed = current time when they modyfying this picture, so we can recover their seed with their modified time with command: os.stat(image).st_mtime
Okay so we have
key and 
 IV 
now let decrypt 
Now we take a look to see how they are encrypted


def encrypt_image(img):
    data = open(img, 'r').read()
    encrypted_img = encrypt(data, sys.argv[1])
    blurred_img = open('/tmp/sha.png', 'r').read()
    stat = os.stat(img)
    with open(img, 'r+') as of:
        of.write('\0' * stat.st_size)
        of.flush()
    open(img, 'w').write(blurred_img + "\n" + encrypted_img)

at first they encrypt the data in image, then they write sha.png data ( is an example image ) + '\n' + encrypted_image
it make the previos data become brurred and the rest of the remain data be encrypted
So we should decrypt the encrypted image to recover our image
and an PNG image should have the ENDING: 49454E44AE426082 + 0A
now we write a script to decrypt: 
result: 
Cryp200: Secure Login

This server uses signed tickets to allow users to login, can you find the flag?


nc secure-login.stillhackinganyway.nl 12345
 chall.py 


So we need to find an input of ticket that after pow( ticket , e , N ) it will give the string: "ticket:admin|root| + ' bla bla '
and d is unknown, and from the 1st function we can know that it use signature to encrypt
S(m) = pow ( m , d , N )
but it will result : "ticket:user| whatever we input | whatever we input"
so i think it just let us know this is signature

and the 3rd fucntion will give us whatever we input but adding "\xff" in the beginning

To solve this task, we can use the multiply property

assume we got:

a*b = ticket with
a = '\xff' + 'flag'
ticket = 'ticket:admin|root|'
now we need t find b that satisfy
num2str (ticket*invert( a + random ,N)  ) [0] = '\xff'

Reason:

We got: a * b = ticket mod N
<=>       invert(a,N) * a * b = invert(a,N) * ticket mod N
<=>       b = invert(a,N) * ticket mod N
We need to find b that b[0] = '\xff'
=>         b = invert(a + random , N) * ticket mod N

so     a*b = ticket mod N
<=>  pow(a,d) * pow(b,d) = pow(ticket,d) mod N

we got a and b then netcat to server, sign them, and calculate ( a*b ) % N to get the sig(ticket) and get the flag

Script





Network 100: Vod Kanockers
 The name is Kanockers. Vod Kanockers.

When we open the website and check their header, we see a strange text 

maybe it mean that we should knock every port ?
let try, "the name is Kanockers " -> the server must be vod.stillhackinganyway.nl ( 34.249.81.124 )
Let knock them one by one
i found a CTF challenge that can help us
From this challenge i wrote a script to do the job





Nhận xét

Đăng nhận xét

Bài đăng phổ biến từ blog này

CSAW 2017 Write up

WhiteHat Challenge 04 Write up ( Misc + 2Cryp + For )