
في النزاعات على الإنترنت وفي الحياة الواقعية ، تتمتع الحجج التي تدعمها الأدلة - لقطات الشاشة والصور وتسجيل الرسائل / المكالمات وتسجيلات الفيديو وما إلى ذلك - بأكبر وزن.
— . . ?
, , - - , , , .
— 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.