1. 程式人生 > >MonoTouch 二三事(二)

MonoTouch 二三事(二)

 2013-02-26 更新 真機秒退問題,授權檔案格式原來的不對。

接上篇。

把client.exe拖入ilspy後發現,授權是靠mac地址+磁碟序列號等資訊,授權驗證依賴了rsa簽名,得了,咱沒超級計算機,跑不出對應的私鑰,只有直接該程式碼爆破了。

但是在改制前呢?我大概瀏覽了下client.exe的功能,並沒有發現有關各種安裝的相關程式碼,也就是說這個東西他只負責驗證授權資訊,並儲存成授權檔案到~/Library/MonoTouch/License.v2,驗證授權成功就可以安裝,驗證授權失敗那就停止安裝。與把程式安裝到哪兒,怎麼安裝並沒有任何關係,那我們何不直接越過這個步驟呢?

別忘了他只是個安裝前執行的指令碼~

因為他是個PackageMaker製作的安裝包,並不能直接刪除我們要刪除的preinstall這個指令碼,那我們直接看monotouch.pkg裡面的PackageInfo檔案,

<pkg-info format-version="2" identifier="com.xamarin.monotouch.pkg" version="1" install-location="/Developer/MonoTouch" auth="root">
    <payload installKBytes="254496" numberOfFiles="4425"/>
    <
scripts> <preinstall file="./preinstall"/> <postinstall file="./postinstall"/> </scripts> </pkg-info>

一種方法是直接刪除<preinstall  file="./preinstall"/>這句,然後再次用PackageMaker打包,嗯,自從XCODE4.*以後這個打包工具從XCODE裡面被Apple給移除了,想用的話得自己下載安裝,我到下載頁面用IE說什麼也下載不下來,chrome倒是下載下來了,2KB。。。不下了。直接按照上面那個XML檔案所給的安裝位置,建立好目錄

/Developer/MonoTouch

(注意這個目錄在之前版本是安裝XCODE後自動建立的,並且XCODE等開發工具也安裝到此目錄,但新版XCODE會直接安裝到/Application/Xcode.app,導致此目錄我們得手動建立)

並拷貝上文提到的Payload解壓後備用的檔案到其下,然後把postinstall這個安裝後執行檔案也拷貝到這個目錄下,然後在終端下執行postinstall,OK,安裝好了,

執行我們之前裝的MonoDevelop,新建一個iPhone專案,編譯模擬器版Debug,會發現如下圖

無授權哦,看看是/Developer/MonoTouch/usr/bin/mtouch這個程式有問題,會驗證授權。這個是mkbundle打包的,用之前的方法提取其託管程式集

我們得到一堆程式集,其中被我選中那幾個是關鍵程式集,其他的都是Mono程式集,把mtouch.exe拖入ilspy,搜尋Main方法,這時找到如下圖的類

Main在我選中的類裡面,這個程式集比較奇怪,Main在一個internal class MTouch裡面,我們看看他的驗證過程

Main呼叫了Main2

Main2裡關於驗證的是

View Code
    bool show_help = false;
    bool show_version = false;
    bool generate_manifests = true;
    List<string> list2 = new List<string>();
    List<string> references = new List<string>();
    List<MTouch.Resource> res = new List<MTouch.Resource>();
    string user_gcc_flags = null;
    string device_name = null;
    try
    {
        Activation activation = new Activation(Certificates.Server, Certificates.Client, null);
        License license = License.LoadFromFile(activation.Crypto, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library/MonoTouch/License.v2"));
        if (Sys.Serial == null)
        {
            Console.Error.WriteLine("Invalid license.  Please contact [email protected]");
            Environment.Exit(97);
        }
        MTouch.ComputeHashes(Sys.Serial, Sys.Mac);
        for (int i = 0; i < license.UserData.H1.Length; i++)
        {
            if (MTouch.H1[i] != license.UserData.H1[i])
            {
                throw new Exception();
            }
        }
        for (int j = 0; j < license.UserData.H2.Length; j++)
        {
            if (MTouch.H2[j] != license.UserData.H2[j])
            {
                throw new Exception();
            }
        }
        for (int k = 0; k < license.UserData.H3.Length; k++)
        {
            if (MTouch.H3[k] != license.UserData.H3[k])
            {
                throw new Exception();
            }
        }
        if (license.UserData.ProductVersion < 5)
        {
            throw new Exception();
        }
    }
    catch (FileNotFoundException)
    {
        Console.Error.WriteLine("License file is missing.  Please activate MonoTouch");
        Environment.Exit(98);
    }
    catch (DirectoryNotFoundException)
    {
        Console.Error.WriteLine("License file is missing.  Please activate MonoTouch");
        Environment.Exit(98);
    }
    catch (Exception value)
    {
        Console.Error.WriteLine("Invalid license.  Please reactivate MonoTouch");
        if (MTouch.verbose > 2)
        {
            Console.WriteLine(value);
        }
        Environment.Exit(99);
    }

這下該修改程式集了,取消驗證那段程式碼,得請出Reflector + reflexil.1.5外掛

去掉相關li程式碼,並保持託管堆疊的平衡,也就是不用想原來的push和pop,然後另存為新程式集,再次開啟

授權相關程式碼消失了。。嘎嘎

把所有解壓的程式集包括[處理]後的mtouch.exe(除去Mono自帶的系統程式集,需要哪個不需要哪個可以執行起來試試能不能執行),複製到

/Developer/MonoTouch/usr/bin/

這個目錄,最終我複製了

Mono.Cecil.dll
Mono.Cecil.Mdb.dll
Mono.Touch.Client.dll
Mono.Touch.Common.dll
monotouch.dll
MonoTouch.Linker.dll
[處理]後的 mtouch.exe

到/Developer/MonoTouch/usr/bin/

因為MonoDevelop.IPhone這個MonoDevelop外掛在專案編譯時呼叫的是沒有exe字尾的那個打包後的Mac原生程式,得讓他執行我們的exe,在

/Developer/MonoTouch/usr/bin/

建立名為mtouch的bash指令碼,替代原來的mtouch,內容如下:

#!/bin/sh
# by BinSsy
 
DIR=$(cd "$(dirname "$0")"; pwd)
MONO_FRAMEWORK_PATH=/Library/Frameworks/Mono.framework/Versions/Current
export DYLD_FALLBACK_LIBRARY_PATH="$DIR:$MONO_FRAMEWORK_PATH/lib:/lib:/usr/lib"
export PATH="$MONO_FRAMEWORK_PATH/bin:$PATH"

#Start mtouch.exe with args

mono "$DIR/mtouch.exe" "[email protected]"

ok再次編譯通過,現在我們改成非模擬器編譯,報錯

No valid iPhone code signing keys found in keychain.

看來涉及簽名啊,最終通過檢視MonoDevelop.IPhone這個外掛程式碼,發現成功編譯需要有開發者證書這個證書的名稱必須類似是

iPhone Developer: BinSys (822ED3R5M7)

還有一個放在路徑 ~/Library/MobileDevice/Provisioning Profiles/ 裡面的以.mobileprovision結尾的裝置預置配置檔案。這個檔案是個pkcs#7訊息信封,

被蘋果一個證書籤名的,具體格式資訊是在

簽名前的內容是個xml檔案,如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <!--蘋果分配,用於保證應用包的唯一性,測試的可隨便填寫等長的-->
        <key>ApplicationIdentifierPrefix</key>
        <array>
            <string>3NZS985WC5</string>
        </array>
        <!--檔案建立日期  UTC時間-->
        <key>CreationDate</key>
        <date>2011-01-20T06:31:45Z</date>
        <!--開發者證書公鑰,二進位制的東西,可以提取二進位制儲存成.cer檔案,這個和之前建立的開發者證書必須一樣-->
        <key>DeveloperCertificates</key>
        <array>
            <data>
                MIIFZzCCBE+gAwIBAgIICD+6XPu04HUwDQYJKoZIhvcNAQEFBQAwgZYxCzAJ
                BgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBs
                ZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBw
                bGUgV29ybGR3aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlv
                biBBdXRob3JpdHkwHhcNMTEwMTIwMDYyMTQxWhcNMTIwMTIwMDYyMTQxWjBb
                MRowGAYKCZImiZPyLGQBAQwKOTNFQTlMNDI5SjEwMC4GA1UEAwwnaVBob25l
                IERldmVsb3BlcjogU3VuIFBlbmcgKDgyMkVEM1I1TTcpMQswCQYDVQQGEwJD
                TjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJv6G9Q1VS+obG9S
                MeLRMkPHfv+jh05P98uIO+uyuOFU5bDDQYAgZLr2qcO90m4KTfwLT/PAbnTy
                PzHYfahTwotyk6yKJrKc+SMVND7MswPVZmHlfnjMWo3C5sVA0ED7PdGPC/eG
                diUPtUBv/08dDjgNmcCuPouqv37JEsh1wfDxsr9SEVBXpSCtuccZbE5EOjJd
                i20AYLH5zpBybvpRXKfFAqU66qIw4iKVzGd0kH+7QOa1t+Q/QuPiOyci4RVL
                FBbPz5MKBwZfMM4TVzy5Zx9vRxtLOabpcXJByEfBzsSowtPAZX6GP8uwqLK8
                Of+KQOKSR5pbm+czi8vB2eBzAR8CAwEAAaOCAfEwggHtMB0GA1UdDgQWBBTc
                Z9iLUFFoFqjbwp0WDLo4n3sInjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaA
                FIgnFwmpthhgi+zruvZHWcVSVKO3MIIBDwYDVR0gBIIBBjCCAQIwgf8GCSqG
                SIb3Y2QFATCB8TCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlz
                IGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ug
                b2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29u
                ZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlm
                aWNhdGlvbiBwcmFjdGljZSBzdGF0ZW1lbnRzLjApBggrBgEFBQcCARYdaHR0
                cDovL3d3dy5hcHBsZS5jb20vYXBwbGVjYS8wTQYDVR0fBEYwRDBCoECgPoY8
                aHR0cDovL2RldmVsb3Blci5hcHBsZS5jb20vY2VydGlmaWNhdGlvbmF1dGhv
                cml0eS93d2RyY2EuY3JsMA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAK
                BggrBgEFBQcDAzATBgoqhkiG92NkBgECAQH/BAIFADANBgkqhkiG9w0BAQUF
                AAOCAQEAAmwcHIVQCv0+oUU2MBMzVYFG0U+dCKgSzpM6FER/ysuzQeqVoTSl
                KflbfVCIVdb6uIOFHymxfv50yyiV6zRF3Y59NuTUaln+Q/wec+OuwxHxMWab
                NA/mAitotXKfRCAI9ZZyA84dVOuJmEFn6txcNSmiGczuRBAHltwVBrRDU/fj
                +Bj8RWSyYQajFxm+7wGqDl6jKttNuG1vYPWis4+3mDFRoXBRwX4kpPJtIbn9
                P0Xv16gBNiJ3B5LBk9DlRsNK/NOLmNlPpRi8NBAtXOeaK+t/UDvnVnX3Xu9Q
                fyRynjHckY5L4wpLOt7xDZgUS5VBEh7u2+AqYjSvL+OLc9yHjg==
            </data>
        </array>
        <!--應用的權利限制,保持預設吧-->
        <key>Entitlements</key>
        <dict>
            <key>application-identifier</key>
            <string>3NZS985WC5.*</string>
            <key>get-task-allow</key>
            <true/>
            <key>keychain-access-groups</key>
            <array>
                <string>3NZS985WC5.*</string>
            </array>
        </dict>
        <!--過期日期,這個必須保證沒有過期,否則MonoDevelop的iPhone外掛不認 UTC時間-->
        <key>ExpirationDate</key>
        <date>2011-04-20T06:31:45Z</date>

        <!--配置的名稱,自己起一個-->
        <key>Name</key>
        <string>Example Provision</string>

        <!--這個就是裝置的UDID列表,如果這個是正規從Apple下載的檔案,下面就是你的測試裝置的UDID-->
        <key>ProvisionedDevices</key>
        <array>
            <string>f9d82b1e14a7becc39cf468a3744d2d927c64ac8</string>
        </array>
        
        <!--此處注意,應該是iOS新特性,網上能找到的所有預置配置檔案都無此項,導致新版monotouch MonoDevelop 的 iPhone外掛編譯異常 空引用異常-->
        <key>TeamIdentifier</key>
        <array>
            <string>3NZS985WC5</string>
        </array>
        
        <!--用途未知-->
        <key>TimeToLive</key>
        <integer>90</integer>

        <!--配置檔案唯一標識,隨機guid-->
        <key>UUID</key>
        <string>8C9691AC-9ABD-49CD-A69A-0DB86319615B</string>

        <!--固定-->
        <key>Version</key>
        <integer>1</integer>
    </dict>
</plist>


這個檔案正規來說是從Apple的開發者計劃的頁面下載的,但我現在沒有開發者帳號,所以自己產生一個,包上面xml儲存成utf8編碼的xml檔案,然後下面程式碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using MonoDevelop.MacDev.Plist;
using System.Xml;

namespace makemp
{
    class Program
    {
        static void Main(string[] args)
        {
            //從MAC匯出的證書檔案 和匯出時設定的密碼
            X509Certificate2 signgercert = new X509Certificate2(@"my.p12", "*****");


            PlistDocument pd = new PlistDocument();
            
            //模版檔案
            pd.LoadFromXmlFile(@"mobileprovision_Template.xml");

            //ApplicationIdentifierPrefix
            PlistDictionary root_dic = pd.Root as PlistDictionary;
            //PlistArray ApplicationIdentifierPrefix_s = root_dic["ApplicationIdentifierPrefix"] as PlistArray;
            //PlistString ApplicationIdentifierPrefix_1 = ApplicationIdentifierPrefix_s.Value.FirstOrDefault() as PlistString;
            //ApplicationIdentifierPrefix_1.Value = "123456789";


            //CreationDate
            PlistDate CreationDate = root_dic["CreationDate"] as PlistDate;
            CreationDate.Value = DateTime.Now;


            //DeveloperCertificates
            PlistArray DeveloperCertificates_s = root_dic["DeveloperCertificates"] as PlistArray;
            PlistData DeveloperCertificates_1 = DeveloperCertificates_s.Value.FirstOrDefault() as PlistData;

            DeveloperCertificates_1.Value = signgercert.Export(X509ContentType.Cert);
            
            //Entitlements

            //ExpirationDate
            PlistDate ExpirationDate = root_dic["ExpirationDate"] as PlistDate;
            ExpirationDate.Value = DateTime.Now.AddYears(10);

            //Name
            PlistString Name = root_dic["Name"] as PlistString;
            Name.Value = "TestApp";


            //ProvisionedDevices
            PlistArray ProvisionedDevices_s = root_dic["ProvisionedDevices"] as PlistArray;
            PlistString ProvisionedDevices_1 = ProvisionedDevices_s.Value.FirstOrDefault() as PlistString;
            ProvisionedDevices_1.Value = "e5fb5e41110b57ad370e0725610b7a9ba31df40e";

            //UUID
            PlistString UUID = root_dic["UUID"] as PlistString;
            UUID.Value = Guid.NewGuid().ToString().ToUpper();


            //pd.WriteToFile("aa.xml");

            MemoryStream ms = new MemoryStream();
            using (XmlTextWriter xmlTextWriter = new XmlTextWriter(ms, UpperCaseUTF8Encoding.UpperCaseUTF8))
            {
                xmlTextWriter.Indentation = 1;
                xmlTextWriter.IndentChar = '\t';
                xmlTextWriter.Formatting = Formatting.Indented;
                pd.Write(xmlTextWriter);
            }


            File.WriteAllBytes("my.mobileprovision", Encode(Encoding.UTF8.GetString(ms.GetBuffer()), signgercert));


        }




        static string Decode(byte[] bytes)
        {
            SignedCms sc = new SignedCms();
            sc.Decode(bytes);
            //foreach (X509Certificate2 cert in sc.Certificates)
            //{
            //    Console.WriteLine(cert.Thumbprint);
            //    File.WriteAllBytes(string.Format("Thumbprint_{0}.cer", cert.Thumbprint), cert.Export(X509ContentType.Cert));
            //}

            return Encoding.UTF8.GetString(sc.ContentInfo.Content);
        }


        static byte[] Encode(string source, X509Certificate2 cert)
        {
            byte[] sourceBytes = Encoding.UTF8.GetBytes(source);
            CmsSigner cs = new CmsSigner(cert);
            cs.IncludeOption = X509IncludeOption.WholeChain;
            ContentInfo ci = new ContentInfo(sourceBytes);
            SignedCms sc2 = new SignedCms(ci, false);
            sc2.ComputeSignature(cs);
            return sc2.Encode();
        }
    }
}

詳細程式碼本文後邊有打包。那個證書是從mac匯出的。

這樣生成了與我們自己的開發者證書想對應的.mobileprovision檔案,把他放到

 ~/Library/MobileDevice/Provisioning Profiles/

目錄裡。

真機編譯,如下:

Building: tt1 (Debug|iPhone)

Detecting signing identity...
Provisioning profile: "TestApp" (07BBFA54-544E-4BB3-83A5-0C5832E25285)
Signing Identity: "iPhone Developer: BinSys (822ED3R5M7)"
App ID: "3NZS985WC5.tt1"
Performing main compilation...
/Developer/MonoTouch/usr/bin/smcs /noconfig "/out:/Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.exe" "/r:/Developer/MonoTouch/usr/lib/mono/2.1/System.dll" "/r:/Developer/MonoTouch/usr/lib/mono/2.1/System.Xml.dll" "/r:/Developer/MonoTouch/usr/lib/mono/2.1/System.Core.dll" "/r:/Developer/MonoTouch/usr/lib/mono/2.1/monotouch.dll" /nologo /warn:4 /debug:full /optimize- /codepage:utf8 "/define:DEBUG"  /t:exe "/Users/binsys/Projects/tt1/tt1/Main.cs" "/Users/binsys/Projects/tt1/tt1/AppDelegate.cs" "/Users/binsys/Projects/tt1/tt1/tt1ViewController.cs" "/Users/binsys/Projects/tt1/tt1/tt1ViewController.designer.cs" 
Compilation succeeded - 3 warning(s)

/Users/binsys/Projects/tt1/tt1/tt1ViewController.cs(30,38): warning CS0672: Member `tt1.tt1ViewController.ViewDidUnload()' overrides obsolete member `MonoTouch.UIKit.UIViewController.ViewDidUnload()'. Add the Obsolete attribute to `tt1.tt1ViewController.ViewDidUnload()'
/Developer/MonoTouch/usr/lib/mono/2.1/monotouch.dll (Location of the symbol related to previous warning)
/Users/binsys/Projects/tt1/tt1/tt1ViewController.cs(42,38): warning CS0672: Member `tt1.tt1ViewController.ShouldAutorotateToInterfaceOrientation(MonoTouch.UIKit.UIInterfaceOrientation)' overrides obsolete member `MonoTouch.UIKit.UIViewController.ShouldAutorotateToInterfaceOrientation(MonoTouch.UIKit.UIInterfaceOrientation)'. Add the Obsolete attribute to `tt1.tt1ViewController.ShouldAutorotateToInterfaceOrientation(MonoTouch.UIKit.UIInterfaceOrientation)'
/Developer/MonoTouch/usr/lib/mono/2.1/monotouch.dll (Location of the symbol related to previous warning)
/Users/binsys/Projects/tt1/tt1/tt1ViewController.cs(32,30): warning CS0618: `MonoTouch.UIKit.UIViewController.ViewDidUnload()' is obsolete: `Deprecated in iOS 6.0'



Compiling interface definitions
/Applications/Xcode.app/Contents/Developer/usr/bin/ibtool --errors --warnings --notices --output-format human-readable-text --compile "/Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app/tt1ViewController.nib" "/Users/binsys/Projects/tt1/tt1/tt1ViewController.xib" --sdk "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk"
2012-11-29 15:27:41.683 Interface Builder Cocoa Touch Tool[345:14603] CFPreferences: user home directory at file://localhost/Users/binsys/Library/Application%20Support/iPhone%20Simulator/User/ is unavailable. User domains will be volatile.
構建完成 --0 個錯誤, 3 個警告

Compiling to native code
/Developer/MonoTouch/usr/bin/mtouch -sdkroot "/Applications/Xcode.app/Contents/Developer" -v --cache "/Users/binsys/Projects/tt1/tt1/obj/Debug/mtouch-cache" --nomanifest --nosign -dev "/Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app" -r "/Developer/MonoTouch/usr/lib/mono/2.1/System.dll" -r "/Developer/MonoTouch/usr/lib/mono/2.1/System.Xml.dll" -r "/Developer/MonoTouch/usr/lib/mono/2.1/System.Core.dll" -r "/Developer/MonoTouch/usr/lib/mono/2.1/monotouch.dll" -debug -profiling -linksdkonly -sdk "6.0" --abi=armv7 "/Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.exe"
MonoTouch version 6.0.6 using framework: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk
Copied /Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.exe to /Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app/tt1.exe
Copied /Developer/MonoTouch/usr/lib/mono/2.1/mscorlib.dll to /Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app/mscorlib.dll
Copied /Developer/MonoTouch/usr/lib/mono/2.1/monotouch.dll to /Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app/monotouch.dll
Copied /Developer/MonoTouch/usr/lib/mono/2.1/System.Core.dll to /Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app/System.Core.dll
Copied /Developer/MonoTouch/usr/lib/mono/2.1/System.dll to /Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app/System.dll
Copied /Developer/MonoTouch/usr/lib/mono/2.1/Mono.Security.dll to /Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app/Mono.Security.dll
Copied /Developer/MonoTouch/usr/lib/mono/2.1/System.Xml.dll to /Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app/System.Xml.dll
Linking SDK only for assembly /Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.exe into /Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app
MONO_PATH=/Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app /Developer/MonoTouch/usr/bin/arm-darwin-mono --debug --aot=mtriple=armv7-darwin,full,static,asmonly,direct-icalls,no-direct-calls,iphone-abi,outfile=/var/folders/gn/rs7j2w411rqc159nhqc2rddc0000gn/T/tmp6163d343.tmp/System.Core.dll.armv7.s "/Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app/System.Core.dll"
AOT Compilation exited with code 4, command:
MONO_PATH=/Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app /Developer/MonoTouch/usr/bin/arm-darwin-mono --debug --aot=mtriple=armv7-darwin,full,static,asmonly,direct-icalls,no-direct-calls,iphone-abi,outfile=/var/folders/gn/rs7j2w411rqc159nhqc2rddc0000gn/T/tmp6163d343.tmp/System.Core.dll.armv7.s "/Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app/System.Core.dll"
MonoTouch license could not be found.  Please activate your MonoTouch installation.

error MT3001: Could not AOT the assembly '/Users/binsys/Projects/tt1/tt1/bin/iPhone/Debug/tt1.app/System.Core.dll'

---------------------- 完成 ----------------------

Project does not have bundle identifier specified. Generated 'tt1' to match an installed provisioning profile.
構建:1 個錯誤, 4 個警告

 編譯出錯。估計拉下哪個檔案沒[處理],看MonoDevelop.IPhone程式碼,可以知道其根據編譯引數呼叫了/Developer/MonoTouch/usr/bin/目錄下的arm-darwin-mono和arm-darwin-mono-sgen這兩個原生蘋果程式。全是Native程式碼,沒發現什麼經過打包的痕跡。

嗯,因為看編譯選項發現我們沒有選中sgen這個垃圾回收器,所以這此編譯呼叫的應該是arm-darwin-mono這個AOT編譯器,用IDA開啟等待分析完畢(檔案大,有點兒慢)

發現驗證授權時打開了~/Library/MonoTouch/License.v2 這個檔案,看了下,也是驗證了RSA sha1簽名,我們通過把三個在破解領域爆破方法裡的關鍵跳jnz改成nop,(arm-darwin-mono-sgen 同樣處理)並偽造一個特定格式的 License.v2檔案,這個格式是一個全0的二進位制檔案,長度為60+N+1+128,60位元組是三個長度為20的hash,N任意,1為一個特定值,必須大於1,後邊128位元組為一個二進位制檔案被1024位rsa key用sha1演算法簽名後產生的簽名指紋的資料長度,128位元組,我麼寫全0吧。這樣把這個檔案放到指定目錄,把在windows裡修改過的兩個程式放到mac替換原來的,編譯。。。。。各種通過,各種ipa都產生了,剩下的就是把ipa放到越獄的裝置裡了,進行效能測試。

這個授權檔案格式如下:

View Code
string IOPlatformSerialNumber = "VMWVk3P/wPmJkRIwb5ycu1EQw";
string IOMACAddress = "00:0c:29:ed:44:43";


GetLicense(Salt, IOPlatformSerialNumber, IOMACAddress);


private static void GetLicense(byte[] salt, string IOPlatformSerialNumber, string IOMACAddress)
{
    byte[] IOPlatformSerialNumber_Bytes = System.Text.Encoding.UTF8.GetBytes(IOPlatformSerialNumber);
    byte[] IOMACAddress_Bytes = System.Text.Encoding.UTF8.GetBytes(IOMACAddress);
    System.IO.MemoryStream ms = new System.IO.MemoryStream(IOPlatformSerialNumber_Bytes.Length + IOMACAddress_Bytes.Length + salt.Length);
    System.Security.Cryptography.HashAlgorithm alg = System.Security.Cryptography.SHA1.Create();
    byte[] hash1 = GetHash(alg, ms, IOPlatformSerialNumber_Bytes, IOMACAddress_Bytes, salt);
    byte[] hash2 = GetHash(alg, ms, IOPlatformSerialNumber_Bytes, salt, IOMACAddress_Bytes);
    byte[] hash3 = GetHash(alg, ms, salt, IOPlatformSerialNumber_Bytes, IOMACAddress_Bytes);


    byte[] LicenseHashs = new byte[60];


    
    Array.Copy(hash1, 00, LicenseHashs, 00, 5);
    Array.Copy(hash2, 00, LicenseHashs, 05, 5);
    Array.Copy(hash3, 00, LicenseHashs, 10, 5);

    Array.Copy(hash1, 05, LicenseHashs, 15, 5);
    Array.Copy(hash2, 05, LicenseHashs, 20, 5);
    Array.Copy(hash3, 05, LicenseHashs, 25, 5);

    Array.Copy(hash1, 10, LicenseHashs, 30, 5);
    Array.Copy(hash2, 10, LicenseHashs, 35, 5);
    Array.Copy(hash3, 10, LicenseHashs, 40, 5);

    Array.Copy(hash1, 15, LicenseHashs, 45, 5);
    Array.Copy(hash2, 15, LicenseHashs, 50, 5);
    Array.Copy(hash3, 15, LicenseHashs, 55, 5);
    


    byte[] bytesPadding = new byte[400];

    for (int index = 0; index < 400; index++)
    {
        bytesPadding[index] = 6;
    }


    byte[] ret;
    using (MemoryStream msff = new MemoryStream())
    {
        msff.Write(LicenseHashs, 0, LicenseHashs.Length);
        msff.Write(bytesPadding, 0, bytesPadding.Length);
        ret = msff.GetBuffer();
        msff.Close();
    }

    File.WriteAllBytes("License.v2", ret);

}

private static byte[] GetHash(System.Security.Cryptography.HashAlgorithm alg, System.IO.MemoryStream ms, byte[] b1, byte[] b2, byte[] b3)
{
    ms.Position = 0L;
    ms.SetLength(0L);
    ms.Write(b1, 0, b1.Length);
    ms.Write(b2, 0, b2.Length);
    ms.Write(b3, 0, b3.Length);
    return alg.ComputeHash(ms.GetBuffer(), 0, (int)ms.Length);
}

至於這個 Salt這個陣列,大家動手去找吧,自己動手豐衣足食嘛。。。嘿嘿, 就在mtouch那幾個程式集裡,是常量,我就不提供了,省的影響較大然後出事兒。 真心想用的不差這幾步,看看就走的就別試了,整的亂飛就不好了。

注意,arm-darwin-mono和sgen這兩個原生程式只驗證了授權檔案的前60個位元組和授權檔案從後向前數第128個位元組大於0, 沒有檢查這個授權檔案的數字簽名,所以我們省事了,而mtouch這個驗證了數字簽名,所以呢,咱得處理它,把數字簽名驗證相關咔嚓掉。

下一篇繼續開始測試之旅。

附件: