Slide 1

Slide 1 text

Swizzling Swizzling Swizzling 2023/9/1 iOSDC 2023 Taiki Komaba @r_plus

Slide 2

Slide 2 text

UBJLJLPNBCB 
 !S@QMVT

Slide 3

Slide 3 text

SwizzlingΛݕ౼͢Δલʹ…

Slide 4

Slide 4 text

SwizzlingΛݕ౼͢Δલʹ… w ͍ͭಈ࡞͠ͳ͘ͳΔ͔Θ͔Βͳ͍4XJ[[MJOHΑΓ΋VQTUSFBN͕ରԠͯ͘͠Ε Δͷ͕Ұ൪Ͱ͢ w ΦʔϓϯιʔεͰ͋Ε͹GPSLͯ͠ύονΛ౰ͯͨ΋ͷΛ࢖͏ w ͦͯͦ͠ͷύονΛૹΓ·͠ΐ͏ w ύον͕೉͚͠Ε͹'FBUVSF3FRVFTUͷ*TTVF࡞੒ w Ϋϩʔζυιʔεͷ৔߹΋'FBUVSF3FRVFTUͷϑΟʔυόοΫ

Slide 5

Slide 5 text

[Obj-C] Swizzling+جຊ

Slide 6

Slide 6 text

[Obj-C] Swizzling • ͓ೃછΈͷObjective-C Runtime API Method class_getInstanceMethod(Class cls, SEL name); IMP method_getImplementation(Method m); IMP method_setImplementation(Method m, IMP imp); void method_exchangeImplementations(Method m1, Method m2); • ͜ΕΒͷϝιουͰIMPΛೖΕସ͑Δͷ͕ObjCͷMethod Swizzling • ͜͜ͰMethod, IMPʹ͍͓ͭͯܰ͘͞Β͍͓͖ͯ͠·͠ΐ͏ Ref: https://developer.apple.com/documentation/objectivec/objective-c_runtime

Slide 7

Slide 7 text

Method • Selectorͱؔ਺ͷΤϯίʔσΟϯάͱ࣮ଶͷIMPΛ࣋ͬͨߏ଄ମ Ref: https://github.com/opensource-apple/objc4/blob/master/runtime/objc-runtime-new.h struct method_t { SEL name; const char *types; IMP imp; } • ؔ਺ͷΤϯίʔσΟϯά͸ฦΓ஋ͱҾ਺Λදͨ͠΋ͷͰ ”v@:@@“ Έ͍ͨͳ ΍ͭͰ͢

Slide 8

Slide 8 text

IMP • IMP͸୯ͳΔCͷؔ਺ϙΠϯλ • ୈ1Ҿ਺͕self, ୈೋҾ਺͕SelectorɺୈࡾҾ਺Ҏ͕࣮߱ࡍͷҾ਺ Ref: https://developer.apple.com/documentation/objectivec/objective-c_runtime/imp id (*IMP)(id, SEL, ...)

Slide 9

Slide 9 text

objc_msgSend • ΠϯελϯεͷisaϙΠϯλ͔Β࣮ࡍͷΫϥεΛಛఆ͠ɺͦͷΫϥεͷϝιο υϦετͷத͔ΒҾ਺ͷSelector͔Βݺͼग़͍ͨ͠MethodΛऔಘ͠IMP(Cؔ ਺)Λ࣮ߦ͢Δ • Έ͍ͨͳ͜ͱΛ΍ͬͯΔɻ • ͭ·ΓIMPΛࠩ͠ସ͑Ε͹࣮૷Λࠩ͠ସ͑ΒΕΔɺ͔͠΋API͕͋Δʂ࠷ߴʂ

Slide 10

Slide 10 text

objc_direct

Slide 11

Slide 11 text

objc_direct Static dispatch for Obj-C • Xcode 12͔Βར༻Ͱ͖Δattribute • objc_msgSendΛ࢖͏ࣄͳ͘static dispatchͷؔ਺ݺͼग़͠ʹͳΔ • Classͷmethod listʹ΋ೖͬͯ͜ͳ͘ͳΔ • αϒΫϥεͰoverrideग़དྷͳ͍౳ͷ੍ݶ΋͔͔Δ • ObjC༻ͷSelector͕ෆཁͳͷͰୈ2Ҿ਺ͷ_cmd͸লུ͞ΕΔ • όΠφϦαΠζͷॖখ͕ओ໨తΒ͍͠ • MobileSafari౳Ͱར༻͞Ε͍ͯΔ

Slide 12

Slide 12 text

objc_direct Static dispatch for Obj-C @interface A : NSObject - (void)dynamic:(int)integer; - (void)direct:(int)integer __attribute__((objc_direct)); @end @implementation A - (void)dynamic:(int)number {} - (void)direct:(int)number {} @end ͜ΕΛAssemblyʹίϯύΠϧͯ͠Έ·͠ΐ͏

Slide 13

Slide 13 text

objc_direct > assembly code .p2align 2 "-[A dynamic:]": sub sp, sp, #32 str x0, [sp, #24] str x1, [sp, #16] str w2, [sp, #12] add sp, sp, #32 ret .private_extern "-[A direct:]" .globl "-[A direct:]" .p2align 2 "-[A direct:]": sub sp, sp, #16 str x0, [sp, #8] str w1, [sp, #4] ldr x8, [sp, #8] subs x8, x8, #0 cset w8, ne tbnz w8, #0, LBB2_2 b LBB2_1 LBB2_1: b LBB2_2 LBB2_2: add sp, sp, #16 ret De f inition ࣮ߦલͷ ୈ1Ҿ਺selfͷnil νΣοΫ

Slide 14

Slide 14 text

objc_direct > assembly code __OBJC_$_INSTANCE_METHODS_A: .long 24 .long 1 .quad l_OBJC_METH_VAR_NAME_ .quad l_OBJC_METH_VAR_TYPE_ .quad "-[A dynamic:]" De f inition • -[A direct:]ͷํ͸ଘࡏ͠ͳ͍

Slide 15

Slide 15 text

objc_direct > assembly code [a dynamic:10]; [a direct:13]; ldr x0, [sp, #32] mov w2, #10 bl "_objc_msgSend$dynamic:" ldr x0, [sp, #32] mov w1, #13 bl “-[A direct:]" Call • Direct dispatchͰ͸Ҿ਺Ϩδελ͕ҧ͏ˠ_cmd͕ແ͍

Slide 16

Slide 16 text

objc_direct Static dispatch for Obj-C • objc_directʹΑΔίʔυͷมԽ • objc_msgSend͕࢖ΘΕͳ͍ • Method, IMPͱ͍ͬͨ࢓૊ΈΛར༻ͤͣʹfunction pointerΛ௚ݺͼग़͠ • Cʹ͓͚Δؔ਺ݺग़ͱಉ౳ • ैདྷͷruntime methodͰ͸Swizzleग़དྷͳ͍

Slide 17

Slide 17 text

Swift Struct

Slide 18

Slide 18 text

Swift Struct • VTableͱ͔witness tableͱ͔৭ʑ͋ΔΜ͚ͩͲstructͷϝιουݺͼग़͕͠ static dispatchͳͷͰ৭ʑΧόʔ͠Α͏ͱߟ͑Δͱstatic dispatchΛ౗͢ඞཁ ͕͋Δ struct OhMyStruct { func method() -> Int { 10 } } OhMyStruct().method()

Slide 19

Slide 19 text

struct OhMyStruct { func method() -> Int { 10 } } OhMyStruct().method() _main: stp x29, x30, [sp, #-16]! mov x29, sp bl _$s5swift10OhMyStructVACycfC bl _$s5swift10OhMyStructV6methodSiyF mov w0, #0 ldp x29, x30, [sp], #16 ret .private_extern _$s5swift10OhMyStructV6methodSiyF .globl _$s5swift10OhMyStructV6methodSiyF .p2align 2 _$s5swift10OhMyStructV6methodSiyF: mov w8, #10 mov x0, x8 ret .private_extern _$s5swift10OhMyStructVACycfC .globl _$s5swift10OhMyStructVACycfC .p2align 2 _$s5swift10OhMyStructVACycfC: ret Swift Struct > assembly code ฦΓ஋ͱͳΔx1ʹ10ΛೖΕͯreturn

Slide 20

Slide 20 text

Swift Struct • Swift Structͷϝιουݺͼग़͠͸static dispatchͰCؔ਺ͱ΄΅ಉ͡ • objc_direct΋ಉ༷Ͱͨ͠Ͷ • ͭ·ΓCؔ਺ͷSwizzle͕ඞཁ

Slide 21

Slide 21 text

C function Swizzle

Slide 22

Slide 22 text

C function Swizzle • ৭ʑ΍Γํ͋Γ·͕͢جຊతʹؔ਺ͷத਎ͷϝϞϦΛ͍ͬͯࣗ͡෼ͷؔ਺΁ ඈ͹͠·͢ • ҰྫΛղઆ͠·͢

Slide 23

Slide 23 text

C function Swizzle 0x100003f24 mov w8, #0xa LDR pc, [pc, #-4] 0x20000000 _$s5swift10OhMyStructV6methodSiyF: 0x100003f28 mov x0, x8 0x100003f2c … 0x20000000 … my_c_func_replace: mov w8, #0xa mov x0, x8 LDR pc, [pc, #-4] 0x100003f2c vm_protect 0x30000000 0x30000004 0x30000008 0x3000000c Bu ff er B໋ྩͰඈ͹͢ํ͕ଟ͍͔΋ɻ ࠷ۙͩͱbrkΛར༻ͨ͠Γ͢Δύλʔϯ΋͋Γ·͢

Slide 24

Slide 24 text

࢒೦ͳ͕Βʂ ࣮ࡍ͸ηΩϡϦςΟ͕ڧྗͳͷͰiOSͰ͸ͦ͏ ؆୯ʹग़དྷ·ͤΜʂʂ C function Swizzle

Slide 25

Slide 25 text

Recap • Cؔ਺ɺSwiftɺobjc_direct͸iOSͰSwizzle͢Δͷ͸ἚͷಓɺఘΊͨ΄͏͕ಘࡦͰ͢ • Ͳ͏ͯ͠΋΍ΔͳΒࣄલʹframeworkͷόΠφϦύον͢Δͷ͕Ұ൪ݱ࣮తͰ͢ • ؆୯ʹSwizzleग़དྷΔObjC࠷ߴʂ • ObjCΛSwizzle͠Α͏ͱ͢Δ࣌ͷ୳͠ํ͸ଟ෼͕࣌ؒ଍Γͳ͍ɻ • ͪΐͬͱલ·ͰBCSymbolMapsͱ͍͏ศརͳͷ͕͋ͬͨͷͰ͕͢bitcodeഇࢭͰফ͑ͨͷͰૉ ௚ʹ `nm` ͠·͠ΐ͏ɻ͋ͱ͸class-dump΍Hopper౳Ͱͷdisassemble

Slide 26

Slide 26 text

͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠