Someone sent me an email a few weeks ago asking me if myFuture plc downloadercould also download Zinio magazines. I had no idea what Zinio is, so Ivisited their website to learn more about theirplatform. They call themselves “The World’s Largest Newsstand” and offerover 5500 magazines (including all of theFuture plc magazines).Such a huge number of magazines instantly made them into a potential targetfor a DRM removal tool. I couldn’t find any existing tool that could convertZinio magazines into PDF (or any other format), so I assumed they had somecomplicated DRM scheme. Initially, I was not interested in breaking it, butI kept the idea in the back of my mind anyway. One day I had a few hoursto spare and decided to give it a try.
Initial investigation
How To Convert Zinio Magazines To Pdf
Jun 23, 2020 EXPORT ZINIO MAGAZINES TO PDF - I couldn't find any existing tool that could convert Zinio magazines into PDF (or any other format), so I assumed they had some complicated. Aug 06, 2020 export zinio magazines to pdf By admin on August 6, 2020 I couldn’t find any existing tool that could convert Zinio magazines into PDF (or any other format), so I assumed they had some complicated. Sep 24, 2012 How to convert zinio to pdf. Thread starter xxxbbxxx; Start date Sep 24, 2012; Sep 24, 2012 #1 X. Xxxbbxxx Newbie. Joined Sep 24, 2012 Messages 2 Reaction score 0. I want to subscribe to zinio and convert the mags to pdf, is there an app to do it? Advertise on BHW. Sep 24, 2012 #2 B. Bruciewong Newbie.
If you search the internet for “Zinio PDF conversion”, one of the first resultswill be a page from the Zinio help center. The entry is calledZinio PDF Filesand it says the following:
Zinio does not provide publication files in PDF format.Your digital edition can be downloaded and saved in aformat optimized for a rich reading experience providedby the Zinio Reader software.
I’m all for a rich reading experience! Well, if they say the don’t providemagazines in PDF format, then it must be true. Or maybe not? It was easy toverify their claims. I created an account, purchased one magazine and downloadedtheir Windows desktop app from Microsoft Store. UsingEverything, I quickly found the folder containingthe issue I just downloaded:
To my eye, that sure looks an awful lot like a bunch of PDF files—Zinio app isyet another glorified PDF reader after all. I tried to open one of the files,but I got the result I expected: encrypted PDF files, we meet again!
Decompiling Zinio app
I usually start with reversing the network API, but this time I changed theprocess and started with decompiling the app first, because trying to decryptthe files is way more fun. Zinioapp targetsboth Windows 8.1 and Windows 10, which means it’s not compiled using .NETNative and can be trivially decompiled. This time I useddnSpy, which is my new favorite toolfor decompiling .NET applications (it’s lightning fast and has great searchcapabilities, among many other great features). I loaded the Zinio app assemblyand searched for “password”. The search returned only a few results, and one ofthem was this function in the ZinioReaderWin8.Util.CryptoUtils class:
This looked like it would be a very quick game over for Zinio. Thisfunction tells us that the PDF password is encrypted withAES-CBCusing the 128-bit key derived from parameters called deviceId and uuid(initialization vector is passed via cipher parameter). But where areall these parameters coming from? GetPdfPassword is called only fromIssueDataHelper.DecryptPdfPassword, and DecryptPdfPassword is calledonly from ZinioReaderWin8.Services.IssueDataHelper.ParsePackingList.Here are the most important lines of the ParsePackingList function:
This code loads the XML node called trackingCode from some larger XML document,and extracts the IV and the ciphertext from it. My assumption was that the XMLwas received over the network when the user logs in or asks for magazine’smetadata. But what about the remaining parameters, deviceIdand uuid? It turns out they are static values initialized inZinioReaderWin8.SettingManager.InitDefaultSettings function:
That was all I needed from the decompiled application. I had analgorithm for deriving the PDF password, so all that was left wasto reverse the API.
Reversing the API
This part of the process was straightforward. Zinio API is super simple,with only three interesting requests: authenticateUser, libraryService,and issueData. Each request and response are self-contained XML documents,without custom HTTP status codes and headers; that made my job even simpler.The API doesn’t even use cookies or authentication tokens: email and passwordare stored on the client and sent with each request (that means theauthenticateUser request is completely redundant, but it still existsfor some reason). The client calls the libraryService to download the listof all purchased issues, and then issueData is called for each of them inorder to retrieve all the data necessary to download it. Here is how issueDatarequest looks in practice:
There are a lot of parameters here, and all of them are required. Login andpassword don’t need an explanation. deviceId and installationUUID areneeded because server has to generate an AES key from them.applicationName is required for the reason I’ll explain later, and the othersare required for no apparent reason. The server responds to this request withthe following response:
Remember the XML document containing the encrypted PDF password? This is it. It alsocontains the hostName and issueAssetDir; when combined, they give us thefolder where PDF pages are located. I was slightly surprised when I foundout that the PDF files don’t require any authentication. That worried me a little,because if the password was same for all the magazines, my program would allow usersto download every available magazine for free, which was not my goal. Fortunately,I discovered later that each magazine issue has unique and randomly generated 128-bitPDF password (at least I hope it’s randomly generated—it could also be an MD5 hashof something).
Now I had all the parameters needed to determine the PDF password, but the code thatI wrote didn’t work as expected. Decrypted PDF password was not a human-readable string, whichdidn’t look right. Usb smart card reader for mac. Server was also generating different IV each time, but that shouldhave affected only the ciphertext—password should have been the same each time. Thatwas not the case when I ran my code: decrypted password was different every time. Thereare only three parameters used in AES-CBC decryption: the key, the initialization vectorand the ciphertext. That meant my decryption key was wrong. I compared my implementationwith the original C# code multiple times, but couldn’t find anything wrong in my code.
Finally, after dozens of unsuccessful attempts, an idea came to my mind: what if thekey derivation is platform dependent? Maybe the problem was that I decompiled the .NET desktop version of the app,but reversed the API using the iOS app (I have Windows only in virtual machine, so I tryto use it only when necessary)? After replacing “Zinio iReader” with the “ZinioWin8”in the applicationName parameter, everything was working: decryption resulted in anice 32-byte hex-encoded string! Few more hours of coding and my application coulddownload, decrypt and merge individual files into a single PDF.
Removing annotations
Export Zinio Magazines To Pdf Online
After opening the generated PDF file, I noticed an ugly blue square at the upper-leftcorner of each page:
Each page apparently had an useless annotation containing the page number. You mightremember that I had similar problem with annotationsbefore),but this time they were much more obtrusive; I had to find a way to remove them.
As I mentioned previously, I’m using UniDoc fordecrypting and merging individual PDF pages. I was hoping that the library couldalso remove annotations. Examples section on their website didn’t have what Ineeded. Unfortunately, their API documentationis next to useless: most of the functions didn’t have any documentation at all, which is a shame,because the library itself is really useful. I started looking for any type or functionthat looked like it could have anything to do with annotations.
I discovered an interesting type called PdfObjectDictionary. PDF file itself is acollection of objects, so there might be a way to find annotations by name andset their values to null or something like that? PdfPage type has GetPageDictmethod that returns PdfObjectDictionary, so I thought I was on to something.But my editor didn’t find GetPageDict method. What was going on? Here is thecode for reading the decrypted PDF page and adding it to a final PDF:
Documentation for GetPage says it returns PdfObject, not PdfPage, but thereis another function called GetPageAsPdfPage that actually returns PdfPage.Well, that is a very confusing API, but let’s try it. Now AddPage callcouldn’t compile, because it only accepts a PdfObject and not a PdfPage.How to get the PdfObject out of the PdfPage? Obviously, by trying each availablemethod until the program compiles! Calling GetPageAsIndirectObject did the job,whatever indirect object was. Find my friend for mac. I started looking throughautocompletion suggestions and found a field called Annots. Let’s set it tonull! My final code looked like this:
Export Zinio Magazines To Pdf Download
Success! Annotations were gone and my application was complete. Youcan download it here.