?? 匯編版正則表達式.txt
字號:
.DATA
lpszString db 'link.exe /SUBSYSTEM:WINDOWS /nologo /OUT:"Main.exe" "Main.obj" "Main.RES"'
lpEnd db 0
.DATA?
hInstance dd ?
lpRet POINT 20 dup() ;最多20個
iCount dd ?
buffer db MAX_PATH*2 dup(?)
.CODE
GetRetString proc uses edx,lpPOINT,lpRetString,iSize
mov edx,lpPOINT
mov eax,[edx].POINT.y
sub eax,[edx].POINT.x
.if eax>iSize
mov eax,iSize
.endif
push eax
invoke RtlMoveMemory,lpRetString,[edx].POINT.x,eax
pop eax
mov edx,lpRetString
mov BYTE ptr [edx+eax],0
ret
GetRetString endp
START:
invoke GetModuleHandle,NULL
mov hInstance,eax
.data
lp2 db '/{OUT}:{(\")+>}',0 ;將返回"Main.exe"包含引號
lp3 db '/{OUT}:(\")+<{?+[\"]}\">',0 ;將返回 main.exe 無引號
lp4 db '/{OUT}(:(\")+<{?+[\"]}\">)*',0
;與lp3相同,但是如果/OUT之后沒有值,也返回成功
;接著,我們進行不定個數的查找測試,查找所有單獨使用引號包含的字符串.
;目標必須是類似組合的字串,并且相連續, "Main.obj" "Main.RES ,分開后就是:
; "Main.obj"
; "Main.RES"
;分析得到表達式如下:
lp5 db '( +{\"?+<\">})+',0
.code
;在每次使用ExpressSearch前都要賦值.因為ExpressSearch會修改它
mov iCount,20
invoke ExpressSearch,0, ;使用默認的字符表
offset lpszString, ;目標地址
offset lpEnd, ;結束地址
offset lp5, ;查找/OUT:"Main.exe",并分離出參數與值
offset lpRet, ;返回結果地址
offset iCount, ;個數
EF_USEEXPRESS ;使用表達式,區分大小寫
.if SDWORD ptr eax>0
;lpRet.x與lpRet.y,分別是整個匹配字符串的開始地址與結束地址.
;如果表達式中沒有符號{}引用,則iCount永遠為1
;這里有兩個{},分別引出參數與值,一共是3個。
.if iCount==3
invoke GetRetString,addr lpRet[sizeof POINT],
addr buffer,sizeof buffer-1
invoke MessageBox,0,addr buffer,CTXT("參數"),0 ;顯示 OUT
invoke GetRetString,addr lpRet[sizeof POINT*2],
addr buffer,sizeof buffer-1
invoke MessageBox,0,addr buffer,CTXT("值"),0
;顯示 "Main.exe" 或 Main.exe
.elseif iCount==2 ;在使用lp4時才會有這個判斷分支.
invoke GetRetString,addr lpRet,addr buffer,sizeof buffer-1
invoke MessageBox,0,addr buffer,CTXT("無值"),0
;顯示整個匹配
;/OUT之后無參數
.endif
.else
; ;錯誤處理
; .if eax==-1
;
; .elseif eax==-2
; ... ...
; .endif
.endif
invoke ExitProcess,0
END START
代碼中都有說明,使用其實是很簡單的,這個表達式庫最強的地方,在于可以選擇性地獲得結果,并一次性得到別的表達式需要多次查找才能得到的效果。是專門為程序員使用而定制的,使用這個表達式庫,最重要的在于了解它的運作原理,使用起來才會得心應手。
我們就表達式來進行分析:
源字符串:
link.exe /SUBSYSTEM:WINDOWS /nologo /OUT:"Main.exe" "Main.obj" "Main.RES"
使用lp2 db '/{OUT}:{(\")+>}',0 時,拆分來分析:
/
{
OUT
}
:
{
(\")+<
?+<
\"
>
>
}
找到字符/,然后匹配OUT,如果有,返回位置(使用了符號{}),接著,后面必須是:號,然后返回兩個”號之間的位置,?+<\”>,表示,任意字符直到碰到”號,合起來,就是/OUT:”*”,引號之間的可以是任意字符。
lp3 db '/{OUT}:(\")+<{?+[\"]}\">',0
這個與lp2的區別在于,返回的值不包含引號, {?+[\"]}\",?+[\”]表示任意字符直到碰到”號,但不把”號放入這次查找范圍之內,也就是指針移動到了”號之前,這樣后面需要再次用\”來匹配。如果已經是表達式的最后,可以不填。
lp4 db '/{OUT}(:(\")+<{?+[\"]}\">)*',0
這個表達式后面的部分用()*來包含,也就是表示,包含的這整個表達式都可以不要。這樣,當只有前面的/OUT匹配時,仍然會返回成功,但返回的位置只有前面的。
lp5 db '( +{\"?+<\">})+',0
這個表達式查找并返回所有引號包含的字符串,但必須是空格開頭,這樣/OUT:”Main.exe”這一項就不會查找到。\"?+<\">就是返回引號之間的所有字符,()+表示,循 環地用這個表達式匹配成功之后的字符串,直到失敗。這種時候,返回的位置{}個數是不確定的。這里使用了()+,也就是表示,至少要有1個,如果是使用()*,則一個都沒有,都會返回成功。這就看使用者如果取舍了。
上述的例子一次性得到/SUBSYSTEM:WINDOWS與/OUT:”Main.exe”,看看吧:
(?+>)}>)+
要注意,這個表達式查找后,iCount是大于3的喔。修改顯示的代碼為:
.if iCount>1
Xor ebx,ebx
@@:
invoke GetRetString,addr lpRet[ebx*sizeof POINT],addr buffer,sizeof buffer-1
invoke MessageBox,0,addr buffer,CTXT("顯示"),0
inc ebx
cmp ebx,iCount
jl @B
.endif
這樣可以依次顯示所有抓到的字串。看很簡單吧。
如果要確定一個字串中是否包含某個字串,如在 Welcome中查找com,直接查找com即可,表達式搜索函數,是先從最開始進行搜索,一個一個向后來匹配,直到完成或失敗,才結束的。
如果是確定不包含com呢?使用!(com)吧,如果包含這個,則表達式失敗。
詳細的,請大家多做一下測試吧,總之,這個表達式庫,是專門為程序員使用而寫的,強調查找與處理的方便性,而不在于功能如何復雜,所以,能夠用在程序開發中的地方是非常之多的,別的表達式庫,使用者總會認為太復雜,如果用得少還不如自己開發專用的函數來完成,事實上,我的這個庫已經夠復雜的了T_T,多分析與組合表達式,是可以實現極為快速的查找的,尤其是需要處理某些特殊的查找時,很多時候,使用這個函數和好的表達式,一次性就可以得到需要的所有字符與結果。當然必須以目標查找字串的格式而定制表達式。同一個表達式,在不同的字串查找中是不同的。
因為表達式的復雜性,是沒辦法詳細舉例的,大家可以利用上述的例子,詳細地進行測試,在下載的表達式庫中,還包含一個測試程序,是專門用來測試表達式是否正確的,根據返回的錯誤,可以慢慢地熟悉,有任何的問題,你可以在我們的論壇提出。
--------------------------------------------------------------------------------
歡迎訪問AoGo匯編小站:http://www.aogosoft.com/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -