?? 用masmplus學習win32匯編(4) .txt
字號:
用MasmPlus學習Win32匯編(4)
作者:Zoologist 于2007-11-16上傳
--------------------------------------------------------------------------------
介紹一個工具 Spy++
上一期的最后,我賣了關子,沒有告訴大家如何使知道記事本窗口的類。這一期我將揭曉謎底,就是 微軟的 Spy++
這款軟件是用來查看Windows消息窗口等等的利器,當然除此之外還有很多類似的工具,比如國產的軟件 Spy4Win 等等。 MS Spy++ 是老牌工具,并且也是其他軟件模仿的對象,學會它一通百通,下面我將介紹這個軟件。
啟動之后,軟件界面如下:
上面列出了當前系統中的全部窗口信息。
比如,當前我打開了一個“記事本程序”,在列出的信息中就能看到:
雙擊會彈出它的屬性
我們可以清楚地看到這個窗口的各種信息。
更多的操作可以參考它的幫助文件(中文的哦~)下面介紹查看一個窗口更簡單的方法:
選擇“監視”下面的“日志消息”
拖動瞄準鏡到你要查看的窗口上:
就可以顯示出來關于這個窗口的信息:
在這里我們可以選擇可以監視的“消息”,當有消息發送給我們監視的窗口時,
Spy++會自動記錄下來。點確定之后,就開始了監視,你可以隨便監視一下NotePad。
上面就是看到的潮水一般的各種消息。
點這個位置,在開始/暫停之間切換。
消息太多了,我們必須過濾一下,留下我們需要的。比如,我們只想監視菜單的消息。在“消息”頁面選擇 WM_COMMAND就夠了。
確定之后,我們在NotePad 上選 “關于”,再查看監聽到的消息:
可以知道發送65彈出關于等等。之后,我們用下面的語句替換上一期程序中自動存盤的命令,就會讓NotePad定期彈出關于窗口。
invoke SendMessage,EAX,WM_COMMAND,65,0
有了Spy++, 我們就可以充分發揮自己的好奇心,東看看西看看,看看我們平常經常使用的各種軟件究竟是什么東西。就像第一次見到望遠鏡的孩子。
關于這個工具的工作原理,在參考[1]上有一點介紹。現在看不明白不要緊,慢慢玩下去。我也希望讀者每一次看都有新的收獲。需要注意的是,如果你安裝了殺毒軟件,它們之間可能會有沖突,你在觀測一些消息的時候也許會有一些差別,另外,可能導致CPU占用率居高不下。因此在使用的時候最好關閉之。
涂鴉之作
一個偉人曾經說過“當你手中只有一把榔頭的時候,世界上的一切問題都是釘子”。在上一期,我們學習了一點如何繪圖,下面就用這些知識做點亂寫亂畫的事情。在此之前,還要再學一點東西,免得每次只能寫“大王八”三個字,太沒有創意了(忽然發現這三個字非常簡單,故兒童常常使用,并且不容易錯。如果中國作協的那個老頭給人題這個字,想必也用不到賈平凹出來捧場)。
下面要玩的就是在NotePad上“寫字”,不過不是打開敲進去的,而是畫上去的。Windows是圖形操作系統,它上面的程序一般都會有窗口,窗口上通常都會有一個叫做 DC的東西,至于具體是什么,后面會講~ 反正您就記著,DC就好比廣告牌面向馬路的那個面,畫點美女汽車都是在它上面。
除此之外,還要介紹一下創建“一種邏輯字體”。這個名字聽起來非常專業,實際上就是設定一個我們需要的字體,給它一個編號(handle),然后我們作畫的時候直接說“要XXX號的字體”(拿著handle給出去就可以了),就是這么簡單。
HFONT CreateFont(
int nHeight, // 字體高度
int nWidth, // 平均寬度
int nEscapement, // 旋轉角度
int nOrientation, // 每個字的傾斜度
int fnWeight, // 字體粗細
DWORD fdwItalic, // 要傾斜否
DWORD fdwUnderline, // 要下劃線否
DWORD fdwStrikeOut, // 要刪除線否
DWORD fdwCharSet, // 字符集
DWORD fdwOutputPrecision, // 輸出精度。輸出精度定義了輸出與所要求的 //字體高度、寬度、字符方向等的接近程度。
DWORD fdwClipPrecision, //指定剪輯精度。剪輯精度定義了當字符的
//一部分超過剪輯區域時對字符的剪輯方式
DWORD fdwQuality, //輸出質量,包括:
DEFAULT_QUALITY (默認質量)
DRAFT_QUALITY (草稿質量)
PROOF_QUALITY (正稿質量)
DWORD fdwPitchAndFamily, //指定字體的字符間距和族
LPCTSTR lpszFace //它指定的所用的字體名。
//如果lfFaceName為NULL,
//圖形設備接口將使用默認的字體名。
);
另外一個函數就是 SelectObject ,意思是我要用什么什么作畫。這個“什么什么”可以是某個畫筆,某張粘貼畫,或者某個字體
The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type.
HGDIOBJ SelectObject(
HDC hdc, // handle to DC
HGDIOBJ hgdiobj // handle to object
);
Parameters:
hdc
[in] Handle to the DC.
hgdiobj
[in] Handle to the object to be selected. The specified object must have been created by using one of the following functions.
程序如下:
;#Mode=CON
;在內存中查找“NotePad”,并且在上面寫字
.586P
.MODEL Flat,StdCall
OPTION CASEMAP:NONE
INCLUDE WINDOWS.INC
INCLUDE KERNEL32.INC
INCLUDE USER32.INC
include masm32.inc
include gdi32.inc
INCLUDELIB KERNEL32.LIB
INCLUDELIB USER32.LIB
includelib masm32.lib
includelib gdi32.lib
include macro.asm
; -----------------------------------
; INPUT red, green & blue BYTE values
; OUTPUT DWORD COLORREF value in eax
; -----------------------------------
RGB MACRO red, green, blue ;輸入RGB,合成一個32位值放在EAX中
xor eax, eax
mov ah, blue ; blue
mov al, green ; green
rol eax, 16
mov al, red ; red
ENDM
.DATA?
lpMsg MSG
TimerID dd ?
iCount dd ?
buffer db 100 dup(?)
hMine dd ? ;找到的NotePad的handle
hdc dd ? ;找到的NotePad的DC的Hand
hFont dd ? ;創建一種字體
.CODE
TimerProc proc
local cfRGB:COLORREF
local fnText:HGDIOBJ
invoke FindWindow,CTEXT('notepad'),NULL
.if (EAX==0)
invoke wsprintf,offset buffer,CTEXT("%d 沒有找到記事本",10,13),iCount
invoke StdOut, offset buffer
inc iCount
ret
.endif
mov hMine,EAX ;保存NotePad的Handler
invoke GetDC,EAX ;取得 DC
mov hdc,EAX
invoke CreateFont,\
100,\
40,\
0,\
0,\
FW_BLACK,\
0,\
0,\
0,\
ANSI_CHARSET,\
OUT_DEFAULT_PRECIS,\
CLIP_CHARACTER_PRECIS,\
DEFAULT_QUALITY,\
DEFAULT_PITCH or FF_SWISS,\
CTEXT("宋體")
mov hFont,eax ;保存一下這種字體的handle
invoke SelectObject,hdc,hFont ;將這種字體設置給DC
RGB 200,200,50
invoke SetTextColor,hdc,eax ;準備好筆
RGB 0,0,255
invoke SetBkMode,hdc,eax ;準備好背景
invoke TextOut,hdc,50, 50,CTEXT('王朝到此一游'),12 ;寫字啦
invoke DeleteObject,hFont ;釋放字體
invoke ReleaseDC,hMine,hdc ;釋放DC
invoke wsprintf,offset buffer,CTEXT("畫一下",13,10),NULL
invoke StdOut, offset buffer
ret
TimerProc endp
Start:
invoke SetTimer, NULL, 0, 1000, addr TimerProc ;200ms一次,觸發 TimerProc
mov TimerID,eax ;存一下,釋放的時候還要用
.WHILE TRUE
invoke GetMessage, ADDR lpMsg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR lpMsg
invoke DispatchMessage, ADDR lpMsg
.ENDW
invoke KillTimer, NULL, TimerID ;釋放定時器
;暫停顯示,回車鍵關閉
invoke StdIn,addr buffer,sizeof buffer
invoke ExitProcess,0
END Start
程序的結構和上一期的沒有什么差別,就是找Notepad-à找DC—〉準備字體—〉畫,然后就收尾了。
特別需要注意的是CreateFont API中 如果使用 DWORD fdwCharSet, // 字符集 設置為ANSI_CHARSET 是無法輸出“華文新魏”這樣的字體的,輸出始終為“宋體”;如果希望輸出其他字體,需要將這項設置為DEFAULT_CHARSET。
另外,告訴大家可以通過invoke GetDC,HWND_DESKTOP取得桌面的DC。我們就可以在屏幕上寫字了,有興趣的讀者不妨實驗一下。
參考:
[1] Visual C++ Team Blog
http://blogs.msdn.com/vcblog/archive/2007/01/16/spy-internals.aspx 關于SPY++ 內部工作機制的一點介紹
[2] Spy4Win http://www.ccrun.com/spy4win/
--------------------------------------------------------------------------------
<<<上一篇 歡迎訪問AoGo匯編小站:http://www.aogosoft.com 下一篇>>>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -