루팅된 앱을 탐지하는 방법에 관하여
기본적으로 명확하게 딱 나오는 경우도 없고
요즘 루팅앱이나 위변조 앱들을 보면 , 계속해서 이름을 바꾸는 ( 게임가디언도 그러더라 ) 식으로
요리조리 피해가므로 , 완전한 해결책 이라기 보다는 ..
아주 기본적으로 체크해야하고 효과 대비 별 비용이 안드는 방법을 기록해놓는다.
우선은, Android.os.Build 에서 제공하는 정보들을 받아와보자.
이 방법은 T or F 로 루팅을 판별한다기 보다는, 각종 정보를 긁어서 운영 서버에 올리거나 로그를 찍어놓아서
나중에 수상한 유저일 경우 조회해 볼 수 있게 한다던가 하는 방법으로 써야할 것 같다.
public static string GetData()
{
string result = "";
if (Application.platform == RuntimePlatform.Android)
{
var osBuild = new AndroidJavaClass("android.os.Build");
string brand = osBuild.GetStatic<string>("BRAND");
string fingerPrint = osBuild.GetStatic<string>("FINGERPRINT");
string model = osBuild.GetStatic<string>("MODEL");
string menufacturer = osBuild.GetStatic<string>("MANUFACTURER");
string device = osBuild.GetStatic<string>("DEVICE");
string product = osBuild.GetStatic<string>("PRODUCT");
result += "Model : " + model;
result += "/";
result += "Menufacturer : " + menufacturer;
result += "/";
result += "Device : " + device;
result += "/";
result += "Fingerprint : " + fingerPrint;
result += "/";
result += "Product : " + product;
}
}
다음으로는 Application (Unity API) 객체에서 도움이 될만한 것들을 가져오는 것이다.
사실 이게 훨씬 더 쉬운 방법이다. (ㅎㅎ.)
참고로 이 방법은 유니티가 제공하는 API 라서,
아이폰이든 안드로이드든 별 상관 없이 잘 된다.
(크로스 플랫폼 만세! )
public static string GetData()
{
string result = "";
if (Application.platform == RuntimePlatform.Android)
{
result += Application.installerName; // 보통 구글스토어 또는 앱스토어를 나타낸다.
result += "/";
result += Application.installMode.ToString(); //Debug 인지 릴리즈인지 뜬다 . 구글 검사봇의 경우에는 Debug 로 뜨니 유의하자.
result += "/";
result += Application.buildGUID; // 빌드 시 마다 다른 고유 GUID 넘버다. 이걸 비교하는 것 만으로도 재 빌드된 변조앱임을 쉽게 유추 가능하다. 물론 GUID 가 들통나버리고 비교 부분이 변조되면 답은 없다 (...)
result += "/";
result += "Genuine :" + Application.genuine; // T or F 로 리턴된다. APK 상태로 풀린뒤에 재 빌드되면 False 된다고 한다 ( 직접 본적이 없어서 .. )
}
}
한편, 루팅 감지로 시간을 꽤 보내고 얻은 결론은..
대부분 특정 경로가 존재하는지 체크한다는 것 .
그래도 대부분이 걸린다는 게 웃기긴 하지만 말이다.
에뮬레이터인지 검사하는 것은 주로 제작사 등을 비교하는 것 같은데 ,
요새 에뮬레이터가 하도 잘나와서 녹스 같은 경우에도
태블릿으로 하면 저걸로 잡히는데 폰 모드로 하면 안잡힌다 ‘-‘…
고로 전적인 신뢰는 하지말고 지속적으로 개량해야 할 듯.
public static bool isRooted()
{
bool isRoot = false;
if (Application.platform == RuntimePlatform.Android)
{
if (isRootedPrivate("/system/bin/su"))
isRoot = true;
if (isRootedPrivate("/system/xbin/su"))
isRoot = true;
if (isRootedPrivate("/system/app/SuperUser.apk"))
isRoot = true;
if (isRootedPrivate("/data/data/com.noshufou.android.su"))
isRoot = true;
if (isRootedPrivate("/sbin/su"))
isRoot = true;
}
return isRoot;
}
public static bool IsEmulator()
{
if (Application.platform == RuntimePlatform.Android)
{
AndroidJavaClass osBuild;
osBuild = new AndroidJavaClass("android.os.Build");
string fingerPrint = osBuild.GetStatic<string>("FINGERPRINT");
string model = osBuild.GetStatic<string>("MODEL");
string menufacturer = osBuild.GetStatic<string>("MANUFACTURER");
string brand = osBuild.GetStatic<string>("BRAND");
string device = osBuild.GetStatic<string>("DEVICE");
string product = osBuild.GetStatic<string>("PRODUCT");
return fingerPrint.Contains("generic")
|| fingerPrint.Contains("unknown")
|| model.Contains("google_sdk")
|| model.Contains("Emulator")
|| model.Contains("Android SDK built for x86")
|| menufacturer.Contains("Genymotion")
|| (brand.Contains("generic") && device.Contains("generic"))
|| product.Equals("google_sdk")
|| product.Equals("unknown");
}
if (Application.platform == RuntimePlatform.OSXEditor)
{
return true;
}
return false;
}
public static bool isRootedPrivate(string path)
{
bool boolTemp = false;
if (File.Exists(path))
{
boolTemp = true;
}
return boolTemp;
}