Skip to content

Instantly share code, notes, and snippets.

@nhanb
Last active March 6, 2018 03:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nhanb/74542c36d3dcc5dde4e90b34437fb523 to your computer and use it in GitHub Desktop.
Save nhanb/74542c36d3dcc5dde4e90b34437fb523 to your computer and use it in GitHub Desktop.
Kissmanga unobfuscated wrapKA() function
// Works with
// https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js
var input = 'mqE5Ec6bMuj1NMBmDOpSx0VBunV1Woj3jJ9/6VAhx6+El9bfvbhuRNIsjbkRWuvXrFTfCgZukx+MAHwkMN5VGolvTK/P24u4BOECXcLudQtgHLD5SKtSKHQeH1cthYMiOP40YKbPD0CtxpIVhCphdMpArArqhVFwdixEO/B+aIQAjHY355p+8AVwWvuSj6qSN79mBQ9ATkzCDvLdi0Y4V9yManh6/gbY/jSVZnvmJqAjgqRNUbTKrpkw90aReGYY';
var iv = CryptoJS.enc.Hex.parse('a5e8e2e9c2721be0a84ad660c472c1f3');
var key = CryptoJS.SHA256("034nsdfns72nasdasd");
var r20 = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Base64.parse(input)
});
var plaintext = CryptoJS.AES.decrypt(r20, key, {
mode: CryptoJS.mode.CBC,
iv: iv,
padding: CryptoJS.pad.Pkcs7
});
var result = plaintext.toString(CryptoJS.enc.Utf8);
console.log(result)
# Python port
from Crypto.Hash import SHA256
from Crypto.Cipher import AES
from base64 import b64decode
input = 'mqE5Ec6bMuj1NMBmDOpSx0VBunV1Woj3jJ9/6VAhx6+El9bfvbhuRNIsjbkRWuvXrFTfCgZukx+MAHwkMN5VGolvTK/P24u4BOECXcLudQtgHLD5SKtSKHQeH1cthYMiOP40YKbPD0CtxpIVhCphdMpArArqhVFwdixEO/B+aIQAjHY355p+8AVwWvuSj6qSN79mBQ9ATkzCDvLdi0Y4V9yManh6/gbY/jSVZnvmJqAjgqRNUbTKrpkw90aReGYY'
iv = 'a5e8e2e9c2721be0a84ad660c472c1f3'.decode('hex')
sha = SHA256.new()
sha.update('034nsdfns72nasdasd')
key = sha.digest()
encoded = b64decode(input)
dec = AES.new(key=key, mode=AES.MODE_CBC, IV=iv)
result = dec.decrypt(encoded)
# unpad
result = result[:-ord(result[-1])]
print(result)
@nhanb
Copy link
Author

nhanb commented Mar 27, 2017

Note that key can vary between sessions so always look for a separate <script> tag that looks something like this:

<script type="text/javascript">
  var _0x7909 = ["\x30\x33\x34\x6E\x73\x64\x66\x6E\x73\x37\x32\x6E\x61\x73\x64\x61\x73\x64"]; chko = _0x7909[0]; key = CryptoJS.SHA256(chko)
</script>

Just parse the sole element inside the array and unescape it with .decode('string_escape') to get the new key so you can feed into sha.update().

@isthelte
Copy link

Thanks for the gist. This saved me an entire evening of hair-pulling trying to figure out how they did it.

Also, as an update, at the time when this comment is written, Kissmanga has changed where the WrapKA() function is defined. It no longer resides directly on the HTML file, but was moved to http://kissmanga.com/Scripts/lo.js. This one seems independent to sessions, since I managed to get the same value of chko and key on 2 different windows of the same browser, one is normal Chrome window and the other one in Chrome in Incognito mode. Thus, I speculate that it is possible to retrieve all the necessary variables for WrapKA() only once when your app starts up, then reuse it across all manga pages fetching attempts.

@cooperspencer
Copy link

May I ask you what python version you are using for this?
I run into troubles at
iv = 'a5e8e2e9c2721be0a84ad660c472c1f3'.decode('hex')

Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'str' object has no attribute 'decode'

@nhanb
Copy link
Author

nhanb commented Mar 6, 2018

@cooperspencer Whoops sorry I missed the notification for your comment somehow. The gist was written for python2 since my project ran on Google App Engine which didn't support python3 at the time. FWIW there's a python3 implementation here: nhanb/fundoshi@b367807 . Not sure if it's working anymore though since I haven't touched the code for months.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment