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_size
filename: 데이터를 저장한 파일 이름로드 시 지정된 값에 사용되는 레이블
데이터:저장할 변수
data_크기: 데이터 크기(byte)
dload "filename", "tag", data, flag
filename: 데이터를 저장한 파일 이름저장할 때 지정한 태그
데이터:대상 변수
flag: 데이터를 저장한 크기에 따라 데이터를 자동으로 초기화할 때 1 지정
저장 데이터의 구조
PROPTECT로 데이터 저장SIGNATURE에서 지정한 4바이트 문자열을 서명으로 시작합니다.이후 기본적으로 다음 네 개의 데이터를 연속으로 기입한다.
이번 데이터 이름의 해시 값과 데이터 검사는 사용하는 함수와 같다.또한 최초 12바이트 및 데이터 바디는 각각 PROPTECT -KEY를 열쇠로 하는 XOR 비밀번호입니다.PROPTECT KEY가 비어 있으면 암호화하지 않고 저장할 수 있습니다.
열쇠를 1바이트로 XOR하는 예가 자주 보이지만 쉽게 망가지기 때문에 키 길이를 좀 늘려 주세요.
결실
우선 암호화되지 않은 example입니다.hsp의 저장 데이터입니다.문자열 같은 것은 원형이고 정수와 실수도 눈으로 보면 이해하기 어렵지만 그렇게 적혀 있다.
그리고 적당한 키로 암호화된 example입니다.hsp의 저장 데이터입니다.서명("HSP3")을 제외하고는 모두 완전히 암호화되었습니다.
총결산
Reference
이 문제에 관하여(HSP의 부정행위 대책은 다양하다. - 데이터 저장 편-), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/ptr-yudai/items/d1583e3206eca1637fea텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)