kone
소미소프트

소미소프트

RJ01103194 정욕의 고식 마사지점 에셋 파일 교체

02/11/2026, 13:19:31
번역
32155 views · 137 likes

원글: https://kone.gg/s/somisoft/c0eHnpymh5Piv6bNUVGjSb


해당 작업 해주신 분이, 이미지를 asset 파일을 수정하는게 아니라 BepInEx의 Texture_Replacer 플러그인을 이용해서 이미지 교체를 하다보니 이미지를 새롭게 로딩하는 구간에서 렉이 너무 심해서 참고 플레이하다가 답답해져서 작업함.


원글 작성자가 작업한 번역 파일을 asset에 적용한 파일임.

원글 작성자에게 허락을 받지 않고 그냥 배포하는거라(이미지 데이터 자체가 원글 작성자가 만든 것이기 때문에), 문제시 글자삭.



링크: aHR0cHM6Ly9raW8uYWMvYy9kRFF6a2R3UDVGS1lUOGlSaHl0aldi

비번: 국룰

기간: 한달인데 원글 기간이 3일 남았으니 빨리 받으시길(8차 올라온다는데 언제 올라올지 몰루)


사용법

  1. 위의 원글에 있는 게임 다운로드해서 압축 풀기

  2. 'BeplnEX\plugins'에 있는 'Texture_Replacer_BE_il2cpp.dll'와 'ModImages'를 제거.

  3. 첨부한 파일 압축 풀어서 나오는 'DefaultPackage'와 'DLC' 폴더를 'MassageShop_Data\StreamingAssets'에 있는 파일에 덮어쓰기.


일단 내가 1회차 플레이할 동안에는 문제가 없었음.


아래에 작업한 방법 및 관련 파이썬 코드 작성하니(코드는 gemini가 거의 만들어줬지만), 혹시 배포한 파일 중에 뭔가 제대로 적용 안되서 문제가 생기는 일이 있는 경우 해당 방법으로 수정해서 재배포하셔도 됨.

원글 작성자의 8차 수정 패치가 올라와도 대응 작업은 제가 안 할 예정.






작업자를 위한 asset 교체 작업 방법 설명

일단 bundle파일이 암호화가 되어있기 때문에, 그냥 해당 bundle을 가지고 그대로 압축해제를 하려고 하면 문제가 발생할거임.


무작위로 파일 하나를 예로 들자면

이런 식으로 파일이 되어있음.

일반적으로 유니티 번들 파일은 utf-8 인코딩으로 헤더 부분에 UnityFS와 해당 asset의 버전 정보로 시작하는데, 이 게임의 asset 파일은 암호화를 해놔서 UnityFS라는 글자가 보이지 않음. 대신 '0x65'라는 문자열이 엄청 나오는 것을 확인할 수 있는데, 이게 이 게임 암호화의 힌트임.


이 게임은 XOR 암호화를 사용해서, 원본 데이터에 어떤 키 값을 가지고 바이트 단위 XOR로 파일을 암호화함.

그래서 이 키 값만 알 수 있다면 다시 복호화할 수 있음.


이 게임은 XOR 암호화를 할 때, asset bundle의 파일명을 기반으로 어떤 해쉬값을 계산해서 "unity_asset_bundle_android"의 문자열 중 한 문자값에 매칭을 시킨 다음, 해당 문자값의 ASCII 코드 값에 해당하는 값을 XOR 암호키로 사용함.

제일 좋은건 이 해쉬 알고리즘을 파악하는거겠지만, 굳이 그렇게 하지 않더라도 암호화/복호화가 가능함.(해쉬 알고리즘은 dll 파일을 리버스 엔지니어링 해야하기 때문에 귀찮음)

"u, n, i, t, y, _, a, s, e, b, d, l, r, o" 이 암호키를 기반으로 XOR 복호화를 이것저것 브루트포스로 실행한 다음에, 헤더에서 UnityFS라는 문자열로 복호화를 하는 암호키를 사용하면 되는거임. (아니면 저기 0x65가 반복해서 등장하는 것을 바탕으로 0x65로 암호화되었다는 것을 알 수도 있음)


올바르게 복호화 된 bundle 파일의 예시


아무튼 그래서 asset을 수정하려면

  1. asset 파일을 XOR 복호화

  2. 복호화된 파일은 이제 정규 unity bundle 파일이기 때문에 AssetStudio 및 UABEA를 사용할 수 있음.

  3. UABEA를 통해서 이미지 texture 교체 후 저장, 그리고 LZ4로 bundle 파일 압축하여 다시 저장.

  4. 수정된 unity bundle 파일을 다시 XOR로 암호화

라는 과정을 거치면 됨.


import osimport jsonimport shutil
# =========================================================# [설정] 작업할 폴더 경로를 여기에 입력하세요.# 예: r"C:\Users\Game\Bundles"TARGET_FOLDER = r"D:\Downloads\RJ01103194_MassageShop_ver_1.9.7_DLC_UNCENSORED_7차수정판\MassageShop_Data\StreamingAssets\Workspace"
# 키를 저장할 데이터베이스 파일명KEY_DB_FILE = "key_database.json"# =========================================================
UNITY_MAGIC = 0x55  # 'U'
def load_key_db():    """저장된 키 데이터베이스를 불러옵니다."""    db_path = os.path.join(TARGET_FOLDER, KEY_DB_FILE)    if os.path.exists(db_path):        with open(db_path, 'r', encoding='utf-8') as f:            return json.load(f)    return {}
def save_key_db(db_data):    """키 데이터베이스를 JSON 파일로 저장합니다."""    db_path = os.path.join(TARGET_FOLDER, KEY_DB_FILE)    with open(db_path, 'w', encoding='utf-8') as f:        json.dump(db_data, f, indent=4)    print(f"💾 키 데이터베이스가 저장되었습니다: {db_path}")
def backup_file(file_path, backup_dir):    """파일을 백업 폴더로 복사합니다."""    if not os.path.exists(backup_dir):        os.makedirs(backup_dir)    filename = os.path.basename(file_path)    shutil.copy2(file_path, os.path.join(backup_dir, filename))
def process_decrypt():    """복호화 모드: 키를 추출/저장하고 복호화 수행"""    print(f"\n🔓 [복호화 모드] 시작: {TARGET_FOLDER}")       key_db = load_key_db()    backup_dir = os.path.join(TARGET_FOLDER, "backup_original")       files = [f for f in os.listdir(TARGET_FOLDER) if os.path.isfile(os.path.join(TARGET_FOLDER, f)) and not f.endswith('.json')]    count = 0
    for filename in files:        filepath = os.path.join(TARGET_FOLDER, filename)
        with open(filepath, 'rb') as f:            data = bytearray(f.read())
        # 이미 복호화된 파일인지 확인 (UnityFS로 시작하면 건너뜀)        if data[:7] == b'UnityFS':            print(f"⚠️  [Skip] 이미 복호화됨: {filename}")            continue
        # 키 추출 로직: 첫 바이트 ^ 0x55        detected_key = data[0] ^ UNITY_MAGIC               # 키 기록        key_db[filename] = detected_key
        # 백업 수행        backup_file(filepath, backup_dir)
        # 복호화 (전체 XOR)        decrypted_data = bytearray([b ^ detected_key for b in data])
        # 검증        if decrypted_data[:7] == b'UnityFS':            with open(filepath, 'wb') as f:                f.write(decrypted_data)            print(f"✅ [Success] 복호화 & 키 저장 (0x{detected_key:02X}): {filename}")            count += 1        else:            print(f"❌ [Fail] 복호화 실패 (헤더 불일치): {filename}")
    # 변경된 키 DB 저장    save_key_db(key_db)    print(f"\n✨ 총 {count}개 파일 복호화 완료. 원본은 'backup_original' 폴더에 있습니다.")
def process_encrypt():    """암호화 모드: 저장된 키를 불러와서 암호화 수행"""    print(f"\n🔒 [암호화 모드] 시작: {TARGET_FOLDER}")       key_db = load_key_db()    if not key_db:        print("❌ 오류: 'key_database.json' 파일이 없습니다. 먼저 복호화를 진행하여 키를 생성하세요.")        return
    files = [f for f in os.listdir(TARGET_FOLDER) if os.path.isfile(os.path.join(TARGET_FOLDER, f)) and not f.endswith('.json')]    count = 0
    for filename in files:        filepath = os.path.join(TARGET_FOLDER, filename)               # DB에서 키 조회        if filename not in key_db:            print(f"⚠️  [Skip] 키 정보 없음 (DB에 없음): {filename}")            continue               xor_key = key_db[filename]
        with open(filepath, 'rb') as f:            data = bytearray(f.read())
        # 안전장치: 이미 암호화된 파일인지 확인 (UnityFS가 아니면 암호화된 것으로 간주하고 경고)        if data[:7] != b'UnityFS':            print(f"⚠️  [Skip] 이미 암호화된 것 같음 (UnityFS 헤더 없음): {filename}")            continue
        # 암호화 (전체 XOR)        encrypted_data = bytearray([b ^ xor_key for b in data])
        # 덮어쓰기        with open(filepath, 'wb') as f:            f.write(encrypted_data)               print(f"✅ [Success] 암호화 완료 (Key: 0x{xor_key:02X}): {filename}")        count += 1
    print(f"\n✨ 총 {count}개 파일 암호화(리팩) 완료.")
def main():    print("=== Unity Bundle XOR Tool ===")    print(f"작업 폴더: {TARGET_FOLDER}")    print("1. 복호화 (Decrypt) -> 키 추출 및 저장")    print("2. 암호화 (Encrypt) -> 저장된 키 사용")       choice = input("\n작업을 선택하세요 (1 또는 2): ").strip()
    if choice == '1':        process_decrypt()    elif choice == '2':        process_encrypt()    else:        print("잘못된 선택입니다.")
if __name__ == "__main__":    if os.path.exists(TARGET_FOLDER):        main()    else:        print(f"❌ 오류: 폴더를 찾을 수 없습니다. 경로를 확인하세요: {TARGET_FOLDER}")




위의 파이썬 코드를 사용하면 복호화(복호화 할 때 json 파일로 복호화 키를 저장함. 나중에 다시 암호화 할 때 복호화 키를 다시 사용해야함) 및 암호화를 수행할 수 있음. (그냥 넣으려니까 사이트가 이상해서 코드 자꾸 이상해지는데 아 몰라 대충 복사해서 알아서 수정해 쓰세요...)




137
28 comments
Sign in to comment
02/11
02/11
난 죽음을 택하겠다
02/11
02/11
코드 감사
02/11
02/11
무슨 말인지 모르겠지만 좋은 말이네요!
에셋 교체하면 뭐가 좋은건가용
02/11
로딩이빨라진데요!
02/11
교체용 파일인거 까지 이해했습니다
02/11
02/11
https://kone.gg/s/somisoft/d69SiMk3_SHVPXneJyk5Sb 이거 쓰면 본문에 코드 그대로 넣어둘 수 있음
02/11 Edited 02/12
오오...대협! 정욕 올리면서 이 해결법을 찾아줄 사람을 애타게 찾았었는데 드디어 나왔네! 8차는 애셋 교체해서 올리겠음 압도적 감사!
02/11 Edited 02/11
번역 보조 프로그램 디버깅 한다고 8차 작업 계속 미루고 있었는데 이런 잭팟이... 님들 이건 앞으로의 유니티 손번역을 위한 주춧돌이다 이말입니다
02/12 Edited 02/12
공유해준 파이썬 코드 GUI 버전으로 만들어 봤어. 코드랑 exe 같이 넣어놨음. aHR0cHM6Ly9raW8uYWMvYy9iN1RQRFNlYmk1TnlYMGl5UG90NVdi 기간무한 국룰
유니티쪽도 좀 툴 한가지로 복호화 암호화 시키고 다 할수 있었으면 좋겠음
02/12
근데 이게 복호화 방법이라는게 너무 워낙 다양하다보니 사실 대부분 인디게임은 그냥 복호화 안 하고 유니티 기본 복호화만 적용하다보니 쉽게 뚫리긴 한다만...
이걸 복호화하네
02/12
Sign in to comment
[자체한글] 에로 검열관 DX 스팀판 ver.4.0.13 (25.09.23)
번역
미스터장
09/24/25 32968 253
[손번역] 돌격! 특수잠입 쿠노이치
번역
미스터장
09/23/25 57721 436
슬레이 더 스파이어 The Life Master ai번역
번역
UnHappy
09/23/25 45700 98
[청아][구매번역][RJ01126154] 다테스지Q
번역
이스라엘
09/23/25 28650 120
[구매보급][VX ACE][RJ158026] 세이크리드 프린세스 성왕녀 이야기 v1.02
번역
이스라엘
09/23/25 19301 91
[구매보급][이미지][RJ01391212] 선생님은 갱생시키고 싶다. (先生は更生させたい)
번역
이스라엘
09/23/25 40895 123
[요청][Renpy][Deeple 기번]Takeis Journey 0.32[Feat. Zenpy]
번역
라미
09/23/25 27722 130
[AI번역](충간) 유충배설 1.0
번역
훌룡한미드라이너
09/23/25 21469 74
[AI번역] 제미니 유니티겜 14개 추가 알림
번역
미스터장
09/23/25 21646 105
[청아/면간][버전업/기계번역] JK 츠루페타 소녀와 연속 절정 개발 일기 v1.04
번역
Ghost
09/22/25 54989 283
[인외종/오픈월드/생존] [버전업/한글지원/노모] 열대 괴물 소녀들 v1.4.1
번역
Ghost
09/22/25 20840 99
[NTR/기번/AI] 사모님은 자위녀 - 헤픈기록담-
번역
낫벧
09/22/25 25169 118
미인계 퀘스트 서큐버스의 유혹과 농락
번역
킬러튠큐
09/22/25 18344 97
[자체한글] 에로 검열관 DX 스팀판 ver.4.0.11 (25.09.21)
번역
미스터장
09/21/25 42077 254
서큐버스 테일 0.77
번역
킬러튠큐
09/21/25 19935 76
[ai번역] 세리카 마기아 ~소꿉친구인 츤데레 숨은 마조 성향의 마법사가 전용 오나홀 NTR당하는 왕도 어덜트샵 편~ v1.07 (번역 파일만)
번역
sno
09/21/25 30535 115
[토트/면간][기번/임시/수정1] 녹화(REC) _ v0.3.3.1
번역
kts
09/21/25 24837 124
[한글패치]TUNNEL ESCAPE FE v0.21.0a
번역
아르
09/21/25 69600 213
[AI번역] 유니티 제미니 번역겜 6개 버전업 및 추가 알림
번역
미스터장
09/20/25 29719 107
[자체기번] Kingdom of Velvet Сhains ver.1.0
번역
미스터장
09/20/25 20969 120
[자체기번] Again!? The Sheriff’s Kinky Justice ver.1.03
번역
미스터장
09/20/25 28238 129
[자체한글] Fallen Brand New World 스팀판 ver.1.05a (25.09.19)
번역
미스터장
09/20/25 39813 309
[자체한글] 에로 검열관 DX 스팀판 ver.4.09 (25.09.20)
번역
미스터장
09/20/25 36125 297
소생하는 퇴마무녀 노모자이크 패치
번역
stargaze
09/20/25 29381 139
[버전업]Cursed Armor v3.01
번역
아르
09/19/25 31894 99
두근두근! 성감 마사지 1.05
번역
아르
09/19/25 75589 502
[RJ01187343] 레이디 나이트 퀘스트 '노모패치'
번역
개구리
09/19/25 29723 113
[타이틀 번역 + 에로스테 노모] 달인 퇴마사는 촉수 요마 따위에 굴복하지 않는다
번역
나나바
09/19/25 71490 261
[버전업/한글지원/노모/스팀] 행복섬 판타지 v1.06
번역
Ghost
09/19/25 34719 196
[여주/3D/클리커] [한글지원/노모/스팀] My Witch Wants Elixirs! v1.0
번역
Ghost
09/19/25 31177 93