I worked on an iOS application that used the Google Maps SDK and noticed a bunch of logging when I backgrounded the application complaining that it couldn’t connect to some server:
123456789
2021-04-17 00:42:48.543716+0300 MyApp[73170:12130630] [connection] nw_socket_connect [C7.1:3] connect failed (fd 23) [64: Host is down]
2021-04-17 00:42:48.543851+0300 MyApp[73170:12130630] [] nw_socket_connect connect failed [64: Host is down]
2021-04-17 00:42:48.545236+0300 MyApp[73170:12130630] Connection 7: received failure notification
2021-04-17 00:42:48.545564+0300 MyApp[73170:12130630] Connection 7: failed to connect 1:64, reason -1
2021-04-17 00:42:48.545708+0300 MyApp[73170:12130630] Connection 7: encountered error(1:64)
2021-04-17 00:42:48.548091+0300 MyApp[73170:12130630] Task <170493E8-F704-4578-AB47-7B9CE76064B1>.<1> HTTP load failed, 0/0 bytes (error code: -1004 [1:64])
2021-04-17 00:42:48.951902+0300 MyApp[73170:12128623] Task <170493E8-F704-4578-AB47-7B9CE76064B1>.<1> finished with error [-1004] Error Domain=NSURLErrorDomain Code=-1004 "Could not connect to the server." UserInfo={_kCFStreamErrorCodeKey=64, NSUnderlyingError=0x600003ccb360 {Error Domain=kCFErrorDomainCFNetwork Code=-1004 "(null)" UserInfo={_kCFStreamErrorCodeKey=64, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <170493E8-F704-4578-AB47-7B9CE76064B1>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <170493E8-F704-4578-AB47-7B9CE76064B1>.<1>"
), NSLocalizedDescription=Could not connect to the server., NSErrorFailingURLStringKey=https://play.googleapis.com/log/batch, NSErrorFailingURLKey=https://play.googleapis.com/log/batch, _kCFStreamErrorDomainKey=1}
And this is just one instance of it; typically it would be repeated a dozen times.
I don’t know if it’s due to Pi-Hole DNS blocking, blacklisting in /etc/hosts, and/or blocking in Little Snitch, but that doesn’t matter.
In AppCode, I tried using the Grep Console plugin to filter out these logs and it’s possible to do for some of these lines, but not all of them. These unnecessary logs are very annoying when I’m debugging something which generates some very specific logs and extra logging (especially a lot of it) adds distraction. I didn’t ask for this logging, I didn’t enable it and there is no official way to disable it, so we’ll have to dig deeper (I’m using Google Maps SDK 4.2.0 here).
Good, we’ve found the framework that contains the string. Let’s open it in Hopper, its demo version is enough for this small task. Select the “x86 (64 bits)” architecture because that’s what is used by the iOS Simulator; I had to disable “Parse exceptions information if present” because otherwise the disassembled would get stuck at “Parsing Exception Tables”. Type the URL in the strings list on the left and you can jump to this location:
12
LC50:
00000000000fee05 db "https://play.googleapis.com/log/batch", 0; DATA XREF=cfstring_https___play_googleapis_com_log_batch
Put the cursor on the address (first field) and press x to see references. There is only one:
A few instructions below (at 0x1803) you can notice the selector for a more specific initializer: initWithAuthorizer:listeners:logDirectory:isSharedDirectory:serverURL:batchServerURL:requestFilter:. Typically less specific initializers (with fewer parameters) call more specific one (with more parameters), so it makes sense to find the most specific one. Paste the name to the procedure list on the left to jump to it:
12
-[GMSx_CCTClearcutUploader initWithAuthorizer:listeners:logDirectory:isSharedDirectory:serverURL:batchServerURL:requestFilter:]:
000000000000188d push rbp ; Objective C Implementation defined at 0x1cf0c0 (instance method), DATA XREF=0x1cf0c0
It doesn’t call any other initializer of GMSx_CCTClearcutUploader, so my idea was to patch this one to immediately return. The status bar shows that this location has file offset 0x234d; note that this is an offset in the x86_64 slice, not in the original fat binary. So I would replace the byte 55 at this address with byte C3 (for ret instruction). To edit this byte, we need to extract this slice first:
Build and launch your app… and you’ll get a crash at startup:
1
Exception: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
So this was a bad idea indeed. Let’s try another way.
Ignoring background events
didEnterBackgroundNotification is the notification name that is sent when the app is backgrounded and it’s likely that the SDK is subscribing to it. We can search for didEnterBackground:
12
aApplicationdid_135862: // aApplicationdid
0000000000135862 db "applicationDidEnterBackground:", 0; DATA XREF=0x1cf240, 0x1d3268, 0x1da120, 0x243a28
We can try patching this block, why not?! When your cursor stays on the address 0x24c3 (beginning of the function), the status bar shows file offset 0x2f83 and the right panel shows Instruction Encoding (aka opcode) 55, press Opt+a to assemble another instruction, enter ret (to return from the procedure), press Esc. Go back to that line, see that the opcode is now C3. We know what to do now (see the previous section for binary patching):
Rebuild and run your program. Voila, no more these annoying logs on backgrounding! The application doesn’t crash either. This may not be the most efficient to block those calls and it may not cover all cases, but it’s good enough for now.
Important to know
If you’ve done something wrong, you’ll very likely get a crash, or, less likely, some incorrect behavior.
Unfortunately I don’t know of an automatic way to find the correct address and binary patch it, so you’ll need to manually patch every new released version.
Use this patched version only for local work, don’t distribute it.
You need to make this edit for every architecture you care about, e.g. x86_64 for iOS Simulator and arm64 for iOS devices: