pif-test-json-files.sh 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. #!/bin/sh
  2. # Crawl recursively and test custom JSON files for PIF module,
  3. # provided by zgfg @ xda
  4. echo "Crawl recursively and test custom JSON files for PIF module\
  5. \n - provided by zgfg @ xda\n"
  6. FOLDERS_DEPTH="4" # Increase for crawling deeper than to sub-sub-sub-sub-folders
  7. USE_MODULE="PI_FORK" # Default, for testing with PI Fork module from Osm0sis
  8. #USE_MODULE="PI_FIX" # For testing with PI Fix module from Chiteroman
  9. MIGRATE_JSON="yes" # Enable to pre-process JSON files by migrate.sh script from Osm0sis, migration script must be in this script's folder or in the PI Fork module's folder - don't use if testing with PI Fix module
  10. DELETE_FAILED="yes" # Enable to automatically delete JSON files that fail to pass Device Integrity
  11. TEST_YASNAC="yes" # Set undefined or empty to skip testing SN with YASNAC, or else script will first test SN with YASNAC (to speed-up filtering of JSON files)
  12. YASNAC_Y_COORD="1250" # Try with lower y if it fails to automatically kick "Run SafetyNet Check" button in YASNAC
  13. YASNAC_WAIT_VERDICT="8" # SafetyNet verdict usually returns in 3-4 seconds, but if you decrease and verdict arrives later, script will miss to read
  14. TEST_PI="TEST_SPIC" # Default, for testing PI with Simple Play Integrity Checker
  15. #TEST_PI="TEST_PICHECK" # For testing PI with Play Integrity API Checker
  16. #TEST_PI="TEST_TBCHECKER" # For testing PI with TB-Checker
  17. #TEST_PI="TEST_IAPI" # For testing PI with Integrity API
  18. PIF_JSON="*.json" # Default, PIF JSON mask to test all *.json files
  19. #PIF_JSON="custom.pif.json" # PIF JSON mask to test only custom.pif.json files
  20. #PIF_JSON="vendor.pif.json" # PIF JSON mask to test only vendor.pif.json files
  21. X_COORD="500" # Should fit for all YASNAC, SPIC, TB-Checker, PI API Checker and Integrity API
  22. PI_WAIT_VERDICT="10" # Play Integrity verdict usually returns in 5-6 seconds, but if you decrease and verdict arrives later, script will miss to read
  23. SPIC_Y_COORD="1000" # Try with lower y if script fails to automatically kick "Make Play Integrity request" button in SPIC
  24. PICHECK_Y_COORD="1600" # Try with lower y if it fails to automatically kick "Check" button in PI API Checker
  25. TBCHECKER_Y_COORD="1900" # Try with lower y if it fails to automatically kick "Check Play Integrity" button in TB-Checker
  26. IAPI_Y_COORD="350" # Try with lower y if it fails to automatically kick "Request A Universal Integrity Token With The Cloud Project" button in Integrity API
  27. # Change the code beyond this line only on your own risk
  28. module_path="/data/adb/modules/playintegrityfix"
  29. [ "$USE_MODULE" != "PI_FIX" ] && USE_MODULE="PI_FORK" && custom_json="$module_path/custom.pif.json"
  30. [ "$USE_MODULE" == "PI_FIX" ] && custom_json="/data/adb/pif.json"
  31. script_path=${0%/*}
  32. migrate_script="$script_path/migrate.sh"
  33. [ ! -f "$migrate_script" ] || [ ! -s "$migrate_script" ] && migrate_script="$module_path/migrate.sh"
  34. [ ! -f "$migrate_script" ] || [ ! -s "$migrate_script" ] && migrate_script=""
  35. test_path="$1"; [ -z "$test_path" ] && test_path="$script_path"
  36. custom_bak="$test_path/custom.pif.bak"
  37. results="$test_path/pif-test-results.txt"; rm -f "$results"
  38. echo "results=$results"
  39. echo "PID=$$" | tee -a "$results"
  40. echo "script_path=$script_path, test_path=$test_path" | tee -a "$results"
  41. echo "USE_MODULE=$USE_MODULE, custom_json=$custom_json" | tee -a "$results"
  42. echo "MIGRATE_JSON=$MIGRATE_JSON, migrate_script=$migrate_script, DELETE_FAILED=$DELETE_FAILED" | tee -a "$results"
  43. echo "TEST_YASNAC=$TEST_YASNAC, TEST_PI=$TEST_PI, PIF_JSON=$PIF_JSON" | tee -a "$results"
  44. echo "" | tee -a "$results"
  45. log="$test_path/pif.log"
  46. yasnac_xml="$test_path/yasnac.xml"; spic_xml="$test_path/spic.xml"; picheck_xml="$test_path/picheck.xml"; tbchecker_xml="$test_path/tbchecker.xml"; iapi_xml="$test_path/iapi.xml"
  47. yasnac="rikka.safetynetchecker"
  48. spic="com.henrikherzig.playintegritychecker"
  49. picheck=gr.nikolasspyr.integritycheck
  50. tbchecker="krypton.tbsafetychecker"
  51. iapi="com.test.integrity.api.qa.googlemanaged"
  52. integrities="NO_INTEGRITY MEETS_VIRTUAL_INTEGRITY MEETS_BASIC_INTEGRITY MEETS_DEVICE_INTEGRITY MEETS_STRONG_INTEGRITY"
  53. rm -f "$custom_bak"; cp "$custom_json" "$custom_bak" >/dev/null 2>&1
  54. orient=$(settings get system user_rotation)
  55. auto_rot=$(settings get system accelerometer_rotation)
  56. settings put system user_rotation 0
  57. settings put system accelerometer_rotation 0
  58. (( folders = 0 )); (( tested = 0 )); (( migrated = 0 )); (( setApi25 = 0 )); (( passed = 0 )); (( failed = 0 )); (( inconclusive = 0 ))
  59. function f_remove_file()
  60. {
  61. local file="$1"
  62. rm -f "$file" >/dev/null 2>&1
  63. }
  64. function f_start_activity()
  65. {
  66. local activity="$1"
  67. am start -n "$activity" >/dev/null 2>&1
  68. }
  69. function f_kill_app()
  70. {
  71. local app="$1"
  72. am force-stop "$app" >/dev/null 2>&1
  73. }
  74. function f_kill_gms()
  75. {
  76. logcat -c
  77. killall com.google.android.gms.unstable >/dev/null 2>&1
  78. }
  79. function f_tap_test()
  80. {
  81. local y_coord="$1"
  82. input tap $X_COORD "$y_coord" >/dev/null 2>&1
  83. }
  84. function f_dump_xml()
  85. {
  86. local xml="$1"
  87. uiautomator dump "$xml" >/dev/null 2>&1
  88. }
  89. function f_test_yasnac()
  90. {
  91. local json="$1"
  92. cp "$json" $custom_json
  93. f_remove_file "$log"; f_remove_file "$yasnac_xml"
  94. f_start_activity $yasnac/$yasnac.main.MainActivity
  95. sleep 2
  96. f_kill_gms
  97. f_tap_test $YASNAC_Y_COORD
  98. sleep $YASNAC_WAIT_VERDICT
  99. f_dump_xml "$yasnac_xml"
  100. f_kill_app $yasnac
  101. logcat -d | grep PIF >> "$log"
  102. (( pass = 0 )); found=$(cat "$yasnac_xml" | grep "Pass")
  103. [ -n "$found" ] && (( pass = 1 ))
  104. (( fail = 0 )); found=$(cat "$yasnac_xml" | grep "Fail")
  105. [ -n "$found" ] && (( fail = 1 ))
  106. (( basic = 0 )); found=$(cat "$yasnac_xml" | grep "BASIC")
  107. [ -n "$found" ] && (( basic = 1 ))
  108. (( hw = 0 )); found=$(cat "$yasnac_xml" | grep "HARDWARE_BACKED")
  109. [ -n "$found" ] && (( hw = 1 ))
  110. # echo "SN Pass:$pass Fail:$fail BASIC:$basic HW:$hw" | tee -a "$results"
  111. ((( basic + hw != 1 )) || (( pass + fail < 1 ))) && return 0
  112. local sn="SN Basic"
  113. (( pass == 0 )) && sn="$sn: Fail"
  114. (( pass > 0 )) && sn="$sn: Pass"
  115. sn="$sn, CTS"
  116. (( hw == 0 )) && sn="$sn: BASIC"
  117. (( hw > 0 )) && sn="$sn: HARDWARE_BACKED"
  118. (( fail > 0 )) && sn="$sn: Fail"
  119. (( fail == 0 )) && sn="$sn: Pass"
  120. echo "$sn" | tee -a "$results"
  121. (( pass == 0 )) && return 1
  122. (( fail > 0 )) && return 2
  123. (( hw == 0 )) && return 3
  124. return 4
  125. }
  126. function f_test_spic()
  127. {
  128. local json="$1"
  129. cp "$json" $custom_json
  130. f_remove_file "$log"; f_remove_file "$spic_xml"
  131. f_start_activity $spic/$spic.MainActivity
  132. sleep 2
  133. f_kill_gms
  134. f_tap_test $SPIC_Y_COORD
  135. sleep $PI_WAIT_VERDICT
  136. f_dump_xml "$spic_xml"
  137. f_kill_app $spic
  138. logcat -d | grep PIF >> "$log"
  139. (( i = 0 )); (( val = i++ ))
  140. for meets in $integrities
  141. do
  142. found=$(cat "$spic_xml" | grep $meets)
  143. [ -n "$found" ] && echo $meets | tee -a "$results" && (( val = i ))
  144. (( i++ ))
  145. done
  146. return $val
  147. }
  148. function f_test_picheck()
  149. {
  150. local json="$1"
  151. cp "$json" $custom_json
  152. f_remove_file "$log"; f_remove_file "$picheck_xml"
  153. f_start_activity $picheck/$picheck.MainActivity
  154. sleep 2
  155. f_kill_gms
  156. f_tap_test $PICHECK_Y_COORD
  157. sleep $PI_WAIT_VERDICT
  158. input tap 870 190
  159. sleep 1
  160. f_dump_xml "$picheck_xml"
  161. f_kill_app $picheck
  162. logcat -d | grep PIF >> "$log"
  163. (( i = 0 )); (( val = i++ ))
  164. for meets in $integrities
  165. do
  166. found=$(cat "$picheck_xml" | grep $meets)
  167. [ -n "$found" ] && echo $meets | tee -a "$results" && (( val = i ))
  168. (( i++ ))
  169. done
  170. (( val > 0 )) && return $val
  171. local deviceIntegrity=$(cat "$picheck_xml" | grep -o "deviceIntegrity")
  172. local deviceRecognition=$(cat "$picheck_xml" | grep -o "deviceRecognitionVerdict")
  173. # echo "integrity=$deviceIntegrity, recognition=$deviceRecognition" | tee -a "$results"
  174. [ -n "$deviceIntegrity" ] && [ -z "$deviceRecognition" ] && echo NO_INTEGRITY | tee -a "$results" && (( val = 1 ))
  175. return $val
  176. }
  177. function f_test_tbchecker()
  178. {
  179. local json="$1"
  180. cp "$json" $custom_json
  181. f_remove_file "$log"; f_remove_file "$tbchecker_xml"
  182. f_start_activity $tbchecker/$tbchecker.main.MainActivity
  183. sleep 2
  184. f_kill_gms
  185. f_tap_test $TBCHECKER_Y_COORD
  186. sleep $PI_WAIT_VERDICT
  187. f_dump_xml "$tbchecker_xml"
  188. f_kill_app $tbchecker
  189. logcat -d | grep PIF >> "$log"
  190. local pass=$(cat "$tbchecker_xml" | grep -o 'Pass' | wc -l)
  191. local fail=$(cat "$tbchecker_xml" | grep -o 'Fail' | wc -l)
  192. # echo "PI Pass:$pass Fail:$fail" | tee -a "$results"
  193. (( val = pass+2 ))
  194. (( pass == 1 )) && meets=MEETS_BASIC_INTEGRITY
  195. (( pass == 2 )) && meets=MEETS_DEVICE_INTEGRITY
  196. (( pass == 3 )) && meets=MEETS_STRONG_INTEGRITY
  197. (( pass == 0 )) && meets=NO_INTEGRITY && (( val = 1 ))
  198. (( pass == 0 )) && (( fail == 0 )) && meets="" && (( val = 0 ))
  199. [ -n "$meets" ] && echo $meets | tee -a "$results"
  200. return $val
  201. }
  202. function f_test_iapi()
  203. {
  204. local json="$1"
  205. cp "$json" $custom_json
  206. f_remove_file "$log"; f_remove_file "$iapi_xml"
  207. f_start_activity $iapi/com.dynamic.integrity.MainActivity
  208. sleep 2
  209. f_kill_gms
  210. f_tap_test $IAPI_Y_COORD
  211. sleep $PI_WAIT_VERDICT
  212. f_dump_xml "$iapi_xml"
  213. f_kill_app $iapi
  214. logcat -d | grep PIF >> "$log"
  215. (( i = 0 )); (( val = i++ ))
  216. for meets in $integrities
  217. do
  218. found=$(cat "$iapi_xml" | grep $meets)
  219. [ -n "$found" ] && echo $meets | tee -a "$results" && (( val = i ))
  220. (( i++ ))
  221. done
  222. return $val
  223. }
  224. function f_test_pi()
  225. {
  226. local json="$1"; local verbose="$2"
  227. local prop=$(cat "$json" | grep -o '"\SECURITY_PATCH"[^,}]*')
  228. [ -n "$verbose" ] && [ -n "$prop" ] && echo "$prop" | tee -a "$results"
  229. prop=$(cat "$json" | grep -o '"\_ORIGINAL_FIRST_API_LEVEL"[^,}]*')
  230. [ -n "$verbose" ] && [ -n "$prop" ] && echo "$prop" | tee -a "$results"
  231. prop=$(cat "$json" | grep -o '"\*api_level"[^,}]*')
  232. [ -n "$prop" ] && echo "$prop" | tee -a "$results"
  233. prop=$(cat "$json" | grep -o '"\DEVICE_INITIAL_SDK_INT"[^,}]*')
  234. [ -n "$prop" ] && echo "$prop" | tee -a "$results"
  235. prop=$(cat "$json" | grep -o '"\FIRST_API_LEVEL"[^,}]*')
  236. [ -n "$prop" ] && echo "$prop" | tee -a "$results"
  237. case "$TEST_PI" in
  238. TEST_PICHECK) f_test_picheck "$json"
  239. ;;
  240. TEST_TBCHECKER) f_test_tbchecker "$json"
  241. ;;
  242. TEST_IAPI) f_test_iapi "$json"
  243. ;;
  244. TEST_SPIC|*) f_test_spic "$json"
  245. ;;
  246. esac
  247. (( val = $? )); return $val
  248. }
  249. function f_set_api_25()
  250. {
  251. local json="$1"
  252. sed -i 's/"\*api_level"[^,}]*/"\*api_level": "25"/' "$json"
  253. sed -i 's/"DEVICE_INITIAL_SDK_INT"[^,}]*/"DEVICE_INITIAL_SDK_INT": "25"/' "$json"
  254. sed -i 's/"FIRST_API_LEVEL"[^,}]*/"FIRST_API_LEVEL": "25"/' "$json"
  255. (( setApi25++ ))
  256. }
  257. function f_migrate_json()
  258. {
  259. local json="$1"; local folder="$2"
  260. local custom=""
  261. [ -f "$migrate_script" ] && sh "$migrate_script" -i -f -o -a "$json" && custom="$folder/custom.pif.json"
  262. [ -f "$custom" ] && mv "$custom" "$json" && (( migrated++ ))
  263. }
  264. function f_prep_json()
  265. {
  266. local json="$1"; local folder="$2"
  267. [ -n "$MIGRATE_JSON" ] && f_migrate_json "$json" "$folder"
  268. # sed -i 's/"VNDK_VERSION"/"ignore-VNDK_VERSION"/' "$json"
  269. [ "$USE_MODULE" == "PI_FORK" ] && api25=$(cat "$json" | grep -o '"\*api_level"[^,}]*' | grep -o '25')
  270. local prop=$(cat "$json" | grep -o '"FIRST_API_LEVEL"[^,}]*')
  271. [ "$USE_MODULE" == "PI_FIX" ] && [ -n "$api25" ] && api25=$(echo "$prop" | grep -o '25')
  272. prop=$(cat "$json" | grep -o '"DEVICE_INITIAL_SDK_INT"[^,}]*')
  273. [ "$USE_MODULE" == "PI_FORK" ] && [ -n "$prop" ] && [ -n "$api25" ] && api25=$(echo "$prop" | grep -o '25')
  274. # echo "api25=$api25" | tee -a "$results"
  275. }
  276. function f_test_json()
  277. {
  278. local json="$1"; local folder="$2"
  279. echo "$json" | tee -a "$results"
  280. (( tested++ ))
  281. f_prep_json "$json" "$folder"
  282. (( val = 0 )); local changeApi=""
  283. if [ -n "$TEST_YASNAC" ]; then
  284. f_test_yasnac "$json"; (( val = $? ))
  285. (( val == 2 )) && changeApi="yes"
  286. fi
  287. # echo "api25=$api25, changeApi=$changeApi" | tee -a "$results"
  288. [ -z "$api25" ] && [ -n "$changeApi" ] && f_set_api_25 "$json"
  289. (( val != 1 )) && f_test_pi "$json" "yes" && (( val = $? ))
  290. (( val > 1 )) && (( val < 4 )) && [ -z "$api25" ] && [ -z "$changeApi" ] && f_set_api_25 "$json" && f_test_pi "$json" && (( val = $? ))
  291. (( val > 0 )) && (( val < 4 )) && (( failed++ ))
  292. (( val > 0 )) && (( val < 4 )) && [ -n "$DELETE_FAILED" ] && echo "Deleted" | tee -a "$results" && f_remove_file "$json"
  293. (( val == 0 )) && echo "Inconclusive" | tee -a "$results" && (( inconclusive++ ))
  294. (( val >= 4 )) && (( passed++ ))
  295. # echo "tested=$tested, setApi25=$setApi25, passed=$passed" | tee -a "$results"
  296. # echo "failed=$failed, inconclusive=$inconclusive" | tee -a "$results"
  297. echo "" | tee -a "$results"
  298. return $val
  299. }
  300. function f_test_folder()
  301. {
  302. local folder="$1"
  303. local list=$( ls "$folder"/$PIF_JSON 2>/dev/null )
  304. [ -z "$list" ] && return
  305. (( folders++ ))
  306. for json in $list
  307. do
  308. [ -n "$json" ] && [ -f "$json" ] && [ -r "$json" ] && [ -s "$json" ] && f_test_json "$json" "$folder"
  309. done
  310. }
  311. list=$( find "$test_path" -maxdepth $FOLDERS_DEPTH -type d 2>/dev/null )
  312. for folder in $list
  313. do
  314. [ -n "$folder" ] && [ -e "$folder" ] && f_test_folder "$folder"
  315. done
  316. echo "folders=$folders" | tee -a "$results"
  317. echo "tested=$tested, migrated=$migrated, setApi25=$setApi25" | tee -a "$results"
  318. echo "passed=$passed, failed=$failed, inconclusive=$inconclusive" | tee -a "$results"
  319. echo "" | tee -a "$results"
  320. f_remove_file "$custom_json"; cp "$custom_bak" "$custom_json" >/dev/null 2>&1
  321. f_kill_gms
  322. f_kill_app $yasnac; f_kill_app $spic; f_kill_app $picheck; f_kill_app $tbchecker; f_kill_app $iapi
  323. f_remove_file "$yasnac_xml"; f_remove_file "$spic_xml"; f_remove_file "$picheck_xml"; f_remove_file "$tbchecker_xml"; f_remove_file "$iapi_xml"
  324. settings put system user_rotation "$orient"
  325. settings put system accelerometer_rotation "$auto_rot"