Skip to main content

E Ink tablets: Rooting a Boox Go 10.3

· 16 min read

Motivation

I haven't worked on a lower-level systems project in a while, I haven't worked on reversing or binaries since a brief stint in college, I've never worked on anything in the Android software ecosystem, and I haven't yet written or modified Linux device drivers myself.

Directly in line with those goals is an unmet hardware need: my growing desire for an E Ink tablet that will run an open source Android build. I've heard that some users have gotten LineageOS running on a Hisense, which is in the neighborhood of what I would be interested in. However, my note taking preferences require the screen real estate of a tablet. For several months, I've used a Boox Go 10.3 as an untrusted device solely for epub reading. As time has gone on, this tablet's full Play Store access on an Android build hints at tantalizing possibilities: the congruous feeling of a paper-like calendar or planner, an E Ink optimized RSS reader, note taking and email on the go, all further enabled by my obsession with small form factor wireless keyboards. With that dream in mind, this is the perfect fit to learn a bit about AOSP and device drivers.

Project Goals

With my lay understanding of the hardware/software boundary in the mobile ecosystem, long term I would be curious how far I can get towards deploying an Android custom ROM to the Boox Go 10.3. This unfortunately entails the very tough challenge of a full device bringup. Boox has made this even tougher by not open sourcing either their kernel or the device tree. For this to be minimally usable, it would require support for:

Rock paper scissors consequentialism

· 8 min read

I've noticed that with big topics about societal issues or values, there are often three types of conversations:

  1. There are conversations about where we are at.
  2. There are conversations about where we should go.
  3. There are conversations about how to get there.

Learning generators part 2: In depth

· 12 min read

How generators can be used in four ways (from simple to complex):

  1. Lazy-like expressions, including unbounded sequences
  2. Alternating control flow with the caller
  3. A "pure-looking" function, with hidden internal state
  4. Internally managing a state-machine, that handles caller-passed input

The first two use cases are covered this previous article, and serve as a primer to the topic. If you don't have a solid understanding of generators in Python, I would recommend starting there.

The second two use cases are covered in this article.

info

Well that's a big gap in time between these two articles!

A peak behind the screen -- I speed wrote the first article and outlined the second, immediately after doing some small projects and consuming some related tech talks. This past month I was able to clean up this section, and finally click publish on both!


Functions Internally Handling State

Both the previous use cases are common ones, made more concise through generators. This use case and the next are less common use cases that are less about convenience, and more becoming possible with generators. (Okay okay, that's not a challenge... There are definitely other ways to construct this logic! But I think these particular formations make me thankful for the tool.)

Learning generators part 1: Basics

· 7 min read

How generators can be used in four ways (from simple to complex):

  1. Lazy-like expressions, including unbounded sequences
  2. Alternating control flow with the caller
  3. A "pure-looking" function, with hidden internal state
  4. Internally managing a state-machine, that handles caller-passed input

The first two use cases are covered in this article, and serve as a primer to the topic.

The second two use cases are covered in the second part here, and might provide a new applied usage for those already familiar with generators and coroutines.


Lazy Expressions and Unbounded Sequences

Users usually first experience lazy-like behavior in Python when iterating through sequences, like so:

10 minute moments

· One min read

16 waking hours ÷ 10 minutes = 96

10 minutes is ~1% of your day.

- credit to Taylor Troesh

When the phone scrolling lasts for 10 minutes, or low-priority yak shaving adds up to 10 minutes, that's one percent of your day spent. That's not necessarily a bad thing or a good thing, but make sure it's a thing you want to have spent one percent of your day on.

You only have this many 10 minute moments.

🥱 📱 🪥 🍳 🥐 📱 ☕ 🧥 💻 💻 💻 🚽 💬 📧 🎧 💻 📞 💻 💻 💻 💻 💻 ☕ 💻 📞 💻 📱 🎧 💻 💻 💬 💻 📱 🍱 🍱 📱 ☕ 💻 📞 💻 💻 🎧 🚽 📱 💻 💻 📧 💻 💻 💻 💻 💻 💻 💻 💻 💬 🥪 📱 💻 🚗 🛒 🛒 🚗 🥏 🥏 🏃 🏃 🥏 🥏 🥏 🏋️ 🏋️ 🏋️ 🏋️ 🧘 🧘 🚗 🚗 🛁 🍲 🍲 📺 📺 📱 📺 💻 🚽 💻 💻 💻 🪥 📖 📖 📖 📖 🛌

Many minutes, but few moments.

picoCTF 2014 part 3: Steve's List

· 5 min read

Summary

Hash extension allows us to enter whatever cookies we choose, without knowledge of the secret, and still pass the website’s checks. Since the cookie is unserialized, we can inject arbitrary php objects into the server. By injecting a Post object, we know it’s destroy method will be called. This method has been redefined to output the Post’s fields in HTML comments after parsing them with the class Filter. The Filter operates by running the given text through preg_replace calls with stored params for match and substitution. As we have injected the object, we have complete control over these stored params, and can thus call the preg_replace with the ‘e’ flag, allowing us to do arbitrary command execution. By catting the necessary file at /home/daedalus/flag.txt, and substituting all of the Post’s text with the file’s contents, we can print the file’s contents in an HTML comment, and thus get the flag.

picoCTF 2014 part 2: secure_page_service

· 3 min read

Summary

This problem is a simple XSS challenge. Using persistent XSS in a newly created page, we can steal the admin’s cookies should they choose to visit the page. The “Report to Moderator” button says, “Report this page, and a moderator will personally review it in the next few minutes!” so it is a safe assumption that we can have an admin view our injected code.

picoCTF 2014 part 1: Injection 2

· 3 min read

Summary

By unioning hard coded values with the prewritten select statement, we can manually control exactly what data the query returns, and thus meet the program’s requirements.

SELECT * FROM users WHERE username='asdf' UNION SELECT 1337 AS a, 1337 AS b, 1337 AS c, 1337 AS d, 1337 AS e LIMIT 1 -- '

(with “1337” entered as the password)