{"id":4488,"date":"2022-06-06T15:06:11","date_gmt":"2022-06-06T23:06:11","guid":{"rendered":"https:\/\/www.pnfsoftware.com\/blog\/?p=4488"},"modified":"2023-10-19T09:18:21","modified_gmt":"2023-10-19T17:18:21","slug":"dart-aot-snapshot-helper-plugin-to-better-analyze-flutter-based-apps","status":"publish","type":"post","link":"https:\/\/www.pnfsoftware.com\/blog\/dart-aot-snapshot-helper-plugin-to-better-analyze-flutter-based-apps\/","title":{"rendered":"Dart AOT snapshot helper plugin to better analyze Flutter-based apps"},"content":{"rendered":"\n<p><em><strong>Update:<\/strong> Oct 18 2023: as of JEB 5.4, JEB can parse Dart AOT snapshots <a href=\"https:\/\/gist.github.com\/nfalliere\/84803aef37291ce225e3549f3773681b\">version 2.10 to 3.1<\/a>.<\/em><\/p>\n\n\n\n<p><em><strong>Update:<\/strong> Oct 5 2022: as of JEB 4.20, this plugin generates <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\/reference\/com\/pnfsoftware\/jeb\/core\/units\/code\/dart\/IDartAotUnit.html\">IDartAotUnit<\/a> objects, easily accessible by <a href=\"https:\/\/github.com\/pnfsoftware\/jeb-samplecode\/blob\/master\/scripts\/PrintOutDartInfo.py\">API<\/a>.<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/10\/image.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"488\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/10\/image-1024x488.png\" alt=\"\" class=\"wp-image-4519\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/10\/image-1024x488.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/10\/image-300x143.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/10\/image-768x366.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/10\/image-1536x733.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/10\/image-2048x977.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">A &#8220;Dart AOT Snapshot&#8221; unit generated by the plugin (JEB &gt;= 4.20), along with unit documents.<\/figcaption><\/figure>\n\n\n\n<p><em>The original post can be found below:<\/em><\/p>\n\n\n\n<p>JEB 4.17 ships with a Dart AOT (ahead-of-time) binary snapshot helper plugin to help with the analysis of pre-compiled Dart programs. A common use case for it may be to offer directions when reverse engineering Flutter apps compiled for Android x86\/x64 or arm\/aarch64 platforms.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Snapshots in ELF<\/h2>\n\n\n\n<p>Release-mode Flutter-based Android apps will generate AOT snapshots instead of shipping with bytecode or Dart code, like Debug-mode apps may choose to. The AOT snapshot contains a state of the Dart VM required to run the pre-compiled code.<\/p>\n\n\n\n<p>A snapshot is generally located in the <code>lib\/&lt;arch&gt;\/libapp.so<\/code> files of an APK. Since Dart may be used outside of Flutter, or since the file name or location may change, a reliable way to locate such files is to look for an ELF <code>so<\/code> exporting the following 4 symbols:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">_kDartVmSnapshotInstructions<br>_kDartIsolateSnapshotInstructions<br>_kDartVmSnapshotData<br>_kDartIsolateSnapshotData<\/pre>\n\n\n\n<p>The <code>XxxSnapshotInstructions<\/code> symbols point to pre-compiled machine code. However, getting a starting point when dealing with stripped or obfuscated binaries may prove difficult. The <code>XxxSnapshotData<\/code> symbols point to Dart VM structures and objects that will be accessed by the executing code. That includes data elements such as pooled strings or arrays of immediate values. Snapshot data also include important metadata that will help restructure the hundreds or thousands of routines compiled in an AOT snapshot.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using the Plugin<\/h2>\n\n\n\n<p>First, make sure that you are dealing Dart AOT snapshots or with a Flutter app containing precompiled AOT snapshots. Indeed other types of snapshots exist, such as JIT snapshots. The plugin does not provide help for those. In practice, non-AOT snapshots may be relatively easy to analyze, but you are unlikely to encounter them in the wild. Most Dart code or Flutter apps will be compiled and distributed in release mode. At best, some symbols and optional metadata may be left over. At worst, most will have been obfuscated (refer to Flutter&#8217;s <code><a href=\"https:\/\/github.com\/flutter\/flutter\/wiki\/Obfuscating-Dart-Code\">--obfuscate<\/a><\/code> option).<\/p>\n\n\n\n<p>The plugin will automatically kick in and analyze AOT snapshots generated by Dart 2.10 (~Fall 2010) to Dart 2.17 (current at the time of writing). The analysis results will be placed in text sub-units located under the elf container unit. The code unit will be annotated (methods will be renamed, etc.), as explained in the next sections.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"635\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-1024x635.png\" alt=\"\" class=\"wp-image-4492\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-1024x635.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-300x186.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-768x476.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-1536x953.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image.png 1948w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">An aarch64 ELF file containing Dart AOT snapshots. The plugin generated reports in the <em>dart_aot_snapshots<\/em> sub-unit folder. Other information would be embedded into the native code unit itself (e.g. renamed routines, re-packaged routines, extra comments, etc.)is directly placed onto .<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Textual Information<\/h3>\n\n\n\n<p>AOT snapshots contain lots of information. Deserializing them is relatively complicated, not to mention the fact that each revision of Dart changes the format &#8212; meaning that support will have to be added for Dart 2.18+ when that version ships&#8230; The plugin does not extract every potentially available bit of information. What is made available at this time is:<\/p>\n\n\n\n<p>1- Basic information about the snapshots, such as version and features<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"220\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-1-1024x220.png\" alt=\"\" class=\"wp-image-4495\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-1-1024x220.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-1-300x64.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-1-768x165.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-1-1536x330.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-1-2048x440.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Basic information about AOT snapshots<\/figcaption><\/figure>\n\n\n\n<p>2- The list of libraries, classes, and methods<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"439\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-2-1024x439.png\" alt=\"\" class=\"wp-image-4496\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-2-1024x439.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-2-300x129.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-2-768x329.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-2-1536x658.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-2.png 1666w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Classes, methods, libraries present a snapshot. Here, we can see that most names were obfuscated.<\/figcaption><\/figure>\n\n\n\n<p>3- A view of the primary pool strings<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"364\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-3-1024x364.png\" alt=\"\" class=\"wp-image-4497\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-3-1024x364.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-3-300x107.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-3-768x273.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-3-1536x546.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-3.png 1996w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Pooled items (including strings), some of them may be used by the natively executed code.<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Code Annotations<\/h3>\n\n\n\n<p>Aside from static information, the plugin also attempts to:<\/p>\n\n\n\n<p><strong>1- Rename methods.<\/strong> Release builds will strip the method names from the ELF file. However, the AOT snapshot information references all AOT methods as well as their names, classes, library, etc. The names provided in the snapshot information will be applied to unnamed native routines.<\/p>\n\n\n\n<p class=\"has-medium-pink-color has-text-color\"><strong>You will be able to locate the <code>main<\/code> method, the entry-point of all Dart applications.<\/strong><\/p>\n\n\n\n<p><strong>2- Annotate access to pooled strings.<\/strong> Native code accesses pooled items through a fixed register (containing an address into a pointer array to pooled elements). Below is a list of registers for the most common architectures:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">arm     : register r5\naarch64 : register x27\nx64     : register r15<\/pre>\n\n\n\n<p>Pooled strings accessed on x64 binaries are marked as a meta-comment in the code unit, as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-4.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"287\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-4-1024x287.png\" alt=\"\" class=\"wp-image-4500\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-4-1024x287.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-4-300x84.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-4-768x216.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-4-1536x431.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-4-2048x575.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">0x1BFF \/ 8 (pointer size on 64-bit arch.) = 0x37F = 895<\/figcaption><\/figure>\n\n\n\n<p>Unfortunately, due to how the assembly code for arm64 binaries is generated, those comments cannot be generated on such binaries. However, decompilation will yield slightly more digestible code, e.g.:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-5.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"678\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-5-1024x678.png\" alt=\"\" class=\"wp-image-4501\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-5-1024x678.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-5-300x199.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-5-768x509.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-5-1536x1017.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/06\/image-5-2048x1356.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Pooled string access on an arm64 binary<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Caveats &amp; Conclusion<\/h2>\n\n\n\n<p>We recommend analyzing x64 or arm64 binaries, instead of their 32-bit x86 or arm counterparts, since the plugin may not parse everything properly in the latter cases. In particular, the functions are not mapped properly for arm 32-bit snapshots generated by recent versions of Dart (2.16&#8217;ish and above).<\/p>\n\n\n\n<p>More could be done, in particular related to calling conventions (for proper decompilation), pseudo-code refactoring and restructuring (via <code>gendec<\/code> IR plugins for instance), library code flagging (e.g. classes and their methods belonging to <code>dart::&lt;well_known_namespace&gt;<\/code> could be visually standing out). Such additional features will be added depending on the feedback and the needs of the users. Please let us know your feedback via the usual means (<a href=\"https:\/\/twitter.com\/jebdec\">Twitter<\/a>, <a href=\"mailto:contact@pnfsoftware.com\">email<\/a>, <a href=\"https:\/\/jebdecompiler.slack.com\/\">Slack<\/a>).<\/p>\n\n\n\n<p>Finally, thanks to Axelle Apvrille (<a href=\"https:\/\/twitter.com\/cryptax\">@cryptax<\/a>) for flagging Dart as something that JEB may be able to help with!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Further Reading<\/h2>\n\n\n\n<p>Discussion of the internal formats and binary details of AOT snapshots was out-of-scope in this blog. Readers interested in digging further should check the following resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>First, read through<a href=\" https:\/\/rloura.wordpress.com\/2020\/12\/04\/reversing-flutter-for-android-wip\/\"> https:\/\/rloura.wordpress.com\/2020\/12\/04\/reversing-flutter-for-android-wip\/<\/a> for an introduction to format generated by Dart version 2.10.<\/li>\n\n\n\n<li>You can proceed with <a href=\"https:\/\/blog.tst.sh\/reverse-engineering-flutter-apps-part-1\/\">https:\/\/blog.tst.sh\/reverse-engineering-flutter-apps-part-1\/<\/a> (as well as part 2) for a deeper dive into the snapshot structures as well as generated native code.<\/li>\n\n\n\n<li>At this point, you should be comfortable to dig through the source code at <a href=\"https:\/\/github.com\/dart-lang\/sdk\">https:\/\/github.com\/dart-lang\/sdk<\/a>. It is the ultimate source of truth, look no further \ud83d\ude42 In particular, the <code>runtime\/vm\/*_snapshot.[h,cc]<\/code> files (and related files, such as <code>class_id.h<\/code> or <code>raw_object.h<\/code>) contain most information about the serialized snapshot formats.<\/li>\n\n\n\n<li>Bonus reading material: <a href=\"https:\/\/mrale.ph\/dartvm\/\">https:\/\/mrale.ph\/dartvm\/<\/a> to get a high-level understanding of the Dart VM.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Miscellanous<\/h2>\n\n\n\n<p>A generated mapping of Dart snapshot&#8217;s version hashes to git version tags can be found here: <a href=\"https:\/\/gist.github.com\/nfalliere\/84803aef37291ce225e3549f3773681b\">https:\/\/gist.github.com\/nfalliere\/84803aef37291ce225e3549f3773681b<\/a><\/p>\n\n\n\n<p>Thank you for reading, until next time! &#8211; Nicolas<\/p>\n\n\n\n<p>&#8212;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update: Oct 18 2023: as of JEB 5.4, JEB can parse Dart AOT snapshots version 2.10 to 3.1. Update: Oct 5 2022: as of JEB 4.20, this plugin generates IDartAotUnit objects, easily accessible by API. The original post can be found below: JEB 4.17 ships with a Dart AOT (ahead-of-time) binary snapshot helper plugin to &hellip; <a href=\"https:\/\/www.pnfsoftware.com\/blog\/dart-aot-snapshot-helper-plugin-to-better-analyze-flutter-based-apps\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Dart AOT snapshot helper plugin to better analyze Flutter-based apps<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25,26,22,13],"tags":[],"class_list":["post-4488","post","type-post","status-publish","format-standard","hentry","category-dart","category-flutter","category-jeb4","category-native-code"],"_links":{"self":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/4488","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/comments?post=4488"}],"version-history":[{"count":0,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/4488\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/media?parent=4488"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/categories?post=4488"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/tags?post=4488"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}