天天看點

【IOS-IAP防護】驗證使用者付費收據!拒絕IAP CRACKER!拒絕IAP FREE!讓IPHONE越獄使用者無從下手!【2012年5月2日更新防護IAP FREE的方法】

對于ios的應用安全這塊主要有兩塊是我們開發者可以避免的,一個是存儲資料加密,這個在上一篇文章himi介紹了base64加密算法;另外一個就是付費産品防護!那麼本篇himi來分享如何防護越獄使用者的iap cracker!

對于iap cracker這個插件,himi簡單介紹下!

iap cracker可以說是ios越獄使用者的終極利器阿,當今app store的所有内置收費的遊戲,基本使用此插件進行秒購買無壓力!(對于那些收費下載下傳的遊戲,對于越獄使用者來說,安裝個xx助手<你懂得~>就可以免費體驗app store的所有遊戲,不管你下載下傳收費還是内置收費!)

iap cracker能繞過appstore的付費流程,其方式是當使用者點選付費産品進行購買後,iap cracker模拟傳回一個購買成功的消息(無需聯網,說白了,連post 資料給app store都沒有!),然後我們應用中收到這個“假的”交易成功的消息直接給使用者加錢,加裝備,加各種….

ok,對于iap cracker就不再多介紹了,下面himi來分享如何防護iap cracker吧;

對于越獄使用者使用付費破解插件進行付費這個問題,其實apple并沒有不管,而是已經在文檔中清晰的說明,隻是很多童鞋并沒有發現,如下截圖:

【IOS-IAP防護】驗證使用者付費收據!拒絕IAP CRACKER!拒絕IAP FREE!讓IPHONE越獄使用者無從下手!【2012年5月2日更新防護IAP FREE的方法】

apple提示開發者付費要進行驗證付費收據! 原文apple dev官方文檔連接配接:

<a href="https://developer.apple.com/library/ios/#documentation/networkinginternet/conceptual/storekitguide/verifyingstorereceipts/verifyingstorereceipts.html%23//apple_ref/doc/uid/tp40008267-ch104-sw1">https://developer.apple.com/library/ios/#documentation/networkinginternet/conceptual/storekitguide…</a>

  下面himi就詳細講解如何在我們付費流程中加入iap防護,步驟如下:

1. 首先将 json類庫和nsdata+base64類導入你的項目中,下載下傳:

2. 然後将himi封裝的如下函數拷貝到你付費代碼所在的類中:

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

35

36

37

38

39

40

41

.h中:

-(bool)putstringtoitunes:(nsdata*)iapdata;

.m中:

#import "nsdata+base64.h"

#import "nsstring+sbjson.h"

#import "json.h"

-(bool)putstringtoitunes:(nsdata*)iapdata{//使用者購成功的transactionreceipt

    nsstring*encodingstr = [iapdata base64encodedstring];

    nsstring *url=@"https://sandbox.itunes.apple.com/verifyreceipt";

    //https://buy.itunes.apple.com/verifyreceipt

    nsmutableurlrequest *request = [[nsmutableurlrequest alloc] init];// autorelease];

    [request seturl:[nsurl urlwithstring:url]];

[request sethttpmethod:@"post"];

    //設定contenttype

    [request addvalue:@"application/json" forhttpheaderfield:@"content-type"];

    //設定content-length

    [request setvalue:[nsstring stringwithformat:@"%d", [encodingstr length]] forhttpheaderfield:@"content-length"];  

    nsdictionary* body = [nsdictionary dictionarywithobjectsandkeys:encodingstr, @"receipt-data", nil];

    sbjsonwriter *writer = [sbjsonwriter new];

    [request sethttpbody:[[writer stringwithobject:body] datausingencoding:nsasciistringencoding allowlossyconversion:yes]];

    nshttpurlresponse *urlresponse=nil;

nserror *errorr=nil;

    nsdata *receiveddata = [nsurlconnection sendsynchronousrequest:request

                                                 returningresponse:&amp;amp;urlresponse

                                                             error:&amp;amp;errorr];

    //解析

nsstring *results=[[nsstring alloc]initwithbytes:[receiveddata bytes] length:[receiveddata length] encoding:nsutf8stringencoding];

    cclog(@"-himi-  %@",results);

    nsdictionary*dic = [results jsonvalue];

    if([[dic objectforkey:@"status"] intvalue]==0){//注意,status=@"0" 是驗證收據成功

        return true;

    }

    return false;

}

接着說下此方法的使用,一般付費代碼中,童鞋們肯定會有如下函數:

- (void)paymentqueue:(skpaymentqueue *)queue updatedtransactions:(nsarray *)transactions//交易結果

{

    for (skpaymenttransaction *transaction in transactions)

    {

        switch (transaction.transactionstate)

        {

            case skpaymenttransactionstatepurchased://交易完成

                 if([self putstringtoitunes:transaction.transactionreceipt]){

                     //這裡給使用者添加錢阿,裝備阿什麼的

                 }

                   break;

             ......代碼省略

         }

     }

上面這個函數當擷取交易成功的消息都會進入到skpaymenttransactionstatepurchased這個case中(不管是iap cracker模拟的還是appstore真的回報的消息), 那麼我們一般不做iap防護情況下,會直接在此case中給使用者添加金币阿,什麼的! 但是如上所說因為iap cracker也會模拟傳回交易成功的消息,也會進入到這個case中,是以我們在此與appstore再次進行一次收據驗證!

另外說一點當交易完成時appstore傳回來的transaction(skpaymenttransaction)類中的transactionreceipt屬性裡包含appstore傳回經過簽名的收據資訊!ok,我們要的就是這個收據并将此收據post給appstore 的server進行收據驗證,是以在skpaymenttransactionstatepurchased這個交易成功的case中再調用himi封裝的函數if([self putstringtoitunes:transaction.transactionreceipt]){} 進行再次确認下購買是否付費流程正确!

那麼下面詳細說下himi封裝的這個putstringtoitunes函數:

此函數中,首先我們将傳入的收據data類型變量進行base64轉換成string類型,然後将此收據以json的形式發送給appstore進行驗證!這裡注意!一定要以json形式發送,否則appstore server端不識别!

最後再次利用json對appstore server傳回的字段(json資料)進行解析,我們隻需要解析出 status 這個key的value即可!

當appstore驗證收據正确時我們解析出來的 status 這個key的value值為0(零)!

下面是appstore傳回json資料的兩種形式:

1. 收據無效的情況:

{"status":21002, "exception":"java.lang.nullpointerexception"}

2.收據正确的情況,如下圖(點選放大):

【IOS-IAP防護】驗證使用者付費收據!拒絕IAP CRACKER!拒絕IAP FREE!讓IPHONE越獄使用者無從下手!【2012年5月2日更新防護IAP FREE的方法】

最後大家需要注意的一點是,himi封裝的函數中post的位址這裡要記得釋出的時候修改!

      因為當你沙盒測試的時候位址是:https://sandbox.itunes.apple.com/verifyreceipt

      但是正式釋出後post的位址應該是:  https://buy.itunes.apple.com/verifyreceipt

千萬不要釋出應用的時候别忘記修改這裡!

ok,本篇就介紹到這裡,希望對還沒有做iap防護的童鞋有所幫助!

—————2012年5月2日更新:

對于iap 的防護,現在除了iap cracker之外,那麼最主要的就是國人的iap free這個插件了,那麼對于iap free的防護,如果我們僅僅隻是跟apple的伺服器進行驗證收據,那麼iap free照樣能破解我們的遊戲/軟體!

我這裡先大概說下iap free:

iap free的功能與iap cracker功能類似,隻是更加強大的iap free能在你與apple伺服器進行驗證收據的步驟中進行截取,并傳回一個模仿apple傳回的假收據!這麼一說大家就很清楚了,我們上面說的iap 驗證收據變得毫無意義,但是不要着急,這裡himi将iap free的假收據形式列印了出來,大家對比看下就知道該如何來做iap free的防護了:

【IOS-IAP防護】驗證使用者付費收據!拒絕IAP CRACKER!拒絕IAP FREE!讓IPHONE越獄使用者無從下手!【2012年5月2日更新防護IAP FREE的方法】

上圖就是iap free制作的假收據啦,那麼至于如何繼續做防護,我想這裡不需要再多解釋了,畢竟有政策就有對策;大家發揮吧~

另外說一點,當使用者在無網的情況下購買任何産品,肯定隻有兩種情況,1.越獄機器想破解。2.忘記;

那麼我們可以使用下面這段代碼判斷目前ios裝置是否聯網了:

-(bool)isnetworkok{

    struct sockaddr_in zeroaddress;

    bzero(&amp;amp;zeroaddress, sizeof(zeroaddress));

    zeroaddress.sin_len = sizeof(zeroaddress);

    zeroaddress.sin_family = af_inet;

    scnetworkreachabilityref defaultroutereachability = scnetworkreachabilitycreatewithaddress(null, (struct sockaddr *)&amp;amp;zeroaddress);

    scnetworkreachabilityflags flags;  

    bool didretrieveflags = scnetworkreachabilitygetflags(defaultroutereachability, &amp;amp;flags);

    cfrelease(defaultroutereachability);  

    if (!didretrieveflags)

        nslog(@"error. could not recover network reachability flags");

        return no;

    }  

    bool isreachable = flags &amp;amp; kscnetworkflagsreachable;

    bool needsconnection = flags &amp;amp; kscnetworkflagsconnectionrequired;

    return (isreachable &amp;amp;&amp;amp; !needsconnection) ? yes : no;

項目中添加    systemconfiguration.framework

然後在導入 :

  #import &lt;systemconfiguration/scnetworkreachability.h&gt;

      #import &lt;netinet/in.h&gt;