
En disputas en Internet y en la vida real, los argumentos respaldados por evidencia (capturas de pantalla, fotos, grabaciĂłn de mensajes / llamadas, grabaciones de video, etc.) tienen el mayor peso.
— . . ?
, , - - , , , .
— screenlife, . : , .
(, ). : / , . , , . : , / .
: screenlife, , , .
, , — Frida, JavaScript . , , DeepFace.
, Frida
, Frida 18 .
Frida — (Dynamic Binary Instrumentation, DBI), runtime JavaScript blackbox / — hooking tracing , , . Frida . Frida , iOS.
/proof
: iPhone 6s iOS 13.2.3
: Instagram (v126.0.0.13.120)
: , .
, . — .
TL;DR
- Frida
“ iOS- Jailbreak”.
:
, , . .
jailbreak, .
, , . UI , ? UI Instagram:
Madonna ( ):

, ( ):

( ):

, ( origUser
— original User), ( replUser
— replicated User), UI , origUser
( , ). replUser
, , , . , , . , ID origUser
replUser
, , .
IPA
, Frida-, ( IPA Instagram). :
- Mac:
Apple configurator 2
AppStore, . . - iPhone jailbreak iOS, frida-ios-dump . , Frida. , IPA Instagram. Frida .
, . iOS bundle . Mach-O 64-bit arm64 :
Instagram.App/Instagram
—Instagram.app/Frameworks/InstagramAppCoreFramework.framework/InstagramAppCoreFramework
— InstagramInstagram.app/Frameworks/FBSharedFramework.framework/FBSharedFramework
— shared Facebook, InstagramAppCoreFramework Instagram.
(Instagram)
— Insagram.App/Instagram
. , IDA Pro.
Instagram, , ( 364), Instagram — :

— . , .
(InstagramAppCoreFramework FBSharedFramework)
InstagramAppCoreFramework
, Instagram.
, FBSharedFramework
Instagram
InstagramAppCoreFramework
, (User, Direct Messages, Message ), controller view InstagramAppCoreFramework
.
, direct . , “Message” origUser
, direct replUser
.
Doxygen
InstagramAppCoreFramework
IDA Pro, , 250000 , , . -, doxygen- header- Objective-C . header- classdumpios, ARM64. iPhone jailbreak, SSH USB IPA Instagram :
iPhone:~/insta $ mkdir headers
iPhone:~/insta $ cp Payload/Instagram.app/Frameworks/InstagramAppCoreFramework.framework/InstagramAppCoreFramework ./headers
iPhone:~/insta $ cp Payload/Instagram.app/Frameworks/FBSharedFramework.framework/FBSharedFramework ./headers
iPhone:~/insta $ cd headers
iPhone:~/insta/headers $ classdumpios -H InstagramAppCoreFramework -o IG_headers
iPhone:~/insta/headers $ classdumpios -H FBSharedFramework -o FB_headers
iPhone:~/insta/headers $ tar -czvf IG_headers.tar.gz IG_headers
iPhone:~/insta/headers $ tar -czvf FB_headers.tar.gz FB_headers
header- iPhone , , doxygen :
Host@Host:~/insta$ mkdir docs && cd docs
Host@Host:~/insta/docs $ scp -P <PORT> root@<IP>:</path/to/instagram>/insta/headers/IG_headers.tar.gz .
Host@Host:~/insta/docs $ scp -P <PORT> root@<IP>:</path/to/instagram>/insta/headers/FB_headers.tar.gz .
Host@Host:~/insta/docs $ tar xf IG_headers.tar.gz
Host@Host:~/insta/docs $ tar xf FB_headers.tar.gz
Host@Host:~/insta/docs $ cp </path/to/dox.template> .
Host@Host:~/insta/docs $ doxygen dox.template
doxygen- , . .
, InstagramAppCoreFramework
FBSharedFramework
:

, IGAuthUserParser
:

, .
Frida-
, . , , Frida- , , , , backtrace, . . . trace-, .
Python- Frida, :
~ $ pip install --upgrade frida frida-tools
, frida-server. , , ( JB) ( JB).
- inputView:didTapStickerButton:
IGDirectThreadViewController
. ? , , . , direct ( , , ). , , , , Frida. NativeFunction
:
var func = ObjC.classes.IGDirectThreadViewController["inputView:didTapStickerButton:"].implementation;
hook, :
Interceptor.attach(func, {
onEnter: function(args) {
console.log("-[IGDirectThreadViewController inputView:didTapStickerButton:] => onEnter");
},
onLeave: function(retval) {
console.log("-[IGDirectThreadViewController inputView:didTapStickerButton:] <= onLeave");
}
}
, .
, , . , , , .
hook, , , . hook — . . :
function addTracer(className, methodName) {
var impl = ObjC.classes[className][methodName].implementation;
Interceptor.attach(impl, {
onEnter: function(a) {
this.log = [];
this.log.push('(' + a[0] + ',' + Memory.readUtf8String(a[1]) + ') ' + className + ' ' + methodName);
if (methodName.indexOf(':') !== -1) {
var params = methodName.split(':');
params[0] = params[0].split(' ')[1];
for (var i = 0; i < params.length - 1; i++) {
try {
this.log.push(params[i] + ': ' + new ObjC.Object(a[2 + i]).toString());
} catch (e) {
this.log.push(params[i] + ': ' + a[2 + i].toString());
}
}
}
this.log.push(
Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress)
.join('\n')
);
},
onLeave: function(r) {
try {
this.log.push('RET: ' + new ObjC.Object(r).toString());
} catch (e) {
this.log.push('RET: ' + r.toString());
}
console.log(this.log.join('\n') + '\n');
}
});
}
:
addTracer("IGDirectThreadViewController", "- inputView:didTapStickerButton:");
, ( Frida- , USB):
$ frida -U -n Instagram -l </path/to/script> --no-pause
direct ( ). :
(0x1269aea00,inputView:didTapStickerButton:) IGDirectThreadViewController - inputView:didTapStickerButton:
inputView: <IGDirectComposer: 0x125d241b0; frame = (0 607; 375 60); text = ''; autoresize = H; layer = <CALayer: 0x281ef5fc0>>
didTapStickerButton: <IGDirectComposerButton: 0x127a5e210; baseClass = UIButton; frame = (319 10; 24 24); opaque = NO; tintColor = <UIDynamicProviderColor: 0x281e29dc0; provider = <__NSMallocBlock__: 0x2810cfdb0>>; layer = <CALayer: 0x281e37900>>
0x1072df1dc InstagramAppCoreFramework!IGHandleURLForIGInstagramToast
0x18743bab0 UIKitCore!-[UIApplication sendAction:to:from:forEvent:]
0x186e738ac UIKitCore!-[UIControl sendAction:to:forEvent:]
0x186e73c10 UIKitCore!-[UIControl _sendActionsForEvents:withEvent:]
0x186e72c2c UIKitCore!-[UIControl touchesEnded:withEvent:]
0x1019378ac FBSharedFramework!IGCrashReportProcessorLatestUploadError
0x187475288 UIKitCore!-[UIWindow _sendTouchesForEvent:]
0x1874765c8 UIKitCore!-[UIWindow sendEvent:]
0x187452b78 UIKitCore!-[UIApplication sendEvent:]
0x1012e0784 FBSharedFramework!IGALLoggerSetTrackingNodeForView
0x1874caef8 UIKitCore!__dispatchPreprocessedEventFromEventQueue
0x1874cd454 UIKitCore!__handleEventQueueInternal
0x1874c62c8 UIKitCore!__handleHIDEventFetcherDrain
0x18334f7c4 CoreFoundation!__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
0x18334f71c CoreFoundation!__CFRunLoopDoSource0
0x18334eeb4 CoreFoundation!__CFRunLoopDoSources0
RET: nil
direct
, Instagram. .
Instagram
direct ( , ) IGDirectThread
( "direct ", "direct thread", "" ).

, , direct thread — _threadId
. ID. . , , direct , .
_metadata
. ( _users
), direct thread.
IGUser
. , . _pk
, . _pk
, ,
, UI IGDirectThread
, — IGDirectThreadViewController
, , . — , .
, direct IGDirectThreadViewController
. , . -[IGDirectThreadViewController initWithUserSession:thread:entryPoint:perfComponents:]
. Frida-hook , , . , IGDirectThreadViewController
:

IGDirectThread
. , IGDirectThread
, , direct , .
direct
, , : origUser
, IGDirectThread
, replUser
. Instagram
, origUser
replUser
. . — _pk
, IGDirectThread
, _users
( _metadata
) _pk
. — hook _threadId
(, ), direct thread ID.
, direct thread — IGDirectThread
, direct , ( _users
):
var IGDirectThreadViewControllerInitWithUserSession = ObjC.classes.IGDirectThreadViewController["- initWithUserSession:thread:entryPoint:perfComponents:"].implementation;
Interceptor.attach(IGDirectThreadViewControllerInitWithUserSession, {
onEnter: function(args) {
this.thread = new ObjC.Object(args[3]);
[origUser, replUser].forEach(function (user) {
var users = this.thread.$ivars["_metadata"].$ivars["_users"];
if (users.count() == 1 && users.objectAtIndex_(0).$ivars["_pk"] == user.pk && user.thread == undefined) {
user.thread = this.thread.retain();
}
}, this);
if (origUser.threadId == undefined || replUser.threadId == undefined) {
return;
}
if (this.thread.$ivars["_threadId"].equals(origUser.threadId)) {
args[3] = replUser.thread.retain();
replaceState = true;
console.log(
FgGreen + "[+]" + Reset +
" Thread " +
origUser.threadId +
" spoofed with " +
replUser.threadId +
"!"
);
}
}
});
Frida- ( , ) direct origUser
, replUser
! , . .
IGDirectThreadViewController
runtime, — _viewModel
. ? IGDirectThreadViewControllerViewModel
, _leftAlignedTitleViewModel
, _leftAlignedTitleViewModel->_titleButton->_titleView->text
, , (.. , direct ). , _viewModel
, origUser
( ), direct origUser
(, )?
, . origUser
— , . replUser
replUser
. , — -[IGDirectViewController _updateThreadNavigationBar]
. . direct origUser
replUser
, origUser
, .
var IGDirectThreadViewControllerUpdateNavigationBar = ObjC.classes.IGDirectThreadViewController["- _updateThreadNavigationBar"].implementation;
Interceptor.attach(IGDirectThreadViewControllerUpdateNavigationBar, {
onLeave: function(retval) {
if (replaceState && this.controller.$ivars["_threadId"].equals(replUser.threadId)) {
this.controller.$ivars["_viewModel"] = origUser.viewModel.retain();
}
if (DEBUG) console.log("IGDirectThreadViewController[onLeave]: -_updateNavigationBar");
}
});
.
— IGUser
_profilePicURL
. direct origUser
replUser
origUser
, . , .
.
, . production-ready , , , .
350 JavaScript . , , — ;)
, , (AR), .
- — ;)
@d1g1 ! :)
P.S.