HSP의 부정행위 대책은 다양하다. - 데이터 저장 편-

8813 단어 싸구려 대책HSP
HSP의 부정행위 대책은 다양하다. - 데이터 저장 편-
이 기사는 HSP3의 윈도를 이용해 게임에 대한 간단한 부정행위 대책을 설명할 것이다.지난번에 썼어요기억 해커 편.
개요
운영 환경
테스트에 사용된 실행 환경의 중요한 부분을 미리 적으십시오.
OS : Windows 10(64bit) on VMware
HSP : v3.4 (32bit)
대상이 된 팀
게임의 부정행위(부정행위)도 여러 종류가 있다.이번에는 게임의 저장 데이터 등을 놓고 게임이 끝난 뒤 남은 데이터를 조작한 데이터 파일 해커의 부정행위 대책 방법을 고민했다.실제 부정행위 대책은 반해석 대책과 메모리 해커에 대한 대책 등이 필요하므로 이 기사의 내용만 만족시키지 마세요.
목표
이번에는 암호화된 저장 데이터를 조작하기 위해 HSP3로 부정행위 대책 모듈을 만들었다.이 모듈은 아래의 부정행위를 방지할 수 있다.
  • 저장된 데이터의 변경
  • 단, 아래의 부정행위는 지지하지 않는다.
  • 게임 실행 중인 메모리 변조 참조->기억 해커 편
  • 타인의 보존 데이터의 복사본
  • 소스 코드 노출을 전제로 하는 부정행위
  • 소스 코드
    갑작스럽지만 최종 소스 코드부터 쓰세요.
    mod_protect.hsp
    #module
        // ここは自由に変更してください
        #define PROTECT_SIGNATURE   "HSP3" // 必ず4バイト
        #define PROTECT_KEY         "53cur3_k3y!" // XOR鍵
        #define PROTECT_SEED        0xFEE1DEAD // ハッシュシード
    
        /*--------------------------------------------------
            暗号化されたセーブデータを読み込む
        --------------------------------------------------*/
        #define global dload(%1, %2, %3, %4=0) dload_ %1, %2, %3, %4
        #deffunc dload_ str fname, str dname_, var data, int flag,\
                        local buf, local size, local hash_dname, local size_data, local chksum, local ret
            sdim buf, 64
            sdim dname, 64 : dname = dname_
            // ファイルを確認
            exist fname
            size = strsize
            if size < 0 {
                bsave fname, buf, 0
                return -1
            }
            // シグネチャを確認
            bload fname, buf, 4, 0
            if buf != PROTECT_SIGNATURE : return -1
            // 特定のデータを探索
            offset = 4
            ret = -1
            repeat -1, 1
                if offset >= size: break
                bload fname, buf, 12, offset
                dxor buf, 12 // 復号化
                hash_dname = lpeek(buf, 0)
                size_data = lpeek(buf, 4)
                chksum = lpeek(buf, 8)
                // 読みたいデータが来た
                if hash_dname == dhash(dname, strlen(dname)) {
                    offset += 12
                    sdim buf, size_data
                    bload fname, buf, size_data, offset
                    dxor buf, size_data // 復号化
                    if chksum != dhash(buf, size_data) {
                        buf = 0
                    }
                    if flag == 1: sdim data, size_data
                    repeat size_data
                        poke data, cnt, peek(buf, cnt)
                    loop
                    ret = 0
                    break
                }
                offset += 12 + size_data
            loop
        return ret
    
        /*--------------------------------------------------
            データを暗号化して保存する
        --------------------------------------------------*/
        #deffunc dsave str fname, str dname_, var data, int size_data,\
                       local size_data_, local size_fill, local size, local ret
            sdim buf, 64
            sdim dname, 64 : dname = dname_
            // ファイルを確認
            exist fname
            size = strsize
            if size < 0 {
                buf = PROTECT_SIGNATURE
                bsave fname, buf, 4
                size = 4
            }
            // シグネチャを確認
            bload fname, buf, 4, 0
            if buf != PROTECT_SIGNATURE : return -1
            // 特定のデータを探索
            offset = 4
            ret = -1
            repeat -1, 1
                if offset >= size: break
                bload fname, buf, 12, offset
                dxor buf, 12 // 復号化
                hash_dname = lpeek(buf, 0)
                size_data_ = lpeek(buf, 4)
                chksum = lpeek(buf, 8)
                // 書きたいデータセクションがあった
                if hash_dname == dhash(dname, strlen(dname)) {
                    // 情報を変更する
                    lpoke buf, 0, dhash(dname, strlen(dname))
                    lpoke buf, 4, size_data
                    lpoke buf, 8, dhash(data, size_data)
                    dxor buf, 12 // 暗号化
                    bsave fname, buf, 12, offset
                    // 以降のデータをずらす
                    offset += 12
                    size_fill = size - offset - size_data_
                    sdim buf, size_fill
                    bload fname, buf, size_fill, offset + size_data_
                    bsave fname, buf, size_fill, offset + size_data
                    // データを書き込み
                    dxor data, size_data // 暗号化
                    bsave fname, data, size_data, offset
                    // 短くなった場合は余りを削除
                    if size_data - size_data_ < 0 {
                        sdim buf, size - (size_data_ - size_data)
                        bload fname, buf, size - (size_data_ - size_data)
                        bsave fname, buf, size - (size_data_ - size_data)
                    }
                    ret = 0
                    break
                }
                offset += 12 + size_data_
            loop
            // 新規データの書き込み
            if ret == -1 {
                offset = size
                sdim buf, 12
                lpoke buf, 0, dhash(dname, strlen(dname))
                lpoke buf, 4, size_data
                lpoke buf, 8, dhash(data, size_data)
                dxor buf, 12 // 暗号化
                bsave fname, buf, 12, offset
                offset += 12
                sdim buf, size_data
                memcpy buf, data, size_data, 0, 0
                dxor buf, size_data // 暗号化
                bsave fname, buf, size_data, offset
                ret = 0
            }
        return ret
    
        /*--------------------------------------------------
            XOR
        --------------------------------------------------*/
        #deffunc dxor var data, int size, local key, local c, local len
            len = strlen(PROTECT_KEY)
            if len == 0: return
            sdim key, len
            key = PROTECT_KEY
            repeat size
                c = peek(data, cnt)
                c ^= peek(key, cnt \ len)
                poke data, cnt, c
            loop
        return
    
        /*--------------------------------------------------
            ハッシュ関数
        --------------------------------------------------*/
        #defcfunc dhash var data, int size, local hash
            hash = PROTECT_SEED
            repeat size
                hash = ((hash << 5) + hash) + peek(data, cnt)
            loop
        return hash
    #global
    
    이 모듈은 다음과 같습니다.
    example.hsp
    #include "mod_protect.hsp"
    
    // 初期書き込み
    data = "Hot Soup Processor"
    score = 3141
    msg = "こんにちは世界"
    dsave "save.dat", "mydata", data, strlen(data)
    dsave "save.dat", "score", score, 4
    dsave "save.dat", "test", msg, strlen(msg)
    
    // データ更新
    data = "HSP"
    score = 2718
    hp = 345.67
    msg = "こんにちは世界!"
    dsave "save.dat", "mydata", data, strlen(data)
    dsave "save.dat", "score", score, 4
    dsave "save.dat", "test", msg, strlen(msg)
    dsave "save.dat", "体力", hp, 8   // データを追加
    
    // 読み込み
    data = ""
    score = 0
    msg = ""
    hp = 0.0
    dload "save.dat", "mydata", data, 1
    dload "save.dat", "score", score
    dload "save.dat", "test", msg, 1
    dload "save.dat", "体力", hp
    
    mes data
    mes score
    mes msg
    mes hp
    
    stop
    
    함수 설명dsave "filename", "tag", data, data_sizefilename: 데이터를 저장한 파일 이름
    로드 시 지정된 값에 사용되는 레이블
    데이터:저장할 변수
    data_크기: 데이터 크기(byte)dload "filename", "tag", data, flagfilename: 데이터를 저장한 파일 이름
    저장할 때 지정한 태그
    데이터:대상 변수
    flag: 데이터를 저장한 크기에 따라 데이터를 자동으로 초기화할 때 1 지정
    저장 데이터의 구조
    PROPTECT로 데이터 저장SIGNATURE에서 지정한 4바이트 문자열을 서명으로 시작합니다.이후 기본적으로 다음 네 개의 데이터를 연속으로 기입한다.
  • 데이터 이름의 하치 (4[byte])
  • 데이터의 크기 n(4[byte])
  • 데이터의 검증 및 (4[byte])
  • 데이터(n[byte])
  • 데이터 이름의 해시 값 예를 들어 변수 score를'score'로 저장할 때 이 해시 값을 탭으로 저장합니다.다음에 불러오거나 덮어쓸 때 같은 표시가 있는 부분을 찾으십시오.데이터의 크기는 바로 데이터의 크기다.데이터 체크섬 은 다음 데이터에 대한 체크섬입니다. 읽을 때 체크섬이 일치하지 않으면 불러오지 않습니다.암호화에 이 검사를 더하면 사실상 특수한 상황에서 이번에 저장된 데이터가 복호화될 수 있다.(데이터 크기의 0x00을 이용한 암호화 해석)
    이번 데이터 이름의 해시 값과 데이터 검사는 사용하는 함수와 같다.또한 최초 12바이트 및 데이터 바디는 각각 PROPTECT -KEY를 열쇠로 하는 XOR 비밀번호입니다.PROPTECT KEY가 비어 있으면 암호화하지 않고 저장할 수 있습니다.
    열쇠를 1바이트로 XOR하는 예가 자주 보이지만 쉽게 망가지기 때문에 키 길이를 좀 늘려 주세요.
    결실
    우선 암호화되지 않은 example입니다.hsp의 저장 데이터입니다.문자열 같은 것은 원형이고 정수와 실수도 눈으로 보면 이해하기 어렵지만 그렇게 적혀 있다.

    그리고 적당한 키로 암호화된 example입니다.hsp의 저장 데이터입니다.서명("HSP3")을 제외하고는 모두 완전히 암호화되었습니다.

    총결산
  • 는 정수, 문자열, 소수 유형에 대응하여 예정보다 실용적인 모듈이 되었다.
  • 적절히 만들어진 산열 함수여서 충돌하지 않을까 우려된다.
  • 파일이 지정한 오프셋 이후의 명령을 삭제하지 않았습니까?
  • 좋은 웹페이지 즐겨찾기