[VB.NET]突破Disable按鈕的封鎖與限制

Introduction

一般來說,當我們程式中有部份功能欲不讓使用者使用時。通常我們會把按鈕給Disable掉,讓使用者無法執行特定的功能。但這樣做真的就安全嗎?答案是否定的。其實光是把按鈕給Disable掉是很容易破解的,在對岸就已有許多破解工具 (e.x. 按鈕突破大師),因此在編碼上最好還是要在程式中自行加上判斷,讓按鈕就算被突破也無法執行。

突破Disable按鈕的封鎖與限制

欲突破Disable按鈕的封鎖與限制,其實很簡單。只要透過Win32 API即可達成。

需要使用的API有:

  • ChildWindowFromPoint
  • GetForegroundWindow
  • IsWindowEnabled
  • EnableWindow
  • GetCursorPos
  • ScreenToClient

程式流程如下:

image

程式範例如下:

MFC

void CBtnEnableDlg::OnButton1() 

{

SetTimer(1,100,NULL);

}

void CBtnEnableDlg::OnTimer(UINT nIDEvent) 

{

HWND hWnd,hWndChild;

POINT point;


hWnd=::GetForegroundWindow();

GetCursorPos(&point);

::ScreenToClient(hWnd,&point);

hWndChild=::ChildWindowFromPoint(hWnd,point);

if(::IsWindowEnabled(hWndChild)==0)

{

::EnableWindow(hWndChild,1);

}


CDialog::OnTimer(nIDEvent);

}

VB.NET

Imports System.Runtime.InteropServices

Public Class Form1


<DllImport(“user32.dll”)>
Private Shared Function ChildWindowFromPoint(ByVal hWndParent As IntPtr, ByVal Point As Point) As IntPtr

End Function


<DllImport(“user32.dll”, SetLastError:=True)>
Private Shared Function GetForegroundWindow() As IntPtr

End Function


<DllImport(“user32.dll”)>
Private Shared Function IsWindowEnabled(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean

End Function


Declare Function EnableWindow Lib “user32” (ByVal hwnd As IntPtr, ByVal fEnable As Integer) As Integer


<DllImport(“user32.dll”, SetLastError:=True)>
Private Shared Function ScreenToClient(ByVal hWnd As IntPtr, ByRef lpPoint As Point) As Boolean

End Function


Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

Dim p As Point = MousePosition

Dim hWnd, hWndChild As IntPtr

hWnd = GetForegroundWindow()

ScreenToClient(hWnd, p)

hWndChild = ChildWindowFromPoint(hWnd, p)


If Not IsWindowEnabled(hWndChild) Then

EnableWindow(hWndChild, 1)

End If

End Sub


Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged

Timer1.Enabled = CheckBox1.Checked

End Sub
End Class

執行後我們把滑鼠移到Disable的按鈕上,按鈕就會被強制變回Enable狀態了。變回Enable的按鈕也變得可以按下與執行。

執行步驟

Step1.開啟按鈕突破程式

image

Step2.開啟欲突破的程式

image

Step3.啟動按鈕突破功能

image

Step4.把滑鼠移到欲突破的按鈕上

當滑鼠移到欲突破的Disable按鈕上,按鈕會被強制設回Enable。

image

P.S.

  • 上述範例對.NET程式的按鈕無效,請使用非.NET程式來測試。
  • 雖範例無法達到突破.NET按鈕,但這不代表.NET程式不需注意這問題。因為能突破.NET按鈕的工具確實存在(e.x. Enable.NET)。
  • 雖範例只能把Disable按鈕設為Enable,但其實運用同樣的概念也可以把隱藏的元件顯示出來。

Conclusion

此篇的主旨不是要教程式員破解,而是要提醒設計員在程式的設計上不是只要把按鈕給Disable掉就安全了。還是要額外利用Code去判斷是否可以執行才是較為安全的作法,尤其是程式中重要的功能更是要加以防堵。