8 changed files with 545 additions and 9 deletions
After Width: | Height: | Size: 5.8 KiB |
@ -0,0 +1 @@
|
||||
adsaf21519189aq1g56161asdff19as1f9:PF:CA[][_159191wef |
@ -0,0 +1,526 @@
|
||||
{% extends "sega.html" %} |
||||
{% block title %}{% endblock %} |
||||
{% block body %} |
||||
<h1>System Security</h1> |
||||
<p>The Ring* series have a number of security measures in place, some easy to bypass, others requiring more work. They |
||||
are listed here in, roughly, the order in which each layer is applied.</p> |
||||
|
||||
<h2 id="ata">Drive ATA Password</h2> |
||||
<p>The SSD contained within the system has an ATA password set. The system BIOS contains a password derivation function |
||||
that derives the specific password for that drive based on its serial number.</p> |
||||
<p>This can be bypassed either by extracting the password used, or by first powering on the Ring* system with the drive |
||||
connected, then hotplugging the SATA data cable on the drive while keeping the drive powered.</p> |
||||
|
||||
<details> |
||||
<summary>Why does this work?</summary> |
||||
<p>The following is the sequence of possible security modes for an ATA drive:</p> |
||||
<svg viewbox="-0.5 -0.5 800 400" style="width: 800px"> |
||||
<defs> |
||||
<marker id="arrowhead-good" markerWidth="10" markerHeight="8" refX="0" refY="4" orient="auto"> |
||||
<polygon points="0 0, 10 4, 0 8" fill="currentColor" class="ata-good" /> |
||||
</marker> |
||||
</defs> |
||||
<defs> |
||||
<marker id="arrowhead-ignore" markerWidth="10" markerHeight="8" refX="0" refY="4" orient="auto"> |
||||
<polygon points="0 0, 10 4, 0 8" fill="currentColor" class="ata-ignore" /> |
||||
</marker> |
||||
</defs> |
||||
<defs> |
||||
<marker id="arrowhead-bad" markerWidth="10" markerHeight="8" refX="0" refY="4" orient="auto"> |
||||
<polygon points="0 0, 10 4, 0 8" fill="currentColor" class="ata-bad" /> |
||||
</marker> |
||||
</defs> |
||||
|
||||
<g class="ata-ignore"> |
||||
<rect fill="transparent" x="0" y="0" width="150" height="20" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="10" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
SEC0 |
||||
</text> |
||||
<rect fill="transparent" x="0" y="20" width="150" height="60" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="43" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Power: off |
||||
</text> |
||||
<text x="75" y="57" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Security: No |
||||
</text> |
||||
</g> |
||||
|
||||
<g class="ata-ignore"> |
||||
<text x="200" y="30" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Power on |
||||
</text> |
||||
<line x1="150" y1="40" x2="240" y2="40" stroke="currentColor" marker-end="url(#arrowhead-ignore)"></line> |
||||
|
||||
<text x="450" y="20" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Freeze |
||||
</text> |
||||
<line x1="400" y1="30" x2="490" y2="30" stroke="currentColor" marker-end="url(#arrowhead-ignore)"></line> |
||||
<line x1="500" y1="50" x2="410" y2="50" stroke="currentColor" marker-end="url(#arrowhead-ignore)"></line> |
||||
<text x="450" y="60" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
HW Reset |
||||
</text> |
||||
|
||||
<line x1="325" y1="80" x2="325" y2="150" stroke="currentColor"></line> |
||||
</g> |
||||
|
||||
<g transform="translate(250 0)" class="ata-ignore"> |
||||
<rect fill="transparent" x="0" y="0" width="150" height="20" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="10" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
SEC1 |
||||
</text> |
||||
<rect fill="transparent" x="0" y="20" width="150" height="60" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="43" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Security: No |
||||
</text> |
||||
<text x="75" y="57" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Frozen: No |
||||
</text> |
||||
</g> |
||||
|
||||
<g transform="translate(500 0)" class="ata-ignore"> |
||||
<rect fill="transparent" x="0" y="0" width="150" height="20" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="10" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
SEC2 |
||||
</text> |
||||
<rect fill="transparent" x="0" y="20" width="150" height="60" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="43" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Security: No |
||||
</text> |
||||
<text x="75" y="57" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Frozen: Yes |
||||
</text> |
||||
</g> |
||||
|
||||
<g transform="translate(250 150)" class="ata-good"> |
||||
<rect fill="transparent" x="0" y="0" width="150" height="20" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="10" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
SEC5 |
||||
</text> |
||||
<rect fill="transparent" x="0" y="20" width="150" height="60" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="36" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Security: Yes |
||||
</text> |
||||
<text x="75" y="50" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Unlocked: Yes |
||||
</text> |
||||
<text x="75" y="64" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Frozen: No |
||||
</text> |
||||
</g> |
||||
|
||||
<g transform="translate(250 300)" class="ata-bad"> |
||||
<rect fill="transparent" x="0" y="0" width="150" height="20" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="10" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
SEC4 |
||||
</text> |
||||
<rect fill="transparent" x="0" y="20" width="150" height="60" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="36" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Security: Yes |
||||
</text> |
||||
<text x="75" y="50" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Unlocked: No |
||||
</text> |
||||
<text x="75" y="64" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Frozen: No |
||||
</text> |
||||
</g> |
||||
|
||||
<g transform="translate(500 225)" class="ata-good"> |
||||
<rect fill="transparent" x="0" y="0" width="150" height="20" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="10" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
SEC6 |
||||
</text> |
||||
<rect fill="transparent" x="0" y="20" width="150" height="60" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="36" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Security: Yes |
||||
</text> |
||||
<text x="75" y="50" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Unlocked: Yes |
||||
</text> |
||||
<text x="75" y="64" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Frozen: Yes |
||||
</text> |
||||
</g> |
||||
|
||||
<g class="ata-bad"> |
||||
<text x="200" y="330" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Power on |
||||
</text> |
||||
<line x1="150" y1="340" x2="240" y2="340" stroke="currentColor" marker-end="url(#arrowhead-bad)"></line> |
||||
|
||||
<text x="470" y="340" fill="currentColor" dominant-baseline="middle" text-anchor="start" |
||||
font-family="monospace"> |
||||
HW reset |
||||
</text> |
||||
<line x1="575" y1="305" x2="410" y2="340" stroke="currentColor" marker-end="url(#arrowhead-bad)"></line> |
||||
</g> |
||||
|
||||
<g class="ata-good"> |
||||
<text x="318" y="265" fill="currentColor" dominant-baseline="middle" text-anchor="end" |
||||
font-family="monospace"> |
||||
Unlock |
||||
</text> |
||||
<line x1="325" y1="300" x2="325" y2="240" stroke="currentColor" marker-end="url(#arrowhead-good)"></line> |
||||
|
||||
<line x1="400" y1="195" x2="490" y2="265" stroke="currentColor" marker-end="url(#arrowhead-good)"></line> |
||||
<text x="435" y="210" fill="currentColor" dominant-baseline="middle" text-anchor="start" |
||||
font-family="monospace"> |
||||
Freeze |
||||
</text> |
||||
</g> |
||||
|
||||
<g transform="translate(0 300)" class="ata-bad"> |
||||
<rect fill="transparent" x="0" y="0" width="150" height="20" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="10" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
SEC3 |
||||
</text> |
||||
<rect fill="transparent" x="0" y="20" width="150" height="60" stroke-width="1px" stroke="currentColor"> |
||||
</rect> |
||||
<text x="75" y="43" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Power: off |
||||
</text> |
||||
<text x="75" y="57" fill="currentColor" dominant-baseline="middle" text-anchor="middle" |
||||
font-family="monospace"> |
||||
Security: Yes |
||||
</text> |
||||
</g> |
||||
</svg> |
||||
<p>When the drive has a password set, it initially starts in SEC3. The RingEdge then transitions the drive to SEC5 |
||||
then SEC6. Importantly, however, as long as power is never lost, the drive will remain in SEC6 mode, even if we |
||||
connect it to a different system.</p> |
||||
<p>This allows us full read-write access to the drive without ever knowing the password!</p> |
||||
</details> |
||||
|
||||
<h2 id="windows">Windows Password</h2> |
||||
<p>It seems silly to mention, but it's worth noting. <code>AppUser</code> will automatically log in, but if you need to |
||||
log back in, or wish to login as <code>SystemUser</code>, you'll need the passwords.</p> |
||||
<p><code>AppUser</code>'s password is <code>segahard</code>.</p> |
||||
<p><code>SystemUser</code>'s password is <code><6/=U=#tpe!$*3!5</code>. <b>NOTE:</b> if a debugger is attached to |
||||
<code>mxprestartup</code>, <code>Miflac=Ifme9Jfp0</code> will be attempted as the password for |
||||
<code>SystemUser</code> instead. This is not the correct password for a production unit. |
||||
</p> |
||||
|
||||
<details> |
||||
<summary>Finding SystemUser's password</summary> |
||||
|
||||
<p>When AppUser logs in, mxprestartup is executed. This binary constructs SystemUser's password then elevates |
||||
permissions. When no debugger is present, the following steps are performed:</p> |
||||
|
||||
<ul> |
||||
<li>Add <code>153815264b5839090b0d1c1a423c02241633130673071a1e38443912410b47380f213c1d</code> and |
||||
<code>2e0247311e162b666c6640393737724157001f56045b4b4f24333457335a26381f4c3349</code> together (these are |
||||
strings contained within the binary). |
||||
</li> |
||||
<ul> |
||||
<li>Result: <code>C:\Windows\System32\wbem\wmitemp.mof</code></li> |
||||
</ul> |
||||
<li>Read <code>C:\Windows\System32\wbem\wmitemp.mof</code>. |
||||
</li> |
||||
<ul> |
||||
<li>Result: <code>270a2a053b29042b261d1b22070d140c</code></li> |
||||
</ul> |
||||
<li>Add <code>152c05381a141f494a48060223260d29</code> to this value. |
||||
</li> |
||||
<ul> |
||||
<li>Result: <code><6/=U=#tpe!$*3!5</code></li> |
||||
</ul> |
||||
</ul> |
||||
|
||||
<p>If a debugger is present, a similar process is performed:</p> |
||||
|
||||
<ul> |
||||
<li>Add <code>d0b1c034a32243340505a343659517c121f0319583d205c593a690719604846000e062a6</code> and |
||||
<code>63f10541f0c201c0703022f332a13094b542f130c25491a1c280a65440831296e2563590</code> together, with each |
||||
byte |
||||
modulo 255 (not 256!). |
||||
</li> |
||||
<ul> |
||||
<li>Result: <code>34a3c57594e444f47535c53797374756d63323c546279667562737c5d68796f6e2379737</code></li> |
||||
</ul> |
||||
<li>Flip the nibbles of each byte.</li> |
||||
<ul> |
||||
<li>Result: <code>C:\WINDOWS\system32\drivers\mxio.sys</code></li> |
||||
</ul> |
||||
<li>Read <code>C:\WINDOWS\system32\drivers\mxio.sys</code>.</li> |
||||
<ul> |
||||
<li>Result: <code>9160e5c22392918371e43573f2b095b1</code></li> |
||||
</ul> |
||||
<li>Add <code>43368004f2a34211f4f12120b1b57151</code> to this value, with each byte modulo 255. |
||||
</li> |
||||
<ul> |
||||
<li>Result: <code>d49666c61636d39466d65693a4660703</code></li> |
||||
</ul> |
||||
<li>Flip the nibbles of each byte.</li> |
||||
<ul> |
||||
<li>Result: <code>Miflac=Ifme9Jfp0</code></li> |
||||
</ul> |
||||
</ul> |
||||
|
||||
<p>Why is the process for a debugged process more elaborate? I'm not sure.</p> |
||||
</details> |
||||
|
||||
<h2 id="sdrive">System binaries encryption</h2> |
||||
<p>The system binaries, normally located on <code>S:</code>, are a TrueCrypt partition. The partition file can be found |
||||
at <code>C:\System\Execute\System</code>. It has password <code>segahardpassword</code>, and used the <a |
||||
href="https://www.sans.org/blog/alternate-data-streams-overview/" rel="noopener noreferrer">alternate data |
||||
stream</a> loated at |
||||
<code>C:\System\Execute\DLL:SystemKeyFile</code> as a keyfile. |
||||
</p> |
||||
<p><code>C:\System\Execute\DLL:UpdateKeyFile</code> is also present here, which is used for encryption of update |
||||
data (but is not utilised in the process of mounting <code>S:</code>).</p> |
||||
|
||||
<details> |
||||
<summary>What's an Alternate Data Stream?</summary> |
||||
<p>An alternate data stream, or ADS for short, is a feature of the NTFS filesystem where additional data can be |
||||
stored alongside a file or directory. On modern Windows systems, they can be shown using <code>dir /R</code>. If |
||||
you are performing analysis on the system using digital forensics software, which you probably should be, all |
||||
major packages will show these streams clearly.</p> |
||||
|
||||
<figure> |
||||
<img class="graphic" src="{{ROOT}}/images/ftk.png"> |
||||
<figcaption>The alternate data streams, in FTK Imager</figcaption> |
||||
</figure> |
||||
|
||||
<p>The <a href="https://www.sans.org/blog/alternate-data-streams-overview/" rel="noopener noreferrer">SANS Institude |
||||
website</a> is a great resource for more information and links.</p> |
||||
</details> |
||||
<details> |
||||
<summary>Finding this information</summary> |
||||
|
||||
<p>The decryption of the system partition is the responsibility of <code>mxstartup</code>. This file contains pairs |
||||
of hex strings which sum to produce the paths to the alternate data streams, and the volume password.</p> |
||||
</details> |
||||
|
||||
<h3 id="keyfiles">Keyfile downloads</h3> |
||||
<ul> |
||||
<li><a href="{{ROOT}}/static/keys/SystemKeyFile">SystemKeyFile</a></li> |
||||
<li><a href="{{ROOT}}/static/keys/UpdateKeyFile">UpdateKeyFile</a></li> |
||||
</ul> |
||||
|
||||
<h2 id="keychip">Keychip</h2> |
||||
<p>This is the first point during the boot process where a physical keychip is required in order to continue the system |
||||
boot process.</p> |
||||
<p>With the exception of <a href="{{ROOT}}/sega/software/mx/mxkeychip.html"><code>mxkeychip</code></a>, processes do not |
||||
directly communicate with the keychip. Instead, they communicate with <a |
||||
href="{{ROOT}}/sega/software/mx/mxkeychip.html"><code>mxkeychip</code> via a PCP</a>. <a |
||||
href="{{ROOT}}/sega/software/mx/mxkeychip.html"><code>mxkeychip</code></a> itself is then responsible for |
||||
communicating with the keychip. These communications are AES encrypted with keys agreed during the initial |
||||
handshake.</p> |
||||
|
||||
<p>The keychip is responsible for a number of functions:</p> |
||||
<ul> |
||||
<li>Each keychip is assigned a region, and this region must match the region stored in the Ring*'s EEPROM.</li> |
||||
<li>It contains configuration tables for the network setup.</li> |
||||
<li>It is able to perform basic encryption and decryption, which is used to derive the game encryption key.</li> |
||||
<li>It includes a large challenge-response table used to authenticate with the specific game.</li> |
||||
<li>It contains Aime billing information regarding how many credits are allowed on this machine before |
||||
re-authenticating with network services.</li> |
||||
<li>It contains a small amount of writable storage used to store trace logs, such as when the system booted or |
||||
authenticated with network services.</li> |
||||
</ul> |
||||
|
||||
<p>This security layer can be bypassed by replacing the <code>mxkeychip.exe</code> binary with a custom binary, |
||||
eliminating the need to emulate the physical parallel device, and its encryption.</p> |
||||
|
||||
<h2 id="game-data">Game data encryption</h2> |
||||
<p>Once the system has verified it is allowed to continue booting, it proceeds to decrypt the game partition. This is |
||||
done by performing a <code>keychip.decrypt</code> request.</p> |
||||
<p>The specific key used varies by game. The easiest way to retrieve this key is to, well, ask the keychip for it. We |
||||
can first start a listener on port <code>40106</code> to retrieve the value that the boot process is passing. |
||||
Following that, we can start the real mxkeychip, and request the same decryption. It will then provide us with the |
||||
key to be used for the game encryption!</p> |
||||
<p>TODO: Some proper digging into the mx binaries to determine exactly where it pulls the encrypted string in the |
||||
request</p> |
||||
<p>The value we have now should be 16 bytes, and is the contents for a keyfile.</p> |
||||
<p>Like the <code>S:</code> drive, game data is a TrueCrypt partition. Check the <a |
||||
href="{{ROOT}}/sega/misc/partition.html">SEGA partition description</a> to determine which partition contains |
||||
the game data. If in doubt, just try they all until one works :).</p> |
||||
|
||||
<h2 id="game-handshake">Game-keychip handshake</h2> |
||||
<p>There is one final security step present, however I believe this to only be present in some games.</p> |
||||
<p>When the game boots, it makes requests to <code>keychip.ssd.proof</code> and <code>keychip.ds.compute</code>. These |
||||
are challenge-response queries, which the keychip will internally look up in a large table of possible values.</p> |
||||
<p>While we could dump the EEPROM chip located on the keychip, there is no need for this. As the game also needs a copy |
||||
of the responses to validate against, we can just grab that file, as we have already decrypted the game partition by |
||||
this point. The file will likely be named <code>[game ID]_Table.dat</code>.</p> |
||||
|
||||
<p>I'll flush this out later, but for now, here's the structure of that file:</p> |
||||
<pre>{% highlight "c" %} |
||||
struct { |
||||
struct { |
||||
char challenge[7]; |
||||
char responses[4][20]; |
||||
} ds[10000]; |
||||
struct { |
||||
char challenge[16]; |
||||
char response[16]; |
||||
} ssd[10000]; |
||||
} |
||||
{% endhighlight %}</pre> |
||||
|
||||
<p>The responses are scrambled as described below:</p> |
||||
<h4>DS Scramble:</h4> |
||||
<table class="code"> |
||||
<thead> |
||||
<tr> |
||||
<td>Output index</td> |
||||
<td>0</td> |
||||
<td>1</td> |
||||
<td>2</td> |
||||
<td>3</td> |
||||
<td>4</td> |
||||
<td>5</td> |
||||
<td>6</td> |
||||
<td>7</td> |
||||
<td>8</td> |
||||
<td>9</td> |
||||
<td>10</td> |
||||
<td>11</td> |
||||
<td>12</td> |
||||
<td>13</td> |
||||
<td>14</td> |
||||
<td>15</td> |
||||
<td>16</td> |
||||
<td>17</td> |
||||
<td>18</td> |
||||
<td>19</td> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr> |
||||
<td>Input index</td> |
||||
<td>15</td> |
||||
<td>5</td> |
||||
<td>13</td> |
||||
<td>14</td> |
||||
<td>10</td> |
||||
<td>1</td> |
||||
<td>2</td> |
||||
<td>11</td> |
||||
<td>16</td> |
||||
<td>7</td> |
||||
<td>4</td> |
||||
<td>18</td> |
||||
<td>12</td> |
||||
<td>6</td> |
||||
<td>3</td> |
||||
<td>0</td> |
||||
<td>17</td> |
||||
<td>8</td> |
||||
<td>19</td> |
||||
<td>9</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
<h4>SSD Scramble:</h4> |
||||
<table class="code"> |
||||
<thead> |
||||
<tr> |
||||
<td>Output index</td> |
||||
<td>0</td> |
||||
<td>1</td> |
||||
<td>2</td> |
||||
<td>3</td> |
||||
<td>4</td> |
||||
<td>5</td> |
||||
<td>6</td> |
||||
<td>7</td> |
||||
<td>8</td> |
||||
<td>9</td> |
||||
<td>10</td> |
||||
<td>11</td> |
||||
<td>12</td> |
||||
<td>13</td> |
||||
<td>14</td> |
||||
<td>15</td> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr> |
||||
<td>Input index</td> |
||||
<td>6</td> |
||||
<td>8</td> |
||||
<td>4</td> |
||||
<td>12</td> |
||||
<td>7</td> |
||||
<td>13</td> |
||||
<td>1</td> |
||||
<td>10</td> |
||||
<td>2</td> |
||||
<td>3</td> |
||||
<td>11</td> |
||||
<td>14</td> |
||||
<td>15</td> |
||||
<td>0</td> |
||||
<td>5</td> |
||||
<td>9</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
|
||||
<p><b>NOTE: The following information may only be true for MaiMai FiNALE! I have not yet verified this on other |
||||
games!</b> |
||||
<br> |
||||
In dev mode, the game will only ever request a single string as the challenge. |
||||
</p> |
||||
<p>This string is <code>2CFECBC71CF1E4</code>, and its corresponding four response pages are (not scrambled):</p> |
||||
<ol> |
||||
<li><code>ca6ed736401682dd4411a27d2440ac4b478bad8b</code></li> |
||||
<li><code>4ac606302ce5ef51abb3df2dc46c863b3c06aa2c</code></li> |
||||
<li><code>2aaf35b2aba4c6840bdb7bd40ecbce2cca934795</code></li> |
||||
<li><code>2f6d713dabde3c43df818491ab9467ba8ba0fed4</code></li> |
||||
</ol> |
||||
<p> |
||||
<b>NOTE: The following information is super un-verified!</b><br> |
||||
Occasionally the game will make a query to the DS table that is not present in the table. In this instance, the |
||||
keychip responds with the entry at index n, where n is a counter that increments every time a |
||||
<code>keychip.ds.compute</code> query is performed, modulo 100. |
||||
</p> |
||||
<p>It should be noted that if the keychip binary imemdiatly terminates the connection, rather than sending a |
||||
known-incorrect response (such as if the challenge matches none in the known tables), the game will re-attempt the |
||||
query, and this query will, with a high likelyhood, be different.</p> |
||||
|
||||
<p>It should additionally be noted that this whole process can be skipped by returning <code>code=54</code> rather than |
||||
a valid response.</p> |
||||
|
||||
{% endblock %} |
Loading…
Reference in new issue