블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2794)
Unity3D (852)
Script (91)
Extensions (16)
Effect (3)
NGUI (81)
UGUI (9)
Physics (2)
Shader (37)
Math (1)
Design Pattern (2)
Xml (1)
Tips (201)
Link (23)
World (1)
AssetBundle (25)
Mecanim (2)
Plugins (78)
Trouble Shooting (70)
Encrypt (7)
LightMap (4)
Shadow (4)
Editor (12)
Crash Report (3)
Utility (9)
UnityVS (2)
Facebook SDK (2)
iTween (3)
Font (13)
Ad (14)
Photon (2)
IAP (1)
Google (8)
Android (51)
iOS (44)
Programming (478)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (11)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

[Asset] Obfuscator

Unity3D/Encrypt / 2017. 11. 17. 10:02

현재 유니티 프로젝트에서 사용중인 난독화 에셋(유료)

 

[링크] https://assetstore.unity.com/packages/tools/utilities/obfuscator-48919

 

Obfuscator | 유틸리티 | Unity Asset Store

Get the Obfuscator package from Beebyte and speed up your game development process. Find this & other 유틸리티 options on the Unity Asset Store.

assetstore.unity.com

 

 

 

반응형
Posted by blueasa
, |

유니티3D_Android dll파일 난독화 가이드

(사용툴 : Spices.Net)



[파일]

BS_Unity3D_Obfuscate_Guide_20131220_v0.1.odt



1. 난독화할 dll파일

  • APK파일을 디컴파일or압축해제를 하면 Asset폴더 내부에 dll파일이 들어있다.

    (유니티 프로젝트의 경우 \assets\bin\Data\Managed\)


  • 난독화할 파일은 Assembly-CSharp.dll


2. Spices.Net 툴을 사용하여 난독화하기




  • 최상위 경로에서 마우스 오른클릭을 하면 메뉴들이 나오는데 Obfuscation Options에서 난독화 설정을 해줄 수 있다.




  • Members 내부에 있는 설정들이 가장 큰 비중을 차지하는것으로 보인다.

  • Members 설정으로 전체적으로 내부설정들을 한번에 바꿀수도 있고

    하나하나 바꿔줄 수도 있다.

  • Methods와 public옵션이 클래스명과 메소드명을 바꿔주는 설정인데 난독화시 가장 효과가 좋은 설정중 하나이다.

    (해당설정 적용시 짜여진 소스 구조에 따라서 작동이 안되는 경우가 있다.

  • Controll Flow 라는 함수 내부 구조를 바꿔주는 난독화부분은 이 툴에서 아직 찾지 못하였음





  • Obfuscation Options 설정이 끝났으면 다시 메뉴를 열어서 Obfuscate!를 선택하면 .iloprj 라는 확장명의 파일 저장경로 확인창이 뜨는데 바로 저장을 해주면 dll파일 경로로 저장된다.

    (툴관련 정보 저장파일인듯 하다)

  • 경로설정이 완료되면 난독화가 진행되고 정상적으로 난독화가 완료되면 “dll파일 경로\Output\”안에 난독화된 Assembly-CSharp.dll 파일이 생성된다.

  • 난독화된 파일을 기존 dll파일 경로에 덮어씌워준후 다시 컴파일 해주면 작업이 완료된다.





*난독화 적용전 .dll 디컴파일 결과





*난독화 적용후 .dll 디컴파일 결과(Members Full옵션 적용)




[출처]

http://theemeraldtablet.tistory.com/entry/Unity3D-Android-dll-%EB%82%9C%EB%8F%85%ED%99%94-%EA%B0%80%EC%9D%B4%EB%93%9C-SpicesNet

반응형

'Unity3D > Encrypt' 카테고리의 다른 글

[Asset] Obfuscator  (2) 2017.11.17
[펌] 기본 변수 저장시 암호화  (0) 2016.05.23
[펌] Playerprefs 암호화  (0) 2016.05.23
C# AES 암복호화 알고리즘  (0) 2014.03.29
안드로이드에서 암호화 팁 - 에셋번들 암호화  (0) 2014.02.28
Posted by blueasa
, |

가장 처음 만들었던 게임을 만들고 난 후에 가장 아쉬운 부분은 보안적인 처리가 취약했다는거.

(취약이라기 보다는 전무...)

이번 프로젝트를 진행하면서 내 자신이 그래도 어느정도는 만족할 만한 보안처리(클라이언트 기준)를 하고싶었고,
그래서 나온 결과물이

- PlayerPrefs 암호화 (사용자의 임의적인 값 변경을 해도 영향을 받지 않도록)
- 변수 암호화 (메모리 주소 스캔이 어렵도록)
- 클라이언트와 서버간 통신중 주고받는 데이터의 암호화

이중 2개는 처리했고 남은 이슈는 3번째 이슈인데 이것도 내일 아마 처리될듯 하다.

첫번째 암호화에 대해서는 이전 포스팅으로 기록을 남겼고,
이번 포스팅에서는 기본 변수를 어떻게 저장해야 메모리 스캔을 어렵도록 할수 있을까에 대한 포스팅이다.


아는 게 너무 없어서 이것저것 서칭해본 결과 아래의 클래스를 프로젝트에 만들어 두었다.

using System;

using System.Collections;

using System.Security.Cryptography;

using System.Text;


public static class SecureConverter

{

    private static int xorCode = (UnityEngine.Random.Range(0, 10000) + UnityEngine.Random.Range(0, 10000) + UnityEngine.Random.Range(0, 10000)).GetHashCode();

        

    public static int SecureInt(int data)

    {

        return  data ^ xorCode;

    }


    public static string SecureString(string data)

    {

        string newText = "";


        for (int i = 0; i < data.Length; i++)

        {

            int charValue = Convert.ToInt32(data[i]); //get the ASCII value of the character

            charValue ^= xorCode; //xor the value


            newText += char.ConvertFromUtf32(charValue); //convert back to string

        }


        return newText;

    }

}


사용은 아래처럼 저장할 변수와 프로퍼티를 관리하는 스크립트에 만들어 두고 프로퍼티로 접근하면 자동으로 암호화된 값이 저장되고, 불러올때는 복호화해서 불러오기 때문에 원래의 데이터 그대로를 사용할 수 있게 해두었다.

private int _abc;
public int abc { get { return SecureConvert.SecureInt(_abc); } set { _abc = SecureConvert.SecureInt(value); } }

어디서든 abc = 300; 과 같은 형태로 저장하면 실제 암호화된 형태로 저장되기 때문에 원시적인 데이터 검색만으로는 실제 메모리 주소를 찾기가 어렵게 된다.


추신. MD5 나 SHA1 같은 것으로 대체하면 더욱 좋을듯. 이는 추후 포스팅~



출처 : http://redccoma.tistory.com/114

반응형
Posted by blueasa
, |

아무런 처리 없이 PlayerPrefs를 사용할 경우 값이 그대로 노출되면서 접근이 가능하고, 프로그램 밖에서 값을 수정할 경우 수정된 값 그대로 프로그램에 적용되는 문제점이 있음.


그런고로 1차적으로 어느정도는 암호화해야 하는데..구글링 한 결과 아주 만족스럽지는 않지만 적어도 원하지 않는 값으로 프로그램에 적용되는 것을 막아주도록 작성된 내용을 유니티포럼에서 찾아 포스팅한다..

(출처 - http://forum.unity3d.com/threads/playerprefs-encryption.26437/)


아래 코드의 포인트는 테스트해본 결과 실제 저장되는 PlayerPrefs의 값은 원본 그대로 저장된다. 노출자체는 된다는 얘기지. 다만, 직접 해당 유저가 해당 값을 수정하면 CheckEncryption함수를 통과하지 못해 DEFAULT 값으로 처리되면서, 기존에 저장되어 있던 PlayerPrefs의 해당 키(3개)는 모두 삭제처리된다.


using UnityEngine;

using System.Collections;

using System.Security.Cryptography;

using System.Text;

 

public class EncryptedPlayerPrefs  {

 

    // Encrypted PlayerPrefs

    // Written by Sven Magnus

    // MD5 code by Matthew Wegner (from [url]http://www.unifycommunity.com/wiki/index.php?title=MD5[/url])

    

    

    // Modify this key in this file :

    private static string privateKey="9ETrEsWaFRach3gexaDr";

    

    // Add some values to this array before using EncryptedPlayerPrefs

    public static string[] keys;

    

    

    public static string Md5(string strToEncrypt) {

        UTF8Encoding ue = new UTF8Encoding();

        byte[] bytes = ue.GetBytes(strToEncrypt);

 

        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

        byte[] hashBytes = md5.ComputeHash(bytes);

 

        string hashString = "";

 

        for (int i = 0; i < hashBytes.Length; i++) {

            hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, '0');

        }

 

        return hashString.PadLeft(32, '0');

    }

    

    public static void SaveEncryption(string key, string type, string value) {

        int keyIndex = (int)Mathf.Floor(Random.value * keys.Length);

        string secretKey = keys[keyIndex];

        string check = Md5(type + "_" + privateKey + "_" + secretKey + "_" + value);

        PlayerPrefs.SetString(key + "_encryption_check", check);

        PlayerPrefs.SetInt(key + "_used_key", keyIndex);

    }

    

    public static bool CheckEncryption(string key, string type, string value) {

        int keyIndex = PlayerPrefs.GetInt(key + "_used_key");

        string secretKey = keys[keyIndex];

        string check = Md5(type + "_" + privateKey + "_" + secretKey + "_" + value);

        if(!PlayerPrefs.HasKey(key + "_encryption_check")) return false;

        string storedCheck = PlayerPrefs.GetString(key + "_encryption_check");

        return storedCheck == check;

    }

    

    public static void SetInt(string key, int value) {

        PlayerPrefs.SetInt(key, value);

        SaveEncryption(key, "int", value.ToString());

    }

    

    public static void SetFloat(string key, float value) {

        PlayerPrefs.SetFloat(key, value);

        SaveEncryption(key, "float", Mathf.Floor(value*1000).ToString());

    }

    

    public static void SetString(string key, string value) {

        PlayerPrefs.SetString(key, value);

        SaveEncryption(key, "string", value);

    }

    

    public static int GetInt(string key) {

        return GetInt(key, 0);

    }

    

    public static float GetFloat(string key) {

        return GetFloat(key, 0f);

    }

    

    public static string GetString(string key) {

        return GetString(key, "");

    }

    

    public static int GetInt(string key,int defaultValue) {

        int value = PlayerPrefs.GetInt(key);

        if(!CheckEncryption(key, "int", value.ToString())) return defaultValue;

        return value;

    }

    

    public static float GetFloat(string key, float defaultValue) {

        float value = PlayerPrefs.GetFloat(key);

        if(!CheckEncryption(key, "float", Mathf.Floor(value*1000).ToString())) return defaultValue;

        return value;

    }

    

    public static string GetString(string key, string defaultValue) {

        string value = PlayerPrefs.GetString(key);

        if(!CheckEncryption(key, "string", value)) return defaultValue;

        return value;

    }

    

    public static bool HasKey(string key) {

        return PlayerPrefs.HasKey(key);

    }

    

    public static void DeleteKey(string key) {

        PlayerPrefs.DeleteKey(key);

        PlayerPrefs.DeleteKey(key + "_encryption_check");

        PlayerPrefs.DeleteKey(key + "_used_key");

    }

    

}


사용법은 PlayerPrefs의 사용법과 동일하다. (아래의 암호화를 위한 키를 추가한 후 사용하면 된다.) 

  EncryptedPlayerPrefs.keys=new string[5];


        EncryptedPlayerPrefs.keys[0]="23Wrudre";

        EncryptedPlayerPrefs.keys[1]="SP9DupHa";

        EncryptedPlayerPrefs.keys[2]="frA5rAS3";

        EncryptedPlayerPrefs.keys[3]="tHat2epr";

        EncryptedPlayerPrefs.keys[4]="jaw3eDAs";

사용시 PlayerPrefs 클래스 대신 EncryptedPlayerPrefs을 사용하면 된다. 키값 전부 지워주는 것은 기존대로 PlayerPrefs꺼 가져다가 쓰면 됨. 추후 빌드시 난독화 과정을 거치면 어느정도 보안처리를 했다고 볼수 있겠지. 


---- 10월 27일 추가.


위의 클래스를 사용하면 값이 그대로 보이기때문에, 이러한 문제를 해결하기위해서는 PlayerPrefs를 약간 가공해서 쓰는것도 한가지 방법이다.

특정 시크릿키를 사용해 Int일 경우 String으로 변환해서 변환된 문자열을 암호화하여 PlayerPrefs.SetString으로 저장하고 불러올때는 복호화 후 Convert 등을 이용해 다시 int 로 바꾸어 호출해 사용하는 방법이 좋아보인다.


이와 관련하여 암/복호화를 특정키를 사용하여 쉽게 할 수 있도록 하는 클래스는 검색하면 어느정도 나오니 그것을 이용해 구현하는 것이 적합.


---- 2015.06.17

http://ikpil.com/1342



출처 : http://redccoma.tistory.com/113

반응형
Posted by blueasa
, |

unity3D용으로 만들어진 암복호화 알고리즘이다.
(출처: 까먹음... T_T)



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using UnityEngine;
using System.Collections;
using System.Security.Cryptography;
using System.Text;
using System.IO;
using System;
 
//중략 Key는 32바이트 "12345678901234567890123456789012"
 
 
     public static string Encrypt(string toEncrypt, string key)
    {
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
        RijndaelManaged rDel = new RijndaelManaged();
        rDel.Key = keyArray;
        rDel.Mode = CipherMode.ECB;
        rDel.Padding = PaddingMode.PKCS7;
        ICryptoTransform cTransform = rDel.CreateEncryptor();
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
        return Convert.ToBase64String(resultArray, 0, resultArray.Length);
    }
    public static string Decrypt(string toDecrypt, string key)
    {
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
        byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
        RijndaelManaged rDel = new RijndaelManaged();
        rDel.Key = keyArray;
        rDel.Mode = CipherMode.ECB;
        rDel.Padding = PaddingMode.PKCS7;
        ICryptoTransform cTransform = rDel.CreateDecryptor();
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
        return UTF8Encoding.UTF8.GetString(resultArray);
    }



* 서버에서도 같이 설정해두면 따로 싱크걱정 사라짐 =)


출처 : http://www.wolfpack.pe.kr/828?category=5

반응형
Posted by blueasa
, |

링크 : http://unitystudy.net/bbs/board.php?bo_table=newwriting&wr_id=357&sca=&sfl=wr_subject&stx=%EC%97%90%EC%85%8B&sop=and

반응형
Posted by blueasa
, |

유니티에서 보통 간단하게 값들을 저장하려면 PlayerPrefs를 많이 씁니다.

물론 로컬에 저장되기 때문에 값이 유저들에게 손쉽게 노출이 되어 변경되기 쉽다는 단점이 있습니다.

 

<PlayerPrefs에 간단한 소개 및 저장위치>

http://docs.unity3d.com/Documentation/ScriptReference/PlayerPrefs.html

 

이를 막기 위해서는 서버에도 값을 저장해서 대조해 본다거나 하는 방법이 필요하겠지만,

간단하게 암호화해서 값이 조작될 경우를 알아내도록 하는 방법이 있습니다.

C#에서 제공하는 라이브러리가 있어 이를 활용해서 만들어 보려고 하다가,

유니티 포럼에 Mudloop란 분이 깔끔하게 클라스로 구현해주셔서 공유하려고 합니다.

저도 덕분에 수고를 많이 줄였거든요 ^^


원리는 secret key 와 private key를 이용해 MD5로 해쉬값을 만들어서,

이를 playerprefs에 저장된 값과 비교하여 일치하는지를 체크하는 방식입니다. 

 

<원본 위치>

http://forum.unity3d.com/threads/26437-PlayerPrefs-Encryption

 

사용법은 간단합니다.

 

우선, https://gist.github.com/ftvs/5299600 에 있는 EncryptedPlayerPrefs.cs를 복붙으로 만듭니다.

 

그리고 아래 키 값을 playerprefs 암호화가 필요한 곳 앞에 넣습니다. (키값은 적당히 바꾸시구요)

아마 start() 같은 곳이 적당하겠죠?

 

  1.         EncryptedPlayerPrefs.keys=new string[5];
  2.         EncryptedPlayerPrefs.keys[0]="23Wrudre";
  3.         EncryptedPlayerPrefs.keys[1]="SP9DupHa";
  4.         EncryptedPlayerPrefs.keys[2]="frA5rAS3";
  5.         EncryptedPlayerPrefs.keys[3]="tHat2epr";
  6.         EncryptedPlayerPrefs.keys[4]="jaw3eDAs"

 

EncryptedPlayerPrefs.cs의 private key 값도 적당히 바꿉니다.


그리고 사용하실 때는 EncryptedPlayerPrefs.SetInt("someKey",value); 와 같이 PlayerPrefs와 동일하게 사용해주시면 됩니다.




출처 : http://ideapot.tistory.com/15


참조 : http://wiki.unity3d.com/index.php/MD5

반응형
Posted by blueasa
, |