前言
年初四月份的時候,有朋友找到我,說想開發一個模擬點擊的軟件。最終軟件做完后,發現效果不理想。唯一開發的我是認為最好是放棄了,做運營的他,堅持說這個沒問題,說是改變合作方式。最終也是不了了之了。
不過,在這中間經歷了一次重寫,三次核心方法的變更,無數次的查資料,找解決辦法至凌晨。中間穿插了無數次的討論修改,修改討論。雖然功能很簡單,但是也花費了三個月的心血。心想,還是想好好總結一下。最后的軟件界面如下:
實現思路&使用控件
首先,在內置瀏覽器里面打開網頁,通過Javascript 獲取需要的點擊的坐標位置;計算網頁中的坐標,在屏幕中的坐標位置;通過模擬鼠標的操作(滾動滑輪,移動,點擊);以及隨機的二次點擊。最后再清除緩存,更換IP,更換分辨率,以及User-Agent。來達到欺騙網站,認為是不同的人來點擊的目的。
使用的具體方法,如下:
- 內置瀏覽器,CefSharp 49.0 為了兼容.NET 4.0,大部分Win7可以直接使用;
- 鼠標,鍵盤模擬輸入,InputSimulator , 最早之前是直接調用Windows API的,沒有這個好用;
- 切換IP,兩種ADSL切換 和 IP精靈軟件(ADSL 這個目前沒有使用的,DotRas.dll);
- 切換分辨率,是直接拿Github上面代碼直接用。ScreenResolutionChanger;
- License 使用 EasyLicense;
- 本地數據庫SQLite;
- 代碼混淆 .NET Reactor;
作為前端的瀏覽器能夠收集到的數據有這些:網站統計中的數據收集原理及實現
小小的記錄
殺毒軟件的坑:使用模擬輸入的時候,一直提示 User Interface Privilege Isolation(用戶界面特權隔離) 的問題,權限不夠。試了關閉Windows的UAC,用超級管理員啟動,給軟件加數字證書,放到C盤系統目錄等等。各種方法都試了就是無法模擬操作。實在沒辦法了,然后在豬八戒上面發布任務,放上Demo。萬萬沒想到,一個大學生給我解決了,是因為360等殺毒軟件導致的。。。。
IP精靈DLL版本的坑:最開始用的他們官網提供的dll,發現他們那個dll基本用不起來,好像是許久不更新了。另外,狀態編碼也會隨意改變,也不發更新通知。造成也結果就是,明明以前好好的,怎么今天就突然用不起來了。
ADSL測試的坑:代碼寫好后無法測試,或者測試起來很麻煩。現在這年代用ADSL撥號上網的越來越少了,同樣想測試也麻煩。好不容易找了個遠程的ADSL主機,結果一測試就斷網,尷尬。。。
獲取網絡時間:為了避免用戶直接修改系統時間,來達到突破License 。獲取到 大門戶網站 http header 中的 date 來檢驗本地時間是否准確。在這中間,我發現大陸封殺了好多的時間同步的網站,只有一兩個能用,又極度不穩定,並且中科院的又用不起。坑貨!!
SQLite小巧玲瓏:之前第一個版本用 純文本來存放配置文件,記錄日志信息。極度不方便,容易出現數組越界這樣的bug。后來采用sqlite后,才發現了開發的美好。sqlite擁有完整的sql那一套東西,並且體積又小,不用安裝,非常適合做本地少量信息的存儲。
屏幕分辨率:最開始是手動實現windows api 來獲取列表,改變分辨率的,bug又多又不完善。某天靈光一閃,在github上面找了一下真還有這個代碼,省了不少事情。另外,我還發現wiki上面寫的,顯示分辨率列表 總共只有那么幾十個,可見分辨率的大小,不是隨意寫的。但是通過windows api 獲取到的列表 就一大堆有幾百個。我分析,是因為分辨率,色深,赫茲。這三個參數排列組合導致的。
Cefsharp文檔的重要性:清除緩存,清除cookie,Storage。設置彈出方式,重寫http header,執行javascript等等。一系列的內置瀏覽器的操作,都是看github上面的wiki,以及google看英文文檔(baidu就是坑爹貨,同樣的文章,轉來轉去;一般第一頁80%廣告,前三頁都是同樣的內容,剩下的風馬牛不相及)。沒有別人幫助,只有硬着頭皮翻譯一點看一點,然后寫代碼試。如果找不到實現方法,也要去看看為什么不能實現。記錄一些,我認為比較重要的地方:
- ILifeSpanHandler 控制Cefsharp彈出的窗口 事件。(DoClose,OnAfterCreated,OnBeforeClose,OnBeforePopup)
- IRequestHandler 控制Cefsharp發送請求的事件,太多了不一一列舉。
- Cef.Initialize 只能初始化一次,如果想徹底清除緩存,必須關閉宿主程序。 如果在主程序內,調用Cef.Shutdown 后再次初始化會報錯的。49.0版本有這個問題,后續的版本修復了這個問題。
- 執行 js 的時候,要注意鎖的問題,使用 Monitor 更加精細的控制。
- 重新翻譯了github上部分Cefsharp文檔。
WinForm開發:第一次寫winform程序,認為是小程序,各種粗制濫造。尤其是到后期,主窗體代碼到達一兩千行,邏輯調用混亂,真心看不下去了,修改起來的很費勁。干脆重新寫吧。重新設計文檔目錄,窗體拆分,代碼分類,左搞右搞,總算勉強能看,但是今天又把代碼翻出來看了看,總感覺什么地方不對,又說不出是哪里不對。。。
- 線程的重要性,寫慣了web,極少情況考慮線程的問題。但是在桌面程序里面,線程是非常重要的問題,尤其是非主線程操作UI界面的時候。
- 事件的運用,同樣,在桌面程序里面,事件使用起來非常舒服。以前對代理,事件也僅僅知道概念。實踐之后,才知道這個是多么優秀的設計。
- VS 所見即所得的窗體設計界面,由於 Cefsharp 運行時加載控件的,也就是開發時設計界面打不開。這也算一點小麻煩。
- 通過句柄的操作。 主要獲得主界面句柄,獲取按鈕句柄,然后SendMessage,來觸發按鈕事件。還有就是,win7 之前和之后的SendMessage 大有不同,要注意。
輔助進程啟動:由於Cef必須完全關掉宿主進程,才可以徹底清除緩存。所以,當時就采用了,輔助進程來重啟主進程。這個比較簡單,涉及到Process的一些操作,為了方便易用,同時還設計了熱鍵功能。
License 注冊:這個比較簡單,參照demo。我獲取的是本機的CPU序列號,主板序列號,硬盤的ID(為什么不是序列號,因為硬盤市場參差不齊,還有的廠家不存在序列號)。為了防止被猜到,我隨便加了點料(當時的真實感受)。最后MD5加密,提取哈希值。如下圖:
總結
- 經過這么一折騰,深深得感覺到,程序員主要作用是在組裝代碼的:把不相干的代碼有機的拼裝在一起,組成一個可以使用的軟件。
- 善於利用google,github,stack overflow,基本能解決99%的技術問題。
- 英語非常非常重要,百度非常非常坑。
- 實在頭疼腦熱的時候,不舒服的時候,不如去休息。
- 需求的確認,這是非常重要的事情。