├── .gitignore ├── LICENSE ├── README.md ├── TODO.md ├── boot-loop.sh ├── channel-jumper.sh ├── cloudprint-connector-instance.sh ├── compile-cros.sh ├── custom_dmserver.sh ├── delayed-boot-loop.conf ├── delayed-boot-loop.sh ├── disable_cros_updates.sh ├── enable_rw_ssd.sh ├── log-hids.conf ├── log-hids.sh ├── recover-psks.sh ├── remote_devtools.sh ├── upload-bios.sh ├── verbose_logging.sh └── whitelist_extension_for_pub_session.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cros-scripts 2 | Scripts to run on Chrome OS 3 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | Possible scripts: 2 | 3 | * switch to canary channel (and possibly other channels) 4 | * force non-delta self-update (OS refresh) to restore SSD verify. 5 | * point device at non-Google policy server (need server capable of sending policy) - https://www.chromium.org/developers/how-tos/enterprise/running-the-cloud-policy-test-server 6 | * show device info including serial # 7 | * validate factory firmware is intact (not factory testing or compromised) 8 | -------------------------------------------------------------------------------- /boot-loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # stop if there's any Yubico key plugged in 4 | STOPSERIAL="idVendor=1050" 5 | 6 | STATEFUL=/mnt/stateful_partition 7 | PATTERN=DmL2nf8Kt 8 | 9 | for ((i=0; i<100; i++)); do 10 | PATTERN100="$PATTERN100$PATTERN" 11 | done 12 | 13 | PATTERN100MD5=321fe3cb8465a0cc689861379c6c9ae2 14 | 15 | # serial of my usb key 16 | if dmesg | grep "$STOPSERIAL"; then 17 | stop ui 18 | # make noise to get attention 19 | speaker-test -l 2 -t sine -c 2 -p2000 -P 2 20 | exit 21 | fi 22 | 23 | for part in encrypted/test test; do 24 | for ((i=0; i<200; i++)); do 25 | file="$STATEFUL/$part.$i" 26 | if md5sum "$file" | grep -v $PATTERN100MD5; then 27 | stop ui 28 | # make noise to get attention 29 | speaker-test -l 0 -t sine -c 2 -p2000 -P 2 30 | exit 31 | fi 32 | rm -f "$file" 33 | for ((j=0; j<100; j++)); do 34 | echo $PATTERN100 >> "$file" 35 | done 36 | done 37 | done 38 | 39 | reboot 40 | -------------------------------------------------------------------------------- /channel-jumper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Jump Chrome OS Channels - switch to newer or older Chrome OS channels without USB recovery. 4 | 5 | # Run this script on a Chromebook: 6 | # 1. Put Chromebook in developer mode - https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device 7 | # 2. Log into device. Press CTRL+ALT+T to open crosh shell. 8 | # 3. Type "shell" to enter Bash shell. 9 | # 4. Type: 10 | # bash <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/channel-jumper.sh) 11 | 12 | get_val_from_file() { 13 | val=$2 14 | filename=$1 15 | echo `cat $filename | grep $val | awk -F= '{print $2}'` 16 | } 17 | 18 | os_version=$( get_val_from_file /etc/lsb-release CHROMEOS_RELEASE_VERSION ) 19 | browser_version=$( get_val_from_file /etc/lsb-release CHROMEOS_RELEASE_CHROME_MILESTONE ) 20 | track=$( get_val_from_file /etc/lsb-release CHROMEOS_RELEASE_TRACK ) 21 | echo -e "You are running:\n Chrome OS $os_version\n Browser $browser_version\n Channel $track\n\n" 22 | 23 | 24 | while true; do 25 | read -p "Which channel do you wish to use switch to (stable, beta, dev or canary)?: " new_channel 26 | case $new_channel in 27 | stable|beta|dev|dev|canary) 28 | break 29 | ;; 30 | *) 31 | echo "Please enter stable, beta, dev or canary." 32 | ;; 33 | esac 34 | done 35 | new_channel="$new_channel-channel" 36 | 37 | sudo mkdir -p /mnt/stateful_partition/etc 38 | 39 | echo -e "CHROMEOS_RELEASE_VERSION=100.0.0" > /tmp/lsb-release 40 | sudo cp /tmp/lsb-release /mnt/stateful_partition/etc/ 41 | update_engine_client --channel=$new_channel 42 | -------------------------------------------------------------------------------- /cloudprint-connector-instance.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # make sure we only run once at VM creation 4 | # additional reboots exit immediately 5 | if [ -f /root/.startup-script-ran ] 6 | then 7 | echo "startup script already ran once" 8 | exit 0 9 | else 10 | touch /root/.startup-script-ran 11 | fi 12 | 13 | metadata_url="http://metadata.google.internal/computeMetadata/v1/instance/attributes/" 14 | 15 | # Config for new users 16 | echo 'export GOROOT=/usr/local/go' >> /etc/skel/.bashrc 17 | echo 'export GOPATH=$HOME/go' >> /etc/skel/.bashrc 18 | echo 'export PATH=$PATH:$GOROOT/bin:$GOPATH/bin' >> /etc/skel/.bashrc 19 | mkdir /etc/skel/go 20 | cat <> /etc/skel/.profile 21 | if [ \! -f ~/.first-login-script-ran ] 22 | then 23 | echo "Installing GoLang GCP 2.0 Connector..." 24 | go get -v -u -ldflags "-X github.com/google/cloud-print-connector/lib.BuildDate=\`date +%Y.%m.%d\`" github.com/google/cloud-print-connector/... 25 | echo 26 | echo "Initializing connector..." 27 | gcp-connector-util init --log-level DEBUG 28 | echo 29 | gcp_command="gcp-cups-connector --config-filename \${HOME}/gcp-cups-connector.config.json --log-to-console" 30 | touch ~/.first-login-script-ran 31 | echo "Starting connector with \$gcp_command" 32 | \$gcp_command 33 | fi 34 | EOT 35 | 36 | # start by making sure all installed packages 37 | # are up to date. 38 | export DEBIAN_FRONTEND=noninteractive 39 | apt-get update 40 | #apt-get -y dist-upgrade 41 | 42 | # install the packages we need. For some reason it 43 | # fails every now and again so loop until success 44 | packages="whois build-essential libcups2-dev libavahi-client-dev git bzr cups cups-pdf apache2" 45 | echo "installing $packages" 46 | until apt-get -y install $packages 47 | do 48 | echo "failed to install packages, sleeping and trying again" 49 | sleep 10 50 | apt-get update 51 | done 52 | 53 | # Install Go 54 | typeset VER=`curl -s https://golang.org/dl/ | grep -m 1 -o 'go\([0-9]\)\+\(\.[0-9]\)\+'` 55 | curl -O https://storage.googleapis.com/golang/$VER.linux-amd64.tar.gz 56 | tar xvf $VER.linux-amd64.tar.gz 57 | chown -R root:root ./go 58 | mv go /usr/local 59 | 60 | # Install GAM 61 | bash <(curl -s -S -L https://git.io/install-gam) -d /usr/local -l 62 | echo 'alias gam="/usr/local/gam/gam"' >> /etc/skel/.bashrc 63 | echo '{"installed":{"client_id":"744500012322-l9k71a79e12lnu87ffqohqjl0141f22h.apps.googleusercontent.com","project_id":"jayhlee-gce-instances","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"hlocexhhxrHWKO3iCxReaPVi","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}' > /usr/local/gam/client_secrets.json 64 | touch /usr/local/gam/nobrowser.txt 65 | chmod a+rwx -R /usr/local/gam 66 | 67 | # Share PDF folder via web 68 | echo '' > /var/www/html/index.html 69 | ln -s /var/spool/cups-pdf/ANONYMOUS/ /var/www/html/pdfs 70 | 71 | # Give jobs unique filenames 72 | echo "Label 1" >> /etc/cups/cups-pdf.conf 73 | 74 | # Reboot or restart services as required 75 | # so that upgrades and config changes are applied 76 | if [ -a /var/run/reboot-required ] 77 | then 78 | reboot 79 | else 80 | service cups restart 81 | fi 82 | -------------------------------------------------------------------------------- /compile-cros.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # make sure we only run once at VM creation 4 | # additional reboots exit immediately 5 | if [ -f /root/.startup-script-ran ] 6 | then 7 | echo "startup script already ran once" 8 | exit 0 9 | else 10 | touch /root/.startup-script-ran 11 | fi 12 | 13 | useradd -m cros 14 | adduser cros google-sudoers 15 | 16 | metadata_url="http://metadata.google.internal/computeMetadata/v1/instance/attributes/" 17 | board=`curl --fail $metadata_url/board -H "Metadata-Flavor: Google"` 18 | if [ -z $board ] 19 | then 20 | board="caroline" 21 | fi 22 | branch=`curl --fail $metadata_url/branch -H "Metadata-Flavor: Google"` 23 | if [ ! -z $branch ] 24 | then 25 | branch_flag="-b $branch" 26 | else 27 | branch="master" 28 | branch_flag="" 29 | fi 30 | export ACCEPT_LICENSES="*" 31 | export ACCEPT_LICENSE=$ACCEPT_LICENSES 32 | 33 | echo "BUILDSCRIPT: building for board $board and branch $branch..." 34 | 35 | # start by making sure all installed packages 36 | # are up to date. 37 | export DEBIAN_FRONTEND=noninteractive 38 | apt update 39 | apt -y upgrade 40 | 41 | # install the packages we need. For some reason it 42 | # fails every now and again so loop until success 43 | packages="git-core gitk git-gui curl lvm2 thin-provisioning-tools python-pkg-resources python-virtualenv python-oauth2client" 44 | echo "installing $packages" 45 | until apt -y install $packages 46 | do 47 | echo "BUILDSCRIPT: failed to install packages, sleeping and trying again" 48 | sleep 10 49 | apt update 50 | done 51 | 52 | sudo -i -u cros bash << EOF 53 | echo "BUILDSCRIPT: setting git defaults..." 54 | git config --global color.ui false 55 | git config --global user.email "jay0lee@gmail.com" 56 | git config --global user.name "Jay Lee" 57 | echo "BUILDSCRIPT: cloning depot_tools..." 58 | git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git 59 | mkdir -p ~/chromiumos 60 | cd ~/chromiumos 61 | echo "BUILDSCRIPT: repo init..." 62 | /home/cros/depot_tools/repo init \ 63 | -u https://chromium.googlesource.com/chromiumos/manifest.git \ 64 | --repo-url https://chromium.googlesource.com/external/repo.git $branch_flag 65 | echo "BUILDSCRIPT: repo sync..." 66 | /home/cros/depot_tools/repo sync -j8 67 | echo "BUILDSCRIPT: cros_sdk --download..." 68 | /home/cros/depot_tools/cros_sdk --download 69 | echo "BUILDSCRIPT: setup_board..." 70 | /home/cros/depot_tools/cros_sdk -- ./setup_board --board=$board --default 71 | echo "BUILDSCRIPT: set_shared_user_password..." 72 | /home/cros/depot_tools/cros_sdk -- ./set_shared_user_password.sh chronos 73 | echo "BUILDSCRIPT: build_packages..." 74 | /home/cros/depot_tools/cros_sdk -- ./build_packages --accept_licenses=$ACCEPT_LICENSES 75 | echo "BUILDSCRIPT: build_image..." 76 | /home/cros/depot_tools/cros_sdk -- ./build_image --noenable_rootfs_verification dev 77 | EOF 78 | -------------------------------------------------------------------------------- /custom_dmserver.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom DM Server - configure Chrome OS to pull policy from a custom URL 4 | 5 | # Run this script on a Chromebook: 6 | # 1. Put Chromebook in developer mode - https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device 7 | # 2. Log into device. Press CTRL+ALT+T to open crosh shell. 8 | # 3. Type "shell" to enter Bash shell. 9 | # 4. Type: 10 | # bash <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/custom_dmserver.sh) 11 | 12 | # Make SSD read/write if it's not 13 | source <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/enable_rw_ssd.sh) 14 | 15 | read -p "Which URL do you wish to use for custom policy?: " policy_url 16 | url_line="--device-management-url=$policy_url" 17 | sudo bash -c 'echo "--enterprise-enrollment-skip-robot-auth" >> /etc/chrome_dev.conf' 18 | sudo bash -c "echo $url_line >> /etc/chrome_dev.conf" 19 | echo 20 | echo "Switched policy to pull from:" 21 | echo 22 | echo $policy_url 23 | echo 24 | echo "Restarting UI in 10 seconds to pull and apply new custom policy" 25 | sleep 10 26 | sudo restart ui 27 | -------------------------------------------------------------------------------- /delayed-boot-loop.conf: -------------------------------------------------------------------------------- 1 | start on starting boot-services 2 | task 3 | 4 | script 5 | sleep SECONDS && reboot & 6 | end script 7 | -------------------------------------------------------------------------------- /delayed-boot-loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Delayed Boot Loop - reboots device after it's been up for N seconds 4 | 5 | # Run this script on a Chromebook: 6 | # 1. Put Chromebook in developer mode - https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device 7 | # 2. Log into device. Press CTRL+ALT+T to open crosh shell. 8 | # 3. Type "shell" to enter Bash shell. 9 | # 4. Type: 10 | # bash <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/delayed-boot-loop.sh) NN 11 | # 12 | # where NN is the number of seconds after boot you'd like to wait before rebooting 13 | 14 | # Make SSD read/write if it's not 15 | source <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/enable_rw_ssd.sh) 16 | 17 | seconds=$1 18 | echo "Getting delayed boot loop config file..." 19 | echo 20 | sudo curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/delayed-boot-loop.conf > /tmp/delayed-boot-loop.conf 21 | sudo sed -i "s/SECONDS/$seconds/g" /tmp/delayed-boot-loop.conf 22 | sudo mv /tmp/delayed-boot-loop.conf /etc/init/ 23 | echo 24 | echo "Enabled Boot delayed boot loop in /var/log/hids.log. Please reboot for logging to take effect." 25 | -------------------------------------------------------------------------------- /disable_cros_updates.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | 4 | # Disable CrOS Updates - prevents Chrome OS from updating by faking a very large version # 5 | 6 | # Run this script on a Chromebook: 7 | # 1. Put Chromebook in developer mode - https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device 8 | # 2. Log into device. Press CTRL+ALT+T to open crosh shell. 9 | # 3. Type "shell" to enter Bash shell. 10 | # 4. Type: 11 | # bash <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/disable_cros_updates.sh) 12 | 13 | sudo mkdir -p /mnt/stateful_partition/etc 14 | sudo bash -c 'echo "CHROMEOS_RELEASE_VERSION=99999.9.9" > /mnt/stateful_partition/etc/lsb-release' 15 | 16 | echo "Disabled Chrome OS updates. Delete /mnt/stateful_partition/etc/lsb-release file to re-enable." 17 | -------------------------------------------------------------------------------- /enable_rw_ssd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Enable RW SSD - Turns off root filesystem verification and puts root partition of Chromebook into RW mode. 4 | # Be aware that Chrome OS updates may overwrite your changes. 5 | 6 | # Run this script on a Chromebook: 7 | # 1. Put Chromebook in developer mode - https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device 8 | # 2. Log into device. Press CTRL+ALT+T to open crosh shell. 9 | # 3. Type "shell" to enter Bash shell. 10 | # 4. Type: 11 | # bash <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/enable_rw_ssd.sh) 12 | 13 | sudo touch /root-is-readwrite &> /dev/null 14 | if [ ! -f /root-is-readwrite ] 15 | then 16 | read -p "Modifying OS. USB Recovery will be needed to get out of developer mode. Are you sure you want to do this? (y/N): " is_user_sure 17 | is_user_sure=${is_user_sure:0:1} 18 | is_user_sure=${is_user_sure,,} 19 | if [ ! ${is_user_sure} = "y" ] 20 | then 21 | echo "Come back when you're sure..." 22 | exit 23 | fi 24 | 25 | # Disable updates 26 | source <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/disable_cros_updates.sh) 27 | 28 | sudo /usr/share/vboot/bin/make_dev_ssd.sh --remove_rootfs_verification --partitions "2 4" 29 | sudo mount -o remount,rw / 30 | if [ $? -ne 0 ]; then 31 | echo 32 | echo 33 | echo 34 | echo "Reboot needed to enable OS writing. Please re-run script after a restart." 35 | echo 36 | echo "Rebooting in 15 seconds..." 37 | sleep 15 38 | sudo reboot 39 | fi 40 | else 41 | sudo rm -rf /root-is-readwrite 42 | echo "Root filesystem is already read/write" 43 | fi 44 | -------------------------------------------------------------------------------- /log-hids.conf: -------------------------------------------------------------------------------- 1 | start on starting boot-services 2 | task 3 | 4 | script 5 | watch -n1 "date >> /var/log/hids.log; lsusb >> /var/log/hids.log; echo '' >> /var/log/hids.log" & 6 | end script 7 | -------------------------------------------------------------------------------- /log-hids.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Log HIDs - creates a /var/log/hids.log file with current list of USB devices every 1 sec 4 | 5 | # Run this script on a Chromebook: 6 | # 1. Put Chromebook in developer mode - https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device 7 | # 2. Log into device. Press CTRL+ALT+T to open crosh shell. 8 | # 3. Type "shell" to enter Bash shell. 9 | # 4. Type: 10 | # bash <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/log-hids.sh) 11 | 12 | # Make SSD read/write if it's not 13 | source <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/enable_rw_ssd.sh) 14 | 15 | echo "Getting HID config file..." 16 | echo 17 | sudo curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/log-hids.conf > /tmp/log-hids.conf 18 | sudo mv /tmp/log-hids.conf /etc/init/ 19 | echo 20 | echo "Enabled HID logging in /var/log/hids.log. Please reboot for logging to take effect." 21 | -------------------------------------------------------------------------------- /recover-psks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Recover WPA PSKs - prints out PSKs for WPA-PSK networks pushed to device via user/device policy 4 | 5 | # Run this script on a Chromebook: 6 | # 1. Put Chromebook in developer mode - https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device 7 | # 2. Log into device. Press CTRL+ALT+T to open crosh shell. 8 | # 3. Type "shell" to enter Bash shell. 9 | # 4. Type: 10 | # bash <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/recover-psks.sh) 11 | 12 | device_policy_file=/var/cache/shill/default.profile 13 | echo "Device PSKs:" 14 | if ls $device_policy_file 1> /dev/null 2>&1; then 15 | sudo cat $device_policy_file | \ 16 | grep -E '^Name=|^Passphrase=' | \ 17 | cut -d "=" -f 2- | \ 18 | while read line 19 | do 20 | if [[ "$line" == "default" ]]; then 21 | continue 22 | fi 23 | if [[ "$line" == "rot47"* ]]; then 24 | rotted=${line:6} 25 | unrotted=`echo $rotted | tr '!-~' 'P-~!-O'` 26 | echo " PSK: $unrotted" 27 | echo 28 | else 29 | echo "SSID: $line" 30 | fi 31 | done 32 | else 33 | echo "No device policy networks found." 34 | fi 35 | echo 36 | echo 37 | echo "User PSKs:" 38 | sudo bash -c 'cat /home/root/*/session_manager/policy/policy' | \ 39 | grep -a -E '\"Passphrase\":|\"SSID\":' 40 | -------------------------------------------------------------------------------- /remote_devtools.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | 4 | # Remote devtools debugging - allows remote connectivity to Chrome dev tools for debugging kiosk session / etc. 5 | 6 | # Run this script on a Chromebook: 7 | # 1. Put Chromebook in developer mode - https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device 8 | # 2. Log into device. Press CTRL+ALT+T to open crosh shell. 9 | # 3. Type "shell" to enter Bash shell. 10 | # 4. Type: 11 | # bash <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/remote_devtools.sh) 12 | # 5. If the device is not already in read-write mode (which it probably isn't) the script will reboot your device. 13 | # 6. Repeat steps 2-4 (same command) after the reboot. 14 | # 7. Make sure the device is connected to an open Wifi network that allows peer-to-peer (p2p) connections). 15 | # 8. Note the IP address of the this device (it may change). You should be able to access the remote devtools at http://:9223 16 | 17 | # Make SSD read/write if it's not 18 | source <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/enable_rw_ssd.sh) 19 | 20 | sudo bash -c 'echo "--remote-debugging-port=9222" >> /etc/chrome_dev.conf' 21 | sudo /usr/libexec/debugd/helpers/dev_features_ssh 22 | 23 | cat >/tmp/remote-devtools.conf < 24 | my_creds=~/.firmware_upload 25 | if [ -s $my_creds ]; then 26 | # if we already have a token stored, use it 27 | . $my_creds 28 | time_now=`date +%s` 29 | else 30 | scope='https://www.googleapis.com/auth/drive.file' 31 | # Form the request URL 32 | # http://goo.gl/U0uKEb 33 | auth_url="https://accounts.google.com/o/oauth2/auth?client_id=$client_id&scope=$scope&response_type=code&redirect_uri=urn:ietf:wg:oauth:2.0:oob&access_type=online" 34 | 35 | echo "Please go to:" 36 | echo 37 | echo "$auth_url" 38 | echo 39 | echo "after accepting, enter the code you are given:" 40 | read auth_code 41 | 42 | # swap authorization code for access and refresh tokens 43 | # http://goo.gl/Mu9E5J 44 | auth_result=$(curl -s https://accounts.google.com/o/oauth2/token \ 45 | -H 'Content-Type: application/x-www-form-urlencoded' \ 46 | -d "code=$auth_code" \ 47 | -d "client_id=$client_id" \ 48 | -d "client_secret=$client_secret" \ 49 | -d "redirect_uri=urn:ietf:wg:oauth:2.0:oob" \ 50 | -d "grant_type=authorization_code") 51 | access_token=$(echo -e "$auth_result" | \ 52 | grep -E '"access_token" *: *.*?[^\\]",' | \ 53 | awk -F'"' '{ print $4 }') 54 | refresh_token=$(echo -e "$auth_result" | \ 55 | grep -E '"refresh_token" *: *.*?[^\\]",*' | \ 56 | awk -F'"' '{ print $4 }') 57 | expires_in=$(echo -e "$auth_result" | \ 58 | grep -E '"expires_in" *: *.*' | \ 59 | awk -F' ' '{ print $3 }' | awk -F',' '{ print $1}') 60 | time_now=`date +%s` 61 | expires_at=$((time_now + expires_in - 60)) 62 | echo -e "access_token=$access_token\nrefresh_token=$refresh_token\nexpires_at=$expires_at" > $my_creds 63 | fi 64 | 65 | # if our access token is expired, use the refresh token to get a new one 66 | # http://goo.gl/71rN6V 67 | if [ $time_now -gt $expires_at ]; then 68 | refresh_result=$(curl -s https://accounts.google.com/o/oauth2/token \ 69 | -H 'Content-Type: application/x-www-form-urlencoded' \ 70 | -d "refresh_token=$refresh_token" \ 71 | -d "client_id=$client_id" \ 72 | -d "client_secret=$client_secret" \ 73 | -d "grant_type=refresh_token") 74 | access_token=$(echo -e "$refresh_result" | \ 75 | grep -E '"access_token" *: *.*?[^\\]",' | \ 76 | awk -F'"' '{ print $4 }') 77 | expires_in=$(echo -e "$refresh_result" | \ 78 | grep -E '"expires_in" *: *.*' | \ 79 | awk -F' ' '{ print $3 }' | awk -F',' '{ print $1 }') 80 | time_now=`date +%s` 81 | expires_at=$(($time_now + $expires_in - 60)) 82 | echo -e "access_token=$access_token\nrefresh_token=$refresh_token\nexpires_at=$expires_at" > $my_creds 83 | fi 84 | 85 | # Dump our firmware to a file 86 | echo -e "\nDumping firmware to temp file /tmp/$drive_filename...\n" 87 | sudo flashrom -r /tmp/$drive_filename 88 | 89 | # Upload the file to drive 90 | # http://goo.gl/VV4mZJ 91 | echo -e "\nUploading firmware to Google Drive...\n" 92 | upload_result=$(curl https://www.googleapis.com/upload/drive/v2/files \ 93 | -d "uploadType=media" \ 94 | -d "prettyPrint=true" \ 95 | -d "fields=id" \ 96 | -H "Content-Type: application/octet-stream" \ 97 | -H "Authorization: Bearer $access_token" \ 98 | --data-binary @/tmp/$drive_filename) 99 | 100 | file_id=$(echo -e "$upload_result" | \ 101 | grep -E '^ "id" *: *.*?[^\\]",' | \ 102 | awk -F'"' '{ print $4 }') 103 | 104 | # Patch file name and description 105 | # http://goo.gl/EZW93n 106 | patch_body="{ \"title\": \"$drive_filename\", \"description\": \"$drive_filedescription\" }" 107 | patch_url="https://www.googleapis.com/drive/v2/files/$file_id" 108 | echo -e "\nSetting firmware filename and description...\n" 109 | patch_result=$(curl -s $patch_url \ 110 | -X PATCH \ 111 | -H "Content-Type: application/json" \ 112 | -H "Authorization: Bearer $access_token" \ 113 | -d "$patch_body") 114 | echo -e "All finished! Please confirm you can see:\n\n $drive_filename\n\nin Google Drive before playing with firmware updates." 115 | -------------------------------------------------------------------------------- /verbose_logging.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Verbose Logging - Add parameters to /etc/chrome_dev.conf that increase logging verbosity. 4 | 5 | # Run this script on a Chromebook: 6 | # 1. Put Chromebook in developer mode - https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device 7 | # 2. Log into device. Press CTRL+ALT+T to open crosh shell. 8 | # 3. Type "shell" to enter Bash shell. 9 | # 4. Type: 10 | # bash <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/verbose_logging.sh) 11 | 12 | # Make SSD read/write if it's not 13 | source <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/enable_rw_ssd.sh) 14 | 15 | sudo bash -c 'echo "--log-net-log=/tmp/netlog" >> /etc/chrome_dev.conf' 16 | sudo bash -c 'echo "--net-log-level=0" >> /etc/chrome_dev.conf' 17 | sudo bash -c 'echo "--v=2" >> /etc/chrome_dev.conf' 18 | sudo bash -c 'echo "vmodule=*/chromeos/login/*=2" >> /etc/chrome_dev.conf' 19 | echo 20 | echo "Enabled verbose logging in /etc/chrome_dev.conf. Please reboot for logging to take effect." 21 | -------------------------------------------------------------------------------- /whitelist_extension_for_pub_session.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Whitelist extensions for public session - modifies the Chrome binary executable replacing an existing 4 | # extension in the whitelist with your own for testing. 5 | 6 | # Run this script on a Chromebook: 7 | # 1. Put Chromebook in developer mode - https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device 8 | # 2. Log into device. Press CTRL+ALT+T to open crosh shell. 9 | # 3. Type "shell" to enter Bash shell. 10 | # 4. Type: 11 | # bash <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/whitelist_extension_for_pub_session.sh) 12 | 13 | function patch_strings_in_file() { 14 | local FILE="$1" 15 | local PATTERN="$2" 16 | local REPLACEMENT="$3" 17 | 18 | # Find all unique strings in FILE that contain the pattern 19 | HASSTRING=$(grep ${PATTERN} ${FILE}) 20 | 21 | if [ "${HASSTRING}" != "" ] ; then 22 | echo "File '${FILE}' contain strings with '${PATTERN}' in them:" 23 | 24 | OLD_STRING=${PATTERN} 25 | NEW_STRING=${REPLACEMENT} 26 | 27 | # Create null terminated ASCII HEX representations of the strings 28 | OLD_STRING_HEX="$(echo -n ${OLD_STRING} | xxd -g 0 -u -ps -c 256)00" 29 | NEW_STRING_HEX="$(echo -n ${NEW_STRING} | xxd -g 0 -u -ps -c 256)00" 30 | 31 | if [ ${#NEW_STRING_HEX} -le ${#OLD_STRING_HEX} ] ; then 32 | # Pad the replacement string with null terminations so the 33 | # length matches the original string 34 | while [ ${#NEW_STRING_HEX} -lt ${#OLD_STRING_HEX} ] ; do 35 | NEW_STRING_HEX="${NEW_STRING_HEX}00" 36 | done 37 | 38 | # Now, replace every occurrence of OLD_STRING with NEW_STRING 39 | echo -n "Replacing ${OLD_STRING} with ${NEW_STRING}... " 40 | tempfile="/tmp/$(basename $0).$$.tmp" 41 | hexdump -ve '1/1 "%.2X"' ${FILE} | \ 42 | sed "s/${OLD_STRING_HEX}/${NEW_STRING_HEX}/g" | \ 43 | xxd -r -p > $tempfile 44 | chmod --reference ${FILE} $tempfile 45 | sudo mv $tempfile ${FILE} 46 | echo "Done!" 47 | else 48 | echo "New string '${NEW_STRING}' is longer than old" \ 49 | "string '${OLD_STRING}'. Skipping." 50 | fi 51 | else 52 | echo "${PATTERN} not found in ${FILE}!" 53 | fi 54 | } 55 | 56 | # Make SSD read/write if it's not 57 | source <(curl -s -S -L https://raw.githubusercontent.com/jay0lee/cros-scripts/master/enable_rw_ssd.sh) 58 | 59 | # Need xxd binary which Chrome OS doesn't have to do search/replace on chrome binary 60 | if [ ! -f /usr/bin/xxd ] 61 | then 62 | echo "Getting xxd binary for editing..." 63 | echo 64 | sudo wget --quiet -O /usr/bin/xxd https://github.com/jay0lee/cros-scripts/releases/download/vBinaries/xxd 65 | sudo chmod a+rx /usr/bin/xxd 66 | else 67 | echo "We already have /usr/bin/xxd binary for editing." 68 | fi 69 | 70 | # Prompt user for extension to allow 71 | while : 72 | do 73 | read -p "Which extension do you want to allow in public sessions?: " allow_extension 74 | string_size=${#allow_extension} 75 | if [ $string_size -ne 32 ] 76 | then 77 | echo -e "\n\nExtension IDs should be 32 chars in length. Try again...\n\n" 78 | continue 79 | fi 80 | break 81 | done 82 | 83 | # Prompt user for extension to replace 84 | while : 85 | do 86 | read -p "Which extension do you want to replace? Press enter to replace Overdrive library app: " replace_extension 87 | if [ -z "${replace_extension}" ] 88 | then 89 | replace_extension="fnhgfoccpcjdnjcobejogdnlnidceemb" # Overdrive (library app) 90 | fi 91 | replace_string_size=${#replace_extension} 92 | if [ $replace_string_size -ne 32 ] 93 | then 94 | echo -e "\n\nExtension IDs should be 32 chars in length. Try again...\n\n" 95 | continue 96 | fi 97 | break 98 | done 99 | 100 | patch_strings_in_file /opt/google/chrome/chrome $replace_extension $allow_extension 101 | 102 | echo 103 | echo "If the replace above succeeeded, reboot to see the changes to public session extension whitelist." 104 | echo 105 | --------------------------------------------------------------------------------