web ctf中的計算器
1 簡介
某ctf的web題是計算器,主要就是考腳本編寫能力,自動化提交,總體還算簡單。 服務端的php文件。 javascript
2 實現數學表達式計算
使用instaparse這個庫,寫parser很是方便,雖然有點殺雞用牛刀,代碼以下: php
1: (require '[instaparse.core :as insta :refer [defparser]]) 2: 3: (defparser ques-exp 4: "expr = add-sub '=' 5: <add-sub> = mul-div | add | sub 6: add = add-sub <'+'> mul-div 7: sub = add-sub <'-'> mul-div 8: <mul-div> = term | mul | div 9: mul = mul-div <'*'> term 10: div = mul-div <'/'> term 11: <term> = number 12: number = #'[0-9]+' 13: " 14: :auto-whitespace :standard ;; 忽略空格 15: ) 16: 17: ;;; 測試解析器 18: (ques-exp "234 + 55 * 28 = ") 19: ;; => [:expr [:add [:number "234"] [:mul [:number "55"] [:number "28"]]] "="] 20: 21: (defn eval-exp 22: "執行表達式" 23: [exp-str] 24: (->> (ques-exp exp-str) 25: (insta/transform {:add + 26: :sub - 27: :mul * 28: :div / 29: :number clojure.edn/read-string 30: :expr (fn [a _] a) ;; 忽略右邊的= 31: :sign nil}))) 32: 33: (eval-exp "234 + 55 * 28 = ") 34: ;; => 1774 35: 36: (eval-exp "2 * 3 / 2 - 8 + 6 / 3 = ") 37: ;; => -3
3 請求表達式和提交計算結果
接下來就是請求頁面,解析出表達式,並提交結果: html
1: (require '[reaver :as html]) ;; 使用Jsoup解析html 2: (require '[clj-http.client :as http]) ;; http請求 3: (require '[clj-http.cookies :as cookies]) 4: 5: ;; 使用統一的cookie,用於保存session 6: (def cs (cookies/cookie-store)) 7: 8: (def default-header 9: {:headers {"User-Agent" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.50 Safari/537.36" 10: "Accept-Charset" "utf-8"} 11: ;; 使用本地代理,方便查找問題 12: :proxy-host "127.0.0.1" 13: :proxy-port 8080 14: :cookie-policy :standard 15: :insecure? true 16: }) 17: 18: (def ctf-u "http://192.168.47.129/web/html/index.php") 19: 20: (defn extract-exp 21: "從html中提取出表達式字符串" 22: [html] 23: (some-> (html/parse html) 24: (html/extract [] "form > div" html/text) 25: (->> (apply str)))) 26: 27: (defn get-question 28: "獲取問題" 29: [] 30: (-> (http/get ctf-u (merge default-header {:cookie-store cs})) 31: :body 32: extract-exp)) 33: 34: (defn post-ans 35: "提交答案" 36: [ans] 37: (-> (http/post ctf-u (merge default-header 38: {:cookie-store cs 39: :form-params ans})) 40: :body)) 41: 42: 43: ;; 提交一次測試 44: (get-question) 45: ;; => "+3572241+1162006+6727538*7357031-2782980-5908042+5687297*3471162+9574274=" 46: ;; => "+3688345*6914278-7003441+7001140+2403633*2570857+7772803-1273673*2507819=" 47: 48: ;; 此次的題目須要前面再加一個數字 49: (eval-exp (str "123456" *1)) 50: ;; => 69236240589747 51: 52: ;; 提交一次請求,返回"must input some big number ~" 53: (post-ans {:ans *1 54: :input 123456})
看後面的提示<!–the big number is the fist prime after 1000000 –>,須要計算素數: java
1: (def certainty 10) 2: 3: (defn prime? [n] 4: "n是否爲一個素數" 5: (.isProbablePrime (BigInteger/valueOf n) certainty)) 6: 7: (defn gen-prime 8: "從start開始產生一個素數" 9: [start] 10: (first 11: (filter prime? 12: (range start Integer/MAX_VALUE)))) 13: 14: (gen-prime 20) 15: ;; => 23 16: 17: (def i1 (gen-prime 1000000)) 18: 19: ;; 再請求一次 20: (->> (get-question) 21: (str i1) 22: eval-exp 23: (hash-map :input i1 :ans) 24: post-ans) 25: 26: ;; 返回結果仍是不對,固然看源碼能夠知道,生成的素數位數不對,少個0。 27: ;; 再來一次 28: (def i1 (gen-prime 10000000)) 29: (->> (get-question) 30: (str i1) 31: eval-exp 32: (hash-map :input i1 :ans) 33: post-ans) 34: ;;; 這一次只有slow down的消息,證實提交的input數字是對的
4 循環提交
單次提交測試沒有問題,就能夠循環提交計算結果,直到返回的頁面中沒有提問,就算計算完成: git
1: ;; 添加了better-cond依賴,爲了使用cond let子句 2: (refer-clojure :exclude '[cond]) 3: (require '[better-cond.core :refer [cond]]) 4: 5: (defn process-answer 6: " 不斷請求答案,直到返回的頁面中沒有提問 7: `format-fn` 格式化請求返回的表達式 8: `answer-fn` 格式化提交的form內容" 9: [{:keys [format-fn answer-fn] 10: :or {format-fn identity 11: answer-fn #(hash-map :ans %)}}] 12: (loop [ques (get-question) 13: result ""] 14: (cond 15: (empty? ques) result 16: 17: ;; 計算表達式 18: :let [ans (-> (format-fn ques) 19: (doto println) 20: (eval-exp))] 21: 22: ;; 表達式計算錯誤 23: (insta/failure? ans) (println :process "no eval result for" ques) 24: 25: ;; 提交結果 26: :let [r (-> (answer-fn ans) 27: (post-ans))] 28: 29: (do 30: (println :process "question:" ques "anser:" ans) 31: (recur (extract-exp r) 32: r))))) 33: 34: (process-answer {:format-fn #(str i1 %) 35: :answer-fn #(hash-map :input i1 :ans %)}) 36:
能夠看到post提交答案,返回的都是slow down,如今加入延時,延時數字要本身調整,固然看了代碼才知道是2-3秒: github
1: (process-answer {:format-fn #(str i1 %) 2: :answer-fn (fn [e] 3: (Thread/sleep 2000.) 4: {:ans e 5: :input i1})}) 6: ;; => "\n\t\t<script language=\"javascript\"> \n\t\talert(\"right answer\"); \n\t </script> got flag....................."
5 總結
考察的就是基本的腳本編程能力,http GET/POST請求,表達式解析計算。 web
做者: ntestoc編程
Created: 2019-06-10 週一 16:48cookie