程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 更改屏幕顯示數據的作弊程序

更改屏幕顯示數據的作弊程序

編輯:關於VC++

前言

本文(其實是隨筆)和實例代碼描述的內容主要包括:API攔截,消息鉤子,枚舉子窗體,注冊系統熱鍵。其中消息鉤子、API攔截、枚舉子窗體實現代碼在dll中,注冊系統熱鍵代碼實現在測試exe中,另外exe代碼段還涉及自定義消息和系統欄圖標。希望對你有用。

一年過去了,仍然是老樣子——為生活而奔波、為money而忙碌。好在身體還蠻健康,吃得好,睡得香:-)但願新的一年裡腰包會鼓一些。今天整理硬盤,發現了這些代碼,回想當初開始寫的時候好像還在 VCKBASE 論壇裡提出過一些問題,也得到了論壇很多朋友的熱心幫助,在此感謝。本來想好好的寫一下心得,特別是能讓VC初學者學到一些東西。但自己語文功底太差,就只能想到哪寫到哪了。希望你邊品茶,邊上網,一手聊天,一手回帖,左眼看PP,右眼能堅持看完下面的這些方塊字。

寫這個程序的來由:最初由於客戶的需求不是很明顯,只是說把他的一個數據庫程序的數據作一個臨時性的欺騙,以應付檢查(誰檢查就不知道了,哈,讓我寫作弊程序呢,考我吶),唯一的要求是不更改真實的數據。我其實比較頭疼數據庫,就想不研究他的數據庫結構了,心想采用一個比較懶的辦法實現就行了。9月份的時候我也挺閒的,在網上狂搜了一通之後,基本就決定用屏幕取詞的方式來做了。就是截獲顯示到屏幕上的數據,只要是數字類型的,就乘以一個基數,然後把算好的數據回寫到屏幕上。其實這個屏幕取詞的技術網上早就公開了,我也剛好想順便練練手。寫得差不多的時候,吐血的時候也就到了,客戶要求除了臨時欺騙之外,還要把顯示的數據當場用原來程序上的打印按鈕打印出來。我傻眼了,所以也就廢棄了這種方法,吐了一通血、憋了一通氣、老老實實的研究了原程序的數據庫結構,還好是 SQL Server 2K,以前弄過,終於趕在檢查之前交了活。

一不小心就說了這麼多廢話。好了,轉到正題。下面分別道來:

攔截API(或者說截獲API 反正一個意思)

先說說截獲API了,在HOOKAPI.h和cpp文件中,這個是繁體版本。網上流行很多個版本,我覺得還是這個比較簡潔一點(簡單萬歲嘛)。原作者不知道是台灣還是香港的,注釋用的BIG5碼。截獲API一般就幾個步驟:

獲得函數地址(GetProcAddress),取得被攔截的函數地址和要替代這個被攔截的函數的地址(也就是攔截後要處理的函數);

形成JMP指令(__asm),准備避開被攔截的函數跳轉到處理函數直接處理;

設置內存可寫(VirtualProtect),跳轉後的函數執行;

記得恢復內存。

網上關於API攔截的教程很多,反正我也說不清楚就不多說了。其實我的理解很簡單,就是想辦法打開老板辦公室的們、潛入、然後替換獎金單、然後關門、走人……就這麼簡單。注意點有三個:一個就是原函數的地址,在哪個dll中,別查錯了;一個就是替換函數的參數,必須遵照游戲規則,該什麼類型就什麼類型;另外一個就是內存的讀寫順序,不能漏也不能反。具體可以參考HookAPI的代碼段,這裡就不帖了。

鉤子(Hook)

關於消息鉤子,其實就兩句話:SetWindowsHookEx ,UnhookWindowsHookEx ,裝載鉤子和卸載鉤子,不過也就這兩句話,學寫鉤子的時候,折騰了好一陣子。給初學者一個建議:理解瘟到死的消息機制,暫時放下MFC,嘗試寫至少一個SDK程序,動手寫之前,好好看看MSDN,很多問題都可以在這裡得到答案。SetWindowsHookEx有四個參數,主要就是注意1和4這兩個參數,第一個參數建議少用WH_CALLWNDPROC 除非必須這麼做。一般情況下,有消息,鍵盤和鼠標鉤子就夠用了,當然特殊情況除外。

枚舉子窗體

至於枚舉子窗體,一般采用兩種方法:

1、EnumChildWindows回調函數 //例子 調用:EnumChildWindows(g_hWndTag, EnumChildWindowsProc,0); 函數:

//-------------------------------------------------------------------------
//枚舉子窗體回調函數
BOOL CALLBACK EnumChildWindowsProc( HWND hWnd, LPARAM lParam )
{
  char buff[256]={''\0''};
  if(::GetWindowLong(hWnd,GWL_STYLE)& WS_VISIBLE)
  {
    ::GetWindowText(hWnd,buff,256);
    //注銷這些按鈕或窗體
    if( NULL != strstr(buff,"打印") ||
      NULL != strstr(buff,"Excel") ||
      NULL != strstr(buff,"導出") )
    {
      //這種只是屏蔽,界面上仍可看見
      //EnableWindow(hWnd,FALSE);
      //徹底注銷,一勞永逸:-)
      DestroyWindow(hWnd);
    }
  }
  return TRUE;
}

2、GetWindow的方法

//例子:百試不爽的while大法,小心while一去不復還
HWND hWndChild=NULL;
hWndChild = ::GetWindow(g_hWnd,GW_CHILD);
while( NULL != hWndChild )
{
  //styleXP.CreateClassXP(hWndChild);
  hWndChild = ::GetWindow(hWndChild,GW_HWNDNEXT);
}
  這裡多說一句,一些換膚程序所采用的窗體子類化,大多就是采用的這兩種方法之一。不過我始終覺得那是一項龐大費時且容易使人崩潰的工作,我曾經嘗試寫了一個小小的類,僅僅只是對按鈕用GDI重畫了一次,就已經接近忍耐極限,最終決定放棄了。

注冊系統熱鍵

要用到RegisterHotKey函數,三步曲:

1、要注冊哪些鍵,先申明一下 //注冊系統熱鍵
#define ID_A  1501
#define ID_B  1502
#define ID_C  1503
#define ID_D  1504
#define ID_E  1505
2、程序初始化的時候,調用注冊熱鍵函數,當然你直接寫在初始化函數中我也不能反駁,這是你的自由:P //RegSysHotkey();
//-------------------------------------------------------------------------
//注冊系統熱鍵
void CTestDlg::RegSysHotkey()
{
  HWND hWnd = this->m_hWnd;
  RegisterHotKey(hWnd, ID_A, MOD_ALT, 65);  //Alt + A
  RegisterHotKey(hWnd, ID_B, MOD_ALT, 66);  //Alt + B
  RegisterHotKey(hWnd, ID_C, MOD_ALT, 67);
  RegisterHotKey(hWnd, ID_D, MOD_ALT, 68);
  RegisterHotKey(hWnd, ID_E, MOD_ALT, 69);
}

3、重載PreTranslateMessage,在你程序運行的時候來截獲熱鍵的輸入。 BOOL CTestDlg::PreTranslateMessage(MSG* pMsg)
{
  switch (pMsg->message)
  {
  //處理系統熱鍵WM_HOTKEY消息
  case WM_HOTKEY:
    switch(pMsg->wParam)
    {
    case ID_A:
      OnAppShow();
      break;
    case ID_B:  //徹底隱藏
      HideMe();
      break;
    case ID_C:…….具體請參照exe代碼片斷
自定義消息和系統欄圖標

就不詳敘了,請參照代碼。

好了,就說這麼多了,新年新氣象,希望大家都有一個好心情。給出的代碼沒有什麼版權,想用就用吧,代碼也沒怎麼整理,只是重新編譯了一下,在demo路徑下,好像用的是靜態鏈接,希望在你的機器上能運行。運行不起來可別怪我。不明白的地方請看目錄下的readme文件和代碼的注釋,或者去VCKBASE論壇提出吧,有很多大俠會幫忙解決的。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved