Skip to content

MASTG-DEMO-0024: Uses of LAContext.canEvaluatePolicy with r2

Download MASTG-DEMO-0024 IPA Open MASTG-DEMO-0024 Folder Build MASTG-DEMO-0024 IPA

Sample

The following sample checks whether the device has a set passcode.

MastgTest.swift
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import SwiftUI
import LocalAuthentication

struct MastgTest {

  static func mastgTest(completion: @escaping (String) -> Void) {
    if devicePasscodeSet(){
      completion("This device is protected with a passcode ✅")
    }
    else{
      completion("This device doesn't have a passcode ⚠️")
    }
  }

  static func devicePasscodeSet() -> Bool {
      // Use LAPolicy.deviceOwnerAuthentication to verify if the device has a passcode.
      // According to docs: "In iOS, policy evaluation fails with the error passcodeNotSet if the device passcode isn’t enabled"
      // Ref: https://developer.apple.com/documentation/localauthentication/lapolicy/deviceownerauthentication
      return LAContext().canEvaluatePolicy(.deviceOwnerAuthentication, error: nil)
    }

}

Steps

  1. Unzip the app package and locate the main binary file ( Exploring the App Package), which in this case is ./Payload/MASTestApp.app/MASTestApp.
  2. Run run.sh.
isDevicePasscodeSet.r2
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
e asm.bytes=false
e scr.color=false
e asm.var=false

?e Print xrefs to \'canEvaluatePolicy\"
f~canEvaluatePolicy

?e

?e Print xrefs to 0x100008360
axt @ 0x100008360

?e

?e Print xrefs to 0x1000100a0
axt @ 0x1000100a0

?e

?e Print disassembly around \"canEvaluatePolicy\" in the function
pdf @ 0x100004f10 | grep -C 5 "canEvaluatePolicy:error:"
run.sh
1
2
#!/bin/bash
r2 -q -i isDevicePasscodeSet.r2 -e emu.str=true -A MASTestApp > output.asm

Observation

output.asm
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Print xrefs to 'canEvaluatePolicy"
0x100008360 24 str.canEvaluatePolicy:error:
Print xrefs to 0x100008360
(nofunc) 0x100000350 [UNKNOWN] invalid
sym.func.100004ea8 0x100004f10 [STRING] ldr x1, [x8, 0xa0]
Print disassembly around "canEvaluatePolicy" in the function
           0x100004f0c      adrp x8, sym.__METACLASS_DATA__TtC10MASTestAppP33_9471609302C95FC8EC1D59DD4CF2A2DB19ResourceBundleClass ; 0x100010000 ; x8=0x100010000 -> 0x81
           0x100004f10      ldr x1, [x8, 0xa0]                        ; 0x100008360 ; char *selector ; tmp=0x1000100a0 ; x1=0x100008360 -> 0x456e6163 section.8.__TEXT.__objc_methname
           0x100004f14      movz w2, 0x2                              ; w2=0x2
           0x100004f18      movz x3, 0                                ; x3=0x0
           0x100004f1c      bl sym.imp.objc_msgSend                   ; void *objc_msgSend(void *instance, char *selector) ; lr=0x100004f20 -> 0xaa0003f7 ; pc=0x100007794 "0"
                                                                      ; void *objc_msgSend(-1, "canEvaluatePolicy:error:")

The output reveals the use of LAContext().canEvaluatePolicy(.deviceOwnerAuthentication, error: nil) in the app. However, it's not exactly the same in the output because the compiler transformed this function call into an Objective-C counterpart under the hood. Therefore, an equivalent Objective-C representation in the binary should look like objc_msgSend(void *address, "canEvaluatePolicy:error:", LAPolicyDeviceOwnerAuthentication). By looking at the output we can find this pattern at line 11/12.

The third argument of objc_msgSend(...) is LAPolicyDeviceOwnerAuthentication because w2 register at the time of the function invocation is set to 2 with a mov instruction at Line 9. 2 is an enum representation of LAPolicyDeviceOwnerAuthentication.

Evaluation

The test passes because the output shows references to passcode verification APIs.