對于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并沒有不管,而是已經在文檔中清晰的說明,隻是很多童鞋并沒有發現,如下截圖:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iMyIzLcNDMvwlMxAjMvw1ckF2bsBXdvwFduVGdu92YtA3dvwVbvNmLl1WYnlWbphmL3d3dvw1LcpDc0RHaiojIsJye.png)
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;urlresponse
error:&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.收據正确的情況,如下圖(點選放大):
最後大家需要注意的一點是,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的防護了:
上圖就是iap free制作的假收據啦,那麼至于如何繼續做防護,我想這裡不需要再多解釋了,畢竟有政策就有對策;大家發揮吧~
另外說一點,當使用者在無網的情況下購買任何産品,肯定隻有兩種情況,1.越獄機器想破解。2.忘記;
那麼我們可以使用下面這段代碼判斷目前ios裝置是否聯網了:
-(bool)isnetworkok{
struct sockaddr_in zeroaddress;
bzero(&amp;zeroaddress, sizeof(zeroaddress));
zeroaddress.sin_len = sizeof(zeroaddress);
zeroaddress.sin_family = af_inet;
scnetworkreachabilityref defaultroutereachability = scnetworkreachabilitycreatewithaddress(null, (struct sockaddr *)&amp;zeroaddress);
scnetworkreachabilityflags flags;
bool didretrieveflags = scnetworkreachabilitygetflags(defaultroutereachability, &amp;flags);
cfrelease(defaultroutereachability);
if (!didretrieveflags)
nslog(@"error. could not recover network reachability flags");
return no;
}
bool isreachable = flags &amp; kscnetworkflagsreachable;
bool needsconnection = flags &amp; kscnetworkflagsconnectionrequired;
return (isreachable &amp;&amp; !needsconnection) ? yes : no;
項目中添加 systemconfiguration.framework
然後在導入 :
#import <systemconfiguration/scnetworkreachability.h>
#import <netinet/in.h>