去掉某应用feed流广告和帖子下方广告

一、所用工具:

  • frida-ios-dump应用砸壳
  • class-dump导出应用头文件
  • reveal查看应用层次结构
  • hopper反汇编工具。其实可以不用,毕竟太费时间
  • debugserver/lldb动态调试工具

二、从界面出发:


得到类TBCAdCriusTableViewCell,查看其头文件

@interface TBCAdCriusTableViewCell : TBCAdCriusBaseTableViewCell <TBCAdCriusRenderDelegate>
{
    _Bool _havaStatDiscardEvent;
    CriusContainerView *_container;
    TBCFRSBatchDeleteCoverView *_batchDeleteCoverView;
}

+ (double)tableView:(id)arg1 rowHeightForObject:(id)arg2;
- (void).cxx_destruct;
@property(nonatomic) _Bool havaStatDiscardEvent; // @synthesize havaStatDiscardEvent=_havaStatDiscardEvent;
@property(retain, nonatomic) TBCFRSBatchDeleteCoverView *batchDeleteCoverView; // @synthesize batchDeleteCoverView=_batchDeleteCoverView;
@property(retain, nonatomic) CriusContainerView *container; // @synthesize container=_container;
- (void)didSelectCriusObjectOnCell:(long long)arg1;
- (_Bool)adCellIsHighlightedOrSelected;
- (void)adCellDetailButtonDidClickEvent:(id)arg1;
- (void)adCellBottomBarReplyButtonDidClickEvent;
- (void)adCellBottomBarAgreeButtonDidClickEvent:(id)arg1;
- (void)adCellBottomBarShareButtonDidClickEvent:(id)arg1;
- (void)adCellCloseButtonDidClickEvent:(id)arg1;
- (void)commonAdStat:(unsigned long long)arg1;
- (void)commonShowStat;
- (void)didSelectObject:(id)arg1;
- (void)setObject:(id)arg1;
- (void)setCommonBackgroundColor;
- (void)layoutSubviews;

// Remaining properties
@property(readonly, copy) NSString *debugDescription;
@property(readonly, copy) NSString *description;
@property(readonly) unsigned long long hash;
@property(readonly) Class superclass;

@end

决定给- (void)layoutSubviews下断点(我是7分靠猜,3分靠调试)
用hopper查看地址(也可以直接使用shortMethodDescription方法找到地址下断点):


拿到地址0x1028d00d4。


三、动态调试:

(使用了xia0lldb脚本)

(lldb) im li -o -f | grep TBClient
[  0] 0x00000000000c0000 /var/containers/Bundle/Application/BC287342-F5D8-450E-8B9D-7972124D7806/TBClient.app/TBClient(0x00000001000c0000)
(lldb) br s -a '0xc0000+0x1028d00d4'
Breakpoint 1: where = TBClient`___lldb_unnamed_symbol197197$$TBClient, address = 0x00000001029900d4
(lldb) c
Process 5773 resuming
Process 5773 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00000001029900d4 TBClient`___lldb_unnamed_symbol197197$$TBClient
TBClient`___lldb_unnamed_symbol197197$$TBClient:
->  0x1029900d4 <+0>:  sub    sp, sp, #0x30             ; =0x30
    0x1029900d8 <+4>:  stp    x20, x19, [sp, #0x10]
    0x1029900dc <+8>:  stp    x29, x30, [sp, #0x20]
    0x1029900e0 <+12>: add    x29, sp, #0x20            ; =0x20
    0x1029900e4 <+16>: mov    x19, x0
    0x1029900e8 <+20>: adrp   x8, 12811
    0x1029900ec <+24>: ldr    x8, [x8, #0xee8]
    0x1029900f0 <+28>: stp    x0, x8, [sp]
Target 0: (TBClient) stopped.

查看调用栈

(lldb) sbt
  ==========================================xia0LLDB===========================================
  BlockSymbolFile    Not Set The Block Symbol Json File, Try 'sbt -f'
  =============================================================================================
  frame #0: [file:0x1028d00d4 mem:0x1029900d4] TBClient`-[TBCAdCriusTableViewCell layoutSubviews] + 0
  frame #1: [file:0x187775cc0 mem:0x190599cc0] UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1200
........
........
  frame #23: [file:0x1877ddc9c mem:0x190601c9c] UIKit`UIApplicationMain + 208
  frame #24: [file:0x1003220d0 mem:0x1003e20d0] TBClient`main + 200
  frame #25: [file:0x18053159c mem:0x18935559c] libdyld.dylib`start + 4

(lldb) c

断点应该下错了,没有看到有用的被调用的方法或函数,回头再看看头文件,有个属性CriusContainerView *_container,猜测是广告容器视图,看看它有什么方法

(lldb) po [CriusContainerView  _shortMethodDescription]
<CriusContainerView: 0x105c6f588>:
in CriusContainerView:
        Class Methods:
                + (id) currentCriusRender; (0x1029815e4)
        Properties:
                @property (copy, nonatomic) NSString* clickCommand;  (@synthesize clickCommand = _clickCommand;)
                @property (nonatomic) BOOL hasSetClickCommand;  (@synthesize hasSetClickCommand = _hasSetClickCommand;)
        Instance Methods:
                - (void) configWithCriusNode:(id)arg1 isNightMode:(unsigned char)arg2 promotionItem:(id)arg3 renderDelegate:(id)arg4; (0x102981794)
                - (double) calculateHeightWithCriusData:(id)arg1; (0x1029818ac)
                - (void) configWithCriusData:(id)arg1 isNightMode:(unsigned char)arg2 promotionItem:(id)arg3 renderDelegate:(id)arg4; (0x1029816d4)
                - (id) clickCommand; (0x102981bc0)
                - (void) setClickCommand:(id)arg1; (0x102981bd0)
                - (BOOL) hasSetClickCommand; (0x102981bdc)
                - (void) setHasSetClickCommand:(BOOL)arg1; (0x102981bec)
                - (id) init; (0x10298167c)
                - (void) .cxx_destruct; (0x102981bfc)
                - (id) hitTest:(struct CGPoint)arg1 withEvent:(id)arg2; (0x102981930)
(UIView ...)

有个我喜欢的初始化方法- (id)init,下断点看看:

(lldb) b 0x10298167c
Breakpoint 2: where = TBClient`___lldb_unnamed_symbol196763$$TBClient, address = 0x000000010298167c
(lldb) c
Process 5773 resuming
Process 5773 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
    frame #0: 0x000000010298167c TBClient`___lldb_unnamed_symbol196763$$TBClient
TBClient`___lldb_unnamed_symbol196763$$TBClient:
->  0x10298167c <+0>:  sub    sp, sp, #0x30             ; =0x30
    0x102981680 <+4>:  stp    x20, x19, [sp, #0x10]
    0x102981684 <+8>:  stp    x29, x30, [sp, #0x20]
    0x102981688 <+12>: add    x29, sp, #0x20            ; =0x20
    0x10298168c <+16>: adrp   x8, 12826
    0x102981690 <+20>: ldr    x8, [x8, #0xeb8]
    0x102981694 <+24>: stp    x0, x8, [sp]
    0x102981698 <+28>: adrp   x8, 12608
Target 0: (TBClient) stopped.

再次查看调用栈:

(lldb) sbt
  ==========================================xia0LLDB===========================================
  BlockSymbolFile    Not Set The Block Symbol Json File, Try 'sbt -f'
  =============================================================================================
  frame #0: [file:0x1028c167c mem:0x10298167c] TBClient`-[CriusContainerView init] + 0
  frame #1: [file:0x10159d968 mem:0x10165d968] TBClient`Maybe c function? Distance:39176 >= 2500 # Symbol:-[Tools setStatusCreateAt_t:] + 39176
  frame #2: [file:0x1028d09dc mem:0x1029909dc] TBClient`-[TBCAdCriusTableViewCell setObject:] + 596
  frame #3: [file:0x10298428c mem:0x102a4428c] TBClient`-[TBCPluginFrsFeedAd tableView:cellForRowAtIndexPath:] + 1528
  frame #4: [file:0x1014bf320 mem:0x10157f320] TBClient`-[TBPluginTableViewProxy tableView:cellForRowAtIndexPath:] + 272
  frame #5: [file:0x187abdd90 mem:0x1908e1d90] UIKit`-[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 688
......
......
  frame #22: [file:0x1877ddc9c mem:0x190601c9c] UIKit`UIApplicationMain + 208
  frame #23: [file:0x1003220d0 mem:0x1003e20d0] TBClient`main + 200
  frame #24: [file:0x18053159c mem:0x18935559c] libdyld.dylib`start + 4

(lldb) c

观察到第一个调用的可能是广告的方法-[TBCPluginFrsFeedAd tableView:cellForRowAtIndexPath:],看看TBCPluginFrsFeedAd有哪些方法:

(lldb) po [TBCPluginFrsFeedAd  _shortMethodDescription]
<TBCPluginFrsFeedAd: 0x105c71ce8>:
in TBCPluginFrsFeedAd:
        Class Methods:
                + (id) hostIdentifications; (0x102a43550)
                + (id) identification; (0x102a435bc)
                + (id) pluginInstance; (0x102a435c8)
        Properties:
                @property (retain, nonatomic) TBPluginItem* item;  (@synthesize item = _item;)
                @property (retain, nonatomic) TBCFCFrsBannerView* bannerView;  (@synthesize bannerView = _bannerView;)
                @property (nonatomic) BOOL confirmedPlayVideoUnderWWAN;  (@synthesize confirmedPlayVideoUnderWWAN = _confirmedPlayVideoUnderWWAN;)
                @property (retain, nonatomic) FMShareUIComponent* component;  (@synthesize component = _component;)
                @property (retain, nonatomic) id selectedLegoObject;  (@synthesize selectedLegoObject = _selectedLegoObject;)
                @property (nonatomic) long sectionIndex;  (@synthesize sectionIndex = _sectionIndex;)
                @property (readonly) unsigned long hash;
                @property (readonly) Class superclass;
                @property (readonly, copy) NSString* description;
                @property (readonly, copy) NSString* debugDescription;
        Instance Methods:
                - (id) contentForType:(int)arg1; (0x102a47a1c)
                - (void) unLoad:(id)arg1; (0x102a43a90)
                - (id) processRequest:(id)arg1 fromPlugin:(id)arg2 andParams:(id)arg3; (0x102a43a88)
                - (id) tableView:(id)arg1 mapIndexPath:(id)arg2; (0x102a43c08)
                - (id) itemClzNames; (0x102a43c24)
                - (void) handleLegoEvent:(unsigned long)arg1 cell:(id)arg2 clickArea:(id)arg3 deepLinkType:(long)arg4 extraInfo:(id)arg5; (0x102a46b94)
                - (void) setConfirmedPlayVideoUnderWWAN:(BOOL)arg1; (0x102a47b24)
                - (void) createForumBannerView:(id)arg1; (0x102a4599c)
                - (void) handleAndInsertAds:(id)arg1; (0x102a44a3c)
                - (void) handleAds:(id)arg1 adList:(id)arg2 minAdSpace:(long)arg3 firstAdLocate:(long)arg4; (0x102a44c70)
                - (long) orientationConvertor:(id)arg1; (0x102a45460)
                - (long) sortTypeConvertor:(id)arg1; (0x102a45494)
                - (void) statLegoPromotionClick:(id)arg1 deepLinkType:(long)arg2 clickArea:(id)arg3 extInfo:(id)arg4; (0x102a46f04)
                - (void) legoCellDidShow:(id)arg1 withObject:(id)arg2; (0x102a46a20)
                - (void) reportCloseAdWithExtInfo:(id)arg1 closeReasons:(id)arg2; (0x102a457a0)
                - (void) removeAdItem:(id)arg1; (0x102a45510)
                - (void) clickPromotionVideoViewUnderWiFi:(id)arg1; (0x102a47188)
                - (void) clickPromotionVideoViewUnderWWAN:(id)arg1; (0x102a471f0)
                - (void) handleLegoShareClick:(id)arg1 withObject:(id)arg2; (0x102a47438)
                - (void) handleLegoLikeClick:(id)arg1 withObject:(id)arg2; (0x102a47868)
                - (void) reportAdNoPicDiscard:(id)arg1; (0x102a45834)
                - (BOOL) confirmedPlayVideoUnderWWAN; (0x102a47b1c)
                - (void) setSelectedLegoObject:(id)arg1; (0x102a47b48)
                - (id) selectedLegoObject; (0x102a47b40)
                - (void) tbcFrsBannerLoadFinished; (0x102a4688c)
                - (void) tbcFrsBannerViewDidClosed; (0x102a46890)
                - (BOOL) load:(id)arg1; (0x102a435f0)
                - (void) .cxx_destruct; (0x102a47b64)
                - (void) tableView:(id)arg1 willDisplayCell:(id)arg2 forRowAtIndexPath:(id)arg3; (0x102a449d4)
                - (void) tableView:(id)arg1 didEndDisplayingCell:(id)arg2 forRowAtIndexPath:(id)arg3; (0x102a448a8)
                - (double) tableView:(id)arg1 heightForRowAtIndexPath:(id)arg2; (0x102a442d8)
                - (void) tableView:(id)arg1 didSelectRowAtIndexPath:(id)arg2; (0x102a44648)
                - (long) tableView:(id)arg1 numberOfRowsInSection:(long)arg2; (0x102a442d0)
                - (id) tableView:(id)arg1 cellForRowAtIndexPath:(id)arg2; (0x102a43c94)
                - (id) item; (0x102a47af4)
                - (BOOL) update:(id)arg1; (0x102a43794)
                - (void) setItem:(id)arg1; (0x102a47afc)
                - (id) component; (0x102a47b2c)
                - (void) setComponent:(id)arg1; (0x102a47b34)
                - (void) setBannerView:(id)arg1; (0x102a47b10)
                - (id) bannerView; (0x102a47b08)
                - (void) setSectionIndex:(long)arg1; (0x102a47b5c)
                - (long) sectionIndex; (0x102a47b54)
(NSObject ...)

猜测- (void) handleAds:(id)arg1 adList:(id)arg2 minAdSpace:(long)arg3 firstAdLocate:(long)arg4是处理广告的方法,下个断点看看:

(lldb) b 0x102a44c70
Breakpoint 3: where = TBClient`___lldb_unnamed_symbol200801$$TBClient, address = 0x0000000102a44c70
(lldb) c
Process 5773 resuming
Process 5773 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
    frame #0: 0x0000000102a44c70 TBClient`___lldb_unnamed_symbol200801$$TBClient
TBClient`___lldb_unnamed_symbol200801$$TBClient:
->  0x102a44c70 <+0>:  sub    sp, sp, #0x1e0            ; =0x1e0
    0x102a44c74 <+4>:  stp    x28, x27, [sp, #0x180]
    0x102a44c78 <+8>:  stp    x26, x25, [sp, #0x190]
    0x102a44c7c <+12>: stp    x24, x23, [sp, #0x1a0]
    0x102a44c80 <+16>: stp    x22, x21, [sp, #0x1b0]
    0x102a44c84 <+20>: stp    x20, x19, [sp, #0x1c0]
    0x102a44c88 <+24>: stp    x29, x30, [sp, #0x1d0]
    0x102a44c8c <+28>: add    x29, sp, #0x1d0           ; =0x1d0
Target 0: (TBClient) stopped.

打印第一个参数:

(lldb) po $x2
<TBPluginContextFrs: 0x175a925c0>

打印第二个参数:

(lldb) po $x3
<__NSArrayM 0x17645a640>(
<TBCPromotionItem: 0x1310accc0>,
<TBCPromotionItem: 0x12f4e3ea0>,
<TBCPromotionItem: 0x12bd5de10>
)

第二个参数为数组,保存的是TBCPromotionItem对象,看起来是激励项目,可能就是广告。尝试将它的值赋为空,再继续运行程序:

(lldb) expression $x3 = nil
(unsigned long) $101 = 0
(lldb) c
Process 5773 resuming
Process 5773 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
    frame #0: 0x0000000102a44c70 TBClient`___lldb_unnamed_symbol200801$$TBClient
TBClient`___lldb_unnamed_symbol200801$$TBClient:
->  0x102a44c70 <+0>:  sub    sp, sp, #0x1e0            ; =0x1e0
    0x102a44c74 <+4>:  stp    x28, x27, [sp, #0x180]
    0x102a44c78 <+8>:  stp    x26, x25, [sp, #0x190]
    0x102a44c7c <+12>: stp    x24, x23, [sp, #0x1a0]
    0x102a44c80 <+16>: stp    x22, x21, [sp, #0x1b0]
    0x102a44c84 <+20>: stp    x20, x19, [sp, #0x1c0]
    0x102a44c88 <+24>: stp    x29, x30, [sp, #0x1d0]
    0x102a44c8c <+28>: add    x29, sp, #0x1d0           ; =0x1d0
Target 0: (TBClient) stopped.
(lldb) po $x3
<__NSArrayM 0x171c5c4d0>(
<TBCPromotionItem: 0x1316b4fd0>,
<TBCPromotionItem: 0x1355bbf20>,
<TBCPromotionItem: 0x1316cd8a0>
)

(lldb) expression $x3 = nil
(unsigned long) $103 = 0
(lldb) c

不再触发断点,且已经看不到feed流广告,说明这个item里包含了feed流广告。再看TBCPromotionItem有什么方法:

(lldb) po [TBCPromotionItem  _shortMethodDescription] 
<TBCPromotionItem: 0x105c2aa28>: 
in TBCPromotionItem: 
Class Methods: 
		+ (BOOL) isPromotionValid:(id)arg1; (0x10132c4ec) 
     ..............
..................
		- (void) setRealIndex:(long)arg1; (0x10132cd98) 
		- (void) setIsPreloadAd:(BOOL)arg1; (0x10132cdb8) 
		- (id) init; (0x10132bf3c) 

它也有个初始化方法- (id)init,使用br del删掉前面的所有断点,也给它下个断点,以便验证我的猜想。然后想看看帖子下面的广告在哪个类的,结果点进去就触发了这个断点,也就意味着帖子下方的广告也是调用的TBCPromotionItem:

(lldb) b 0x10132bf3c
Breakpoint 6: where = TBClient`___lldb_unnamed_symbol90120$$TBClient, address = 0x000000010132bf3c
(lldb) c
error: Process is running.  Use 'process interrupt' to pause execution.
Process 5773 stopped
* thread #100, queue = 'com.tieba.baidu.immq', stop reason = breakpoint 6.1
    frame #0: 0x000000010132bf3c TBClient`___lldb_unnamed_symbol90120$$TBClient
TBClient`___lldb_unnamed_symbol90120$$TBClient:
->  0x10132bf3c <+0>:  sub    sp, sp, #0x40             ; =0x40
    0x10132bf40 <+4>:  stp    x22, x21, [sp, #0x10]
    0x10132bf44 <+8>:  stp    x20, x19, [sp, #0x20]
    0x10132bf48 <+12>: stp    x29, x30, [sp, #0x30]
    0x10132bf4c <+16>: add    x29, sp, #0x30            ; =0x30
    0x10132bf50 <+20>: adrp   x8, 18540
    0x10132bf54 <+24>: ldr    x8, [x8, #0x7c0]
    0x10132bf58 <+28>: stp    x0, x8, [sp]
Target 0: (TBClient) stopped.
(lldb) x/s $x1
0x1910d9b38: "init"
(lldb) thread return nil
* thread #100, queue = 'com.tieba.baidu.immq', stop reason = breakpoint 6.1
    frame #0: 0x00000001015dc180 TBClient`___lldb_unnamed_symbol105441$$TBClient + 2864
TBClient`___lldb_unnamed_symbol105441$$TBClient:
->  0x1015dc180 <+2864>: mov    x21, x22
    0x1015dc184 <+2868>: mov    x22, x24
    0x1015dc188 <+2872>: mov    x24, x26
    0x1015dc18c <+2876>: mov    x26, x19
    0x1015dc190 <+2880>: mov    x19, x28
    0x1015dc194 <+2884>: mov    x28, x0
    0x1015dc198 <+2888>: mov    x0, x25
    0x1015dc19c <+2892>: ldr    x1, [sp, #0x18]
(lldb) c

返回空后帖子下方的广告也没有了。

整理一下:

feed流广告和帖子下方的广告都是在TBCPromotionItem中的,干掉里面的初始化方法,就能简单的达到去广告的效果


四、编写插件:

%hook TBCPromotionItem
- (id)init
{
       return nil;
}
%end
2 个赞

老人家来学习