lilac.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. #include <algorithm>
  2. #include <cstring>
  3. #include <iterator>
  4. #include <openssl/evp.h>
  5. #include <stdio.h>
  6. #include <iostream>
  7. #include <fstream>
  8. #include <string>
  9. #include <sys/stat.h>
  10. #include <filesystem>
  11. #include "device_management_backend.pb.h"
  12. #include "chrome_device_policy.pb.h"
  13. #include "boringssl/install/include/openssl/evp.h"
  14. #include "boringssl/install/include/openssl/bn.h"
  15. #include "boringssl/install/include/openssl/bytestring.h"
  16. #include "boringssl/install/include/openssl/base.h"
  17. #include "boringssl/install/include/openssl/mem.h"
  18. #include "boringssl/install/include/openssl/rsa.h"
  19. using namespace std;
  20. /*
  21. * holy shit, we actually have device policy editing, holy fucking bingle what?! :3
  22. * rip ultrablue 07
  23. *
  24. * to add a policy value:
  25. * - find the policy protobuf class
  26. * - create a new const variable below the other ones, label it properly, and set the value
  27. * - in patch() copy one of the existing policy editors and modify it
  28. * - in help() add a new line that prints the const variable
  29. * - if info() does not print out the value of the policy already, add it
  30. */
  31. // Signing key test data in DER-encoded PKCS8 format.
  32. const uint8_t kSigningKey[] = {
  33. 0x30, 0x82, 0x01, 0x55, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
  34. 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
  35. 0x01, 0x3f, 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
  36. 0xd9, 0xcd, 0xca, 0xcd, 0xc3, 0xea, 0xbe, 0x72, 0x79, 0x1c, 0x29, 0x37,
  37. 0x39, 0x99, 0x1f, 0xd4, 0xb3, 0x0e, 0xf0, 0x7b, 0x78, 0x77, 0x0e, 0x05,
  38. 0x3b, 0x65, 0x34, 0x12, 0x62, 0xaf, 0xa6, 0x8d, 0x33, 0xce, 0x78, 0xf8,
  39. 0x47, 0x05, 0x1d, 0x98, 0xaa, 0x1b, 0x1f, 0x50, 0x05, 0x5b, 0x3c, 0x19,
  40. 0x3f, 0x80, 0x83, 0x63, 0x63, 0x3a, 0xec, 0xcb, 0x2e, 0x90, 0x4f, 0xf5,
  41. 0x26, 0x76, 0xf1, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x64,
  42. 0x29, 0xc2, 0xd9, 0x6b, 0xfe, 0xf9, 0x84, 0x75, 0x73, 0xe0, 0xf4, 0x77,
  43. 0xb5, 0x96, 0xb0, 0xdf, 0x83, 0xc0, 0x4e, 0x57, 0xf1, 0x10, 0x6e, 0x91,
  44. 0x89, 0x12, 0x30, 0x5e, 0x57, 0xff, 0x14, 0x59, 0x5f, 0x18, 0x86, 0x4e,
  45. 0x4b, 0x17, 0x56, 0xfc, 0x8d, 0x40, 0xdd, 0x74, 0x65, 0xd3, 0xff, 0x67,
  46. 0x64, 0xcb, 0x9c, 0xb4, 0x14, 0x8a, 0x06, 0xb7, 0x13, 0x45, 0x94, 0x16,
  47. 0x7d, 0x3f, 0xe1, 0x02, 0x21, 0x00, 0xf6, 0x0f, 0x31, 0x6d, 0x06, 0xcc,
  48. 0x3b, 0xa0, 0x44, 0x1f, 0xf5, 0xc2, 0x45, 0x2b, 0x10, 0x6c, 0xf9, 0x6f,
  49. 0x8f, 0x87, 0x3d, 0xc0, 0x3b, 0x55, 0x13, 0x37, 0x80, 0xcd, 0x9f, 0xe1,
  50. 0xb7, 0xd9, 0x02, 0x21, 0x00, 0xe2, 0x9a, 0x5f, 0xbf, 0x95, 0x74, 0xb5,
  51. 0x7a, 0x6a, 0xa6, 0x97, 0xbd, 0x75, 0x8c, 0x97, 0x18, 0x24, 0xd6, 0x09,
  52. 0xcd, 0xdc, 0xb5, 0x94, 0xbf, 0xe2, 0x78, 0xaa, 0x20, 0x47, 0x9f, 0x68,
  53. 0x5d, 0x02, 0x21, 0x00, 0xaf, 0x8f, 0x97, 0x8c, 0x5a, 0xd5, 0x4d, 0x95,
  54. 0xc4, 0x05, 0xa9, 0xab, 0xba, 0xfe, 0x46, 0xf1, 0xf9, 0xe7, 0x07, 0x59,
  55. 0x4f, 0x4d, 0xe1, 0x07, 0x8a, 0x76, 0x87, 0x88, 0x2f, 0x13, 0x35, 0xc1,
  56. 0x02, 0x20, 0x24, 0xc3, 0xd9, 0x2f, 0x13, 0x47, 0x99, 0x3e, 0x20, 0x59,
  57. 0xa1, 0x1a, 0xeb, 0x1c, 0x81, 0x53, 0x38, 0x7e, 0xc5, 0x9e, 0x71, 0xe5,
  58. 0xc0, 0x19, 0x95, 0xdb, 0xef, 0xf6, 0x46, 0xc8, 0x95, 0x3d, 0x02, 0x21,
  59. 0x00, 0xaa, 0xb1, 0xff, 0x8a, 0xa2, 0xb2, 0x2b, 0xef, 0x9a, 0x83, 0x3f,
  60. 0xc5, 0xbc, 0xd4, 0x6a, 0x07, 0xe8, 0xc7, 0x0b, 0x2e, 0xd4, 0x0f, 0xf8,
  61. 0x98, 0x68, 0xe1, 0x04, 0xa8, 0x92, 0xd0, 0x10, 0xaa,
  62. };
  63. const bool GMEV = 1; // GuestModeEnabledProto
  64. const bool SUNOSV = 1; // ShowUserNamesOnSigninProto
  65. const bool PVAV = 1; // PluginVmAllowedProto
  66. const bool VMAV = 1; // VirtualMachinesAllowedProto
  67. const bool DUCAV = 1; // DeviceUnaffiliatedCrostiniAllowedProto
  68. const std::string RCP_MRCV = ""; // ReleaseChannelProto.mutable_release_lts_tag
  69. const bool SSPV = 0; // SystemSettingsProto.block_devmode
  70. const std::string DWIP_MDWIV = "{ \"hash\": \"f0f4170422c4c3c0c6a4cd8b7b71479b1a9b8f258a321110ee456e228390e8aa\", \"url\": \"https://cdn.r58playz.dev/sh1mmerbg.jpeg\" }"; // DeviceWallpaperImageProto.mutable_device_wallpaper_image
  71. bool file_exists (const std::string& name) {
  72. struct stat buffer;
  73. return (stat (name.c_str(), &buffer) == 0);
  74. }
  75. void help(int exitcode) {
  76. std::cerr << "lilac is a device policy editor for chromeos." << std::endl;
  77. std::cerr << "lilac [/var/lib/devicesettings/policy.XX] [info|patch|help|--help|-h]" << std::endl;
  78. std::cerr << "arguments:" << std::endl;
  79. std::cerr << " info:" << std::endl;
  80. std::cerr << " show some info about the policy file including what policy values are" << std::endl;
  81. std::cerr << " patch:" << std::endl;
  82. std::cerr << " patch the given policy file" << std::endl;
  83. std::cerr << " help|--help|-h:" << std::endl;
  84. std::cerr << " show this help" << std::endl;
  85. std::cerr << "usage:" << std::endl;
  86. std::cerr << " run lilac on a policy file with patch" << std::endl;
  87. std::cerr << " lilac will modify the policy file and create a new file called owner.key" << std::endl;
  88. std::cerr << " copy the files to /var/lib/devicesettings and turn wifi off so chrome doesn't sync policies" << std::endl;
  89. std::cerr << "this version of lilac sets:" << std::endl;
  90. std::cerr << " guest_mode_enabled = " << GMEV << std::endl;
  91. std::cerr << " show_user_names = " << SUNOSV << std::endl;
  92. std::cerr << " plugin_vm_allowed = " << PVAV << std::endl;
  93. std::cerr << " virtual_machines_allowed = " << VMAV << std::endl;
  94. std::cerr << " device_unaffiliated_crostini_allowed = " << DUCAV << std::endl;
  95. std::cerr << " release_lts_tag = " << RCP_MRCV << std::endl;
  96. std::cerr << " device_wallpaper_image = " << DWIP_MDWIV << std::endl;
  97. std::cerr << " block_devmode = " << SSPV << std::endl;
  98. exit(exitcode);
  99. }
  100. void sign(uint8_t const key[], size_t keySize, std::string data, std::string* const signature, std::string* pubkey) {
  101. CBS cbs;
  102. CBS_init(&cbs, key, keySize);
  103. EVP_PKEY* pkey = EVP_parse_private_key(&cbs);
  104. if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey) != EVP_PKEY_RSA) {
  105. std::cerr << "sign: failed to create private key" << std::endl;
  106. exit(1);
  107. }
  108. std::vector<uint8_t> pubkey_vec;
  109. uint8_t *der;
  110. size_t der_len;
  111. bssl::ScopedCBB cbb;
  112. if (!CBB_init(cbb.get(), 0) ||
  113. !EVP_marshal_public_key(cbb.get(), pkey) ||
  114. !CBB_finish(cbb.get(), &der, &der_len)) {
  115. std::cerr << "sign: failed to create public key" << std::endl;
  116. exit(1);
  117. }
  118. pubkey_vec.assign(der, der + der_len);
  119. OPENSSL_free(der);
  120. pubkey->assign(std::string(reinterpret_cast<const char*>(pubkey_vec.data()), pubkey_vec.size()));
  121. const EVP_MD* const digest = EVP_sha1();
  122. EVP_MD_CTX *context = EVP_MD_CTX_new();
  123. if (!EVP_DigestSignInit(context, nullptr, digest, nullptr, pkey)) {
  124. std::cerr << "sign: failed to init signing context" << std::endl;
  125. exit(1);
  126. }
  127. if (!EVP_DigestSignUpdate(context, data.c_str(), data.size())) {
  128. std::cerr << "sign: failed to update signing context" << std::endl;
  129. exit(1);
  130. }
  131. std::vector<uint8_t> signature_bytes;
  132. // get max length of sig
  133. size_t lenSig = 0;
  134. if (!EVP_DigestSignFinal(context, nullptr, &lenSig)) {
  135. std::cerr << "sign: failed to finalize signature" << std::endl;
  136. exit(1);
  137. }
  138. signature_bytes.resize(lenSig);
  139. if (!EVP_DigestSignFinal(context, signature_bytes.data(), &lenSig)) {
  140. std::cerr << "sign: failed to finalize signature" << std::endl;
  141. exit(1);
  142. }
  143. signature_bytes.resize(lenSig);
  144. signature->assign(reinterpret_cast<const char*>(signature_bytes.data()),signature_bytes.size());
  145. OPENSSL_free(context);
  146. OPENSSL_free(pkey);
  147. }
  148. void info(enterprise_management::ChromeDeviceSettingsProto* CDSP) {
  149. std::cout << "DevicePolicyRefreshRate = " << CDSP->device_policy_refresh_rate().device_policy_refresh_rate() << std::endl;
  150. std::cout << "UserWhitelistProto = ";
  151. if(CDSP->user_whitelist().user_whitelist_size() == 0) {
  152. std::cout << std::endl;
  153. } else {
  154. for(int i = 0; i < CDSP->user_whitelist().user_whitelist_size(); i++) {
  155. std::cout << " " << CDSP->user_whitelist().user_whitelist().Get(i) << std::endl;
  156. }
  157. }
  158. std::cout << "DeviceGuestModeEnabled = " << CDSP->guest_mode_enabled().guest_mode_enabled() << std::endl;
  159. std::cout << "CameraEnabledProto = " << CDSP->camera_enabled().camera_enabled() << std::endl;
  160. std::cout << "DeviceShowUserNamesOnSignin = " << CDSP->show_user_names().show_user_names() << std::endl;
  161. std::cout << "DeviceDataRoamingEnabled = " << CDSP->data_roaming_enabled().data_roaming_enabled() << std::endl;
  162. std::cout << "DeviceAllowNewUsers = " << CDSP->allow_new_users().allow_new_users() << std::endl;
  163. std::cout << "DeviceMetricsReportingEnabled = " << CDSP->metrics_enabled().metrics_enabled() << std::endl;\
  164. std::cout << "ChromeOsReleaseChannel = " << CDSP->release_channel().release_channel() << std::endl;
  165. std::cout << "DeviceOpenNetworkConfiguration = " << CDSP->open_network_configuration().open_network_configuration() << std::endl;
  166. std::cout << "DeviceReportingProto is currently not implemented for parsing" << std::endl;
  167. std::cout << "DeviceEphemeralUsersEnabled = " << CDSP->ephemeral_users_enabled().ephemeral_users_enabled() << std::endl;
  168. std::cout << "DeviceAutoUpdateDisabled = " << CDSP->auto_update_settings().update_disabled() << std::endl;
  169. std::cout << "DeviceAutoUpdateP2PEnabled = " << CDSP->auto_update_settings().p2p_enabled() << std::endl;
  170. std::cout << "DeviceAutoUpdateTimeRestrictions = " << CDSP->auto_update_settings().disallowed_time_intervals() << std::endl;
  171. std::cout << "SystemTimezone = " << CDSP->system_timezone().timezone() << std::endl;
  172. std::cout << "SystemTimezoneAutomaticDetection = " << CDSP->system_timezone().timezone_detection_type() << std::endl;
  173. std::cout << "DeviceLocalAccounts is currently not implemented for parsing" << std::endl;
  174. std::cout << "DeviceAllowRedeemChromeOsRegistrationOffers = " << CDSP->allow_redeem_offers().allow_redeem_offers() << std::endl;
  175. std::cout << "FeatureFlagsProto is currently not implemented for parsing" << std::endl;
  176. std::cout << "UptimeLimit = " << CDSP->uptime_limit().uptime_limit() << std::endl;
  177. std::cout << "DeviceChromeVariations = " << CDSP->device_chrome_variations_type().value() << std::endl;
  178. std::cout << "AttestationSettingsProto is currently not implemented for parsing" << std::endl;
  179. std::cout << "AccessibilitySettingsProto is currently not implemented for parsing" << std::endl;
  180. std::cout << "LoginScreenPowerManagement = " << CDSP->login_screen_power_management().login_screen_power_management() << std::endl;
  181. std::cout << "SystemUse24HourClock = " << CDSP->use_24hour_clock().use_24hour_clock() << std::endl;
  182. std::cout << "AutoCleanupSettigsProto (yes they misspelled it lmfao) is currently not implemented for parsing" << std::endl;
  183. std::cout << "SAMLSettingsProto is currently not implemented for parsing" << std::endl;
  184. std::cout << "DeviceRebootOnShutdown = " << CDSP->reboot_on_shutdown().reboot_on_shutdown() << std::endl;
  185. std::cout << "DeviceHeartbeatSettingsProto is currently not implemented for parsing" << std::endl;
  186. std::cout << "PluginVmAllowed = " << CDSP->plugin_vm_allowed().plugin_vm_allowed() << std::endl;
  187. std::cout << "VirtualMachinesAllowed = " << CDSP->virtual_machines_allowed().virtual_machines_allowed() << std::endl;
  188. std::cout << "DeviceUnaffiliatedCrostiniAllowed = " << CDSP->device_unaffiliated_crostini_allowed().device_unaffiliated_crostini_allowed() << std::endl;
  189. std::cout << "release_lts_tag = " << CDSP->release_channel().release_lts_tag() << std::endl;
  190. std::cout << "DeviceWallpaperImage = " << CDSP->device_wallpaper_image().device_wallpaper_image() << std::endl;
  191. if(CDSP->has_system_settings()) {
  192. enterprise_management::SystemSettingsProto SSP = CDSP->system_settings();
  193. std::cout << "DeviceBlockDevmode = " << SSP.block_devmode() << std::endl;
  194. }
  195. }
  196. void patch(enterprise_management::ChromeDeviceSettingsProto* CDSP) {
  197. enterprise_management::GuestModeEnabledProto* GMEP = CDSP->mutable_guest_mode_enabled();
  198. GMEP->set_guest_mode_enabled(GMEV);
  199. enterprise_management::ShowUserNamesOnSigninProto* SUNOSP = CDSP->mutable_show_user_names();
  200. SUNOSP->set_show_user_names(SUNOSV);
  201. enterprise_management::PluginVmAllowedProto* PVAP = CDSP->mutable_plugin_vm_allowed();
  202. PVAP->set_plugin_vm_allowed(PVAV);
  203. enterprise_management::VirtualMachinesAllowedProto* VMAP = CDSP->mutable_virtual_machines_allowed();
  204. VMAP->set_virtual_machines_allowed(VMAV);
  205. enterprise_management::DeviceUnaffiliatedCrostiniAllowedProto* DUCAP = CDSP->mutable_device_unaffiliated_crostini_allowed();
  206. DUCAP->set_device_unaffiliated_crostini_allowed(DUCAV);
  207. enterprise_management::ReleaseChannelProto* RCP = CDSP->mutable_release_channel();
  208. std::string* RCP_MRC = RCP->mutable_release_lts_tag();
  209. RCP_MRC->assign(RCP_MRCV);
  210. enterprise_management::DeviceWallpaperImageProto* DWIP = CDSP->mutable_device_wallpaper_image();
  211. std::string* DWIP_MDWI = DWIP->mutable_device_wallpaper_image();
  212. DWIP_MDWI->assign(DWIP_MDWIV);
  213. if(CDSP->has_system_settings()) {
  214. enterprise_management::SystemSettingsProto* SSP = CDSP->mutable_system_settings();
  215. SSP->set_block_devmode(SSPV);
  216. }
  217. }
  218. int main(int argc, char *argv[]) {
  219. if (argc != 3) {
  220. std::cerr << "lilac: not enough arguments" << std::endl;
  221. help(1);
  222. } else if(!strcmp(argv[2], "help")) {
  223. help(0);
  224. } else if(!strcmp(argv[2], "--help")) {
  225. help(0);
  226. } else if(!strcmp(argv[2], "-h")) {
  227. help(0);
  228. }
  229. string infile(argv[1]);
  230. if(!file_exists(infile)) {
  231. std::cerr << "lilac: input policy file does not exist" << std::endl;
  232. exit(1);
  233. }
  234. std::filesystem::path infilepath = infile; // bro i imported filesystem why is clangd complainingggg
  235. std::string parent = infilepath.parent_path().string();
  236. fstream input(infile, ios::in | ios::binary);
  237. enterprise_management::PolicyFetchResponse PFR;
  238. enterprise_management::PolicyData PD;
  239. enterprise_management::ChromeDeviceSettingsProto CDSP;
  240. PFR.ParseFromIstream(&input);
  241. input.close();
  242. PD.ParseFromString(PFR.policy_data());
  243. CDSP.ParseFromString(PD.policy_value());
  244. if (!strcmp(argv[2], "info")) {
  245. std::cout << "PFR.has_policy_data_signature = " << PFR.has_policy_data_signature() << std::endl;
  246. info(&CDSP);
  247. } else if (!strcmp(argv[2], "patch")) {
  248. patch(&CDSP);
  249. string PATCHED_CDSP;
  250. CDSP.SerializeToString(&PATCHED_CDSP);
  251. PD.set_policy_value(PATCHED_CDSP);
  252. string PATCHED_PD;
  253. PD.SerializeToString(&PATCHED_PD);
  254. std::string pubkey = std::string();
  255. sign(kSigningKey, sizeof(kSigningKey), PFR.policy_data(), PFR.mutable_policy_data_signature(), &pubkey);
  256. PFR.set_new_public_key(pubkey);
  257. PFR.set_policy_data(PATCHED_PD);
  258. ofstream output(infile, ios::out | ios::binary);
  259. PFR.SerializeToOstream(&output);
  260. output.close();
  261. ofstream keyout(parent + "owner.key", ios::out | ios::binary);
  262. keyout << pubkey;
  263. keyout.close();
  264. } else {
  265. std::cerr << "invalid 2nd argument " << argv[2] << std::endl;
  266. help(1);
  267. }
  268. return 0;
  269. }