Vài ngày trước, một người dùng đã upload video lỗi wifi của IOS lên twitter:
https://twitter.com/vm_call/status/1405937492642123782
Nhìn sơ thì có vẻ dịch vụ Wifi bị format string, lỗi gần như "tuyệt chủng" ngày nay.
Người dùng chichou đã phân tích về lỗi khá hiếm gặp này, và chúng mình xin phép dịch lại bài này:
Đầu tiên, setup một trạm phát wifi có tên như "%p%s%s%s%s%n", và kết nối vào mạng đó bằng Iphone. Dịch vụ nền wifi, wifid, ngay sau đó liền bị crash. Nội dung file symbolicated crash log như sau:
Thread 2 name: Dispatch queue: com.apple.wifid.managerQueueThread 2 Crashed:0 libsystem_platform.dylib 0x00000001ebcb9724 _platform_strlen + 41 CoreFoundation 0x00000001a381d84c __CFStringAppendFormatCore + 88122 CoreFoundation 0x00000001a381efa8 _CFStringCreateWithFormatAndArgumentsReturningMetadata + 1603 WiFiPolicy 0x00000001d0895f8c -[WFLogger WFLog:message:] + 1924 ??? 0x000000010692c00c 0 + 44052480125 wifid 0x0000000100f58a74 0x100e40000 + 11495566 wifid 0x0000000100f58c74 0x100e40000 + 1150068
Vây đây chắc chắn là lỗi format string rồi!
Dịch ngược hàm -[WFLogger WFLog:message:] trong ndyld_shared_cache. Hàm này có hai tham chiếu đến CFStringCreateWithFormatAndArguments.
v7 = j__CFStringCreateWithCString_107(0LL, a4, 0x8000100u); // the format string if ( v7 || (v7 = j__CFStringCreateWithCString_107(0LL, a4, 0)) != 0LL ) { if ( self->_destination == 2 ) { v8 = j__CFStringCreateWithFormatAndArguments_26(0LL, 0LL, v7, v21); v18[3] = (__int64)v8; }
và ở đây
if ( self->_destination != 2 && (!self->_wflRunningOnWatchClassDevice || self->_wflEnableDualLoggingOnWatchClassDevice) ) { *(_QWORD *)&v16.tm_sec = 0LL; *(_QWORD *)&v16.tm_hour = &v16; *(_QWORD *)&v16.tm_mon = 0x2020000000LL; *(_QWORD *)&v16.tm_wday = 0LL; v10 = j__CFStringCreateWithFormatAndArguments_26(0LL, 0LL, v7, v21); // <-- here
Bởi vì hàm này được gọi nhiều lần quá, việc debug với lldb sẽ là công việc đầy chông gai. Thay vào đó, mình sẽ attach frida vào : frida-trace -U wifid -m '-[WFLogger WFLog:message:]' và sửa script một xíu:
onEnter(log, args, state) { const msg = '' + args[3].readUtf8String(); log(
-[WFLogger WFLog:</span><span class="p">${</span><span class="nx">args</span><span class="p">[</span><span class="mi">2</span><span class="p">]}</span><span class="s2"> message:</span><span class="p">${</span><span class="nx">msg</span><span class="p">}</span><span class="s2">]
); if (msg.indexOf('%p%s%s%s%s%n') > -1) { for (let i = 3; i < 10; i++) { log(args[i], JSON.stringify(Process.findRangeByAddress(args[i]))); } log('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE) .map(DebugSymbol.fromAddress).join('\n') + '\n'); } },
Đoạn log ngay trước khi crash như sau:
17863 ms -[WFLogger WFLog:0x3 message:Dequeuing command type: “%@” pending commands: %ld]
17863 ms -[WFLogger WFLog:0x3 message:{ASSOC+} Attempting Apple80211AssociateAsync to %p%s%s%s%s%n]
v27 = sub_1000A25D4(v21);v28 = objc_msgSend( &OBJC_CLASS___NSString, "stringWithFormat:", CFSTR("Attempting Apple80211AssociateAsync to %@"), v27);v29 = objc_msgSend(&OBJC_CLASS___NSString, "stringWithFormat:", CFSTR("{ %@+} %@"), CFSTR("ASSOC"), v28);v30 = objc_autoreleasePoolPush();v31 = (void *)qword_100251888;if ( qword_100251888 ){ v32 = objc_msgSend(v29, "UTF8String"); objc_msgSend(v31, "WFLog:message:", 3LL, v32);}objc_autoreleasePoolPop(v30);
nó nối SSID thành format string và chuyển qua phương thức WFLog:message: . Vì tham số bên cạnh là 3, ta có thể suy ra được là tham chiếu thứ hai của hàm CFStringCreateWithFormatAndArguments đã gây ra lỗi
Các tham số còn lại có vẻ không thay đổi được, nên lỗi này không có khả nang bị thai khác sâu hơn. Suy cho cùng, muốn thai khác lỗi này, nạn nhân phải kết nối đến mạng wifi này, mà nhìn tên ssid đã thấy đáng ngờ. Còn nhiều cách khác hiệu quả hơn phương pháp này.
Nguồn: Chichou.me