2020年 IOS 逆向 反編譯 注入修改遊戲或APP的調用參數新手系列教程——使用theos tweak 注入hook修改遊戲執行代碼上傳動態頭像

開篇

太懶這篇其實文章很早就該寫的了,一方面記錄一下自己的代碼另一方面分享。

需求&最終效果

遊戲本身不支持上傳gif動態圖片,上傳前圖片會客戶端會做截圖處理,通過注入修改代碼,成功上傳動圖。

環境要求與即將使用的工具

之前我的MacOSX版本是10.10,只能安裝xcode7以下的版本,xcode7以下的版本沒有真機調試功能,於是升級了版本到MacOSX Catalina 10.15.4也安裝了最新版xcode,但是這個版本太卡而且有些問題,很多軟件兼容不了了,想以後降級。

環境 版本
操作系統 MacOSX Catalina 10.15.4 版本太新了不太好用很多工具用不了,我後面打算降級
手機系統 Iphone7 IOS11 需要越獄
mac上面的 theos 最新版
手機助手傳輸工具或SSH連接操作 -
xcode 11.5
手機端FLEXible(具備瀏覽appUI結構和APP抓包功能);或者用charles來抓包 -
mac 上面的 hopper disassembler反編譯工具 -

工具介紹

theos是用來編寫tweak代碼並且打包成deb包的工具。
FLEXible是手機端調試神器,可以查看APP的UI層級和代碼頭文件的方法和變量,更有抓包的功能!

ios11的ssh本人用不了,從cydia安裝了openssh,但是用命令行執行ssh報無法打開二進制文件的英文錯誤,不知道爲何,誰能在ios11運行ssh並且電腦連接手機ssh的麻煩告知我一下謝謝。

實現過程

思路

思路a:首先我要找到上傳圖片的POST請求,然後把上傳圖片參數的圖片url地址改掉。
思路a行不通,因爲上傳的時候遊戲客戶端對全部參數通過加密算法計算出了一個sign的參數提供給後臺,如果修改了其中任意參數會導致後臺驗證簽名失敗。
思路b:在本地上傳圖片裁剪窗口點擊保存圖片的的時候把本地圖片路徑改成我指定的路徑。
思路b可能可行但是我想還有更簡單的做法。
思路c:在上傳前對組裝的參數數組的代碼注入,強行改變圖片參數的url。也不會影響sign的生成正確邏輯。
思路d:反編譯看彙編代碼逆向sign參數的加密過程。這個難度比較大,耗時,但是如果把sign的生成過程解密了基本所有請求就都可以通過中間人攻擊來僞造數據。
思路c會簡單一點。用思路c的做法來做

理清圖片上傳請求過程

可以先通過FLEXible來看看目錄結構,有哪些控制器類和方法大致看看。


其實也可以不用看層級結構,我只要讓圖片上傳觸發抓包就行。
打開FLEXible的menu再選擇Network History ,點擊一下Settings把抓包功能開啓。
然後返回遊戲界面隨便上傳一張圖片,再打開Network查看抓包列表。

可以看到兩個比較可疑的POST請求就是最前面兩個:upload.qiniup.com和update_user_info
打開詳細查看

圖片看不全,我還是copy成curl貼出來吧。
如果不知道curl的同學可以自行去其他地方瞭解一下。

curl -v -X POST ‘https://upload.qiniup.com’ -H ‘User-Agent: QiniuObject-C/7.3.2 (iPhone; iOS 11.2.6; ABE768DC-FA02-4CAB-9DF8-2720B0E7C890; GcvQmcsBpX-WqRIW_YTKKXua3PbSXh831RS_u2NW)’ -H ‘Content-Type: multipart/form-data; boundary=werghnvt54wef654rjuhgb56trtg34tweuyrgf’ -H ‘Content-Length: 27824’ -H ‘Cookie:’ [TOO MUCH DATA TO INCLUDE]

這一個請求是把圖片流提交上去,當然這裏的boundary無法寫全,FLEXible工具無法顯示圖片流數據。Cookie數據也沒補全。cookie裏面是用戶的sid等之類的信息。
其實這個請求還依賴列表第三的那個請求的token,需要先獲取token再請求上傳,後面我會寫shell來體現。
成功上傳的話最終返回的是圖片的key和hash值,這一步僅僅只是把圖片上傳到了圖牀,還沒有鏈接在遊戲頭像上。
返回:

{
  "key" : "sa/fc6861905d20200613100399.jpg",
  "hash" : "FifEYajsNl7aqU88gsOYSyewk199"
}

這個key就是下面請求用到的headimgurl參數。
另外的一個POST請求:
下面我對於敏感參數用“某某”代替。

curl -v -X POST ‘https://某某.com/user_api/update_user_info’ -H ‘market: apple’ -H ‘Content-Type: application/x-www-form-urlencoded’ -H ‘某某Version: 4.3.31’ -H ‘某某UserID: 某某-5631-4446-某某-09da14d65cb9’ -H ‘某某Product: 某某’ -H ‘User-Agent: 某某/4.1.31 (iPhone; iOS 11.2.6; Scale/3.00)’ -H ‘Accept-Language: zh-Hans-CN;q=1’ -H ‘nonce: 1592013691’ -H ‘Cookie:’ -d ‘build_tag=4531.0&device_id=某某-A6FA-4A74-8CA3-某某-1779-0000008790C7E566&device_name=iPhone%207%20Plus&device_system_platform=iPhone9%2C2&headimgurl=https某某com/sa/fc6861905d20200613100399.jpg&idfa=0D79361D-C19F-4A77-84Bd-D725AA96B4D8&market=apple&os_version=11.2&platform=1&sid=某某&某某_sign=%2B70m/3s/1314dgNQ641mE9YmN6c%3D&uid=某某&version=4.1.31’

這個POST請求就是修改用戶頭像的請求,最關鍵的參數就是其中的headimgurl,前面提到如果直接通過修改url請求參數變更headimgurl這個地址的話是行不通的,因爲某某_sign這個參數是通過所有請求參數計算出來的,除非知道算法計算修改後的sign,否則後臺會提示簽名失敗。

shell實現上傳自己的gif動態圖片到圖牀

我要注入的代碼其實就是update_user_info這個請求拼裝的方法,拼裝headimgurl參數的時候修改成我要的圖片地址就ok了。
那麼我要先自定義圖片上傳到圖牀,不是用遊戲上傳圖片入口,而是用我自己寫的shell腳本來模擬post提交圖片到圖牀!最終獲取上傳圖片後的url地址。

#! bin/shell#! bin/shell

# 內容,查找的關鍵詞
getContentByKeyword() {
	content=$1
	keyword=$2
	echo $content | awk -F \"$keyword\"\:\" '{ print $2 }' | awk -F \" '{print $1}'
}
 
getHeaderByKeyword() {
	content=$1
	keyword=$2
	echo $content | grep $keyword | awk -F $keyword\:\  '{ print $2 }' | awk -F \  '{print $1}'
}

content=`curl -v -X POST 'https://某某.com/config/get_upload_token' -H 'market: apple' -H 'Content-Type: application/x-www-form-urlencoded' -H '某某Version: 4.1.26' -H '某某UserID: 某某' -H '某某Product: 某某' -H 'User-Agent: 某某/4.3.26 (iPhone; iOS 11.2.6; Scale/3.00)' -H 'Accept-Language: zh-Hans-CN;q=1' -H 'nonce: 1589783647' -H 'Cookie:' -d 'bucket=某某&build_tag=某某.0&device_id=某某-A4FA-4A64-某某-某某-1779-某某&device_name=iPhone%207%20Plus&device_system_platform=iPhone9%2C2&idfa=某某-C18F-4A77-84BC-某某&market=apple&os_version=11.2&platform=1&sid=某某&某某_sign=8HX%某某%3D&type=2&uid=某某-5495-439f-某某-某某&version=4.1.26'`
token=`getContentByKeyword "$content" "token"`
echo $token >> test2.txt


uploadResponse=`curl  -v -i https://upload.qbox.me  -F "token=$token"     -H 'User-Agent: QiniuObject-C/7.1.0 (iPhone; iOS 11.2.6; 某某-FA02-4CAB-某某-某某)' -H 'Content-Type: multipart/form-data' -H 'Accept-Language: zh-cn' -H 'Accept-Encoding: br, gzip, deflate' -H 'Cookie:'  -H 'Accept: */*' -F "file=@/Users/mac/Desktop/test4.gif"`
nonce=`getHeaderByKeyword "$uploadResponse" "EagleId"`
picPath=`getContentByKeyword "$uploadResponse" "key"`
echo $nonce >> test2.txt
echo $picPath >> test2.txt
nonce=${nonce:8:10}
timeStamp=`date +%s`   
nonce=timeStamp
echo $nonce >> test2.txt

第一步獲取token,通過用戶uid sid等參數請求get_upload_token得到。
第二步請求upload.qbox.me把本地gif動態圖片傳上去
例如上面代碼中 -F “file=@/Users/mac/Desktop/test4.gif”
上傳成功得到類似的數據,key就是headimgurl要拼裝的圖片地址。

{
  "key" : "sa/fc6861905d20200613100399.gif",
  "hash" : "FifEYajsNl7aqU88gsOYSyewk199"
}

反編譯分析彙編代碼找出注入的方法(函數)

先砸殼,本文略過,詳情查看我文章:用bfinject脫殼、注入自己的動態framework、cycript的使用
的到Mach-O文件後,用 hopper disassembler打開,查找關鍵詞。
例如我查找修改頭像的api關鍵詞:update_user_info

右鍵進入誰調用這個地址,跳轉切換成僞代碼一看。

基本是這個方法了userApiUpdateUserInfoWithDict。
意思是通過字典變量來修改用戶信息。headimgurl就是其中一個字典鍵,只要我們修改headimgurl的值就達到換圖片地址的目的。當然只是猜想。

編寫tweak

驗證猜想。
我是這樣做的,tweak寫hook這個方法,打印一下這個方法的實參,看看是什麼內容。
可以先用class-dump把頭文件導出來看看參數類型是啥,這裏省略。
寫tweak hook。mac 執行命令nic.pl來新建個tweak工程。

choose a template 填11。
MobileSubstrate Bundle filter 要填寫對應APP的bundleID,可以通過手機連接電腦查看電腦控制檯來觀察到相關關鍵字。
其他選項回車就行。
最終生成目錄:

修改一下Makefile,在include $(THEOS… 上面新增兩行代碼

ARCHS = armv7 arm64
TARGET = iphone:latest:8.0

指定arm版本和編譯手機的ios版本

打開Tweak.xm寫代碼:

%hook SnakeAPI
+ (void)userApiUpdateUserInfoWithDict:(id)arg1 success:(id)arg2 failure:(id)arg3 {
	NSLog(@"打印。。。%@", arg1);
 	%log;
	%orig; 
}
%end

保存,mac執行make package最終生成一個deb包。把deb通過ssh或者手機助手工具拷貝到手機安裝,如果手機有Filza文件瀏覽器,可以通過Filza打開deb安裝;如果沒有隻能通過terminal命令行工具安裝,命令如下:

dpkg -i 包名.deb

手機連接mac,打開mac控制檯軟件。
手機打開遊戲,上傳一下頭像,觀察mac控制檯是否有觸發到日誌,日誌要自己篩選。最終我看到了日誌有輸出。
內容類似:

[headimgurl] = 'sa/234234234234234.jpg'

證明arg1是一個字典。
只要修改arg1的headimgurl就能實現圖片自定義。

因爲arg1是一個不可變字典,直接修改key對應值是行不通的,所以我簡單粗暴,銷燬arg1從新定義一個。
最終tweak代碼如下:

%hook SnakeAPI
+ (void)userApiUpdateUserInfoWithDict:(id)arg1 success:(id)arg2 failure:(id)arg3 {
	NSLog(@"打印前。。。%@", arg1);
	arg1 =nil;
	arg1 = [NSDictionary dictionaryWithObjectsAndKeys:
    	@"https://某某/sa/2345345345345345.jpg", @"headimgurl",nil];
	NSLog(@"打印後。。。%@", arg1);
 	%log;
  	%orig; 
}
%end

圖片地址我寫死了,就是我用shell上傳圖片返回的地址,是一張動圖。
再次編譯tweak代碼生成deb安裝到手機。
手機去上傳一下頭像。
上傳成功,但是頭像並不是我們的動態圖,我猜是本地緩存,重啓遊戲,喲嚯,頭像刷新了,變成我們要的動圖:

結束

此教程僅做學習交流和知識記錄方便以後查看使用,如果涉及到利益相關的請告知本人進行刪帖處理。

本人想通過這些博客記錄自己這兩週內折騰的過程以及分享最後成功的成果。另外想結交志同道合對IT行業感興趣的盆友,互相交流學習。可以通過博客聯繫我或加QQ號:1321691245
只交朋友不接受接單之類的騷擾。

博文主索引目錄入口

我會把這系列的文章更新到這個入口裏面,分享我的心得,大家互相學習。
2020年 IOS 逆向 反編譯 注入修改遊戲或APP的調用參數新手系列教程主目錄入口

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章