From b7b3a02bfed1b7eec2ad66b08fb2893f8599fb54 Mon Sep 17 00:00:00 2001 From: Peter Deutsch Date: Wed, 16 Aug 2023 19:19:15 -0700 Subject: [PATCH] Lab fixes for 2024 --- automate.py | 16 +-- part2/index.html | 186 +++++++++++++++++++++++++++++++++- part2/worker.js | 15 +-- part3/index.html | 186 +++++++++++++++++++++++++++++++++- part3/worker.js | 15 +-- part4/eval.py | 27 ----- part4/extension.crx | Bin 2109 -> 0 bytes part4/extension/background.js | 162 ----------------------------- part4/extension/manifest.json | 10 -- part4/index.html | 1 - part4/worker.js | 32 ------ 11 files changed, 389 insertions(+), 261 deletions(-) mode change 120000 => 100644 part2/index.html mode change 120000 => 100644 part3/index.html delete mode 100644 part4/eval.py delete mode 100644 part4/extension.crx delete mode 100644 part4/extension/background.js delete mode 100644 part4/extension/manifest.json delete mode 120000 part4/index.html delete mode 100644 part4/worker.js diff --git a/automate.py b/automate.py index a25f908..bc8a725 100644 --- a/automate.py +++ b/automate.py @@ -14,20 +14,15 @@ from selenium.webdriver.chrome.options import Options parser = argparse.ArgumentParser() parser.add_argument("--browser", type=str, choices=["chrome", "firefox", "safari"], default="chrome", help="Browser to run automation in.") parser.add_argument("--domains", type=str, default="google.com,youtube.com,baidu.com,facebook.com", help="Comma-separated list of domain names to collect traces from. Defaults to google.com,youtube.com,baidu.com,facebook.com") -parser.add_argument("--enable_countermeasure", type=bool, default=False, help="Set to true to enable the countermeasure. Browser must be set to Chrome. Defaults to false.") parser.add_argument("--num_traces_per_domain", type=int, default=40, help="Number of traces to collect per domain.") parser.add_argument("--trace_length", type=int, default=5000, help="The length of each recorded trace, in milliseconds. Defaults to 5000.") required = parser.add_argument_group("required arguments") required.add_argument("--out_filename", type=str, required=True, help="Name of the output file to save traces to.") -required.add_argument("--part", type=int, choices=[2, 3, 4], required=True, help="Set to the part of the lab you're working on.") +required.add_argument("--part", type=int, choices=[2, 3], required=True, help="Set to the part of the lab you're working on.") opts = parser.parse_args() -if opts.browser != "chrome" and opts.enable_countermeasure: - print("Browser must be set to Chrome in order to enable the countermeasure.") - sys.exit(1) - if os.path.exists(opts.out_filename): print(f"WARNING: Data already exists at {opts.out_filename}. What do you want to do?") res = input("[C]ancel [O]verwrite ").lower() @@ -40,11 +35,6 @@ if os.path.exists(opts.out_filename): # Start serving attacker app app = Flask(__name__) -# Disable Flask logs -os.environ["WERKZEUG_RUN_MAIN"] = "true" -log = logging.getLogger("werkzeug") -log.disabled = True - @app.route("/") def root(): return send_from_directory(f"part{opts.part}", "index.html") @@ -63,10 +53,6 @@ def get_browser(victim): chrome_opts = Options() chrome_opts.add_experimental_option("excludeSwitches", ["enable-automation"]) - if opts.enable_countermeasure and victim: - # Victim has the extension enabled -- attacker does not - chrome_opts.add_extension("part4/extension.crx") - return webdriver.Chrome(options=chrome_opts) elif opts.browser == "firefox": return webdriver.Firefox() diff --git a/part2/index.html b/part2/index.html deleted file mode 120000 index 79c5d6f..0000000 --- a/part2/index.html +++ /dev/null @@ -1 +0,0 @@ -../index.html \ No newline at end of file diff --git a/part2/index.html b/part2/index.html new file mode 100644 index 0000000..eff4b48 --- /dev/null +++ b/part2/index.html @@ -0,0 +1,185 @@ + + + + + Website Fingerprinting Lab + + + +

Website Fingerprinting Lab

+
+ + +
+
+ + + + diff --git a/part2/worker.js b/part2/worker.js index 5b706ad..fed89d2 100644 --- a/part2/worker.js +++ b/part2/worker.js @@ -1,7 +1,11 @@ -// Duration of your trace, in milliseconds -let TRACE_LENGTH; +// Number of sweep counts +// TODO: Choose an appropriate value! +let P; -// Array of length TRACE_LENGTH with your trace's values +// Number of elements in your trace +let K = 5 * 1000 / P; + +// Array of length K with your trace's values let T; // Value of performance.now() when you started recording your trace @@ -9,7 +13,7 @@ let start; function record() { // Create empty array for saving trace values - T = new Array(TRACE_LENGTH); + T = new Array(K); // Fill array with -1 so we can be sure memory is allocated T.fill(-1, 0, T.length); @@ -17,7 +21,7 @@ function record() { // Save start timestamp start = performance.now(); - // TODO (Exercise 2-2): Record data for TRACE_LENGTH seconds and save values to T. + // TODO: Record data for 5 seconds and save values to T. // Once done recording, send result to main thread postMessage(JSON.stringify(T)); @@ -26,7 +30,6 @@ function record() { // DO NOT MODIFY BELOW THIS LINE -- PROVIDED BY COURSE STAFF self.onmessage = (e) => { if (e.data.type === "start") { - TRACE_LENGTH = e.data.trace_length; setTimeout(record, 0); } }; diff --git a/part3/index.html b/part3/index.html deleted file mode 120000 index 79c5d6f..0000000 --- a/part3/index.html +++ /dev/null @@ -1 +0,0 @@ -../index.html \ No newline at end of file diff --git a/part3/index.html b/part3/index.html new file mode 100644 index 0000000..eff4b48 --- /dev/null +++ b/part3/index.html @@ -0,0 +1,185 @@ + + + + + Website Fingerprinting Lab + + + +

Website Fingerprinting Lab

+
+ + +
+
+ + + + diff --git a/part3/worker.js b/part3/worker.js index 46c8d96..fed89d2 100644 --- a/part3/worker.js +++ b/part3/worker.js @@ -1,7 +1,11 @@ -// Duration of your trace, in milliseconds -let TRACE_LENGTH; +// Number of sweep counts +// TODO: Choose an appropriate value! +let P; -// Array of length TRACE_LENGTH with your trace's values +// Number of elements in your trace +let K = 5 * 1000 / P; + +// Array of length K with your trace's values let T; // Value of performance.now() when you started recording your trace @@ -9,7 +13,7 @@ let start; function record() { // Create empty array for saving trace values - T = new Array(TRACE_LENGTH); + T = new Array(K); // Fill array with -1 so we can be sure memory is allocated T.fill(-1, 0, T.length); @@ -17,7 +21,7 @@ function record() { // Save start timestamp start = performance.now(); - // TODO (Exercise 3-1): Record data for TRACE_LENGTH seconds and save values to T. + // TODO: Record data for 5 seconds and save values to T. // Once done recording, send result to main thread postMessage(JSON.stringify(T)); @@ -26,7 +30,6 @@ function record() { // DO NOT MODIFY BELOW THIS LINE -- PROVIDED BY COURSE STAFF self.onmessage = (e) => { if (e.data.type === "start") { - TRACE_LENGTH = e.data.trace_length; setTimeout(record, 0); } }; diff --git a/part4/eval.py b/part4/eval.py deleted file mode 100644 index 7c13310..0000000 --- a/part4/eval.py +++ /dev/null @@ -1,27 +0,0 @@ -import json -import numpy as np - -from sklearn.ensemble import RandomForestClassifier -from sklearn.metrics import classification_report -from sklearn.model_selection import train_test_split - -def eval(): - y_pred_full, y_test_full = [], [] - - # Re-train 10 times in order to reduce effects of randomness - for i in range(10): - ### TODO: Exercise 4-1 - ### 1. Load data from traces file - ### 2. Split data into X_train, X_test, y_train, y_test with train_test_split - ### 3. Train classifier with X_train and y_train - ### 4. Use classifier to make predictions on X_test. Save the result to a variable called y_pred - - # Do not modify the next two lines - y_test_full.extend(y_test) - y_pred_full.extend(y_pred) - - ### TODO: Exercise 4-1 (continued) - ### 5. Print classification report using y_test_full and y_pred_full - -if __name__ == "__main__": - eval() diff --git a/part4/extension.crx b/part4/extension.crx deleted file mode 100644 index c857b6d4d2beaae8374d25bbf32d54e28fa1310c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2109 zcmZ|Qc{J2(9{}**7$#;ern!TNq7b&Q?@9n(r`+U!HzUTX#=ljq1Jm>T11u7_l0RYfv0{}!N zJMrHSevwMTzGc}#r;rAsLJHdz&|_#BzZ_!a5s+26GmWSvt8uNrNgBgSSJsW~zrEa- zB;^sWP{pHFt1el}`3ev9ug=o0C;!jK0E8hA2^ z16|uASzz9&tUB#6x9E6Ce-;hLP=pY|HZhfBMq&lAY+#?clS5_mvo8nyKM2B4N0cq{ zr;(}!`^;cI2zE%@yy45ge&GM`e(vtiO3>3j&ISenAVf49#f;tU=B3@(^|{6ObKiZR zLBmJ*Zhc@1wqB>{1$?rH(HT=xtU+u^=<0x|m3e!&dJG2(g`#v$h336kd7fY@y}yF5 zdblQ*$z?+|ww61CX5zevoD=*-6Sl6_ThT)}$|=n!OZeo;!vxVayKRx+#q(~%CM-3C7cv^OCp4$qLs)a2%f3w+;Lr5hm(VUHXk{q_%LpExc%oHz*D_`jR zsL{6LQCP}tX;i5*F4{P=uA5MB#z3HWWp%vK%%tmexgvdc&tvmy=!?_Jf)c4pM>@NU zO9XWwSCvy_oM?&AZrk{0v)4dyJ7#K*hvGq;+ji=Wim6({2! zbK3g8d8#%)f{!hdslRRe%77QKb8f_mS1$b-kL^G{iwgc;IP{qo#>WOTYAM~CzFMKJ z1xuN11oH~dCD2Si7pPvIK6dYzW4v(pIMfALKx2hX(pcY)U-U-}_4@2EI#vi6X$q2# z9uC;y;ljmrQ9b;~<%X!l#JG|YITKBJYck)%b1=JT^8 zhd?TEK?Q;`swI?EsZwE{5VZRJma8sR+hU_Jl#U?or3~Sj@HNfz{0$#Fu9MiMsP&7@ zzGyY>w9*ur-W{vT<5Ba*Iu3+GI775XEpn9G)cEelYs|9?wl)Tvv$rD`63mJO&!KS% z%_w0wne=F`-1KlbM)GYP(i6#FJT0f?;ssh1$ffr15BH`;*dINiCIMr5c|KDqYE(3^ zo%WvAIOSSXHghCnMP+H!=8c=rBh-Gqz0B80hBD{Z8w#clTP;K)vHxZH$GcZcm{2(# zZerKW#k4=jO_D+dhN-CSV*R~`FoqTWG4W9EhE}+uL0Gf4xOimmAYJRx8#ij+tp@R; z2jS~aTP4KdF_oAos@y%@o1*sB;fr(IMMlD@{2NN>6UNDB9iOYWw1@|XC+!I&<=pSs z+8&=-pMqCpy+Z7g_tm;|A(3hnvcWqARIltzWBcW>ADbS#leA5VOW87S0{!>rroLI8 z{Pa2|tU1N?g3xfiMZtvPq;px)QP$7}~-iA_< z_saX@tkTSgFY2CmhB3q zOZ!D?RARMC5B*#~*q`cw>38Fh%TeZ5n&Oz;ud*VZ&4|~C%!o{B9rZhBM6t?ajhtITE8L`s!^5VYP}WPllf<2#B~Nlx~ZZHZ&-QhQ0*;roGBm!tyc=hYbvz!(K@ZlpU?%c6>UqZ_$LP849jfXf=$|J*;}o z4yPv*!Nr*8{f|h5d<~nuWXyW{fjO@Z_D_*8&VF7V?m@Q>Ji_|@FOl@qba-O4f7Aa~ z=<@o{uIN`?@J7E@f;`!2BtuT`JxCz7Wt_m#+qSN}jdLla*($=s!WY>uOMQKHr#5yRf;0+T*kE zvCpkbbr^fzU-Ccz5<$PLb|QbG1Euc_gQfd2_AE?52VXVv{|NgpOhNxP^%rmd+4|q3 d_-AY80olI{#=?XH^78`QLEJvbP8>h0zX6pzv@HMt diff --git a/part4/extension/background.js b/part4/extension/background.js deleted file mode 100644 index e85606f..0000000 --- a/part4/extension/background.js +++ /dev/null @@ -1,162 +0,0 @@ -const domains = [ - "https://www.google.com/", - "https://www.youtube.com/", - "https://www.tmall.com/", - "https://www.qq.com/", - "https://www.baidu.com/", - "https://www.sohu.com/", - "https://www.facebook.com/", - "https://www.taobao.com/", - "https://www.jd.com/", - "https://www.amazon.com/", - "https://www.yahoo.com/", - "https://www.wikipedia.org/", - "https://www.weibo.com/", - "https://sina.com.cn/", - "https://www.zoom.us/", - "http://www.xinhuanet.com/", - "https://www.live.com/", - "https://www.reddit.com/", - "https://www.netflix.com/", - "https://www.microsoft.com/", - "https://www.instagram.com/", - "https://www.office.com/", - "https://panda.tv/", - "https://www.zhanqi.tv/", - "https://www.alipay.com/", - "https://www.bing.com/", - "https://www.csdn.net/", - "https://www.vk.com/", - "https://www.myshopify.com/", - "https://www.naver.com/", - "https://www.okezone.com/", - "https://www.twitch.tv/", - "https://www.twitter.com/", - "https://www.ebay.com/", - "https://www.adobe.com/", - "https://www.tianya.cn/", - "https://www.huanqiu.com/", - "https://www.yy.com/", - "https://www.aliexpress.com/", - "https://www.linkedin.com/", - "https://www.force.com/", - "https://www.aparat.com/", - "https://www.mail.ru/", - "https://www.msn.com/", - "https://www.dropbox.com/", - "https://www.whatsapp.com/", - "https://www.apple.com/", - "https://www.1688.com/", - "https://www.wordpress.com/", - "https://www.canva.com/", - "https://www.indeed.com/", - "https://www.stackoverflow.com/", - "https://www.ok.ru/", - "https://www.so.com/", - "https://www.chase.com/", - "https://www.imdb.com/", - "https://www.slack.com/", - "https://www.etsy.com/", - "https://www.tiktok.com/", - "https://www.booking.com/", - "https://www.babytree.com/", - "https://rakuten.co.jp/", - "https://www.salesforce.com/", - "https://www.spotify.com/", - "https://www.tribunnews.com/", - "https://www.fandom.com/", - "https://www.tradingview.com/", - "https://www.github.com/", - "https://www.haosou.com/", - "https://www.paypal.com/", - "https://www.cnblogs.com/", - "https://www.alibaba.com/", - "https://www.kompas.com/", - "https://gome.com.cn/", - "https://www.walmart.com/", - "https://www.roblox.com/", - "https://www.6.cn/", - "https://www.zillow.com/", - "https://www.godaddy.com/", - "https://www.imgur.com/", - "https://www.espn.com/", - "https://www.bbc.com/", - "https://www.hao123.com/", - "https://www.pikiran-rakyat.com/", - "https://www.grammarly.com/", - "https://www.cnn.com/", - "https://www.telegram.org/", - "https://www.tumblr.com/", - "https://www.nytimes.com/", - "https://www.detik.com/", - "https://www.wetransfer.com/", - "https://www.savefrom.net/", - "https://www.rednet.cn/", - "https://www.freepik.com/", - "https://www.ilovepdf.com/", - "https://www.daum.net/", - "https://www.pinterest.com/", - "https://www.primevideo.com/", - "https://www.intuit.com/", - "https://www.medium.com/", -]; - -const loadTime = 5000; -let loading = false; -let startTime = 0; - -function randomPing() { - const controller = new AbortController(); - const id = setTimeout( - () => controller.abort(), - loadTime - (performance.now() - startTime) - ); - - fetch( - domains[Math.floor(Math.random() * domains.length)] + - "?" + - new Date().getTime(), - { - signal: controller.signal, - } - ); -} - -function activityBurst() { - switch (Math.floor(Math.random() * 2)) { - case 0: - let start = performance.now(); - let counter = 0; - - while (performance.now() - start < 5) { - counter += 1; - } - - console.log(counter); - break; - case 1: - randomPing(); - break; - } -} - -chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { - if (changeInfo.status === "loading") { - if (loading) { - return; - } - - startTime = performance.now(); - loading = true; - - for (let i = 0; i < 20; i++) { - randomPing(); - } - - for (let i = 0; i < loadTime / 10; i++) { - setTimeout(activityBurst, Math.random() * loadTime); - } - } else if (changeInfo.status === "complete") { - loading = false; - } -}); diff --git a/part4/extension/manifest.json b/part4/extension/manifest.json deleted file mode 100644 index cd43bd6..0000000 --- a/part4/extension/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "Lab Countermeasure", - "version": "1.0", - "manifest_version": 3, - "background": { - "service_worker": "background.js" - }, - "action": {}, - "host_permissions": ["*://*/*"] -} diff --git a/part4/index.html b/part4/index.html deleted file mode 120000 index 79c5d6f..0000000 --- a/part4/index.html +++ /dev/null @@ -1 +0,0 @@ -../index.html \ No newline at end of file diff --git a/part4/worker.js b/part4/worker.js deleted file mode 100644 index 13eb53c..0000000 --- a/part4/worker.js +++ /dev/null @@ -1,32 +0,0 @@ -// Duration of your trace, in milliseconds -let TRACE_LENGTH; - -// Array of length TRACE_LENGTH with your trace's values -let T; - -// Value of performance.now() when you started recording your trace -let start; - -function record() { - // Create empty array for saving trace values - T = new Array(TRACE_LENGTH); - - // Fill array with -1 so we can be sure memory is allocated - T.fill(-1, 0, T.length); - - // Save start timestamp - start = performance.now(); - - // TODO (Exercise 4-4): Copy your solution from part 3. Optionally make changes to your part 3 solution if you need to. - - // Once done recording, send result to main thread - postMessage(JSON.stringify(T)); -} - -// DO NOT MODIFY BELOW THIS LINE -- PROVIDED BY COURSE STAFF -self.onmessage = (e) => { - if (e.data.type === "start") { - TRACE_LENGTH = e.data.trace_length; - setTimeout(record, 0); - } -};