昔々、人気のあるPvPシューティングゲームの保護を完全に作り直さなければなりませんでした。その結果、詐欺師が更新を徐々に追跡するのを防ぐために、同時に準備してリリースした多数のツールが作成されました。
.
Photon Plugin.
.
.
.
, .
№6.
, ( Android) ( iOS), .
(iOS)
Jailbreak Cydia , . ( *.plist), .
/Library/MobileSubstrate/DynamicLibraries/ ( ).
, Jailbreak, , .
string finalPath = string.Empty;
string substratePath = "/Library/MobileSubstrate/DynamicLibraries/";
bool bySymlink = false;
if (!Directory.Exists(substratePath)) // ( xCon),
{
string symlinkPath = CreateSymlimk(substratePath);
if (!string.IsNullOrEmpty(symlinkPath))
{
bySymlink = true;
finalPath = symlinkPath;
}
}
else
{
finalPath = substratePath;
}
bool detected = false;
string detectedFile = string.Empty;
try
{
if (!string.IsNullOrEmpty(finalPath))
{
string[] plistFiles = Directory.GetFiles(finalPath, "*.plist"));
foreach (var plistFile in plistFiles)
{
if (File.Exists(plistFile))
{
StreamReader file = File.OpenText(plistFile);
string con = file.ReadToEnd();
string bundle = "app_bundle";
if (con.Contains(bundle))
{
detectedFile = plistFile;
detected = true;
break;
}
}
}
}
}
catch (Exception ex)
{
Debug.LogError(ex.ToString());
}
, (KernBypass, A-Bypass). , .
, .
KernBypass ( ):
if (File.Exists("/var/mobile/Library/Preferences/jp.akusio.kernbypass.plist")
{
StreamReader file = File.OpenText("/var/mobile/Library/Preferences/jp.akusio.kernbypass.plist");
string con = file.ReadToEnd();
if (con.Contains("app_bundle")
{
//detected
}
}
(Android)
— , , ( Parallel Space). , root-. : , Application Info .
, . — (dataDir applicationInfo) access ( ). , , Persistent Data .
C:
JavaVM* java_vm;
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
java_vm = vm;
return JNI_VERSION_1_6;
}
int CheckParentDirectoryAccess()
{
JNIEnv* jni_env = 0;
(*java_vm)->AttachCurrentThread(java_vm, &jni_env, NULL);
jclass uClass = (*jni_env)->FindClass(jni_env, "com/unity3d/player/UnityPlayer");
jfieldID activityID = (*jni_env)->GetStaticFieldID(jni_env, uClass, "currentActivity", "Landroid/app/Activity;");
jobject obj_activity = (*jni_env)->GetStaticObjectField(jni_env, uClass, activityID);
jclass classActivity = (*jni_env)->FindClass(jni_env, "android/app/Activity");
jmethodID mID_func = (*jni_env)->GetMethodID(jni_env, classActivity,
"getPackageManager", "()Landroid/content/pm/PackageManager;");
jobject pm = (*jni_env)->CallObjectMethod(jni_env, obj_activity, mID_func);
jmethodID pmmID = (*jni_env)->GetMethodID(jni_env, classActivity,
"getPackageName", "()Ljava/lang/String;");
jstring pName = (*jni_env)->CallObjectMethod(jni_env, obj_activity, pmmID);
jclass pm_class = (*jni_env)->GetObjectClass(jni_env, pm);
jmethodID mID_ai = (*jni_env)->GetMethodID(jni_env, pm_class, "getApplicationInfo","(Ljava/lang/String;I)Landroid/content/pm/ApplicationInfo;");
jobject ai = (*jni_env)->CallObjectMethod(jni_env, pm, mID_ai, pName, 128);
jclass ai_class = (*jni_env)->GetObjectClass(jni_env, ai);
jfieldID nfieldID = (*jni_env)->GetFieldID(jni_env, ai_class,"dataDir","Ljava/lang/String;");
jstring nDir = (*jni_env)->GetObjectField(jni_env, ai, nfieldID);
const char *nDirStr = (*jni_env)->GetStringUTFChars(jni_env, nDir, 0);
char parentDir[200];
snprintf(parentDir, sizeof(parentDir), "%s/..", nDirStr);
if (access(parentDir, W_OK) != 0)
{
return 1;
}
else
{
return 0;
}
}
apk (Android)
apk- , . , .
, root-, . - , .
# Java-:
Lazy<byte[]> defaultResult = new Lazy<byte[]>(() => new byte[20]);
if (Application.platform != RuntimePlatform.Android)
return defaultResult.Value;
#if UNITY_ANDROID
var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
if (unityPlayer == null)
throw new InvalidOperationException("unityPlayer == null");
var _currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
if (_currentActivity == null)
throw new InvalidOperationException("_currentActivity == null");
var packageManager = _currentActivity.Call<AndroidJavaObject>("getPackageManager");
if (packageManager == null)
throw new InvalidOperationException("getPackageManager() == null");
// http://developer.android.com/reference/android/content/pm/PackageManager.html#GET_SIGNATURES
const int getSignaturesFlag = 64;
var packageInfo = packageManager.Call<AndroidJavaObject>("getPackageInfo", PackageName, getSignaturesFlag);
if (packageInfo == null)
throw new InvalidOperationException("getPackageInfo() == null");
var signatures = packageInfo.Get<AndroidJavaObject[]>("signatures");
if (signatures == null)
throw new InvalidOperationException("signatures() == null");
using (var sha1 = new SHA1Managed())
{
var hashes = signatures.Select(s => s.Call<byte[]>("toByteArray"))
.Where(s => s != null)
.Select<byte[], byte[]>(sha1.ComputeHash);
var result = hashes.FirstOrDefault() ?? defaultResult.Value;
return result;
}
#else
return defaultResult.Value;
#endif
№7. Photon Plugin
Photon Cloud, . .
Photon Server , , . , Photon, Photon Plugin.
Photon Plugin Enterprise Cloud #. Photon , , :
;
;
;
http- .
, , (, , , , ), , .
, . .
№8.
. , . .
:
. .
. .
, (, Android — id ).
/ . (, ) .
, , . , .
— , , . .
id — , . , , id .
, .
.
№9.
, , (, GameGuardian Android). . , , , .
«» :
internal int Value
{
get { return _salt ^ _saltedValue; }
set { _saltedValue = _salt ^ value; }
}
, . . , 0 1000 ( , , ).
private static int[] refNumbers;
internal static void Start()
{
refNumbers = new int[1000];
for (int i = 0; i < refNumbers.Length; i++)
{
refNumbers[i] = i;
}
}
internal static bool Check()
{
for (int i = 0; i < 1000; i++)
{
if (!refNumbers [i].Equals(i))
return true;
}
}
№10.
devtodev Flurry. . .
. Data-Driven . ., , . , 500 - , 500 , — . , , .
SQL- . ( , ), . , , - , 0. , - . . , , , - id . — .
. , . 9999 — , - . . , , 15 30, , , , . , . id , , , 1000 , — . .
, , . , .
, . , , , . .
, . « » , .
, , . , . .
.
— . , .
, , .
. , .