import sys import struct import hashlib import binascii def F(x, y, z): return (x & y) | ((~x) & z) def G(x, y, z): return (x & z) | (y & (~z)) def H(x, y, z): return x ^ y ^ z def I(x, y, z): return y ^ (x | (~z)) def _rotateLeft( x, n): return (x << n) | (x >> (32-n)) def XX(func, a, b, c, d, x, s, ac): res = 0L res = res + a + func(b, c, d) res = res + x res = res + ac res = res & 0xffffffffL res = _rotateLeft(res, s) res = res & 0xffffffffL res = res + b return res & 0xffffffffL class md5(): def __init__(self): self.A, self.B, self.C, self.D = (0x67452301L, 0xefcdab89L, 0x98badcfeL, 0x10325476L) def md5_compress(self, buf): if len(buf) != 64: raise ValueError, "Invalid buffer of length %d: %s" % (len(buf), repr(buf)) inp = struct.unpack("I"*16, buf) a, b, c, d = self.A, self.B, self.C, self.D S11, S12, S13, S14 = 7, 12, 17, 22 a = XX(F, a, b, c, d, inp[0], S11, 0xD76AA478L) d = XX(F, d, a, b, c, inp[1], S12, 0xE8C7B756L) c = XX(F, c, d, a, b, inp[2], S13, 0x242070DBL) b = XX(F, b, c, d, a, inp[3], S14, 0xC1BDCEEEL) a = XX(F, a, b, c, d, inp[4], S11, 0xF57C0FAFL) d = XX(F, d, a, b, c, inp[5], S12, 0x4787C62AL) c = XX(F, c, d, a, b, inp[6], S13, 0xA8304613L) b = XX(F, b, c, d, a, inp[7], S14, 0xFD469501L) a = XX(F, a, b, c, d, inp[8], S11, 0x698098D8L) d = XX(F, d, a, b, c, inp[9], S12, 0x8B44F7AFL) c = XX(F, c, d, a, b, inp[10], S13, 0xFFFF5BB1L) b = XX(F, b, c, d, a, inp[11], S14, 0x895CD7BEL) a = XX(F, a, b, c, d, inp[12], S11, 0x6B901122L) d = XX(F, d, a, b, c, inp[13], S12, 0xFD987193L) c = XX(F, c, d, a, b, inp[14], S13, 0xA679438EL) b = XX(F, b, c, d, a, inp[15], S14, 0x49B40821L) S21, S22, S23, S24 = 5, 9, 14, 20 a = XX(G, a, b, c, d, inp[1], S21, 0xF61E2562L) d = XX(G, d, a, b, c, inp[6], S22, 0xC040B340L) c = XX(G, c, d, a, b, inp[11], S23, 0x265E5A51L) b = XX(G, b, c, d, a, inp[0], S24, 0xE9B6C7AAL) a = XX(G, a, b, c, d, inp[5], S21, 0xD62F105DL) d = XX(G, d, a, b, c, inp[10], S22, 0x02441453L) c = XX(G, c, d, a, b, inp[15], S23, 0xD8A1E681L) b = XX(G, b, c, d, a, inp[4], S24, 0xE7D3FBC8L) a = XX(G, a, b, c, d, inp[9], S21, 0x21E1CDE6L) d = XX(G, d, a, b, c, inp[14], S22, 0xC33707D6L) c = XX(G, c, d, a, b, inp[3], S23, 0xF4D50D87L) b = XX(G, b, c, d, a, inp[8], S24, 0x455A14EDL) a = XX(G, a, b, c, d, inp[13], S21, 0xA9E3E905L) d = XX(G, d, a, b, c, inp[2], S22, 0xFCEFA3F8L) c = XX(G, c, d, a, b, inp[7], S23, 0x676F02D9L) b = XX(G, b, c, d, a, inp[12], S24, 0x8D2A4C8AL) S31, S32, S33, S34 = 4, 11, 16, 23 a = XX(H, a, b, c, d, inp[5], S31, 0xFFFA3942L) d = XX(H, d, a, b, c, inp[8], S32, 0x8771F681L) c = XX(H, c, d, a, b, inp[11], S33, 0x6D9D6122L) b = XX(H, b, c, d, a, inp[14], S34, 0xFDE5380CL) a = XX(H, a, b, c, d, inp[1], S31, 0xA4BEEA44L) d = XX(H, d, a, b, c, inp[4], S32, 0x4BDECFA9L) c = XX(H, c, d, a, b, inp[7], S33, 0xF6BB4B60L) b = XX(H, b, c, d, a, inp[10], S34, 0xBEBFBC70L) a = XX(H, a, b, c, d, inp[13], S31, 0x289B7EC6L) d = XX(H, d, a, b, c, inp[0], S32, 0xEAA127FAL) c = XX(H, c, d, a, b, inp[3], S33, 0xD4EF3085L) b = XX(H, b, c, d, a, inp[6], S34, 0x04881D05L) a = XX(H, a, b, c, d, inp[9], S31, 0xD9D4D039L) d = XX(H, d, a, b, c, inp[12], S32, 0xE6DB99E5L) c = XX(H, c, d, a, b, inp[15], S33, 0x1FA27CF8L) b = XX(H, b, c, d, a, inp[2], S34, 0xC4AC5665L) S41, S42, S43, S44 = 6, 10, 15, 21 a = XX(I, a, b, c, d, inp[0], S41, 0xF4292244L) d = XX(I, d, a, b, c, inp[7], S42, 0x432AFF97L) c = XX(I, c, d, a, b, inp[14], S43, 0xAB9423A7L) b = XX(I, b, c, d, a, inp[5], S44, 0xFC93A039L) a = XX(I, a, b, c, d, inp[12], S41, 0x655B59C3L) d = XX(I, d, a, b, c, inp[3], S42, 0x8F0CCC92L) c = XX(I, c, d, a, b, inp[10], S43, 0xFFEFF47DL) b = XX(I, b, c, d, a, inp[1], S44, 0x85845DD1L) a = XX(I, a, b, c, d, inp[8], S41, 0x6FA87E4FL) d = XX(I, d, a, b, c, inp[15], S42, 0xFE2CE6E0L) c = XX(I, c, d, a, b, inp[6], S43, 0xA3014314L) b = XX(I, b, c, d, a, inp[13], S44, 0x4E0811A1L) a = XX(I, a, b, c, d, inp[4], S41, 0xF7537E82L) d = XX(I, d, a, b, c, inp[11], S42, 0xBD3AF235L) c = XX(I, c, d, a, b, inp[2], S43, 0x2AD7D2BBL) b = XX(I, b, c, d, a, inp[9], S44, 0xEB86D391L) self.A = (self.A + a) & 0xffffffffL self.B = (self.B + b) & 0xffffffffL self.C = (self.C + c) & 0xffffffffL self.D = (self.D + d) & 0xffffffffL def padding(self, n, sz=None): if sz is None: sz = n pre = 64-8 sz = struct.pack("Q",sz*8) pad = '\x80' n += 1 if n % 64 <= pre: pad += '\x00' * (pre - n % 64) pad += sz else: pad += '\x00' * (pre + 64 - n % 64) pad += sz return pad def pad(self, msg): return msg + self.padding(len(msg)) def md5_iter(self, padding_msg): assert len(padding_msg) % 64 == 0 for i in range(0, len(padding_msg), 64): block = padding_msg[i:i+64] self.md5_compress(padding_msg[i:i+64]) def digest(self): return struct.pack('<IIII', self.A, self.B, self.C, self.D) def hexdigest(self): return binascii.hexlify(self.digest()).decode() def my_md5(self, msg): padding_msg = self.pad(msg) self.md5_iter(padding_msg) return self.hexdigest() def compute_magic_number(self, md5str): self.A = struct.unpack("I", md5str[0:8].decode('hex'))[0] self.B = struct.unpack("I", md5str[8:16].decode('hex'))[0] self.C = struct.unpack("I", md5str[16:24].decode('hex'))[0] self.D = struct.unpack("I", md5str[24:32].decode('hex'))[0] def extension_attack(self, md5str, str_append, lenth): self.compute_magic_number(md5str) p = self.padding(lenth) padding_msg = self.padding( len(str_append), lenth + len(p) + len(str_append) ) self.md5_iter(str_append + padding_msg) return self.hexdigest() if __name__ == "__main__": m = md5() if len(sys.argv) != 4: src = m.pad(sys.argv[1]) + sys.argv[2] print 'md5 padding ->',m.my_md5(src) else: print 'md5 extension_attack ->',m.extension_attack(sys.argv[1], sys.argv[2], int(sys.argv[3]))
|