Files
ericxliu-me/posts/rooting-pixel-2-xl-for-reverse-engineering/index.html
2026-01-22 05:11:15 +00:00

38 lines
20 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html><html lang=en><head><title>Why I Downgraded Magisk to Root My Pixel 2 XL · Eric X. Liu's Personal Page</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=color-scheme content="light dark"><meta http-equiv=Content-Security-Policy content="upgrade-insecure-requests; block-all-mixed-content; default-src 'self'; child-src 'self'; font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net/; form-action 'self'; frame-src 'self' https://www.youtube.com https://disqus.com; img-src 'self' https://referrer.disqus.com https://c.disquscdn.com https://*.disqus.com; object-src 'none'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com/ https://cdn.jsdelivr.net/; script-src 'self' 'unsafe-inline' https://www.google-analytics.com https://cdn.jsdelivr.net/ https://pagead2.googlesyndication.com https://static.cloudflareinsights.com https://unpkg.com https://ericxliu-me.disqus.com https://disqus.com https://*.disqus.com https://*.disquscdn.com https://unpkg.com; connect-src 'self' https://www.google-analytics.com https://pagead2.googlesyndication.com https://cloudflareinsights.com ws://localhost:1313 ws://localhost:* wss://localhost:* https://links.services.disqus.com https://*.disqus.com;"><meta name=author content="Eric X. Liu"><meta name=description content="For the past few weeks, I&rsquo;ve been stuck in a stalemate with my EcoFlow Bluetooth Protocol Reverse Engineering Project. I have the hci snoop logs, I have the decompiled APK, and I have a strong suspicion about where the authentication logic is hiding. But suspicion isn&rsquo;t proof.
Static analysis has its limits. I found the &ldquo;smoking gun&rdquo; function—a native method responsible for encrypting the login payload—but understanding how it constructs that payload within a strict 13-byte limit purely from assembly (ARM64) was proving to be a headache."><meta name=keywords content="software engineer,performance engineering,Google engineer,tech blog,software development,performance optimization,Eric Liu,engineering blog,mountain biking,Jeep enthusiast,overlanding,camping,outdoor adventures"><meta name=twitter:card content="summary"><meta name=twitter:title content="Why I Downgraded Magisk to Root My Pixel 2 XL"><meta name=twitter:description content="For the past few weeks, Ive been stuck in a stalemate with my EcoFlow Bluetooth Protocol Reverse Engineering Project. I have the hci snoop logs, I have the decompiled APK, and I have a strong suspicion about where the authentication logic is hiding. But suspicion isnt proof.
Static analysis has its limits. I found the “smoking gun” function—a native method responsible for encrypting the login payload—but understanding how it constructs that payload within a strict 13-byte limit purely from assembly (ARM64) was proving to be a headache."><meta property="og:url" content="https://ericxliu.me/posts/rooting-pixel-2-xl-for-reverse-engineering/"><meta property="og:site_name" content="Eric X. Liu's Personal Page"><meta property="og:title" content="Why I Downgraded Magisk to Root My Pixel 2 XL"><meta property="og:description" content="For the past few weeks, Ive been stuck in a stalemate with my EcoFlow Bluetooth Protocol Reverse Engineering Project. I have the hci snoop logs, I have the decompiled APK, and I have a strong suspicion about where the authentication logic is hiding. But suspicion isnt proof.
Static analysis has its limits. I found the “smoking gun” function—a native method responsible for encrypting the login payload—but understanding how it constructs that payload within a strict 13-byte limit purely from assembly (ARM64) was proving to be a headache."><meta property="og:locale" content="en"><meta property="og:type" content="article"><meta property="article:section" content="posts"><meta property="article:published_time" content="2026-01-07T00:00:00+00:00"><meta property="article:modified_time" content="2026-01-08T06:02:38+00:00"><link rel=preload href=/fonts/fa-solid-900.woff2 as=font type=font/woff2 crossorigin><link rel=preload href=/fonts/fa-brands-400.woff2 as=font type=font/woff2 crossorigin><link rel=canonical href=https://ericxliu.me/posts/rooting-pixel-2-xl-for-reverse-engineering/><link rel=preload href=/fonts/fa-brands-400.woff2 as=font type=font/woff2 crossorigin><link rel=preload href=/fonts/fa-regular-400.woff2 as=font type=font/woff2 crossorigin><link rel=preload href=/fonts/fa-solid-900.woff2 as=font type=font/woff2 crossorigin><link rel=stylesheet href=/css/coder.min.4b392a85107b91dbdabc528edf014a6ab1a30cd44cafcd5325c8efe796794fca.css integrity="sha256-SzkqhRB7kdvavFKO3wFKarGjDNRMr81TJcjv55Z5T8o=" crossorigin=anonymous media=screen><link rel=stylesheet href=/css/coder-dark.min.a00e6364bacbc8266ad1cc81230774a1397198f8cfb7bcba29b7d6fcb54ce57f.css integrity="sha256-oA5jZLrLyCZq0cyBIwd0oTlxmPjPt7y6KbfW/LVM5X8=" crossorigin=anonymous media=screen><link rel=icon type=image/svg+xml href=/images/favicon.svg sizes=any><link rel=icon type=image/png href=/images/favicon-32x32.png sizes=32x32><link rel=icon type=image/png href=/images/favicon-16x16.png sizes=16x16><link rel=apple-touch-icon href=/images/apple-touch-icon.png><link rel=apple-touch-icon sizes=180x180 href=/images/apple-touch-icon.png><link rel=manifest href=/site.webmanifest><link rel=mask-icon href=/images/safari-pinned-tab.svg color=#5bbad5><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3972604619956476" crossorigin=anonymous></script><script type=application/ld+json>{"@context":"http://schema.org","@type":"Person","name":"Eric X. Liu","url":"https:\/\/ericxliu.me\/","description":"Software \u0026 Performance Engineer at Google","sameAs":["https:\/\/www.linkedin.com\/in\/eric-x-liu-46648b93\/","https:\/\/git.ericxliu.me\/eric"]}</script><script type=application/ld+json>{"@context":"http://schema.org","@type":"BlogPosting","headline":"Why I Downgraded Magisk to Root My Pixel 2 XL","genre":"Blog","wordcount":"775","url":"https:\/\/ericxliu.me\/posts\/rooting-pixel-2-xl-for-reverse-engineering\/","datePublished":"2026-01-07T00:00:00\u002b00:00","dateModified":"2026-01-08T06:02:38\u002b00:00","description":"\u003cp\u003eFor the past few weeks, I\u0026rsquo;ve been stuck in a stalemate with my EcoFlow Bluetooth Protocol Reverse Engineering Project. I have the hci snoop logs, I have the decompiled APK, and I have a strong suspicion about where the authentication logic is hiding. But suspicion isn\u0026rsquo;t proof.\u003c\/p\u003e\n\u003cp\u003eStatic analysis has its limits. I found the \u0026ldquo;smoking gun\u0026rdquo; function—a native method responsible for encrypting the login payload—but understanding \u003cem\u003ehow\u003c\/em\u003e it constructs that payload within a strict 13-byte limit purely from assembly (ARM64) was proving to be a headache.\u003c\/p\u003e","author":{"@type":"Person","name":"Eric X. Liu"}}</script></head><body class="preload-transitions colorscheme-auto"><div class=float-container><a id=dark-mode-toggle class=colorscheme-toggle><i class="fa-solid fa-adjust fa-fw" aria-hidden=true></i></a></div><main class=wrapper><nav class=navigation><section class=container><a class=navigation-title href=https://ericxliu.me/>Eric X. Liu's Personal Page
</a><input type=checkbox id=menu-toggle>
<label class="menu-button float-right" for=menu-toggle><i class="fa-solid fa-bars fa-fw" aria-hidden=true></i></label><ul class=navigation-list><li class=navigation-item><a class=navigation-link href=/posts/>Posts</a></li><li class=navigation-item><a class=navigation-link href=https://chat.ericxliu.me>Chat</a></li><li class=navigation-item><a class=navigation-link href=https://git.ericxliu.me/user/oauth2/Authenitk>Git</a></li><li class=navigation-item><a class=navigation-link href=https://coder.ericxliu.me/api/v2/users/oidc/callback>Coder</a></li><li class=navigation-item><a class=navigation-link href=/about/>About</a></li><li class=navigation-item><a class=navigation-link href=/>|</a></li><li class=navigation-item><a class=navigation-link href=https://sso.ericxliu.me>Sign in</a></li></ul></section></nav><div class=content><section class="container post"><article><header><div class=post-title><h1 class=title><a class=title-link href=https://ericxliu.me/posts/rooting-pixel-2-xl-for-reverse-engineering/>Why I Downgraded Magisk to Root My Pixel 2 XL</a></h1></div><div class=post-meta><div class=date><span class=posted-on><i class="fa-solid fa-calendar" aria-hidden=true></i>
<time datetime=2026-01-07T00:00:00Z>January 7, 2026
</time></span><span class=reading-time><i class="fa-solid fa-clock" aria-hidden=true></i>
4-minute read</span></div></div></header><div class=post-content><p>For the past few weeks, I&rsquo;ve been stuck in a stalemate with my EcoFlow Bluetooth Protocol Reverse Engineering Project. I have the hci snoop logs, I have the decompiled APK, and I have a strong suspicion about where the authentication logic is hiding. But suspicion isn&rsquo;t proof.</p><p>Static analysis has its limits. I found the &ldquo;smoking gun&rdquo; function—a native method responsible for encrypting the login payload—but understanding <em>how</em> it constructs that payload within a strict 13-byte limit purely from assembly (ARM64) was proving to be a headache.</p><p>I needed to move from <strong>static analysis</strong> to <strong>dynamic analysis</strong>. I needed to hook the function at runtime, inspect the memory, and see the data before it gets encrypted. To do that, I needed a rooted Android device.</p><p>The only candidate in my drawer? An 8-year-old <strong>Google Pixel 2 XL (&ldquo;taimen&rdquo;)</strong> that hadn&rsquo;t been turned on since 2017.</p><h2 id=the-objective>The Objective
<a class=heading-link href=#the-objective><i class="fa-solid fa-link" aria-hidden=true title="Link to heading"></i>
<span class=sr-only>Link to heading</span></a></h2><p>Bring this relic back to life, update it to the final official firmware, and gain <code>su</code> access to install Frida and tcpdump. It sounds simple, but 2026 tools don&rsquo;t always play nice with 2017 hardware.</p><h2 id=phase-1-the-i-forgot-my-password-hurdle>Phase 1: The &ldquo;I Forgot My Password&rdquo; Hurdle
<a class=heading-link href=#phase-1-the-i-forgot-my-password-hurdle><i class="fa-solid fa-link" aria-hidden=true title="Link to heading"></i>
<span class=sr-only>Link to heading</span></a></h2><p>The first problem was mundane: I didn&rsquo;t remember the PIN. My only way in was a physical <strong>Hard Reset</strong>, which relies on a specific sequence of hardware button inputs:</p><ol><li><strong>Fastboot Mode</strong>: Hold <code>Power</code> + <code>Vol Down</code> until the familiar bootloader screen appears.</li><li><strong>Recovery Mode</strong>: Use volume keys to select &ldquo;Recovery Mode&rdquo;.</li><li><strong>The &ldquo;No Command&rdquo; Trick</strong>: The phone reboots to a broken android logo. To get the actual menu, you have to hold <code>Power</code> and tap <code>Vol Up</code> <em>once</em>.</li><li><strong>Wipe</strong>: Select <code>Wipe data/factory reset</code>.</li></ol><p><strong>The Catch</strong>: This triggers <strong>Factory Reset Protection (FRP)</strong>. Upon boot, the device required authentication with the Google Account previously synced to the hardware. Since I verified my identity using the original credentials, I could proceed; otherwise, bypassing this security feature would have been a significant roadblock.</p><h2 id=phase-2-the-update-trap>Phase 2: The Update Trap
<a class=heading-link href=#phase-2-the-update-trap><i class="fa-solid fa-link" aria-hidden=true title="Link to heading"></i>
<span class=sr-only>Link to heading</span></a></h2><p>Once in, I checked the version: <code>Android 10 (QP1A.190711.020)</code>. This was ancient. The Pixel 2 XL officially supports Android 11, and I wanted the latest possible base for compatibility with modern tools.</p><p>I tried the easy route: <strong>Settings > System Update</strong>.
<strong>The Result</strong>: Failure. The phone refused to pull the final OTA (<code>RP1A.201005.004.A1</code>), likely due to the Google update servers no longer prioritizing this EOL device.</p><h3 id=the-fix-manual-flashing>The Fix: Manual Flashing
<a class=heading-link href=#the-fix-manual-flashing><i class="fa-solid fa-link" aria-hidden=true title="Link to heading"></i>
<span class=sr-only>Link to heading</span></a></h3><p>I had to bypass the OTA system entirely. I downloaded the <a href=https://developers.google.com/android/images class=external-link target=_blank rel=noopener>final Factory Image</a> from Google.</p><div class=highlight><pre tabindex=0 style=color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span><span style=color:#8b949e;font-style:italic># Don&#39;t rely on OTA. Flash the whole valid state.</span>
</span></span><span style=display:flex><span>fastboot -w update image-taimen-rp1a.201005.004.a1.zip
</span></span></code></pre></div><p><em>Note: I used the <code>-w</code> flag here since I had just wiped the device anyway. This gave me a pristine, stock Android 11 environment to break.</em></p><h2 id=phase-3-the-magisk-time-travel>Phase 3: The Magisk &ldquo;Time Travel&rdquo;
<a class=heading-link href=#phase-3-the-magisk-time-travel><i class="fa-solid fa-link" aria-hidden=true title="Link to heading"></i>
<span class=sr-only>Link to heading</span></a></h2><p>This is where &ldquo;modern tools meets old hardware&rdquo; caused the most pain.</p><p><strong>The Hypothesis</strong>: Rooting a Pixel is standard procedure.</p><ol><li>Extract <code>boot.img</code> from the factory zip.</li><li>Patch it with the latest <strong>Magisk</strong> app.</li><li>Flash it back.</li></ol><p><strong>The Reality</strong>: Bootloop.
I used <strong>Magisk v30.6</strong> (the latest as of writing). The patch process &ldquo;succeeded,&rdquo; but flashing the resulting image caused the phone to immediately crash back to the bootloader with a &ldquo;Cannot find valid operating system&rdquo; error.</p><h3 id=debugging-the-bootloop>Debugging the Bootloop
<a class=heading-link href=#debugging-the-bootloop><i class="fa-solid fa-link" aria-hidden=true title="Link to heading"></i>
<span class=sr-only>Link to heading</span></a></h3><p>I suspected a regression in how modern Magisk handles the antiquated boot partition structure of the Pixel 2 (A/B partitions, but pre-GKI).</p><p>I decided to perform some &ldquo;software archaeology&rdquo; and use a version of Magisk that was contemporary with the device&rsquo;s lifespan. I grabbed <strong>Magisk v25.0</strong> (released around 2022).</p><ol><li><strong>Repatch</strong>: I patched the <em>exact same</em> stock <code>boot.img</code> using the v25.0 app.</li><li><strong>Reflash</strong>:</li></ol><div class=highlight><pre tabindex=0 style=color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span><span style=color:#8b949e;font-style:italic># Flash to both slots to be safe</span>
</span></span><span style=display:flex><span>fastboot flash boot_a magisk_patched_25000.img
</span></span><span style=display:flex><span>fastboot flash boot_b magisk_patched_25000.img
</span></span></code></pre></div><p><strong>The Result</strong>: Success. The phone booted, and the Magisk app confirmed <code>Installed: 25.0</code>.</p><div class=highlight><pre tabindex=0 style=color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span> adb shell <span style=color:#a5d6ff>&#34;su -c id&#34;</span>
</span></span><span style=display:flex><span><span style=color:#79c0ff>uid</span><span style=color:#ff7b72;font-weight:700>=</span>0<span style=color:#ff7b72;font-weight:700>(</span>root<span style=color:#ff7b72;font-weight:700>)</span> <span style=color:#79c0ff>gid</span><span style=color:#ff7b72;font-weight:700>=</span>0<span style=color:#ff7b72;font-weight:700>(</span>root<span style=color:#ff7b72;font-weight:700>)</span> <span style=color:#79c0ff>groups</span><span style=color:#ff7b72;font-weight:700>=</span>0<span style=color:#ff7b72;font-weight:700>(</span>root<span style=color:#ff7b72;font-weight:700>)</span> <span style=color:#79c0ff>context</span><span style=color:#ff7b72;font-weight:700>=</span>u:r:magisk:s0
</span></span></code></pre></div><h2 id=key-insights>Key Insights
<a class=heading-link href=#key-insights><i class="fa-solid fa-link" aria-hidden=true title="Link to heading"></i>
<span class=sr-only>Link to heading</span></a></h2><ul><li><strong>Don&rsquo;t Trust OTAs on EOL Devices</strong>: If you&rsquo;re reviving old hardware, the OTA mechanism is likely broken or unreliable. Go straight to the factory images.</li><li><strong>Version Matching Matters</strong>: Tools like Magisk evolve. Using a 2026 root method on a 2017 kernel is a recipe for instability. Sometimes, downgrading your tools is the only way forward.</li><li><strong>A/B Partitions</strong>: Always flash your patched boot image to <em>both</em> slots (<code>boot_a</code> and <code>boot_b</code>) to avoid active slot mismatches causing boot failures.</li></ul><p>With root access secured, the path is now clear to install Frida and finally intercept those elusive EcoFlow authentication packets.</p><h2 id=references>References
<a class=heading-link href=#references><i class="fa-solid fa-link" aria-hidden=true title="Link to heading"></i>
<span class=sr-only>Link to heading</span></a></h2><ol><li><a href=https://developers.google.com/android/images class=external-link target=_blank rel=noopener>Google Pixel Factory Images</a></li><li><a href=https://topjohnwu.github.io/Magisk/install.html class=external-link target=_blank rel=noopener>Magisk Installation Guide</a></li><li><a href=https://github.com/topjohnwu/Magisk/releases class=external-link target=_blank rel=noopener>Magisk GitHub Releases</a></li><li><a href=https://xdaforums.com/t/guide-unlock-flash-root-for-the-pixel-2-xl-taimen.3702418/ class=external-link target=_blank rel=noopener>XDA Guide: Unlock/Flash/Root Pixel 2 XL</a></li></ol></div><footer><div id=disqus_thread></div><script>window.disqus_config=function(){},function(){if(["localhost","127.0.0.1"].indexOf(window.location.hostname)!=-1){document.getElementById("disqus_thread").innerHTML="Disqus comments not available by default when the website is previewed locally.";return}var t=document,e=t.createElement("script");e.async=!0,e.src="//ericxliu-me.disqus.com/embed.js",e.setAttribute("data-timestamp",+new Date),(t.head||t.body).appendChild(e)}(),document.addEventListener("themeChanged",function(){document.readyState=="complete"&&DISQUS.reset({reload:!0,config:disqus_config})})</script></footer></article><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css integrity=sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0 crossorigin=anonymous><script defer src=https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.js integrity=sha384-PwRUT/YqbnEjkZO0zZxNqcxACrXe+j766U2amXcgMg5457rve2Y7I6ZJSm2A0mS4 crossorigin=anonymous></script><script defer src=https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/contrib/auto-render.min.js integrity=sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05 crossorigin=anonymous onload='renderMathInElement(document.body,{delimiters:[{left:"$$",right:"$$",display:!0},{left:"$",right:"$",display:!1},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}]})'></script></section></div><footer class=footer><section class=container>©
2016 -
2026
Eric X. Liu
<a href="https://git.ericxliu.me/eric/ericxliu-me/commit/c112e1e">[c112e1e]</a></section></footer></main><script src=/js/coder.min.6ae284be93d2d19dad1f02b0039508d9aab3180a12a06dcc71b0b0ef7825a317.js integrity="sha256-auKEvpPS0Z2tHwKwA5UI2aqzGAoSoG3McbCw73gloxc="></script><script defer src=https://static.cloudflareinsights.com/beacon.min.js data-cf-beacon='{"token": "987638e636ce4dbb932d038af74c17d1"}'></script></body></html>