Skip to content

Commit af5d7fc

Browse files
committedMar 8, 2016
Added ltseorg writeup
1 parent 2b4441c commit af5d7fc

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## ltseorg (crypto, 4 points, 93 solves)
2+
make some (charlie)hash collisions!
3+
4+
In this task we were given a code with function hashing strings and were asked to create
5+
a hash collision. After reading the
6+
algorithm, we quickly noticed that the padding function was non-standard and flawed:
7+
```
8+
def pad_msg(msg):
9+
while not (len(msg) % 16 == 0): msg+="\x00"
10+
return msg
11+
```
12+
This simply added `\x00` bytes until message length is divisible by 16. That means that
13+
two messages: "a" and "a\x00", although being different, create same hashes. After sending
14+
them to the server, we receive the flag.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
require 'socket'
2+
require 'shellwords'
3+
server = TCPServer.new(9090)
4+
5+
while (connection = server.accept)
6+
Thread.new(connection) do |conn|
7+
conn.puts "gimme str 1"
8+
s1 = conn.gets.chomp
9+
conn.puts "gimme str 2"
10+
s2 = conn.gets.chomp
11+
exec = "python ./tlseorg.py --check #{Shellwords.shellescape s1} #{Shellwords.shellescape s2}"
12+
out = `#{exec}`
13+
puts out
14+
if out == "Success\n"
15+
conn.puts "FLAG"
16+
else
17+
conn.puts "failure"
18+
end
19+
conn.close
20+
end
21+
end
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import sys, binascii, os, time
2+
from Crypto.Cipher import AES
3+
4+
def gqq():
5+
def qqg():gqq();qq(q("20206c7473656f72673a20416d2049206265696e672064657461696e65643f"));qq(q("20206c7473656f72673a20416d2049206672656520746f20676f3f"));qg()
6+
def qqq():qq(q("6c7473656f72673a204920616d206e6f7420616e73776572696e6720616e79207175657374696f6e7320776974686f7574206d79206c61777965722070726573656e742e"));qg()
7+
def gqq():time.sleep(1)
8+
def qg():qqg()
9+
def q(qq):return binascii.unhexlify(qq)
10+
def qq(q):print(q)
11+
def gq():qqg()
12+
qqq()
13+
14+
# March-15: After 23 tries I think we fixed the issue with the IV.
15+
IV = binascii.unhexlify("696c61686773726c7177767576646968")
16+
17+
BLOCK_SIZE = 16
18+
19+
key1 = ["00" for x in xrange(32)]; key1[0] = "11";key1 = binascii.unhexlify("".join(key1))
20+
key2 = ["00" for x in xrange(32)]; key2[0] = "FF";key2 = binascii.unhexlify("".join(key2))
21+
22+
P = AES.new(key1, AES.MODE_ECB)
23+
Q = AES.new(key2, AES.MODE_ECB)
24+
25+
def pad_msg(msg):
26+
while not (len(msg) % 16 == 0): msg+="\x00"
27+
return msg
28+
29+
def xor(str1, str2):
30+
out = []
31+
for i in xrange(len(str1)):
32+
out.append( chr(ord(str1[i])^ord(str2[i])) )
33+
return "".join(out)
34+
35+
# "Pretty much" Grostl's provably secure compression function assuming ideal ciphers
36+
# Grostl pseudo-code is: h = P(m + h) + h + Q(m) and this is basically the same thing, right?
37+
# Ltsorg pseudo-code: h = P(m + h) + m + Q(h)
38+
def compress(m, h): return xor( xor( P.encrypt( xor(m, h) ), m), Q.encrypt(h) )
39+
40+
def finalization(m, h): return xor(m, h)[0:14]
41+
42+
def hash(msg):
43+
msg=pad_msg(msg)
44+
# groestl's IV was boring
45+
h = IV
46+
47+
for i in xrange(0, len(msg), BLOCK_SIZE):
48+
m = msg[i: i+BLOCK_SIZE]
49+
h = compress(m ,h)
50+
return finalization(m, h)
51+
52+
53+
def check(hashstr1, hashstr2):
54+
hash1 = binascii.unhexlify(hashstr1);hash2 = binascii.unhexlify(hashstr2)
55+
if hashstr1 == hashstr2 or hash1 == hash2: return False
56+
elif hash(hash1) == hash(hash2): return True
57+
return False
58+
59+
60+
def main():
61+
if len(sys.argv) == 2:
62+
if sys.argv[1] == "-v": gqq()
63+
else:
64+
print "input: "+sys.argv[1]
65+
print "output: "+binascii.hexlify(hash(binascii.unhexlify(sys.argv[1])))
66+
return
67+
elif len(sys.argv) == 3 and (sys.argv[1] == "-v" or sys.argv[2] == "-v"): gqq()
68+
elif len(sys.argv) == 4 and (sys.argv[1] == "--check"):
69+
if check(sys.argv[2], sys.argv[3]): print "Success"
70+
else: print "Failure"
71+
else:
72+
print("ltseorg: missing argument")
73+
print("Usage: ltseorg [OPTION...] [input]")
74+
print("-v \t Display Software version information")
75+
print("--check \t Check if two inputs break collision resistance.")
76+
77+
if __name__ == "__main__":
78+
main()

0 commit comments

Comments
 (0)
Please sign in to comment.