2014년 3월 14일 금요일

유니티 안드로이드/iOS 버전 Crypto Obfuscator를 이용해 Assembly-CSharp.dll 난독화하기

 던전워즈
Crypto Obfuscator 난독화 툴을 통해서 유니티 안드로이드 버전 난독화방법은 이미 잘알려져있다.
난독화시 각종 난독화 예외사항들만 잘 설정해주면
문제없이 동작한다. 어떤 클래스들을 난독화하고 어떤것을 제외할 것인가 하는 부분은 개별 프로젝트마다
다를 수 있으므로 언급하지 않는다.
현재 개발중인 게임에서 사용중인 안드로이드쪽 난독화 셋팅은 다음과 같다


 심볼 리네이밍 스킴은 적절한것을 선택하면된다. 나의 경우에는 프로시저이름의 해시형태로 나바꾸게 해놨는데
해시형태가 오히려 보기 더 어려운듯하여(보는 사람에게 짜증을 유발) 선택했다. Unprintable형태는 출력되지 않은 기호형태로 리네이밍하게 된다.(아예 알아볼수 없으니 짜증이고 나발이고 없다) 해시방식의 단점은 dll 파일의 크기가 커진다는 것이다.



난독화 예외항목에는 잘알려진 난독화 하면 안되는 유니티 관련된 것들과 NGUI관련한것을 포함시켰다. 하나하나 세세하게 설정하면
아주 훌륭한 수준의 난독화가 가능하겠지만 설정할것들이 너무 많아서 그냥 두리뭉실하게 뭉탱이 단위로 설정했다.
그래서 그런지 MonoBehaviour를 상속받은 것들은 난독화 되지 않는다. 각종게임 로직들은 그대로 노출되겠지만  민감한 코드들은 모두 외부로 빼서 처리하기 때문에 크게 문제는 없을듯하다.

문제는 iOS쪽이다. ios쪽 DLL난독화는 안드로이드나 PC쪽에 비해 아주 귀찮은 작업이다.
자세히 알지는 못하지만 iOS에서 유니티 xcode 프로젝트를 출력할때는 AOT단계를 거치게된다.
iOS의 LLVM이라는 환경이 온전하게 .NET가상머신 환경을 제공하지 못해.
각종 DLL의 바이트코드들이 LLVM의 형식이 맞게 변환되어서 메인 바이너리에 포함되는듯하다.
mac 버전의 유니티에는 mono-xcompiler라는 크로스 컴파일러가 있다. (4.3버전의 유니티인경우 윈도우 환경에서도
xcode프로젝트 생성이 가능하지만 DateTime관련해서 버그가 있으므로 iOS버전은 여전히 Mac에서 뽑는게 안전하다.)
아무튼 실질적으로 우리가 만들어 컴파일된 .NET의 스크립트파일들은 실질적으로는 사용되지 않지만 여전히 내부의
소스를 훤히 들어낸체 xcode의 프로젝트에 포함되어 있다. 단지 인터페이스의 역할만 하는 정도라면 메소드의 내부를 모두제거
하고 중요 심볼만 남겨둬도 될텐데 유니티는 왜그렇게 하지 않는지 이유를 모르겠다.

xcode 프로젝트의 data\managed\ 폴더안에보면 Assembly-CSharp.dll 이 존재하고
Libraries\폴더안에 보면 Assembly-CSharp.dll.s 라는 어셈블리 소스 파일이 존재한다.
실제 ios의 실행 바이너리에 포함되어 작동되는 코드들은 Assembly-CSharp.dll.s라는 어셈블리로 재컴파일되어
xcode빌드시 포함되게 된다.
Assembly-CSharp.dll.s 파일은 mono-xcompiler를 통해서 유니티 AOT단계를 거칠때 생성하게 된다.
mono-xcompiler는 .NET DLL파일로 부터 iOS의 LLVM에 맞는 적절한 어셈블리 명령을 생성하게 되는 것이다.

그렇기 때문에 우리가 iOS버전의 DLL을 난독화하기 위해서는 두가지의 단계를 거쳐야한다.
첫째는 xcode프로젝트의 Assembly-CSharp.dll을 난독화하고
두번째는 이렇게 난독화된, DLL로부터 어셈블리 소스를 mono-xcompiler를 이용해서 다시 생성하는 것이다.

iOS버전 DLL난독화에는 다음과 같은 셋팅을 사용했다.


안드로이드 난독화 셋팅과의 차이점은 어셈블리 상세 설정의 체크를 모두 해제 했다는 것이다.
mono-xcompiler가 난독화된 DLL과 별로 친하지 않기 때문에 조금이라도 민감한 수준의 난독화를 하게 되면
크로스컴파일이 실패하게 된다.
crypto obfuscator의 맥 버전이 없어서 난독화는 매우 귀찮은 작업이다.
mac에서 xcode 프로젝트 생성 -> Data\Managed\ 폴더내의 모든 파일들을 윈도우로 옮겨서 Assembly-CSharp.dll 난독화
다시 난독화된 파일을 맥으로 옮겨서 Data\Managed\ 폴더에 있는 원본과 교체
이휴 mono-xcompiler를 이용해서 어셈블리 재생성
iOS 및 Mac os와 전혀 친하지 않기 때문에 나에게는 너무나 불편하고 힘든작업이다.

Mono-xcompiler는 맥의 다음경로에 위치하고 있다.

유니티 아이콘에서 패키지 내용보기-> Contents\BuildTargetTools\iPhonePlayer\  폴더내부에 있는데
전체 경로는 어플리케이션 뭐시기로 시작하는 어딘가이다.
저기 보이는 저 mono-xcompiler를 사용해서 *.dll.s 파일을 만들면된다.
mono-xcompiler 를 다음형태로  작동시키면되는데 나의 경우 a\라는 폴더를 만들고 거기 안에 xcode프로젝트의 data\managed안에 있는 모든 내용들을 복사해서 넣어놓고 작업한다.

export MONO_PATH=/Applications/Unity/Unity.app/Contents/BuildTargetTools/iPhonePlayer/a/
export MONO_CFG_DIR=/Applications/Unity/Unity.app/Contents/BuildTargetTools/iPhonePlayer/a/mono/2.0/
/Applications/Unity/Unity.app/Contents/BuildTargetTools/iPhonePlayer/mono-xcompiler --aot=full,asmonly,nodebug,static,outfile="/Applications/Unity/Unity.app/Contents/BuildTargetTools/iPhonePlayer/Assembly-CSharp.dll.s" "/Applications/Unity/Unity.app/Contents/BuildTargetTools/iPhonePlayer/a/Assembly-CSharp.dll"

콘솔에서 작업해야 하는데 유닉스 쉘 스크립트를 만들어 놓고쓰면 편하게 작업할 수 있다.
위의 그림에 보이는 cli-unity-xcp 라는게 위의 명령을 처리하는 스크립트 파일이다.
스크립트 파일링크

아무튼 해당 스크립트를 실행하면 몇초후 Assembly-CSharp.dll.s 라는 파일이 만들어질텐데 이파일을 xcode프로젝트의 Libraries 폴더내에 있는 것과 교체해주면 난독화 작업이 완료되게 된다.


c# web safe base64

 던전워즈
기본적으로 c#의 base64로 변환후 스트링의 Replace기능을 이용해서
+는 -로 /는 _로 변환하면된다.

string strInput = "base64로 바꿀 문자열";



string strWebSafeBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(strInput)).Replace('+', '-').Replace('/', '_');

유니티 프로젝트 다운그레이드하기

4.3 버전에서 4.2 또는 4.1 버전으로 다운그레이드 하기
4.3 버전에서 유니티 2D기능관련해서 대대적인 패치가 이루어졌는데 써본결과 아직 상당히 문제가 많다
퍼포먼스문제 안드로이드쪽 디바이스 호환문제등 여러가지 등등..
뭣모르고 업그레이드 했다가 위와 같은문제때문에 위기에 봉착
다시 프로젝트를 이전 버전으로 되돌려야 하는 사태가 발생해서 구글링해본결과
다음과 같은 방법으로 다운그레이드가 가능하다고 한다.

Here is something worth trying, make sure you create backs ups before you start!
여기에 뭔가 가치있는 시도가 있다, 시작하기 전에 백업을 만들어둘것
  1. Enable source control on your project: Edit/Project Settings/Editor/Visible Meta Files (This will create meta files for every asset you have, these fiels contain information such as how the asset should be imported as well as a unique guid so you should not lose links to scripts etc)
  2. 당신의 프로젝트에 소스 컨트롤을 활성화한다 : Edit->Project Settings->Editor->Visible Meta Files(이것은 당신의 프로젝트가 가진 모든 애셋 파일들의 메타데이터를 생성할 것이다, 이파일들은 GUID뿐만 아니라 애셋들이 어떻게 임포트되어야하는지와 같은 정보들을 담고 있다 그러므로 당신은 스크립트등과 같은 것들의 링크를 잃지 않게 된다)
  3. Create a new project with unity 4.2.2. Keep the project empty. Enable source control on this project like you did with the other.
  4. 유니티 4.2.2등의 버전에서 새로운 프로젝트를 생성한다. 빈프로젝트로 유지할것. 이프로젝트의 소스컨트롤 방식을 위와 같은(Visible Meta Files) 형태로 활성화한다.
  5. Now replace the "Assets" folder from your 4.2.2 project with the 4.3 project Assets folder.
  6. 이제 4.3프로젝트의 애셋폴더를 4.2프로젝트의 애셋폴더에 복사한다.
  7. Unity 4.2.2 should import all the assets with the correct settings and you should have a 4.2.2 project again. You can now disable source control and it will remove the meta files.
  8. 유니티 4.2는 모든애셋들을 올바른 셋팅으로 임포트할것이고, 당신은 다시 4.2버전의 프로젝트를 가지게 된다. 이제 소스컨트롤을 비활성화 할수 있고, 그를통해 모든 메터파일들은 제거될것이다.
  9. Update:(추가사항)
Once you have downgraded you may start to get some errors about the Unity serializer. Such as this:typeTree.m_Children.front ().m_Type != SerializeTraits::GetTypeString (NULL) This is likely caused by Unity 4.3 adding in some data into its assets/prefabs/scenes etc that 4.2.2 does not recognise. A possible fix is this: Goto your project settings/Editor/Asset Serialisation and change it to either force text or force binary. This will force Unity to re-serialise all your asset files. So potentially it could get rid of any Unity 4.3 serialisation data.
다운그레이드된 유니티 프로젝트를 시작할때 몇개의 유니티 시리얼라이저관련 에러를 보게 될것이다. typeTree.m_Children.front ().m_Type != SerializeTraits::GetTypeString (NULL)과 같은것으로  이것은 유니티 4.3에서 몇몇 데이터드을 애셋의 씬에 추가한것이 원인이다. 가능한 수리법은 다음과 같다 : Project Settings->Editor->Asset Serialisation 으로 가서 force text 또는 force binary중하나로 바꾼다. 이것은 강제적으로 유니티가 모든 애셋파일들을 다시 직렬화하게 할것이다. 그러므로 잠재적으로 유니티 4.3에서 만들어진 직렬화 데이터들은 사라질수 있다.

위에 나와 있는 방법되로 4.3 버전을 4.1 버전으로 바꿔보니 과연잘된다. 물론 몇몇 재질의 셰이더가 날아간게 한두개 정도



나오긴했지만 그외에는 별문제 없는듯하다.

프로가드 오류

 던전워즈
SDK에 기본적으로 포함되어있는 프로가드를 사용해서 유니티 프로젝트로 부터 뽑은 안드로이드 프로젝트를 난독화 하게 되면
오류가 발생한다.
유니티의 classes.jar 파일이 이미 난독화 처리가 되어 프로가드가 해당 파일을 읽을때 오류가 발생하는 문제인데
Caused by: java.io.IOException: Can't process class [com/unity3d/player/UnityPlayer.class] (Unknown verification type [230] in stack map frame)
대략 이런 유형의 에러메시지가 난다.

이번에 ADT버전업을 하면서 프로가드 까지 갱신되버려서 또 같은 문제가 생겼다.

 인터넷에 나와 있는 여러가지 해결책을 모두 적용해봐도 해결이 안돼서 한동안 고심했었다.
프로가드 제작자가 제시한 해결책은 stack map frame관련해서 소스의 특정 부분을 어떤 값으로 바꾸고 재컴파일하면된다고
했던 기억만 가물가물하게 나는데
구체적으로 어떻게 해결했는지 자세히 기억은 안나지만
소스를 수정하고 다시 컴파일해서 proguard.jar파일을 만든다음
해당 파일을 안드로이드 sdk의
adt-bundle-windows-x86\sdk\tools\proguard\lib\ 대략 이런 경로에 있는 프로가드 jar파일과 교체하면된다.

Unknown verification type [230] in stack map frame 라고 구글링을 해보면 자세한 내용이 나올테지만 귀찮아서 안할란다.
다행히 그때 만든 jar파일을 하드 구석탱이에서 찾아서 넣어보니 잘된다.



다운로드 링크
https://dl.dropboxusercontent.com/u/211062767/proguard.jar