Guest User

Remove Kobo's DRM (kdrm) from their kepub format ebooks.

a guest
Aug 28th, 2013
3,971
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Batch 15.13 KB | None | 0 0
  1. @ECHO OFF
  2.  
  3. REM ============================================================================ FIRSTRUN
  4. CLS
  5. ECHO.
  6. ECHO DEKDRM.BAT ^(by Kobostaya^) is a Windows batch script to remove Kobo's
  7. ECHO proprietary DRM ^(kdrm^) from their kepub format ebooks. It can free your Kobo
  8. ECHO ebooks that are not available for download as regular epubs with Adobe DRM.
  9. ECHO.
  10. ECHO ^|======================================================================
  11. ECHO ^| USAGE: DEKDRM [path]00000000-0000-0000-0000-000000000000[.ext] [...]
  12. ECHO ^|======================================================================
  13. ECHO ^| Output file location: [path]00000000-0000-0000-0000-000000000000.epub
  14. ECHO ^|======================================================================
  15. ECHO.
  16. ECHO 00000000-0000-0000-0000-000000000000 is the name of a kepub file with DRM.
  17. ECHO.
  18. ECHO The script will put the DRM-free version in the same folder the original file
  19. ECHO is in, named as .epub added to the original name.
  20. ECHO.
  21. ECHO You can pass more than one file at a time ^(but not folder names^).
  22. ECHO.
  23. ECHO Already DRM-free files are automatically skipped.
  24. ECHO.
  25. PAUSE
  26. CLS
  27. ECHO.
  28. ECHO If you don't want to log processing messages, it's probably easiest to
  29. ECHO simply drag files from your Kobo kepub folder onto this .BAT file.
  30. ECHO Dragging many files in one go is supported as well, but can obviously take
  31. ECHO a while to process.
  32. ECHO.
  33. ECHO IMPORTANT!
  34. ECHO If the kepub file's name has been changed from its original GUID-style name,
  35. ECHO this script ^(specifically the second database lookup^) will fail, as the GUID
  36. ECHO is needed to determine the encrypted files inside the kepub and their
  37. ECHO decryption keys. Kepub files can have extensions though, these will simply be
  38. ECHO ignored in the processing.
  39. ECHO.
  40. PAUSE
  41. CLS
  42. ECHO                                   REQUIREMENTS:
  43. ECHO 1. Windows XP.
  44. ECHO    ^(Tested on Windows XP Pro SP3.^)
  45. ECHO    Vista, Win7 and Win8 should work with no or minimal changes but the point is
  46. ECHO    THEY HAVEN'T BEEN TESTED so DO NOT try the script on them "as is" unless
  47. ECHO    you're positive you know what you're doing!
  48. ECHO 2. Kobo Desktop Edition for PC.
  49. ECHO    World: http://download.kobobooks.com/desktop/kobodesktop/kobosetup.exe
  50. ECHO    Japanese: http://download.kobobooks.com/desktop/RakutenBooks/KoboSetup.exe
  51. ECHO    ^(Tested with 3.2.3.0 of both.^)
  52. ECHO 3. A command-line zip archiver of your choice.
  53. ECHO    ^(Tested with 7-Zip 9.20 from http://www.7-zip.org/^)
  54. ECHO    === You MUST adjust all ZIPCMD calls if using a different zip program!
  55. ECHO 4. SQLite command-line shell.
  56. ECHO    http://www.sqlite.org/download.html
  57. ECHO    ^(Tested with 3.7.17.^)
  58. ECHO 5. OpenSSL command-line.
  59. ECHO    http://gnuwin32.sourceforge.net/packages/openssl.htm
  60. ECHO    ^(Tested with 0.9.8h from GNUWin32 and 1.0.1b from a Perl distro.^)
  61. ECHO 6. Hexdump.
  62. ECHO    http://gnuwin32.sourceforge.net/packages/util-linux-ng.htm
  63. ECHO    ^(Tested with util-linux-ng 2.14.1.^)
  64. ECHO.
  65. PAUSE
  66. CLS
  67. ECHO.
  68. ECHO.
  69. ECHO.
  70. ECHO ^|==============================================================================
  71. ECHO ^|
  72. ECHO ^|                                   WARNING!
  73. ECHO ^|
  74. ECHO ^| If you execute this script, you agree to do so ENTIRELY AT YOUR OWN RISK.
  75. ECHO ^| ABSOLUTELY NO GUARANTEES are given as to the results.
  76. ECHO ^| Input sanity checks are NOT EXHAUSTIVE and DATA LOSS IS POSSIBLE.
  77. ECHO ^|
  78. ECHO ^|==============================================================================
  79. ECHO.
  80. ECHO.
  81. ECHO Comment out the FIRSTRUN section of the script to use it for real.
  82. ECHO.
  83. ECHO.
  84. ECHO Also, feel free to create a more portable and user-friendly version of this.
  85. ECHO I've already spent enough time digging out the information needed to get this
  86. ECHO to work and it "works for me", so I'm not going to do any more work on this.
  87. ECHO.
  88. GOTO :EOF
  89. REM ============================================================================= FIRSTRUN
  90.  
  91.  
  92. SETLOCAL ENABLEEXTENSIONS
  93.  
  94. REM |=======================================
  95. REM |
  96. REM | Check the prerequisites.
  97. REM |
  98. REM |=======================================
  99.  
  100.  
  101. REM ===================================================================== OSCHECK
  102. VER | FIND "Microsoft Windows XP [Version 5.1.2600]" >NUL
  103. IF %ERRORLEVEL%==1 (
  104.     CLS
  105.     ECHO.
  106.     ECHO ^|======================================================================
  107.     ECHO ^|
  108.     ECHO ^| This script has only been tested on Windows XP.
  109.     ECHO ^|
  110.     ECHO ^| To run it on a different Windows version, comment out the OSCHECK
  111.     ECHO ^| section of the script.
  112.     ECHO ^|
  113.     ECHO ^| SOMETHING COULD GO WRONG, better be sure you know what you're doing!
  114.     ECHO ^|
  115.     ECHO ^|======================================================================
  116.     ECHO.
  117.     GOTO :EOF
  118. )
  119. REM ===================================================================== OSCHECK
  120.  
  121. IF [%1] == [] (
  122.     ECHO.
  123.     ECHO ^|======================================================================
  124.     ECHO ^| USAGE: DEKDRM [path]00000000-0000-0000-0000-000000000000[.ext] [...]
  125.     ECHO ^|======================================================================
  126.     ECHO ^| Output file location: [path]00000000-0000-0000-0000-000000000000.epub
  127.     ECHO ^|======================================================================
  128.     ECHO.
  129.     GOTO :EOF
  130. )
  131.  
  132. REM The prefix used for device ID generation.
  133. SET PREFIX=NoCanLook
  134. REM PREFIX is CaSe SeNsItIvE!
  135.  
  136. REM The wording seems to hint that on an actual Kobo device Nickel would use either the
  137. REM device serial number or serial+MAC, something not available on a PC. Pardon me for
  138. REM not finding out for sure, it's a pain to trace code that doesn't get executed.
  139.  
  140. REM The MAC address used for device ID generation.
  141. SET MACADDR=00:00:00:00:00:00
  142. REM MACADDR is CaSe SeNsItIvE, with UPPERCASE hex!
  143. REM Be sure to use colons and not dashes like in ipconfig display.
  144. IF %MACADDR%==00:00:00:00:00:00 (
  145.     ECHO.
  146.     ECHO You need to edit MACADDR in this script with your network card MAC address.
  147.     ECHO Use "ipconfig /all" to see your MAC address^(es^) ^("Physical Address"^).
  148.     ECHO If there is more than one, try them all until you find the one that works.
  149.     GOTO :EOF
  150. )
  151.  
  152. REM Nickel first tries to get a cached MAC from /tmp/.mac-address and then /.mac-address,
  153. REM after which it queries all network interfaces and takes the MAC of the first non-loopback
  154. REM interface it sees.
  155. REM Which means that on the PC it may easily end up with a VPN or VM interface instead of the
  156. REM real network card. So if you uninstalled your VPN, you'd lose access to your DRM-ed
  157. REM kepubs that are on that PC. At least until you can resync/redownload, provided all the
  158. REM books are still available.
  159.  
  160. REM Works under WinXP, adjust for others.
  161. REM Be sure to use double quotes if the the path contains spaces.
  162. SET KOBODB="%USERPROFILE%\Local Settings\Application Data\Kobo\Kobo Desktop Edition\Kobo.sqlite"
  163. IF NOT EXIST %KOBODB% (
  164.     ECHO.
  165.     ECHO Kobo database not found at %KOBODB%.
  166.     ECHO.
  167.     ECHO Find Kobo.sqlite on your computer and edit KOBODB in this script.
  168.     GOTO :EOF
  169. )
  170.  
  171. REM These will most likely need adjusting on your system.
  172. REM If using another archiver, be sure to adjust all ZIPCMD switches below.
  173. SET ZIPCMD="C:\Program Files\7-zip\7z.exe"
  174. SET SQLITECMD=sqlite3.exe
  175. SET OPENSSLCMD=openssl.exe
  176. SET HEXDUMPCMD=hexdump.exe
  177.  
  178. %ZIPCMD% >NUL 2>&1
  179. IF %ERRORLEVEL%==3 GOTO BADZIP
  180. IF %ERRORLEVEL%==9009 GOTO BADZIP
  181. ECHO.
  182. ECHO Using Zip: %ZIPCMD%
  183. %ZIPCMD% | FIND /I "copyright (c)"
  184. GOTO GOODZIP
  185. :BADZIP
  186. ECHO.
  187. ECHO Zip program not found: %ZIPCMD%.
  188. ECHO.
  189. ECHO Check your PATH and/or edit ZIPCMD in this script.
  190. GOTO :EOF
  191. :GOODZIP
  192.  
  193. %SQLITECMD% -version >NUL 2>&1
  194. IF %ERRORLEVEL%==3 GOTO BADSQLITE
  195. IF %ERRORLEVEL%==9009 GOTO BADSQLITE
  196. ECHO.
  197. ECHO Using SQLite: %SQLITECMD%
  198. %SQLITECMD% -version
  199. GOTO GOODSQLITE
  200. :BADSQLITE
  201. ECHO.
  202. ECHO SQLite program not found: %SQLITECMD%.
  203. ECHO.
  204. ECHO Check your PATH and/or edit SQLITECMD in this script.
  205. GOTO :EOF
  206. :GOODSQLITE
  207.  
  208. %OPENSSLCMD% version >NUL 2>&1
  209. IF %ERRORLEVEL%==3 GOTO BADOPENSSL
  210. IF %ERRORLEVEL%==9009 GOTO BADOPENSSL
  211. ECHO.
  212. ECHO Using OpenSSL: %OPENSSLCMD%
  213. %OPENSSLCMD% version 2>NUL
  214. GOTO GOODOPENSSL
  215. :BADOPENSSL
  216. ECHO.
  217. ECHO OpenSSL program not found: %OPENSSLCMD%.
  218. ECHO.
  219. ECHO Check your PATH and/or edit OPENSSLCMD in this script.
  220. GOTO :EOF
  221. :GOODOPENSSL
  222.  
  223. %HEXDUMPCMD% <NUL >NUL 2>&1
  224. IF %ERRORLEVEL%==3 GOTO BADHEXDUMP
  225. IF %ERRORLEVEL%==9009 GOTO BADHEXDUMP
  226. ECHO.
  227. ECHO Using Hexdump: %HEXDUMPCMD%
  228. GOTO GOODHEXDUMP
  229. :BADHEXDUMP
  230. ECHO.
  231. ECHO Hexdump program not found: %HEXDUMPCMD%.
  232. ECHO.
  233. ECHO Check your PATH and/or edit HEXDUMPCMD in this script.
  234. GOTO :EOF
  235. :GOODHEXDUMP
  236.  
  237.  
  238. REM |===========================================
  239. REM |
  240. REM | Calculate the global kepub decryption key.
  241. REM |
  242. REM |===========================================
  243.  
  244. SETLOCAL ENABLEDELAYEDEXPANSION
  245.  
  246. ECHO.
  247. ECHO -------------------------------------------------------------------------------
  248.  
  249. ECHO.
  250. ECHO MAC address: %MACADDR%.
  251. ECHO.
  252. ECHO Hashing "%PREFIX%%MACADDR%" for DeviceID.
  253. REM Calculate the deviceID SHA-256 digest.
  254. REM Really "nice" syntax to set a variable from command output without a temp file...
  255. REM ECHO | SET /P is needed to avoid a newline, as openssl must get only the string.
  256. REM Openssl errors are flushed because it tends to throw useless warnings about
  257. REM a missing config file. Remove the 2> redirects if you need to debug the script.
  258. FOR /F "tokens=* delims=" %%I IN ('ECHO ^| SET /P dummyName^="%PREFIX%%MACADDR%" ^| %OPENSSLCMD% dgst -sha256 2^>NUL') DO (
  259.     SET DEVID=%%I
  260. REM Newer openssl versions include "(stdin)= " in their output but older ones don't,
  261. REM so we need to strip it if it's there.
  262.     SET DEVID=!DEVID:* =!
  263. )
  264. REM DEVID is CaSe SeNsItIvE, with lowercase hex!
  265. ECHO DeviceID: %DEVID%.
  266.  
  267. ECHO.
  268. ECHO Kobo database: %KOBODB%.
  269.  
  270. REM Get the userID from database
  271. FOR /F "usebackq delims=" %%I IN (`%SQLITECMD% %KOBODB% "select UserID from user;"`) DO SET USERID=%%I
  272. REM USERID is CaSe SeNsItIvE, with lowercase hex!
  273. ECHO.
  274. ECHO UserID: %USERID%.
  275.  
  276. ECHO.
  277. ECHO Hashing "%DEVID%%USERID%" ^(DeviceID+UserID^) for kepub key.
  278. REM Calculate the deviceID+userID SHA-256 digest.
  279. REM Really "nice" syntax to set a variable from command output without a temp file...
  280. REM ECHO | SET /P is needed to avoid a newline, as openssl must get only the string.
  281. FOR /F "tokens=* delims=" %%I IN ('ECHO ^| SET /P dummyName^="%DEVID%%USERID%" ^| %OPENSSLCMD% dgst -sha256 2^>NUL') DO (
  282.     SET KEPUBKEY=%%I
  283.    REM Newer openssl versions include "(stdin)= " in their output but older ones don't,
  284.    REM so we need to strip it if it's there.
  285.     SET KEPUBKEY=!KEPUBKEY:* =!
  286.     ECHO Hash: !KEPUBKEY!.
  287.     ECHO                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  288.    REM The actual decryption key is only the tail-end 128 bits of the digest.
  289.     SET KEPUBKEY=!KEPUBKEY:~32,32!
  290. )
  291. REM KEPUBKEY is not case sensitive.
  292. ECHO Kepub key: %KEPUBKEY%.
  293.  
  294. REM Pass KEPUBKEY out.
  295. ENDLOCAL & SET KEPUBKEY=%KEPUBKEY%
  296.  
  297. :PROCESS
  298.  
  299. ECHO.
  300. ECHO -------------------------------------------------------------------------------
  301.  
  302. REM |=============================================================================
  303. REM |
  304. REM | A few sanity checks to make reasonably sure we can work with our input.
  305. REM |
  306. REM |=============================================================================
  307.  
  308. IF NOT EXIST %1 (
  309.     ECHO.
  310.     ECHO File not found: %~f1.
  311.     GOTO :NEXTFILE
  312. )
  313.  
  314. REM Check for folder attribute.
  315. ECHO %~a1 | FIND /I "d" >NUL
  316. IF %ERRORLEVEL%==0 (
  317.     ECHO.
  318.     ECHO %~f1 is a folder, this script only works on files.
  319.     GOTO :NEXTFILE
  320. )
  321.  
  322. ECHO.
  323. ECHO Removing DRM from file %~f1.
  324.  
  325. %ZIPCMD% l -tzip %1 mimetype | FIND /I "mimetype" >NUL
  326. IF %ERRORLEVEL%==1 (
  327.     ECHO.
  328.     ECHO This file does not seem to be an ebook.
  329.     GOTO :NEXTFILE
  330. )
  331.  
  332. %ZIPCMD% l -tzip %1 -r rights.xml | FIND /I "rights.xml" >NUL
  333. IF %ERRORLEVEL%==1 (
  334.     ECHO.
  335.     ECHO This ebook does not seem to have DRM ^(no rights.xml^).
  336.     GOTO :NEXTFILE
  337. )
  338.  
  339. REM |=======================================
  340. REM |
  341. REM | Kepub file DRM removal starts here.
  342. REM |
  343. REM |=======================================
  344.  
  345. ECHO.
  346. ECHO Setting up and unpacking.
  347.  
  348. REM Drive and path of the input file.
  349. SET INFILEDIR=%~dp1
  350. REM Name of the input file.
  351. SET INFILENAME=%~n1
  352.  
  353. SET WORKDIR=%TEMP%\%RANDOM%%RANDOM%%RANDOM%%RANDOM%%RANDOM%
  354. MKDIR %WORKDIR%
  355.  
  356. REM Expand the EPUB archive.
  357. %ZIPCMD% x -tzip -o%WORKDIR% %1 * >NUL
  358.  
  359. PUSHD %WORKDIR%
  360.  
  361. REM Get the encrypted decryption keys for individual encrypted files from Kobo database.
  362. REM Keys in the database are Base64 encoded.
  363. %SQLITECMD% %KOBODB% -separator "," "select elementKey,elementId from content_keys where volumeid = '%INFILENAME%';" > keys.tmp
  364.  
  365. SETLOCAL ENABLEDELAYEDEXPANSION
  366.  
  367. FOR /F "tokens=1,2 delims=," %%I IN (keys.tmp) DO (
  368.    REM Switching to better named variables for clarity.
  369.     SET ENCFILEKEY=%%I
  370.     SET FILENAME=%%J
  371.     ECHO.
  372.     ECHO Decrypting key "!ENCFILEKEY!" for !FILENAME!.
  373.    REM Both the decryption keys and the files are encrypted with AES-128 ECB.
  374.    REM Need to Base64 decode the keys before decrypting them (-a).
  375.    REM For opensll's pleasure, for that to work, the Base64 string must end with a newline.
  376.    REM Use no padding (-nopad) when decrypting the keys.
  377.    REM IV is not really useful here, but older openssl will fail without it.
  378.    REM Decrypting these keys will result in their binary form, so we have
  379.    REM to use a temp file here because piping binary is problematic.
  380.     ECHO !ENCFILEKEY! | %OPENSSLCMD% enc -d -aes-128-ecb -iv 00000000000000000000000000000000 -K %KEPUBKEY% -a -nopad -out bin.tmp 2>NUL
  381.    REM Turn binary keys into hex for command-line usage. Case is unimportant here.
  382.     FOR /F "delims=" %%K IN ('%HEXDUMPCMD% -e "16/1 ""%%02x""" bin.tmp') DO (
  383.         SET DECFILEKEY=%%K
  384.        REM And we decrypt the files with the decrypted keys.
  385.         ECHO Key: !DECFILEKEY!.
  386.         ECHO Decrypting !FILENAME!.
  387.         %OPENSSLCMD% enc -d -aes-128-ecb -iv 00000000000000000000000000000000 -K !DECFILEKEY! -in !FILENAME! -out !FILENAME!.new 2>NUL
  388.         SET NAMEWITHPATH=!FILENAME!
  389.        REM Need to turn slashes into backslashes for Windows commands.
  390.         SET NAMEWITHPATH=!NAMEWITHPATH:/=\!
  391.        REM Strip down to filename only for REN syntax.
  392.         FOR %%N IN ("!NAMEWITHPATH!") DO SET NAMEONLY=%%~nxN
  393.        REM Replace encrypted files with decrypted ones.
  394.         DEL /F /Q !NAMEWITHPATH!
  395.         REN !NAMEWITHPATH!.new !NAMEONLY!
  396.     )
  397. )
  398.  
  399. ENDLOCAL
  400.  
  401. ECHO.
  402. ECHO Repacking and cleaning up.
  403.  
  404. REM Off with the garbage before repacking.
  405. DEL /Q rights.xml
  406. DEL /Q *.tmp
  407.  
  408. REM Store mimetype first and then add the rest compressed.
  409. %ZIPCMD% a -tzip %INFILENAME%.epub mimetype -mx0 >NUL
  410. %ZIPCMD% a -tzip %INFILENAME%.epub * -r -x!mimetype -x!%INFILENAME%.epub >NUL
  411.  
  412. :end
  413.  
  414. POPD
  415.  
  416. REM Put the DRM-free version in the same directory the DRM'ed one is in.
  417. MOVE %WORKDIR%\%INFILENAME%.epub "%INFILEDIR%"
  418.  
  419. REM Clean up.
  420. RMDIR /S /Q %WORKDIR%
  421.  
  422. ECHO.
  423. ECHO DRM-free version is at %INFILEDIR%%INFILENAME%.epub.
  424.  
  425. REM Any more files to process?
  426. :NEXTFILE
  427. SHIFT
  428. IF [%1]==[] GOTO :EOF
  429. GOTO :PROCESS
Add Comment
Please, Sign In to add comment