前言
此文為逆向微信二進(jìn)制文件,實(shí)現(xiàn)偽裝定位,查看附近的人的教程,手把手教你玩轉(zhuǎn)微信!學(xué)會(huì)之后再去逆向微信其他功能易如反掌。
在實(shí)踐之前,需要準(zhǔn)備好一部越獄的手機(jī),涉及到的開發(fā)工具有cycript,LLDB與debugserver,OpenSSH,IDA,Reveal,theos,CydiaSubstrate,dumpdecrypted,class-dump等,具體安裝過(guò)程請(qǐng)參考iOS應(yīng)用逆向工程(第2版)書籍。
當(dāng)前微信版本號(hào)為6.5.18。
git地址 https://github.com/zhaochengxiang/iOSWeChatFakeLocation
需求
自定義用戶當(dāng)前所在的位置,從而查看附近的人。
實(shí)現(xiàn)界面



對(duì)需求進(jìn)行分析
1.查看附近的人。
我們?cè)谖⑿诺母浇娜私缑妫窃趺磳?shí)現(xiàn)獲取附近的人功能的呢?我想的話,大家一定很容易就知道,微信肯定是通過(guò)用戶所在位置的經(jīng)緯度來(lái)判斷的,那我們?nèi)绻茉诟浇娜私缑?,找到使用?jīng)緯度的函數(shù),在里面使用我們之前保存在本地的經(jīng)緯度等信息,我們的需求就能實(shí)現(xiàn)了。
2.自定義用戶當(dāng)前所在的位置。
我們?cè)谖⑿诺牧奶旖缑嬷杏袀€(gè)發(fā)送位置的界面,可以從界面中的地圖上選取地點(diǎn),也可以搜索地點(diǎn),點(diǎn)擊右上角的發(fā)送,即可發(fā)送選中的位置,那如果發(fā)送的數(shù)據(jù)里面能獲取到用戶的經(jīng)緯度等信息,再將這些信息保存在本地,我們的偽裝定位功能就能實(shí)現(xiàn)了。
3.如何跳轉(zhuǎn)到發(fā)送位置界面。
這里跳轉(zhuǎn),可以參考下從聊天界面跳轉(zhuǎn)到發(fā)送位置界面的實(shí)現(xiàn)過(guò)程。
OK,需求分析到此結(jié)束,是時(shí)候來(lái)看看具體的操作了。
找到附近的人界面使用經(jīng)緯度的函數(shù)
1.通過(guò)Reveal以及cycript,找到微信附近的人界面。
微信進(jìn)入附近的人界面,連接Reveal,可以發(fā)現(xiàn)這個(gè)界面使用了一個(gè)名為MMTableView的控件。接下來(lái)我們通過(guò)這個(gè)控件,來(lái)一步一步找到附近的人界面的ViewController。
使用USB連接到iOS,具體操作請(qǐng)參考iOS應(yīng)用逆向工程(第二版)中usbmuxd的介紹。
接下來(lái)使用cycript來(lái)找到這個(gè)ViewController。

我們?cè)诮K端搜索MMTableView,找到這個(gè)類的地址。通過(guò)這個(gè)地址找到ViewController。

找到PeopleNearByListViewController,設(shè)置它的右側(cè)導(dǎo)航控件為空,發(fā)現(xiàn)界面沒反應(yīng),這個(gè)PeopleNearByListViewController可能不是我們要找的目標(biāo),通過(guò)PeopleNearByListViewController繼續(xù)往上找。

找到SeePeopleNearbyViewController,設(shè)置它的右側(cè)導(dǎo)航控件為空,發(fā)現(xiàn)界面右上角控件消失,可以肯定,這個(gè)SeePeopleNearbyViewController就是我們要找的。
我們打開SeePeopleNearbyViewController.h文件,大致瀏覽一下,發(fā)現(xiàn)該類未找到使用用戶地址相關(guān)的接口,但是在里面發(fā)現(xiàn)了SeePeopleNearByLogicController類,微信通常將ViewController中使用的邏輯放在LogicController中進(jìn)行處理,看一下SeePeopleNearByLogicController.h文件,能夠看到很多與地址有關(guān)的數(shù)據(jù)以及接口,這個(gè)類并不復(fù)雜,我相信大家很快就能確定- (void)onRetrieveLocationOK:(id)arg1這個(gè)接口,可能就是我們需要的接口,arg1可能就是用戶當(dāng)前的經(jīng)緯度等信息。如果真是我們分析的這樣,讓我們直接在這里使用我們偽裝后的位置,就能達(dá)到我們的目的。
那怎么確定這個(gè)接口就是我們要找的呢?
有兩種方法,第一種方法是通過(guò)LLDB與debugserver。首先在IDA中打開微信的二進(jìn)制文件,找到上述接口。

符號(hào)所在模塊的ASLR偏移為0x1016e8250

偏移前符號(hào)基地址為0x2c000
偏移后符號(hào)基地址為 0x1016e8250+ 0x2c000=0x101714250

設(shè)置斷點(diǎn),重新進(jìn)入附近的人界面。

輸出arg1的值。

可以看到,這是用戶當(dāng)前的經(jīng)緯度信息。
第二種方法是通過(guò)Tweek,直接hook上述接口,打印arg1參數(shù)即可,這種比較簡(jiǎn)單,在這里就不做介紹了。
在發(fā)送位置界面截獲經(jīng)緯度等信息
1.通過(guò)Reveal以及cycript,找到發(fā)送位置的界面。這里就就具體介紹了,參考上面的過(guò)程。相信大家很快就能找到MMPickLocationViewController。那右上角的發(fā)送按鈕是如何設(shè)置的呢?右上角的按鈕一般是UIBarButtonItem通過(guò)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action來(lái)初始化,如果我們找到了設(shè)置按鈕的地方,也就找到了事件響應(yīng)的地方,里面一定有我們所需要的位置的經(jīng)緯度等信息。帶著問(wèn)題,我們看看MMPickLocationViewController.h,發(fā)現(xiàn)未找到與右上角相關(guān)的接口信息,但是我們發(fā)現(xiàn)了MMPickLocationViewControllerDelegate,我們看看代理中的方法,發(fā)現(xiàn)了- (UIBarButtonItem *)onGetRightBarButton,原來(lái)是在上層界面中進(jìn)行的設(shè)置。在微信頭文件搜索MMPickLocationViewControllerDelegate,能找到BaseMsgContentLogicController.h,該類是用來(lái)處理聊天界面中的邏輯,使用IDA看看BaseMsgContentLogicController中onGetRightBarButton的具體實(shí)現(xiàn)。

分析匯編,能判斷出發(fā)送按鈕的響應(yīng)函數(shù)為onFinishSelectedLocation,使用IDA分析這個(gè)函數(shù)實(shí)現(xiàn)。

上面只截取了部分信息。分析匯編,首先[m_pickLocationViewController DismissMyselfAnimated:YES] 來(lái)返回聊天界面,接著使用[m_pickLocationViewController getCurrentPOIInfo]獲取POIInfo信息,最后調(diào)用[m_pickLocationViewController reportOnDone]徹底釋放發(fā)送位置界面。打開POIInfo.h,能很快發(fā)現(xiàn)@property(nonatomic) struct CLLocationCoordinate2D coordinate,這就是我們要找的位置信息,將它保存在本地即可。
如何跳轉(zhuǎn)到發(fā)送位置界面
這里我們參考聊天界面跳轉(zhuǎn)到發(fā)送位置界面的過(guò)程,如果能找到相關(guān)函數(shù),分析里面的實(shí)現(xiàn),那我們這個(gè)問(wèn)題就能得到解決。
那我們打開聊天界面的邏輯控制器BaseMsgContentLogicController,觀察該頭文件,發(fā)現(xiàn)兩個(gè)可疑的接口:
- (void)ViewLocation:(id)arg1;
- (void)SelectLocation:(_Bool)arg;
首先通過(guò)IDA來(lái)分析ViewLocation實(shí)現(xiàn)。

分析匯編,很容易知道,這是個(gè)彈出提示,用來(lái)提示是發(fā)送位置還是共享實(shí)時(shí)位置。
接著來(lái)分析SelectLocation實(shí)現(xiàn)。



分析匯編,首先MMPickLocationViewController通過(guò)- (id)initWithScene:(unsigned int)arg1 OnlyUseUserLocation:(_Bool)arg2來(lái)進(jìn)行初始化,然后[[MMUINavigationController alloc] initWithRootViewController: m_pickLocationViewController]來(lái)初始化NavigationController,這里假設(shè)該NavigationController命名為nc,最后使用[self PresentModalViewController:nc animated:YES]來(lái)進(jìn)行跳轉(zhuǎn)。
(initWithScene:OnlyUseUserLocation:的參數(shù)請(qǐng)參考之前介紹的調(diào)適方法來(lái)獲取值,這里就不重復(fù)介紹了)。
OK,分析完畢,開始寫tweek吧。
后期我將繼續(xù)微信的一些小插件開發(fā),請(qǐng)關(guān)注一下我,謝謝!
如果覺得我的文章不錯(cuò),請(qǐng)我喝杯熱茶吧
