catsital / pyccoma

Scrape and download from Piccoma/ピッコマ (France/Japan).
Apache License 2.0
20 stars 2 forks source link

Output images are not correctly unscrambled #2

Closed mekozoko closed 8 months ago

mekozoko commented 9 months ago

Perhaps the unscramble algorithm was updated.

catsital commented 8 months ago

Hi! Apologies for the late response. I'm investigating it now. Seems like they finally implemented two-pass encryption on their keys (and it's in assembly :/). Will keep you posted! Thanks for reporting.

mekozoko commented 8 months ago

Thx for the reply! Seems like the new algorithms is difficult to crack, so I wonder if this discussion could help you.

TehUncleDolan commented 8 months ago

So, over there they fixed it using my crafted WASM.

Since your script is in Python, it may not be convenient to use so here is a Python version of the infamous "dd" function:

import base64
import marshal

magic = '''
4wAAAAAAAAAAAAAAAAEAAAAAAAAA8wwAAACXAGQAhABaAGQBUwApAmMBAAAAAAAAAAAAAAAHAAAAAwA
AAPMCAgAAlwB0AQAAAAAAAAAAAACmAAAAqwAAAAAAAAAAAH0BdAMAAAAAAAAAAAAAdAUAAAAAAAAAAA
AAfABkAaYCAACrAgAAAAAAAAAApgEAAKsBAAAAAAAAAABEAF3EXAIAAH0CfQN8AmQCawAAAAAAcg98A
2QDZAR8A2QEegYAAHoFAAB6CgAAegAAAH0DbpVkBHwCYwJ4AmsAAAAAAHIGZAVrAAAAAABzCG4BAQB8
AmQGawIAAAAAcgFuf3wCZAdrAAAAAAByD3wDZANkBHwDZAR6BgAAegUAAHoKAAB6AAAAfQNuamQIfAJ
jAngCawAAAAAAcgZkCWsAAAAAAHMIbgEBAHwCZAprAgAAAAByD3wDZANkBHwDZAR6BgAAegUAAHoKAA
B6AAAAfQNuRnwCdAcAAAAAAAAAAAAAfABkAGQLhQIZAAAAAAAAAAAApgEAAKsBAAAAAAAAAABrAgAAA
ABzG3wCdAcAAAAAAAAAAAAAfABkAGQMhQIZAAAAAAAAAAAApgEAAKsBAAAAAAAAAABrAgAAAAByD3wD
ZANkBHwDZAR6BgAAegUAAHoKAAB6AAAAfQNuAQkAfAGgBAAAAAAAAAAAAAAAAAAAAAAAAAAAfAOmAQA
AqwEAAAAAAAAAAAEAjMV0CwAAAAAAAAAAAAB8AWQBpgIAAKsCAAAAAAAAAABTACkNTnoFdXRmLTjpAw
AAAOkBAAAA6QIAAADpBgAAAOkIAAAA6QoAAADpDAAAAOkPAAAA6RAAAADp/////+n+////KQbaCWJ5d
GVhcnJhedoJZW51bWVyYXRl2gVieXRlc9oDbGVu2gZhcHBlbmTaA3N0cikE2gpJSUlsbElJbGxs2glJ
bElsSWxsbGzaEElJSUlsSUlsbGxsbGxJbEnaDklJbElsbGxJSUlsbGxJcwQAAAAgICAg+gg8c3RyaW5
nPtoCZGRyGQAAAAIAAABzcgEAAIAA3RAZkQuUC4BJ3Sw1tWW4SsgH0TZQ1DZQ0SxR1CxR8AANBSnwAA
0FKdEIKNAIGJgu2AsbmGHSCx/QCx/YHSuocbAxuA7IEdE4StEzS9EvS9EdTIhOiE7YDQ7QESHQDSXQD
SXSDSXQDSWgQdINJdANJdANJdANJdApObhU0ilB0ClB2AwQ2A0doALSDSLQDSLYHSuocbAxuA7IEdE4
StEzS9EvS9EdTIhOiE7YDhHQFSXQDS/QDS/SDS/QDS+oFdINL9ANL9ANL9ANL9AzQ8B00jNL0DNL2B0
rqHGwMbgOyBHROErRM0vRL0vRHUyITohO2A0dpROgWrADsBKwA6Rf0SE11CE10g010A010DlJzVPQUV
vQXF/QXV/QXF/UUWDRTWHUTWHSOWHQOWHYHSuocbAxuA7IEdE4StEzS9EvS9EdTIhOiE7gDBDYCBHXC
BjSCBiYHtEIKNQIKNAIKNAIKN0LDoh5mCfRCyLUCyLQBCLzAAAAAE4pAXIZAAAAqQByGgAAAHIYAAAA
+gg8bW9kdWxlPnIcAAAAAQAAAHMeAAAA8AMBAQHwBBABI/AAEAEj8AAQASPwABABI/AAEAEjchoAAAA=
'''

# Import the dd function in the current namespace.
exec(marshal.loads(base64.b64decode(magic)))

# Now the `dd` function is usable.
print(dd('TBSLV030DAZSA1PQ5I0CDC'))

It should be called on the seed before passing it to the scrambling algorithm, e.g.:

 Canvas(img.raw, (50, 50), dd(seed))

I guess...

catsital commented 8 months ago

Cool, thanks! Works like a charm.

SnifferNandez commented 1 month ago

This could be used instead of the magic string:

def dd(input_string):
    result_bytearray = bytearray()
    for index, byte in enumerate(bytes(input_string, 'utf-8')):
        if index < 3:
            byte = byte + (1 - 2 * (byte % 2))
        elif 2 < index < 6 or index == 8:
            pass
        elif index < 10:
            byte = byte + (1 - 2 * (byte % 2))
        elif 12 < index < 15 or index == 16:
            byte = byte + (1 - 2 * (byte % 2))
        elif index == len(input_string[:-1]) or index == len(input_string[:-2]):
            byte = byte + (1 - 2 * (byte % 2))
        else:
            pass
        result_bytearray.append(byte)
    return str(result_bytearray, 'utf-8')
catsital commented 2 weeks ago

This could be used instead of the magic string:

def dd(input_string):
    result_bytearray = bytearray()
    for index, byte in enumerate(bytes(input_string, 'utf-8')):
        if index < 3:
            byte = byte + (1 - 2 * (byte % 2))
        elif 2 < index < 6 or index == 8:
            pass
        elif index < 10:
            byte = byte + (1 - 2 * (byte % 2))
        elif 12 < index < 15 or index == 16:
            byte = byte + (1 - 2 * (byte % 2))
        elif index == len(input_string[:-1]) or index == len(input_string[:-2]):
            byte = byte + (1 - 2 * (byte % 2))
        else:
            pass
        result_bytearray.append(byte)
    return str(result_bytearray, 'utf-8')

Thank you for the suggestion, will apply this in the newest release.