{"id":38823,"date":"2023-03-21T14:49:24","date_gmt":"2023-03-21T18:49:24","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=38823"},"modified":"2023-03-21T14:51:39","modified_gmt":"2023-03-21T18:51:39","slug":"recovering-cropped-parts-of-google-pixel-screenshots","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2023\/03\/21\/recovering-cropped-parts-of-google-pixel-screenshots\/","title":{"rendered":"Recovering Cropped Parts of Google Pixel Screenshots"},"content":{"rendered":"<p><a href=\"https:\/\/twitter.com\/ItsSimonTime\/status\/1636857478263750656\">Simon Aarons<\/a> (via <a href=\"https:\/\/news.ycombinator.com\/item?id=35207787\">Hacker News<\/a>):<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/ItsSimonTime\/status\/1636857478263750656\"><p>Introducing acropalypse: a serious privacy vulnerability in the Google Pixel&rsquo;s inbuilt screenshot editing tool, Markup, enabling partial recovery of the original, unedited image data of a cropped and\/or redacted screenshot.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/www.da.vidbuchanan.co.uk\/blog\/exploiting-acropalypse.html\">David Buchanan<\/a> (via <a href=\"https:\/\/news.ycombinator.com\/item?id=35208721\">Hacker News<\/a>):<\/p>\n<blockquote cite=\"https:\/\/www.da.vidbuchanan.co.uk\/blog\/exploiting-acropalypse.html\">\n<p>Google was passing <code>\"w\"<\/code> to a call to <code>parseMode()<\/code>, when they should've been passing <code>\"wt\"<\/code> (the t stands for truncation). This is an easy mistake, since similar APIs (like POSIX <a href=\"https:\/\/man7.org\/linux\/man-pages\/man3\/fopen.3.html\">fopen<\/a>) will truncate by default when you simply pass <code>\"w\"<\/code>. Not only that, but previous Android releases had <code>parseMode(\"w\")<\/code> truncate by default too! This change wasn't even documented until some time after the aforementioned <a href=\"https:\/\/issuetracker.google.com\/issues\/180526528\">bug report<\/a> was made.<\/p>\n<p>The end result is that the image file is opened <em>without<\/em> the <code>O_TRUNC<\/code> flag, so that when the cropped image is written, the original image is not truncated. If the new image file is smaller, the end of the original is left behind.<\/p><\/blockquote>\n\n<p>This reminds me of the old Microsoft Word issue where if you had it set to &ldquo;fast save&rdquo; it would leave deleted text in the file. Sometimes there even seemed to be chunks of unzeroed content from other apps&rsquo; deleted files.<\/p>\n\n<blockquote cite=\"https:\/\/www.da.vidbuchanan.co.uk\/blog\/exploiting-acropalypse.html\"><p>I found that the data was indeed compressed using dynamic Huffman coding, but that the Huffman tree was re-specified every ~16KB or so. This was <em>excellent<\/em> news because it meant I didn&rsquo;t have to solve the &ldquo;Huffman coding cryptanalysis&rdquo; problem, and could instead solve the much simpler-in-practice problem of &ldquo;find the start of a dynamic-Huffman-coded zlib block&rdquo;.<\/p><p>[&#8230;]<\/p><p>Although I&rsquo;m currently an iPhone user, I used to use a Pixel 3XL. I&rsquo;m also a heavy Discord user, and in the past I&rsquo;d shared plenty of cropped screenshots through the Discord app.<\/p><p>I wrote a script to scrape my own message history to look for vulnerable images. There were lots of them, although most didn&rsquo;t leak any particularly private information.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/news.ycombinator.com\/item?id=35212745\">Juerd<\/a>:<\/p>\n<blockquote cite=\"https:\/\/news.ycombinator.com\/item?id=35212745\">\n<p>Very simple <a href=\"https:\/\/gist.github.com\/Juerd\/40071ec6d1da9d4610eba4417c8672de\">script<\/a> to check which PNG files have trailing data.<\/p>\n<p>I hope that people who host forums, image boards, chat applications, etc., will delete or fix potentially vulnerable images before anyone uses them maliciously.<\/p>\n<p>One way to repair a vulnerable image is to use <code>optipng -fix<\/code>.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/news.ycombinator.com\/item?id=35209638\">jsjohnst<\/a>:<\/p>\n<blockquote cite=\"https:\/\/news.ycombinator.com\/item?id=35209638\"><p>These types of issues are exactly why whenever it&rsquo;s sensitive, I screenshot, crop\/edit, then screenshot the crop&rsquo;d\/edited screenshot. There&rsquo;s other possible issues than this bug (like iOS&rsquo;s non-destructive edits by default), so it&rsquo;s better to be safe than sorry.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/pxlnv.com\/linklog\/google-pixel-acropalypse\/\">Nick Heer<\/a>:<\/p>\n<blockquote cite=\"https:\/\/pxlnv.com\/linklog\/google-pixel-acropalypse\/\">\n<p>There are some people in the replies to Aarons&rsquo; tweet claiming the same is true for cropped iPhone screenshots. In my testing, that is not exactly right: if you crop an iPhone screenshot and then share it with default sharing options, it does not transmit edit history or removed image data, as best as I can tell. When I AirDropped a cropped screenshot to myself, it sent a re-encoded JPG image instead of the HEIF original. In the iOS Share sheet, there is an &ldquo;Options&rdquo; button; if you want, you can toggle the switch to &ldquo;include all photos data&rdquo; which includes &ldquo;edit history and metadata&rdquo;, including image data removed via cropping. This option is off by default.<\/p>\n<\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2016\/08\/26\/the-elegance-of-deflate\/\">The Elegance of Deflate<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Simon Aarons (via Hacker News): Introducing acropalypse: a serious privacy vulnerability in the Google Pixel&rsquo;s inbuilt screenshot editing tool, Markup, enabling partial recovery of the original, unedited image data of a cropped and\/or redacted screenshot. David Buchanan (via Hacker News): Google was passing \"w\" to a call to parseMode(), when they should've been passing \"wt\" [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2023-03-21T18:49:28Z","apple_news_api_id":"1ad8cffa-68a3-4214-94c4-7d875a1ae12c","apple_news_api_modified_at":"2023-03-21T18:51:42Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAQ==","apple_news_api_share_url":"https:\/\/apple.news\/AGtjP-mijQhSUxH2HWhrhLA","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[2],"tags":[248,131,357,1428,31,2185,445,1661,355,71],"class_list":["post-38823","post","type-post","status-publish","format-standard","hentry","category-technology","tag-android","tag-bug","tag-compression","tag-google-pixel","tag-ios","tag-ios-16","tag-microsoftword","tag-png","tag-privacy","tag-programming"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/38823","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=38823"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/38823\/revisions"}],"predecessor-version":[{"id":38829,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/38823\/revisions\/38829"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=38823"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=38823"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=38823"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}