Closed bowilliams closed 9 years ago
I've looked into this issue a bit, the 'ping_flash2' command has been changed (again), but it isn't a simple key change this time.
We will probably need to determine the new algorithm used for generating 'pong_flash2' responses. I've traced this back to a "ping_pong" method in "player.swf", but this would need to be deobfuscated.
Not sure how this was found originally, maybe someone else has some ideas?
Bummer, that's what I was afraid of! Thanks for looking.
I can't get it the way I'd like, seems like it's not a simple XOR operation anymore but a bit more complex logic, but I can brute force it (ugly I know, but it works): https://gist.github.com/adammw/7f192694c3ed0b13f1f9
@adammw Good work, that really works!
Do you have means to run player.swf locally, or did you make 256 manual calls to sp_run?
I tried to find any way to calculate the correct number, but so far no luck ...
I have been working a bit with this too. I haven't had any luck in decompiling the flash file, but I managed to host the flash file in a local server and obtaining the real pong value using a headless selenium.
I am using flask to load a webserver and then I use selenium to fetch the page and look for the value, whichs opens a firefox to render the page. I managed to do it headless in linux with xvfb.
Final user don't see what is happeing behind the hood, but is slow, requires firefox and flash, so is not something you would like in a library.
Anyway I wanted to share this info, in case you can think of a better alternative based on this. Firefox is the real PITA, I couldn't find a better way to render a HTML+JS+Flash.
In a perfect world we would fire up Shumway within Node.js and load up the player.swf file and invoke the ping_pong function directly.
I know that @adammw looked into this idea though and there were complications related to the fact that the swf file uses Adobe Alchemy to compile C code to Flash, which Shumway didn't support (at the time... not sure if that's changed or not).
Just in case it matters, the flash funtion I call is "sp_run"
@adammw 's solution doesnt work for me unfortunetly, atleast thats how I interprete it...
C:\Users\miladiir\Desktop\spotify-mp3-downloader-master>node app.js
Server running, to use, open http://localhost:1717 in your browser.
ReferenceError: message is not defined
at Spotify.<anonymous> (C:\Users\miladiir\Desktop\spotify-mp3-downloader-mas
ter\app.js:104:15)
at C:\Users\miladiir\Desktop\spotify-mp3-downloader-master\spotify-web\lib\s
potify.js:65:8
at Spotify.onLogin (C:\Users\miladiir\Desktop\spotify-mp3-downloader-master\
spotify-web\lib\spotify.js:197:5)
at Spotify.EventEmitter.emit (events.js:92:17)
at Spotify._onuserinfo (C:\Users\miladiir\Desktop\spotify-mp3-downloader-mas
ter\spotify-web\lib\spotify.js:1239:8)
at fn (C:\Users\miladiir\Desktop\spotify-mp3-downloader-master\spotify-web\l
ib\spotify.js:396:10)
at Spotify._onmessage (C:\Users\miladiir\Desktop\spotify-mp3-downloader-mast
er\spotify-web\lib\spotify.js:412:5)
at WebSocket.EventEmitter.emit (events.js:98:17)
at Receiver.self._receiver.ontext (C:\Users\miladiir\node_modules\ws\lib\Web
Socket.js:697:10)
at Receiver.opcodes.1.finish (C:\Users\miladiir\node_modules\ws\lib\Receiver
.js:397:14)
^C
Without the modification I don't get any message at all.
@Miladiir that's an exception in your code, not ours.
Replaced Spotify.prototype.sendPong
in lib/spotify.js
with @adammw s code, but still not getting logged in.
This is the debug log: https://gist.github.com/dralletje/fbeffd8a0afb1ed14468
Am I doing something wrong?
@adammw thanks for the fix!
You know, I'm not sure what changed on their end, but the current code in the repo is working for me again (without @adammw's patch).
Can anybody else confirm?
Yep.
I used npm install spotify-web
so not entirely sure if it is the code from master or from some tag, but it definetly works without the fix again. Seems a little bit slower than before though.
I seem to be running into this issue as of this morning.
Yup :(
On Mon, Jul 28, 2014 at 8:15 AM, Patrick Burns notifications@github.com wrote:
I seem to be running into this issue as of this morning.
— Reply to this email directly or view it on GitHub https://github.com/TooTallNate/node-spotify-web/issues/87#issuecomment-50352036 .
I tried putting @adammw brute force into the spotify.js, no luck. Can we open the issue back up?
Any idea?
I've been working on this issue. I've only discover that 5º position on pong is 4º ping position XOR 37, and last ping position (19) changes first pong position sometimes. I'm trying to find any pattern. I think it should be great if anyone who discover something could share it here. I'll post my discovers if anyone want :)
It looks like the algorithm got a lot smarter, it is not relating one index to one other. It seems it is changing the internals quite a lot, the final byte looks like it triggers some sort of if/ else effect.
The final byte seems to trigger position 1, 2, 6, 7 and 9, but it also varies at what number it uses the if/ else branche ....
document.querySelector('[id_=_player]').sprun("12 23 125 43 56 72 56 76 45 34 12 64 127 143 1 2 3 4 5 10") "116 189 235 111 47 29 228 95 97 132" document.querySelector('[id=_player]').sp_run("12 23 125 43 56 72 56 76 45 34 12 64 127 143 1 2 3 4 5 11") "116 70 228 111 47 29 235 164 97 175"
document.querySelector('[id_=_player]').sprun("0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0") "95 159 26 39 208 37 53 150 97 187" document.querySelector('[id=_player]').sp_run("0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1") "95 100 53 39 208 37 26 109 97 144"
10 and 11 here both give: "95 159 26 39 208 37 53 150 97 187"
Yep, looks really complex. I'm guessing the idea is that to brute force the algorithm will take a non-trivial amount of time. So I've found pretty much the same as you @juanmito and @AndreSteenbergen: https://gist.github.com/adammw/150435df1e8987606a7e
Interesting. I decided to investigate byte 3 further and found that it depends on input byte 7 when input byte 6 is zero, and then only on input byte 6 for all other values. But it doesn't seem to be an XOR of byte 6 so it's only so helpful.
Update: it uses the same 256-item sequence though: https://gist.github.com/adammw/31d7fcf571947f62cea0 (gives byte 3 output)
Update: I was wrong. This is crazy.
Its really complex. Almost all inputs affect all outputs
0 --> 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1 --> 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 2 --> 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 3 --> 0 1 2 3 4 5 6 7 4 --> 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 5 --> 0 1 2 3 4 6 --> 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 7 --> 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 8 --> 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 9 --> 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Maybe we can try another solution. Instead of emulating player.swf functionality, we could call and use it to get the pong chain and follow the workflow. Any idea of executing the swf file directly from node and calling sp_run function?
I've been trying this evening to call sp_run
using Shumway, but I don't fully understand it.
Using Shumway, I console.log'd all calls to ExternalInterface.addCallback
and the following callbacks got registered:
sp_hasSound
sp_load
sp_play
sp_playpause
sp_stop
sp_pause
sp_resume
sp_time
sp_seek
sp_playerState
sp_setVolume
sp_getVolume
sp_getDuration
sp_initializePlayerById
sp_addPlayer
sp_removePlayerAtIndex
No sp_run
there :( It's probably because the part of player.swf
that does the pong stuff is obfuscated whilst the rest isn't, and I don't think Shumway understands it.
Even if sp_run
was there, I haven't figured out a way to invoke any of the external callbacks :(
Most likely sp_run
is part of the native C code (Alchemy-compiled) portion of the SWF, which indeed, Shumway does not (yet) support. See https://github.com/mozilla/shumway/issues/1110 for some more details.
Ah thanks for that! I wasn't even aware Flash allowed you to use C!
Couldn't the swf be run from an own server somewhere, as hsalps has done for spotlite (example: http://spotlite.cloudapp.net/api/pong/139_8_161_89_158_172_20_143_185_165_0_71_169_174_31_176_77_61_116_87)
Yeah that's a possibility. PhantomJS can be used to invoke sp_run
in an actual webpage.
This could be done on a remote server somewhere, but the library is then dependant on that server being up.
I guess an advantage to that is when Spotify updates the "ping pong", only the server needs updating and we don't need to wait for a new version of the library.
With regards to Shumway, I managed to extract the abc of the spotify pong method and tried to run it using Shumway, but I got errors about Unknown Op's or something. Digging deeper I discovered that operands lix8 0x33
and a bunch more were being looked up in opcodes.ts
but haven't yet been implemented in Shumway. I have very little knowledge about Flash and Actionscript so I'm not really sure what that means at this point :P If anyone wants the abc of the spotify pong function I can upload it later :) I guess I'll be reading up on the AVM2 spec at some point then to see what all this means!
Hmm, how could you invoke sp_run using PhantomJS? Has anybody used this software?
As far as I know, PhantomJs can not run flash at all. PhantomJs does only include a browser with a DOM and javascript, no flash player.
Maybe ask the author of spotlite how he did this?
shumay has an avm2 impl -- https://github.com/mozilla/shumway/tree/master/src/avm2 -- including some nice disam tools for avm2 bytecode... will experiment when I have more time..
@dralletje That's true actually. Ages ago when I was playing around with Spotify's websocket stuff I managed to use PhantomJS to call some functions, but they have dropped support for flash since then. Still, something similar like Awesomium could be used.
SlimerJS, which is like PhantomJS but runs Gecko, is able to run flash if corresponding addons are installed. Though in my opinion running something like that alongside this libary is bit unpractical, even if it would work.
@9uuso I don't think SlimerJS is truly headless, which would cause problems on servers unless you're running something like xvfb. But yeah I agree that the library should probably be as lightweight as possible. Shumway or something similar would be the way to go, but unfortunately I don't think Shumway has implemented all of the avm2 opcodes which are necessary to get the ping_pong function working.
I think @AndreSteenbergen's idea is the best for now, just have an HTTP API which we can query which runs something like SlimerJS (with xvfb) or Awesomium to access the actual flash file.
Hello, I also think @AndreSteenbergen's idea is the best for now. I already set up everything on my local computer. Currently someone can send a request like "http://xxx/12 23 125 43 56 72 56 76 45 34 12 64 127 143 1 2 3 4 5 10" and will get the Pong as the response. I am going to upload this tommorow and publish a working link here if someone is interested.
@1994rstefan Can you open-source the "server" portion so that we can spin up our own and check out the code?
@1994rstefan Thanks a lot :)
Sure https://github.com/1994rstefan/Spotify-Ping-Pong-API
But it is realy ugly currently ;D You have to start the server.js with node and then open http://localhost:8080/browser.html in your local browser. The node server queues ping requests, the browser checks for new pings and sends back the pong via ajax to the node server which then response with the pong to the inital request.
Hey,
I have gone that road. I have implemented a local server, with xvfb and an old version of phantomJS that supports flash. You can see my implementation in python here https://github.com/pablorusso/Spotify2.bundle/tree/local_flash (its a plex media server spotify plugin)
As I was not building a library, the solution was not that bad but it still has lot of drawbacks (very slow and linux only); Its more a workaround to be able to listen spotify in my living :-P In case you want to try it, note that I haven't updated yet the player.swf file in my github repo.
Btw, I have too tried different tools and approaches to reverse de C code inside the flash without any luck.
On Wed, Jul 30, 2014 at 6:59 PM, Stefan notifications@github.com wrote:
Sure https://github.com/1994rstefan/Spotify-Ping-Pong-API
But it is realy ugly currently ;D You have to start the server.js with node and then open http://localhost:8080/browser.html in your local browser. The node server queues ping requests, the browser checks for new pings and sends back the pong via ajax to the node server which then response with the pong to the inital request.
— Reply to this email directly or view it on GitHub https://github.com/TooTallNate/node-spotify-web/issues/87#issuecomment-50686189 .
Pablo.- http://about.me/russopablo
I also experimented earlier with a server using atom-shell as the browser for running player.swf. atom-shell isn't headless, but I've pushed it to github anyway as it might be of some use.
https://github.com/madjam002/node-spotify-pingpong
This could be run on a server somewhere using xvfb. Horrible implementation for now, but I was just experimenting :)
@madjam002 Could I use your implementation using another browser instead atom-shell? I've been experimenting some problems installing Atom..
What problems are you having with atom-shell? You shouldn't need to install Atom (the text editor), only atom-shell. You can follow the guide at https://github.com/atom/atom-shell/blob/master/docs/tutorial/quick-start.md
I'll have a look into using other browsers later if I have time :)
Yes, i've tried downloading the zip file, but, when i'm going to execute it, it says: ./atom: Cannot execute binary file.
What operating system are you using and which atom-shell release are you downloading? Make sure it's the x64 or ia32 depending on your processor.
Yes, I know. I've using Ubuntu Linux x64, but don't know what happen exactly.
Hmm okay, I'm not sure sorry. I haven't tried atom-shell on Linux, only OS X :P I'll look at using other browsers later :)
Nah, don't worry, I'll try to run atom later.. thx anyway :)
Finally, i've been using the solution proposed by @1994rstefan. I wanted to use it in a Raspberry PI, but I realized that there is no flash plugin for Rasp, and I couldn't read player.swf.
Thanks for all. Btw, has anybody done any discover about the new pingpong algorithm?
The problem with this algorithm is all indexes from ping are affecting some value on the pong. I have tried to go through the AVM bytecode, but that is a job for a monk, and by the time the algorithm is found, it will be changed again. I guess a lot of the 256 ^ 20 options will end up in the same pong, but going down that road isn't going to really work either. We would need huge storage capabilities, for something lame as a ping pong ...
I think now we need to try and work out a solution which is practical for the library. If we're going down the road of calling the pong function directly, maybe a hosted API like Spotlite? In that case we would need to work out a way of setting up a central server for this.
At the moment that seems like the only practical way until something like Shumway is capable of running it.
Starting this morning, I'm not able to login. I've tried several accounts (all premium).
Never gets to logged in- it either hangs at about to login, or I get this error: