From 077b1df51f501ed44c7e9a421301174ac7efeaeb Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 30 Nov 2014 01:55:46 -0800 Subject: Progress! last block still improperly reversed. --- src/utils/CryptoUtils.scala | 77 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 11 deletions(-) diff --git a/src/utils/CryptoUtils.scala b/src/utils/CryptoUtils.scala index fc33220..6fe6b19 100644 --- a/src/utils/CryptoUtils.scala +++ b/src/utils/CryptoUtils.scala @@ -59,6 +59,8 @@ object CryptoUtils { def extractUnknownViaEcbOracle(encrypt: Seq[Byte] => Seq[Byte]) = { val blockSize = detectEcbBlockSize(encrypt) + def blocksIn(xs: Seq[Byte]) = xs.length / blockSize + val baseBlockCount = blocksIn(encrypt(Seq())) def rainbow(prefix: Seq[Byte]): Map[Seq[Byte], Byte] = { (0 to 255) @@ -71,6 +73,17 @@ object CryptoUtils { .toMap } + def postfixRainbow(prefix: Seq[Byte]): Map[Seq[Byte], Byte] = { + (0 to 255) + .map(_.toByte) + .map(_ +: prefix) + .map(encrypt) + .map(_.take(16).toSeq) + .zipWithIndex + .map(_ :-> { _.toByte } ) + .toMap + } + def probeFirstBlockAndPaddings: (Seq[Byte], Map[Int, Seq[Byte]]) = { def prefix(known: Seq[Byte]) = (" " * (blockSize - 1 - known.length)).asBytes def genRainbow(known: Seq[Byte]) = rainbow(prefix(known) ++ known) @@ -82,18 +95,19 @@ object CryptoUtils { } def probeLastBlockSize: Int = { - val baseBlockCount = encrypt(Seq[Byte]()).length val firstLargerCiphertext = (0 until blockSize) .map(" " * _).map(_.asBytes).map(encrypt) .zipWithIndex - .find(_._1.length != baseBlockCount) + .find(x => blocksIn(x._1) != baseBlockCount) // this will always be Some(_) because // somewhere between 0..blockSize WILL grow the text. firstLargerCiphertext.get._2 } - println("Last block is " + probeLastBlockSize + " bytes") + val lastBlockSize = probeLastBlockSize + + println("Last block is " + lastBlockSize + " bytes") val (firstBlock, ciphertexts) = probeFirstBlockAndPaddings /* @@ -102,19 +116,45 @@ object CryptoUtils { * rot0b1, rot1b1, rot2b1, ... * */ - val transposed = ciphertexts.toSeq.sortBy(_._1).map(_ :-> { x => - val y = x.grouped(16).toSeq - println(y.length) - y + val cipherBlocks: Seq[(Int, Seq[Seq[Byte]])] = ciphertexts.toSeq.sortBy(_._1).map(_ :-> { x => + x.grouped(16).toSeq }) + val (middleBlocks, lastBlocks) = + cipherBlocks.foldLeft((Seq[Seq[Seq[Byte]]](), Seq[Option[Seq[Byte]]]()))( (ac, curr) => { + val maybeLastBlock = + if (curr._2.length > baseBlockCount) Some(curr._2.last) + else None + + val middleBlocks = curr._2.take(baseBlockCount).tail + + (ac._1 :+ middleBlocks, ac._2 :+ maybeLastBlock) + }) :-> { _.flatten } + + println(lastBlocks.mkString("\n")) + + def breakLastBlock(blocks: Seq[Seq[Byte]]) = { + /* + * plaintext looks something like... + * X 15 15 15 15 15 ... 15 + * Y X 14 14 14 14 ... 14 + * ... pkcs7 + */ + blocks.foldLeft(Seq[Byte]()) { (bytes, block) => { + val postfix = pkcs7pad("?".asBytes ++ bytes, blockSize).tail + val b = postfixRainbow(postfix)(block) + println("Got " + b) + bytes :+ b + }} + } + // val lastBlockBytes = crackLastBlock(lastBlocks) // println("Also...") -// println(rainbow(firstBlock.tail)(transposed(1)(0))) +// println(rainbow(firstBlock.tail)(middleBlocks(1)(0))) val prefix = firstBlock.tail val currRainbow = rainbow(prefix) - println(ciphertexts(0).drop(16).take(16)) - val next = currRainbow(ciphertexts(0).drop(16).take(16).toSeq) + println(middleBlocks(0)(0))//ciphertexts(0).drop(16).take(16)) + val next = currRainbow(middleBlocks(0)(0)) println("Next: " + new String(Array(next.toByte))) val nowPrefix = (prefix.tail :+ next) val r2 = rainbow(nowPrefix) @@ -125,7 +165,22 @@ object CryptoUtils { val next3 = r3(ciphertexts(2).drop(16).take(16).toSeq) println("Next: " + new String(Array(next3.toByte))) - firstBlock + def breakBlock(plaintext: Seq[Byte], padded: Seq[Seq[Byte]]): Seq[Byte] = + padded.foldLeft(Seq[Byte]()) { (blockText: Seq[Byte], block: Seq[Byte]) => { + val prefix = (plaintext ++ blockText).takeRight(blockSize - 1) + val b = rainbow(prefix)(block) + blockText :+ b + }} + + val middleBytes = + middleBlocks.transpose.init.foldLeft(firstBlock) { (plaintext, padded: Seq[Seq[Byte]]) => + println("Block " + padded(0)) + val bytes = breakBlock(plaintext, padded) + println(".... Done!") + plaintext ++ bytes + } + + middleBytes ++ breakLastBlock(lastBlocks) } } -- cgit v1.1