<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.yobi.be/index.php?action=history&amp;feed=atom&amp;title=Hack.lu_2017_Writeups</id>
	<title>Hack.lu 2017 Writeups - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.yobi.be/index.php?action=history&amp;feed=atom&amp;title=Hack.lu_2017_Writeups"/>
	<link rel="alternate" type="text/html" href="https://wiki.yobi.be/index.php?title=Hack.lu_2017_Writeups&amp;action=history"/>
	<updated>2026-05-22T18:49:38Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki.yobi.be/index.php?title=Hack.lu_2017_Writeups&amp;diff=10373&amp;oldid=prev</id>
		<title>PhilippeTeuwen at 20:31, 20 October 2017</title>
		<link rel="alternate" type="text/html" href="https://wiki.yobi.be/index.php?title=Hack.lu_2017_Writeups&amp;diff=10373&amp;oldid=prev"/>
		<updated>2017-10-20T20:31:36Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 20:31, 20 October 2017&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 102:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 102:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;Assume the secret is &quot;XXXXXXXXXXXXX&quot;, hash the message &quot;012345678901234567890123456789012345678901234567890123456XXXXXXXXXXXXX&quot;. It will be split in two blocks and the secret will be split across the two blocks: 7 chars at the end of the first block and 6 chars at the beginning of the second block. Compute backwards the states against all possible second blocks (given the message hash returned by the oracle, which is &quot;be75f49ca582d673346bf85209aba13c&quot; for message &quot;012345678901234567890123456789012345678901234567890123456&quot;) and store these chaining values, then compute all possible first blocks and check for a match.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;Assume the secret is &quot;XXXXXXXXXXXXX&quot;, hash the message &quot;012345678901234567890123456789012345678901234567890123456XXXXXXXXXXXXX&quot;. It will be split in two blocks and the secret will be split across the two blocks: 7 chars at the end of the first block and 6 chars at the beginning of the second block. Compute backwards the states against all possible second blocks (given the message hash returned by the oracle, which is &quot;be75f49ca582d673346bf85209aba13c&quot; for message &quot;012345678901234567890123456789012345678901234567890123456&quot;) and store these chaining values, then compute all possible first blocks and check for a match.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;This requires quite some RAM, so in practice one can store only partial results (e.g. about half of the chaining value, ~32b as address and 32b as data) in a table smaller than the possible 36^6 values.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;This requires quite some RAM, so in practice one can store only partial results (e.g. about half of the chaining value, ~32b as address and 32b as data) in a table smaller than the possible 36^6 values.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;E.g. when using &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;8Gb&lt;/del&gt;, we get 2^31 buckets. This will cause quite some collisions as we&#039;re storing &quot;randomly&quot; about the same amount of values in the buckets and about 50% of the stored values will be overwritten by a newer value. Then we&#039;ll need a third phase to run again the backward phase and check the matches of phase 2. Because of the collisions in storage, the process may fail and will have to be restarted with different initial conditions.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;E.g. when using &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;8GB&lt;/ins&gt;, we get 2^31 buckets. This will cause quite some collisions as we&#039;re storing &quot;randomly&quot; about the same amount of values in the buckets and about 50% of the stored values will be overwritten by a newer value. Then we&#039;ll need a third phase to run again the backward phase and check the matches of phase 2. Because of the collisions in storage, the process may fail and will have to be restarted with different initial conditions.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;The source code is available here: https://gist.github.com/doegox/d222ab2aab3d7baa0613e12400d42d2d&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;The source code is available here: https://gist.github.com/doegox/d222ab2aab3d7baa0613e12400d42d2d&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;At the end, only one candidate is left: &amp;lt;code&amp;gt;candidate: 8spld0srmk4jf&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;At the end, only one candidate is left: &amp;lt;code&amp;gt;candidate: 8spld0srmk4jf&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>PhilippeTeuwen</name></author>
	</entry>
	<entry>
		<id>https://wiki.yobi.be/index.php?title=Hack.lu_2017_Writeups&amp;diff=10372&amp;oldid=prev</id>
		<title>PhilippeTeuwen at 20:12, 20 October 2017</title>
		<link rel="alternate" type="text/html" href="https://wiki.yobi.be/index.php?title=Hack.lu_2017_Writeups&amp;diff=10372&amp;oldid=prev"/>
		<updated>2017-10-20T20:12:58Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 20:12, 20 October 2017&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 101:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 101:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;This allows to mount a [https://en.wikipedia.org/wiki/Meet-in-the-middle_attack meet-in-the-middle attack]:&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;This allows to mount a [https://en.wikipedia.org/wiki/Meet-in-the-middle_attack meet-in-the-middle attack]:&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;Assume the secret is &quot;XXXXXXXXXXXXX&quot;, hash the message &quot;012345678901234567890123456789012345678901234567890123456XXXXXXXXXXXXX&quot;. It will be split in two blocks and the secret will be split across the two blocks: 7 chars at the end of the first block and 6 chars at the beginning of the second block. Compute backwards the states against all possible second blocks (given the message hash returned by the oracle, which is &quot;be75f49ca582d673346bf85209aba13c&quot; for message &quot;012345678901234567890123456789012345678901234567890123456&quot;) and store these chaining values, then compute all possible first blocks and check for a match.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;Assume the secret is &quot;XXXXXXXXXXXXX&quot;, hash the message &quot;012345678901234567890123456789012345678901234567890123456XXXXXXXXXXXXX&quot;. It will be split in two blocks and the secret will be split across the two blocks: 7 chars at the end of the first block and 6 chars at the beginning of the second block. Compute backwards the states against all possible second blocks (given the message hash returned by the oracle, which is &quot;be75f49ca582d673346bf85209aba13c&quot; for message &quot;012345678901234567890123456789012345678901234567890123456&quot;) and store these chaining values, then compute all possible first blocks and check for a match.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;This requires quite some RAM, so in practice one can store only partial results (e.g. &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;a&lt;/del&gt; &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;quarter&lt;/del&gt; of the chaining value, 32b) in a table smaller than the possible 36^6 values.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;This requires quite some RAM, so in practice one can store only partial results (e.g. &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;about&lt;/ins&gt; &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;half&lt;/ins&gt; of the chaining value, &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;~&lt;/ins&gt;32b&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; as address and 32b as data&lt;/ins&gt;) in a table smaller than the possible 36^6 values.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;E.g. when using 8Gb, we get 2^31 buckets. This will cause quite some collisions as we&#039;re storing &quot;randomly&quot; about the same amount of values in the buckets and about 50% of the stored values will be overwritten by a newer value. &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Because the chaining values are truncated,&lt;/del&gt; we&#039;ll need a third phase to check the &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;possible&lt;/del&gt; &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;collisions&lt;/del&gt;. Because of the collisions &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;when storing&lt;/del&gt; &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;them&lt;/del&gt;, the process may fail and will have to be restarted with different initial conditions.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;E.g. when using 8Gb, we get 2^31 buckets. This will cause quite some collisions as we&#039;re storing &quot;randomly&quot; about the same amount of values in the buckets and about 50% of the stored values will be overwritten by a newer value. &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Then&lt;/ins&gt; we&#039;ll need a third phase to&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; run again the backward phase and&lt;/ins&gt; check the &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;matches&lt;/ins&gt; &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;of phase 2&lt;/ins&gt;. Because of the collisions &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;in&lt;/ins&gt; &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;storage&lt;/ins&gt;, the process may fail and will have to be restarted with different initial conditions.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;The source code is available here: https://gist.github.com/doegox/d222ab2aab3d7baa0613e12400d42d2d&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;The source code is available here: https://gist.github.com/doegox/d222ab2aab3d7baa0613e12400d42d2d&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;At the end, only one candidate is left: &amp;lt;code&amp;gt;candidate: 8spld0srmk4jf&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;At the end, only one candidate is left: &amp;lt;code&amp;gt;candidate: 8spld0srmk4jf&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>PhilippeTeuwen</name></author>
	</entry>
	<entry>
		<id>https://wiki.yobi.be/index.php?title=Hack.lu_2017_Writeups&amp;diff=10371&amp;oldid=prev</id>
		<title>PhilippeTeuwen at 19:57, 20 October 2017</title>
		<link rel="alternate" type="text/html" href="https://wiki.yobi.be/index.php?title=Hack.lu_2017_Writeups&amp;diff=10371&amp;oldid=prev"/>
		<updated>2017-10-20T19:57:19Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 19:57, 20 October 2017&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 96:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 96:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/source&amp;gt;&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/source&amp;gt;&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Ha, this is why they removed the indentation, to make it a bit harder to find the bug :)&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Ha, this is why they removed the indentation, to make it a bit harder to find the bug :)&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;The consequence is that &amp;lt;code&amp;gt;$sum_[abcd]&amp;lt;/code&amp;gt; are not applied and updated properly after each intermediate block and only at the very end the MD5 state is added with the initial &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;constants&lt;/del&gt;.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;The consequence is that &amp;lt;code&amp;gt;$sum_[abcd]&amp;lt;/code&amp;gt; are not applied and updated properly after each intermediate block and only at the very end the MD5 state is added with the initial &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;chaining value&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;So when getting a 2-block message hash, we can subtract the &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;constants&lt;/del&gt; from the hash to get the intermediate values a, b, c, d after the MD5 rounds and the mix with the second message block.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;So when getting a 2-block message hash, we can subtract the &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;initial chaining value&lt;/ins&gt; from the hash to get the intermediate values a, b, c, d after the MD5 rounds and the mix with the second message block.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;These rounds are revertible so if we make a guess about the content of the second block, one can compute a, b, c, d values before the processing of the second block &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;=&lt;/del&gt; after the processing of the first block.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;These rounds are revertible so if we make a guess about the content of the second block, one can compute a, b, c, d values before the processing of the second block &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;which is therefore the chaining value&lt;/ins&gt; after the processing of the first block.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;This allows to mount a [https://en.wikipedia.org/wiki/Meet-in-the-middle_attack meet-in-the-middle attack]:&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;This allows to mount a [https://en.wikipedia.org/wiki/Meet-in-the-middle_attack meet-in-the-middle attack]:&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;Assume the secret is &quot;XXXXXXXXXXXXX&quot;, hash the message &quot;012345678901234567890123456789012345678901234567890123456XXXXXXXXXXXXX&quot;. It will be split in two blocks and the secret will be split across the two blocks: 7 chars at the end of the first block and 6 chars at the beginning of the second block. Compute backwards the states against all possible second blocks (given the message hash returned by the oracle, which is &quot;be75f49ca582d673346bf85209aba13c&quot; for message &quot;012345678901234567890123456789012345678901234567890123456&quot;) and store these &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;states&lt;/del&gt;, then compute all possible first blocks and check for a match.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;Assume the secret is &quot;XXXXXXXXXXXXX&quot;, hash the message &quot;012345678901234567890123456789012345678901234567890123456XXXXXXXXXXXXX&quot;. It will be split in two blocks and the secret will be split across the two blocks: 7 chars at the end of the first block and 6 chars at the beginning of the second block. Compute backwards the states against all possible second blocks (given the message hash returned by the oracle, which is &quot;be75f49ca582d673346bf85209aba13c&quot; for message &quot;012345678901234567890123456789012345678901234567890123456&quot;) and store these &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;chaining values&lt;/ins&gt;, then compute all possible first blocks and check for a match.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;This requires quite some RAM, so in practice one can store partial results &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;at&lt;/del&gt; &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;the&lt;/del&gt; &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;cost&lt;/del&gt; of &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;false&lt;/del&gt; &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;positives&lt;/del&gt; &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;to&lt;/del&gt; &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;test and discard&lt;/del&gt; in a &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;third&lt;/del&gt; &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;phase&lt;/del&gt;.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;This requires quite some RAM, so in practice one can store&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; only&lt;/ins&gt; partial results &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;(e.g.&lt;/ins&gt; &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;a&lt;/ins&gt; &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;quarter&lt;/ins&gt; of &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;the&lt;/ins&gt; &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;chaining&lt;/ins&gt; &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;value,&lt;/ins&gt; &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;32b)&lt;/ins&gt; in a &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;table smaller than the possible 36^6&lt;/ins&gt; &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;values&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;E.g. when using 8Gb, we get 2^31 buckets. This will cause quite some collisions as we&#039;re storing &quot;randomly&quot; about the same amount of values in the buckets and about 50% of the stored values will be overwritten by a newer value. Because the chaining values are truncated, we&#039;ll need a third phase to check the possible collisions. Because of the collisions when storing them, the process may fail and will have to be restarted with different initial conditions.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;The source code is available here. TODO&lt;/div&gt;&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-added&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;The source code is available here: https://gist.github.com/doegox/d222ab2aab3d7baa0613e12400d42d2d&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;At the end, only one candidate is left: &amp;lt;code&amp;gt;candidate: 8spld0srmk4jf&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;At the end, only one candidate is left: &amp;lt;code&amp;gt;candidate: 8spld0srmk4jf&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;Now let&#039;s compute &amp;lt;code&amp;gt;MD5_custom(&quot;the earth is not flat!8spld0srmk4jf&quot;) = 82136dab78e42b520168c6acc0408bf9&amp;lt;/code&amp;gt; and forge the message &quot;the earth is not flat!82136dab78e42b520168c6acc0408bf9&quot;.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;Now let&#039;s compute &amp;lt;code&amp;gt;MD5_custom(&quot;the earth is not flat!8spld0srmk4jf&quot;) = 82136dab78e42b520168c6acc0408bf9&amp;lt;/code&amp;gt; and forge the message &quot;the earth is not flat!82136dab78e42b520168c6acc0408bf9&quot;.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>PhilippeTeuwen</name></author>
	</entry>
	<entry>
		<id>https://wiki.yobi.be/index.php?title=Hack.lu_2017_Writeups&amp;diff=10368&amp;oldid=prev</id>
		<title>PhilippeTeuwen: Created page with &quot;==2017== ===2017 Not My Digest=== cf https://flatearth.fluxfingers.net/challenges/15 and https://notmydigest.flatearth.fluxfingers.net/  A webpage allows to sign and verify me...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.yobi.be/index.php?title=Hack.lu_2017_Writeups&amp;diff=10368&amp;oldid=prev"/>
		<updated>2017-10-20T18:59:33Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==2017== ===2017 Not My Digest=== cf https://flatearth.fluxfingers.net/challenges/15 and https://notmydigest.flatearth.fluxfingers.net/  A webpage allows to sign and verify me...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==2017==&lt;br /&gt;
===2017 Not My Digest===&lt;br /&gt;
cf https://flatearth.fluxfingers.net/challenges/15 and https://notmydigest.flatearth.fluxfingers.net/&lt;br /&gt;
&lt;br /&gt;
A webpage allows to sign and verify messages.&lt;br /&gt;
&amp;lt;br&amp;gt;[https://notmydigest.flatearth.fluxfingers.net/?s2 index.php] and [https://notmydigest.flatearth.fluxfingers.net/?s1 md5.php] are made available.&lt;br /&gt;
&lt;br /&gt;
Signature:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
// $secret = 13 chars a-z0-9&lt;br /&gt;
function sign($str, $secret) {&lt;br /&gt;
    if(preg_match(&amp;quot;/[a-zA-Z]/&amp;quot;, $str)) { die( &amp;quot;Alpha characters are evil, thus you are not allowed to sign them!&amp;quot; ); }&lt;br /&gt;
    return htmlspecialchars($str.MD5_custom($str.$secret));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
So a signed message is &amp;lt;code&amp;gt;my_message|MD5_custom(my_message|secret)&amp;lt;/code&amp;gt; but &amp;lt;code&amp;gt;my_message&amp;lt;/code&amp;gt; can&amp;#039;t contain alphabetic chars (accentuated chars still work).&lt;br /&gt;
&lt;br /&gt;
Verification:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
function verify($str, $secret)&lt;br /&gt;
{&lt;br /&gt;
    if(strlen($str) &amp;lt; 32) { return false; }&lt;br /&gt;
    $md5 = substr($str, -32);&lt;br /&gt;
    $content = substr($str, 0, -32);&lt;br /&gt;
    if($md5 === MD5_custom($content.$secret)) { return true; }&lt;br /&gt;
}&lt;br /&gt;
[...]&lt;br /&gt;
//main&lt;br /&gt;
    if($valid) {&lt;br /&gt;
        $result = &amp;quot;success!&amp;quot;;&lt;br /&gt;
        $str = substr($_POST[&amp;quot;postdata&amp;quot;], 0, -32);&lt;br /&gt;
        if($str === &amp;quot;the earth is not flat!&amp;quot;) {&lt;br /&gt;
            $result = &amp;quot;LIAR! GO AWAY, REPTILIAN AND DON&amp;#039;T COME BACK: &amp;quot; . $flag;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        $result = &amp;quot;fail!&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
So it expects a signed message with at least a hash appended, and it&amp;#039;s computing again the custom MD5 and comparing it.&lt;br /&gt;
&amp;lt;br&amp;gt;It&amp;#039;s funny to note that when the hash is incorrect, the function returns nothing...&lt;br /&gt;
&amp;lt;br&amp;gt;if the signature is correct and if the message is exactly &amp;lt;code&amp;gt;the earth is not flat!&amp;lt;/code&amp;gt;, then the flag will be displayed. Note the usage of &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; so we can&amp;#039;t abuse it.&lt;br /&gt;
&lt;br /&gt;
So the goal is to craft a signature on a given message which contains obviously chars that will be rejected by the &amp;lt;code&amp;gt;sign&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
Let&amp;#039;s look a bit closer to the custom MD5.&lt;br /&gt;
&amp;lt;br&amp;gt;The obvious customization is highlighted at the beginning:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
define(&amp;quot;MD5_R_A&amp;quot;, 0x67452301);&lt;br /&gt;
define(&amp;quot;MD5_R_B&amp;quot;, 0xefcdab89);&lt;br /&gt;
define(&amp;quot;MD5_R_C&amp;quot;, 0x98badcfe);&lt;br /&gt;
define(&amp;quot;MD5_R_D&amp;quot;, 0x10325476);&lt;br /&gt;
*/&lt;br /&gt;
// switch constants 4 security!&lt;br /&gt;
define(&amp;quot;MD5_R_A&amp;quot;, 0x10325476);&lt;br /&gt;
define(&amp;quot;MD5_R_B&amp;quot;, 0x98badcfe);&lt;br /&gt;
define(&amp;quot;MD5_R_C&amp;quot;, 0xefcdab89);&lt;br /&gt;
define(&amp;quot;MD5_R_D&amp;quot;, 0x67452301);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Modified constants could leak to backdoors, remember https://malicioussha1.github.io/ ? But in this case a simple swap A, B, C, D = D, C, B, A is not likely to affect MD5 security.&lt;br /&gt;
&amp;lt;br&amp;gt;We can ask oracle to sign an empty message, it returns &amp;lt;code&amp;gt;a4c9bcbb5a72ff69fc02f35d2c13f338&amp;lt;/code&amp;gt;, so we have &amp;lt;code&amp;gt;MD5_custom(secret) = a4c9bcbb5a72ff69fc02f35d2c13f338&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;At first, we modified hashcat to tackle this modified MD5, simply by swapping &amp;lt;code&amp;gt;typedef enum md5_constants&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;OpenCL/inc_hash_constants.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;With that, we could break short secrets we hashed ourselves with the php code (just add &amp;lt;code&amp;gt;echo (MD5_custom($argv[1]));&amp;lt;/code&amp;gt; at the end of &amp;lt;code&amp;gt;md5.php&amp;lt;/code&amp;gt; and use PHP CLI), but if &amp;lt;code&amp;gt;[a-z0-9]{9}&amp;lt;/code&amp;gt; is doable, &amp;lt;code&amp;gt;[a-z0-9]{13}&amp;lt;/code&amp;gt; is out of reach.&lt;br /&gt;
&lt;br /&gt;
When comparing with another implementation (and because the [https://github.com/FiloSottile/crypto.py/blob/master/2/md5.py implementation of Filippo] is much easier to read), we noticed a first difference:&lt;br /&gt;
&amp;lt;br&amp;gt;Normally the 8 last characters of the padding are the length of the message in &amp;#039;&amp;#039;bits&amp;#039;&amp;#039;: &amp;lt;code&amp;gt;struct.pack(&amp;#039;&amp;lt;Q&amp;#039;, len(message) * 8)&amp;lt;/code&amp;gt;, but in PHP it does &amp;lt;code&amp;gt;pack(&amp;quot;ll&amp;quot;, $len*8, 0);&amp;lt;/code&amp;gt;, so the last 4 bytes are forced to zero. This means a message of (512Mb*&amp;quot;A&amp;quot; + &amp;quot;B&amp;quot;), when padded, would get the same last padded block as the message &amp;quot;B&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;It&amp;#039;s unclear anything could be abused in this specific CTF scenario, but when trying to validate this finding, we quickly found that there was yet another divergence between MD5_custom and our custom version of FiloSottile MD5: As soon as there is more than one MD5 block, i.e. as soon as the message is &amp;gt;= 43 chars, the hashes differ.&lt;br /&gt;
&amp;lt;br&amp;gt;One can notice MD5.php is not indented. Running &amp;lt;code&amp;gt;astyle&amp;lt;/code&amp;gt; can fix that.&lt;br /&gt;
&amp;lt;br&amp;gt;When comparing both implementations and the intermediate states, it appeared that the end of MD5_custom&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
        $a &amp;amp;= 0xffffffff;&lt;br /&gt;
        $b &amp;amp;= 0xffffffff;&lt;br /&gt;
        $c &amp;amp;= 0xffffffff;&lt;br /&gt;
        $d &amp;amp;= 0xffffffff;&lt;br /&gt;
    }&lt;br /&gt;
    $a = $sum_a = ($sum_a + $a) &amp;amp; 0xffffffff;&lt;br /&gt;
    $b = $sum_b = ($sum_b + $b) &amp;amp; 0xffffffff;&lt;br /&gt;
    $c = $sum_c = ($sum_c + $c) &amp;amp; 0xffffffff;&lt;br /&gt;
    $d = $sum_d = ($sum_d + $d) &amp;amp; 0xffffffff;&lt;br /&gt;
    return bin2hex(pack(&amp;quot;l&amp;quot;, $sum_a).pack(&amp;quot;l&amp;quot;, $sum_b).pack(&amp;quot;l&amp;quot;, $sum_c).pack(&amp;quot;l&amp;quot;, $sum_d));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
should have been&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
        $a &amp;amp;= 0xffffffff; // even not required actually&lt;br /&gt;
        $b &amp;amp;= 0xffffffff;&lt;br /&gt;
        $c &amp;amp;= 0xffffffff;&lt;br /&gt;
        $d &amp;amp;= 0xffffffff;&lt;br /&gt;
        $a = $sum_a = ($sum_a + $a) &amp;amp; 0xffffffff;&lt;br /&gt;
        $b = $sum_b = ($sum_b + $b) &amp;amp; 0xffffffff;&lt;br /&gt;
        $c = $sum_c = ($sum_c + $c) &amp;amp; 0xffffffff;&lt;br /&gt;
        $d = $sum_d = ($sum_d + $d) &amp;amp; 0xffffffff;&lt;br /&gt;
    }&lt;br /&gt;
    return bin2hex(pack(&amp;quot;l&amp;quot;, $sum_a).pack(&amp;quot;l&amp;quot;, $sum_b).pack(&amp;quot;l&amp;quot;, $sum_c).pack(&amp;quot;l&amp;quot;, $sum_d));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ha, this is why they removed the indentation, to make it a bit harder to find the bug :)&lt;br /&gt;
&amp;lt;br&amp;gt;The consequence is that &amp;lt;code&amp;gt;$sum_[abcd]&amp;lt;/code&amp;gt; are not applied and updated properly after each intermediate block and only at the very end the MD5 state is added with the initial constants.&lt;br /&gt;
&amp;lt;br&amp;gt;So when getting a 2-block message hash, we can subtract the constants from the hash to get the intermediate values a, b, c, d after the MD5 rounds and the mix with the second message block.&lt;br /&gt;
&amp;lt;br&amp;gt;These rounds are revertible so if we make a guess about the content of the second block, one can compute a, b, c, d values before the processing of the second block = after the processing of the first block.&lt;br /&gt;
&amp;lt;br&amp;gt;This allows to mount a [https://en.wikipedia.org/wiki/Meet-in-the-middle_attack meet-in-the-middle attack]:&lt;br /&gt;
&amp;lt;br&amp;gt;Assume the secret is &amp;quot;XXXXXXXXXXXXX&amp;quot;, hash the message &amp;quot;012345678901234567890123456789012345678901234567890123456XXXXXXXXXXXXX&amp;quot;. It will be split in two blocks and the secret will be split across the two blocks: 7 chars at the end of the first block and 6 chars at the beginning of the second block. Compute backwards the states against all possible second blocks (given the message hash returned by the oracle, which is &amp;quot;be75f49ca582d673346bf85209aba13c&amp;quot; for message &amp;quot;012345678901234567890123456789012345678901234567890123456&amp;quot;) and store these states, then compute all possible first blocks and check for a match.&lt;br /&gt;
&amp;lt;br&amp;gt;This requires quite some RAM, so in practice one can store partial results at the cost of false positives to test and discard in a third phase.&lt;br /&gt;
&amp;lt;br&amp;gt;The source code is available here. TODO&lt;br /&gt;
&amp;lt;br&amp;gt;At the end, only one candidate is left: &amp;lt;code&amp;gt;candidate: 8spld0srmk4jf&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;Now let&amp;#039;s compute &amp;lt;code&amp;gt;MD5_custom(&amp;quot;the earth is not flat!8spld0srmk4jf&amp;quot;) = 82136dab78e42b520168c6acc0408bf9&amp;lt;/code&amp;gt; and forge the message &amp;quot;the earth is not flat!82136dab78e42b520168c6acc0408bf9&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;Verify it. We&amp;#039;re greeted with&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;LIAR! GO AWAY, REPTILIAN AND DON&amp;#039;T COME BACK: FLAG{One_bad_curly_breaks_your_crypto}&amp;lt;/code&amp;gt;.&lt;/div&gt;</summary>
		<author><name>PhilippeTeuwen</name></author>
	</entry>
</feed>