As an avid Karaoke Pasela user, I’ve been finding it increasingly difficult to overlook all of the shortcomings of the service. It’s cheap and doesn’t require you to purchase a drink, but otherwise the user experience is pretty terrible:
- Poor substring/fuzzy matching on song search
- Multiple versions of the same song with little/no disambiguation
- Awful search performance with no caching
- Arbitrary limit of 10 songs in the queue at once
- Unstable sessions that disconnect non-deterministically
So on little more than spur of the moment, @astrobunny and I figured we should just make our own Pasela application to address all of these issues, since there was likely more engineering prowess between the two of us than the entire company that was outsourced the official app development. As the process would likely involve reversing the Pasela stack, I decided to name our project Alesap.
Packet Sniffing
The first step was to develop a basic PoC to determine if it was even possible to control the karaoke system externally. The tablet the store provides is wireless and had a wifi icon in the status bar, indicating that control is likely done over the network. So the immediate goal was clear: get onto the same network as the tablet and spin up Wireshark. This was harder than it sounds.
The tablet OS was (unsurprisingly) heavily locked-down so we couldn’t get into anything resembling system settings to see what network it was on, let alone connect to a different one. We played around a bit trying to reboot it, get it into recovery mode, even pulling off the cover to see if we could ADB it or find an ethernet port, but no luck.
We figured we should just try the PASELA-RESORTS network, which is available for guests and the only one clearly associated with the store; the thinking being that the tablet would either be on this or a hidden staff SSID. This ended up also being quite challenging, as upon connecting on our respective devices we realised we were not on the same network.
Since the stores served dozens of rooms across multiple floors, they naturally had an access point per room, or at least several per floor. Obviously there are ways to identify the networks with MAC addresses and such, but this approach was looking to be more effort than it was worth.
MueNavi Arc
In addition to the Chinese tablets the stores provide in each room, guests also have the option of installing the MueNavi mobile app to control the karaoke machine with their phones. This is what we use normally because the tablet keyboards are horrible to use. It’s also a much more suitable target for investigating as we have full control over what we do on our phones. This was pretty promising as the UI indicated that the app probably hadn’t seen an update since Kitkat.
To connect your MueNavi to the karaoke machine in the room, the tablet gives you a QR code. This is what it contains:
http://rdn_6921969c7c7108.88681683,968283092c07f5789bc11ade92f6a2f8,613/
Doesn’t look like any kind of HTTP URI I’m familiar with, but we’ll get back to this in a second. The obvious thing to check is the network traffic when we send a song to the machine using the app.
POST http://order.mashup.jp/bridge/post_request.php
body: {
ecd: 4771A47
akey: rdn_6921969c7c7108.88681683
skey: 968283092c07f5789bc11ade92f6a2f8
scd: 613
}
Well we found out very quickly where the values from the QR code go. Looks like they’re session identifiers so that the app knows which machine in which store to send requests to. My guess is scd is “store code”, and akey and skey are related to the session. ecd is one we haven’t seen before but we were able to quickly verify that this is just the song ID. You can see this for yourself via the online search:
Looks like the endpoint has no SSL either. It’s a bit amusing to think about MITMing karaoke requests.
Proof of Concept
You know what happens next. We just need to see if we could send this POST request without using the app.
We could.
While we were digging around, we also checked what other options are included in the request bodies for all the various controls that the app provides. This is how I was able to stop the song as well.
Since the endpoint is public facing, you could totally curl it from the machine you’re reading this blog on, but the session keys are reset at the store when they prepare the room for the next customer so it won’t do anything. Presumably this is meant to stop you trolling the next person who uses the room after you, which I’m glad they considered as a bare minimum.
$ curl -X POST -d 'ecd=4771A47&akey=rdn_6921969c7c7108.88681683&skey=968283092c07f5789bc11ade92f6a2f8&scd=613' http://order.mashup.jp/bridge/post_request.php
{
"status": true,
"code": 200,
"message": "OK",
"result": {
"status": false,
"code": 408,
"message": "ご使用の端末は入室していないか、既に退室済みです。",
"SHOP_CODE": "613",
"SHOP_NAME": "パセラ池袋本店"
}
}
You may have noticed from the screenshots that the app also lets you order food and drinks. I’ll admit I had the passing thought to see if we could set the price or modify the items, but quickly decided against it. We’re here to sing karaoke, not to disrupt businesses and commit actual crimes. Though if it were that easy they’d probably benefit from someone pointing it out to them.
Anyways, we got what we needed so we just sang a few songs until our time ran out.
Backend Construction
Once we got back home, the next order of business was to build our own Pasela stack. I left the backend development to astro since he’s an actual software developer, and not a cyber security fraud. He did all of the work here, so you’ll have to excuse me for describing all of this second-hand.
The flow we wanted to achieve was to be able to search for songs and send them to the machine, but the officially-provided search was unacceptable. Try to search for “numb”; see how long it takes, and see if you even find the Linkin Park song. In fact, see if you can even figure out why half of the results even show up.
So astro wanted to create his own fancy search algorithm that could do not only substring and fuzzy searching, but also searching on specific fields, by artist nicknames, and a slew of other extra (by every definition of the word) features. However doing so requires us to have the song database, which we didn’t have. Not yet, anyway.
As it turns out, the Pasela API has no rate limiting. So he was able to dump all of the song data overnight and cross-reference it with the karaokebase open-source database to build a pretty comprehensive data set with Pasela’s song IDs. Interestingly the fields from the API don’t exactly match the search results you get from the tablet, so our running theory is that they have a separate offline database for the tablets because that search is slightly less shit. The tablet data is more complete so getting our hands on it is homework for another day, but we have a working product you can follow at davidsiaw/alesap-server.
Frontend Development
I took it upon myself to take up the other half of the project: building the user-facing component. This isn’t my forte either, but it is the piece with lower stakes so I was pretty happy to contribute beyond the initial hacking session, if you can even call it that.
We figured a web application would be ideal so that it’d work on any device and we wouldn’t need to mess with Apple developer certificates and all that other nonsense for our fruit-enjoying friends. astro atually has a static site framework he’s developed so I also took the opportunity to give it a crack.
The frontend needs to get session info from the tablet, which I borrowed mebjas/html5-qrcode to take care of. Otherwise it just needs to make POST requests to the backend to search for songs and add them to the queue or stop playback, which was all rather trivial in the grand scheme of things. Most of the work was cosmetic so the only real hindrance was the fact that I wanted to jump off a roof everytime I had to type async or await.
If it wasn’t clear I’m not the biggest fan of web dev, so go ahead and send your PRs to blankaex/alesap.
What’s next?
The app is more or less functional in production so I think we’ve reached a pretty comfortable MVP. We’ll probably get our friends on board to provide user feedback and make minor improvements to the UX and whatnot. There’s also some major upgrades we can do like getting the tablet database or implementing a server-side queue to bypass the inbuilt limit.
These are all nice-to-haves though so at this stage I’m pretty happy to relegate this to a hobby project that we come to every now and then. Really it was just a nice exercise to reaffirm that knowing a bit of code is all you need to make improvements to your quality of life and that of those around you.