會用到以下的元件與方法:
- Recursive - 用來窮舉所有密碼的方式
- EnumWindows, EnumChildWindows, CALLBACK function - 用來找出所有相關的視窗標題,按鈕等等
- Thread - 不是用來找密碼,而是用來做正確或失敗視窗的判斷
說明:
1. 密碼可以輸入鍵盤上的數字(0-9),符號,文字(英文大小寫)這些,包含空白總共有96個符號。找密碼的方式,運用Recursive的方式,所謂Recursive就是自己呼叫自己,然後根據終止條件停止。
char pw_NumericalWord[96] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','~','!','@','#','\$','%','^','&','*','(',')','_','+','|','`','-','=','\\\\','{','}','[',']','\"',':','\'',';','<','>','?',',','.','/',' '}; void backtrack(int n) // n 為現在正在列舉的維度 { if (n == 3)//假設要找的是三位數密碼 { //found totalcount++; return; } // 逐步列舉,並且各自遞迴下去 for(int i=0; i<96; i++)//96個符號 { if(isFoundPw) break; solution[n] = pw_NumericalWord[i]; backtrack(n+1); } }
2. 找出輸入密碼的視窗,通常都是一個EditBox,帶有ES_PASSWORD屬性(就是輸入會變成'*'的那個),所以我們只要判斷視窗中的那個元件,有這個屬性,就可以準確抓取到元件
if((GetWindowLong(hwnd,GWL_STYLE) & ES_PASSWORD))
3. 然後抓到元件之後,根據計算的密碼,對這個元件,把密碼用一個WM_SETTEXT的訊息送出
::SendMessageA(hwnd, WM_SETTEXT, NULL,(LPARAM)solution);
4. 送出密碼字串後,還要按下確定,所以要找到這個確定的按鈕後,對這個按鈕下按下的命令,利用WM_COMMAND
::SendMessage(::GetParent(hwnd), WM_COMMAND, (WPARAM)::GetWindowLong(hwnd, GWL_ID), (LPARAM)hwnd);
5. 送出後有兩種狀況,一個是成功,一個是失敗。失敗的話通常會有另一個提示視窗,按掉之後繼續回到Step 2。成功的話.....阿就成功,跳出程式,最後一個找到的就是密碼啦!因為輸入後跳出的視窗時間不一定,這裡要開個thread去抓跳出的視窗裡頭的元件,不然會被先前的視窗thread hold住,變成手動要按掉,那就不自動了。但是這個thread也需要等待一段時間才起來,可以用先建立後,判斷有視窗了,再去resume也可以,不過我就偷懶用個Sleep()固定時間後,再去列舉視窗,通常要設定Sleep(100)比較保險,不然如果他不是像我直接程式判斷跳出,而是去連網或是去DB裡查找的話,那時間就更久,設太短會找不到跳出的視窗的。
::Sleep(50); EnumWindows(PassWindowCallBack, reinterpret_cast<LPARAM>(&arg));
--程式執行圖--
我現在是寫成console程式,試跑一下結果而已。他會不斷地去嘗試輸入,遇到錯誤畫面會關閉,所以看起來就像半透明視窗不斷閃動。輸入的畫面如果要美觀一點,可以把一些參數拉出來設定,弄的比較美觀好用一點,像這樣:
這個方法,雖然可以用暴力的方式,把所有密碼找出來,最終可以破解所有密碼沒錯,但是重點還是在於時間。光是5位數的密碼,窮舉出來不做任何事情,就花我5分多鐘,再去乘上等待視窗查找的時間,等於差不多要花上500分鐘。現在密碼幾乎都是6位數以上,這樣算起來6位數要全破,得花上至少6天不間斷的跑呢!所以如果看到有些密碼欄位,要求只有數字+英文字母,而不能用符號的,那就可以省下很多時間破解!喔不是,是相對來說不安全啦.....這個程式,還是別亂用的好。
--完整Source Code(VC++ 2008 vaildated)
testRecusive.7z
- 延伸
這個方法,反過來用的話,就是去取的這個密碼輸入框,然後可以獲取別人輸入的密碼了。怎麼感覺好不安全壓!所以現在很多的程式可能要改一下,用自己方法來加密符號,不要用他的這個內建密碼顯示方式,多少可以避免被這種方法破解的。
2 意見:
Dear TK哥 您好:
閱覽您許多[工作]經驗的分享,與您不吝的分享各種案子使用的(完整Demo)原始碼,
分常感您的分享,我是私立科大畢業的游先生,程式涉略經驗相當少,工作經驗也只有1年,
使用的是C++ MFC開發,讀到您一篇COPY DATA讓我受益良多,在工作上取代了(解決了)我原本使用read & write file產生問題的方式。
iguitar31@yahoo.com.tw 這是我的一般使用的信箱,對於TK哥的經驗與技術有很大的興趣,也很希望TK哥流您的line或mail與我聯繫,技術交流,及未來有機會找您教學。
非常感謝您
TK大~
這篇邏輯分析好厲害
但是程式連結已失效
能否重新分享呢?
目前非常需要~
感謝你的指導文~
張貼留言