{"id":219,"date":"2007-12-05T10:48:26","date_gmt":"2007-12-05T08:48:26","guid":{"rendered":"http:\/\/daniel.haxx.se\/blog\/2007\/12\/05\/i-solved-the-ams-sansas-firmware-checksum-puzzle\/"},"modified":"2007-12-05T10:51:30","modified_gmt":"2007-12-05T08:51:30","slug":"i-solved-the-ams-sansas-firmware-checksum-puzzle","status":"publish","type":"post","link":"https:\/\/daniel.haxx.se\/blog\/2007\/12\/05\/i-solved-the-ams-sansas-firmware-checksum-puzzle\/","title":{"rendered":"I Solved the AMS-Sansas&#8217; Firmware Checksum Puzzle"},"content":{"rendered":"<p>On my <a href=\"http:\/\/daniel.haxx.se\/sansa\/v2.html\">Sansa v2 web page<\/a>, I&#8217;m collecting firmware binaries for these new targets in order to figure them out and kickstart the Rockbox effort for them. All firmware files have a .bin extension.<\/p>\n<p>It is quite clear (by simple human inspection) that the first 0x400 bytes in each .bin file is a header (padded with 0xff bytes), as on the 0x400 index there is the ARM exception vector and then there&#8217;s ARM code following.<img decoding=\"async\" src=\"http:\/\/daniel.haxx.se\/blog\/wp-content\/uploads\/2007\/11\/sandisk-chip.jpg\" title=\"SanDisk marked chip, an AMS AS3525\" alt=\"SanDisk marked chip, an AMS AS3525\" align=\"right\" border=\"0\" hspace=\"8\" vspace=\"8\" \/><\/p>\n<p>In the header there are numerous values, but the 32 bit value at index 4 immediately looked like it could be a checksum of some sorts.<\/p>\n<p>We found <a href=\"http:\/\/files.zefie.com\/PMP\/sansa\/m200\/firmware\/4.1.08\/\">two very similar firmwares for the M200<\/a> model, one for the European and one for the American in which the &#8220;checksum&#8221; values only differed by 2 even though there were clearly multiple (although not extensive) differences in the files.<\/p>\n<p>A checksum that differs with so little indicates a simple algorithm. With something more fancy, like CRC32 or similar, a very small change in the files would cause a major change in the checksum value. Two checksum values near each other rather hinted on a simple addition, subtraction, xor or similar.<\/p>\n<p>So I did a hexdump of the two files, cut off the headers and ran a &#8216;diff -u&#8217; on them. That showed me that the first lines that differed (on index 0x15990) looked like this in the euro version:<\/p>\n<p><code><strong>00<\/strong> 00 a0 e3 a4 40 9f e5  00 00 c1 e5 04 00 a0 e1<br \/>\n00 fb ff eb 04 00 80 e0  <strong>45<\/strong> 10 a0 e3 01 10 40 e5<\/code><\/p>\n<p>And like this in the US version.<\/p>\n<p><code><strong>02<\/strong> 00 a0 e3 a4 40 9f e5  00 00 c1 e5 04 00 a0 e1<br \/>\n00 fb ff eb 04 00 80 e0  <strong>41<\/strong> 10 a0 e3 01 10 40 e5<\/code><\/p>\n<p>The differences are shown in bold above to make them more obvious. Plus 4, minus 2&#8230; Or the other way, minus 4 plus 2. <em>That was almost too good to be true!<\/em> The fact that these particular differences seemed to be 2 when the values were added just have to mean that the checksum is done with addition (if I was lucky). And if so, this was the only change that mattered to the header so therefore the checksum didn&#8217;t take the whole file into account&#8230;<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/daniel.haxx.se\/blog\/wp-content\/uploads\/2007\/11\/sansaclip170x264.jpg\" title=\"SanDisk Sansa Clip\" alt=\"SanDisk Sansa Clip\" align=\"left\" border=\"0\" hspace=\"8\" vspace=\"8\" \/>I wrote up a small tool that would try out some variations of an &#8220;addition algorithm&#8221; with 32 bit adds and with 8 bit adds and then I tried with XORs instead to the same effect. Then it struck me that the value in the header at index 0x0c was not changing by a lot between firmwares and it had a number which was an index <em>after<\/em> the change I mentioned above, but <em>before the subsequent changes<\/em>&#8230;<\/p>\n<p>The program still didn&#8217;t spit out the right value when I restricted the algorithm to the size mentioned in the header&#8230; until I realized my tool didn&#8217;t skip the header when it did the checksum, and when I added a 0x400 bytes skip <strong>the values matched<\/strong>! It was as simple as that. Here&#8217;s <a href=\"http:\/\/daniel.haxx.se\/sansa\/v2\/checksum.txt\">checksum.c<\/a>.<\/p>\n<p>There are still a few other unidentified fields in the header.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>On my Sansa v2 web page, I&#8217;m collecting firmware binaries for these new targets in order to figure them out and kickstart the Rockbox effort for them. All firmware files have a .bin extension. It is quite clear (by simple human inspection) that the first 0x400 bytes in each .bin file is a header (padded &hellip; <a href=\"https:\/\/daniel.haxx.se\/blog\/2007\/12\/05\/i-solved-the-ams-sansas-firmware-checksum-puzzle\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">I Solved the AMS-Sansas&#8217; Firmware Checksum Puzzle<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-219","post","type-post","status-publish","format-standard","hentry","category-rockbox"],"_links":{"self":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/posts\/219","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/comments?post=219"}],"version-history":[{"count":0,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/posts\/219\/revisions"}],"wp:attachment":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/media?parent=219"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/categories?post=219"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/tags?post=219"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}