⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wordsys.asm

📁 《Visual C++编程技巧典型案例解析:基础与应用篇(下)(含1CD-ROM)——编程技巧典型案例集锦系列》源码
💻 ASM
字号:
;WORDSYS.ASM
; *******************************************************************************
; *       全屏截词DLL,通过修改TextOutW,ExtTextOutA,ExtTextOutW三个函数的首     *
; *   条指令实现的截词。                                                        *
; *                                                                             *
; *  支持Windows 2000  Windows XP                                               *
; *                                                                             *
; *  版本:0.93                                                                 *
; *  代码:江华  2001年6月20日。                                                *
; *                                                                             *
; *  ml /c /coff /Cp WORDSYS.ASM                                                *
; *  Link /SECTION:.data,S /subsystem:windows /dll /def:WORDSYS.def WORDSYS.obj *
; *******************************************************************************

;ml /c /coff /Cp WORDSYS.asm
;Link /SECTION:.data,S /subsystem:windows /dll /def:WORDSYS.def WORDSYS.obj

.386
.model flat, stdcall
option casemap :none
             include ..\include\windows.inc
             include ..\include\user32.inc
             include ..\include\kernel32.inc              
             includelib ..\lib\user32.lib
             includelib ..\lib\kernel32.lib
;---------------------------------------------------------------------------
ProcessBufS STRUCT         ;每个进程私有
    ProcessHandle dd ?     ;进程句柄
    BufNo         dd ?     ;缓冲区号,指明这个进程最后一次用的缓冲区号
ProcessBufS ENDS
PublicBufS STRUCT          ;共享结构
    ProcessHandle  dd ?    ;进程句柄
    WirteCount     dd ?    ;访问的频烦程度
    LastBufNo      dw ?
    Pos            dw ?    ;当前缓冲区的偏移
PublicBufS ENDS
;---------------------------------------------------------------------------
.data                 ;共享数据段,所有进程共享
AllWCharNum           dd 0
AllACharNum           dd 0
Busy                  db 0
TextOutWName          db 'TextOutW',0
ExtTextOutWName       db 'ExtTextOutW',0
ExtTextOutAName       db 'ExtTextOutA',0
gdi32                 db '\gdi32.dll' ,0
SystemPath            db MAX_PATH dup(0)
gdiModuleHandle       dd 0
Allp                  dd 0
PublicBufW            PublicBufS 30 dup (<0,0,0>)
SaveBufferW           db 256*30  dup(' ')              ;unicode缓冲区
PublicBufA            PublicBufS 10 dup (<0,0,0>)
SaveBufferA           db 256*10  dup(' ')               ;ansi缓冲区
;PublicBufW中的30个结构按顺序,与SaveBufferW中的内容对应,每个缓冲区长256个字节
;---------------------------------------------------------------------------
.data?
ModuleHandle          dd ?
TextOutWAddr          dd ?
TextOutWretAddr       dd ?
ExtTextOutWAddr       dd ?
ExtTextOutWretAddr    dd ?
ExtTextOutAAddr       dd ?
ExtTextOutAretAddr    dd ?
ProcessBufW   ProcessBufS <?>       
ProcessBufA   ProcessBufS <?>       
pflOldProtect         dd ?
temp                  dd ?
;---------------------------------------------------------------------------
.code
GetWord  PROC
  push ebp
  mov ebp,esp
  cld
  mov esi, offset PublicBufW
  mov edi, [ebp+8]
  mov ecx, (30*sizeof(PublicBufS)+256*30)/4
  rep movsd
  mov esi, offset PublicBufA
  mov edi, [ebp+12]
  mov ecx, (10*sizeof(PublicBufS)+256*10)/4
  rep movsd
  xor eax,eax
  mov esi,offset PublicBufW
  add esi,10
  mov ecx,30
clear1:
  mov word ptr [esi],ax
  add esi,12
  loop clear1
  mov esi,offset PublicBufA
  add esi,10
  mov ecx,10
clear2:
  mov word ptr [esi],ax
  add esi,12
  loop clear2
  mov edi, offset SaveBufferW
  mov ecx,256*30/4
  rep stosd
  mov edi, offset SaveBufferA
  mov ecx,256*10/4
  rep stosd
  pop ebp
  ret 8  
GetWord  ENDP
;---------------------------------------------------------------------------
GetWBufNo  PROC    ;eax为进程号,eax返回一个缓冲区号,找出访问频率最小的.并设置WirteCount和Pos域
   push edi
   push edx
   push ecx
   push ebx       
   push eax
   mov eax,30
   mov ecx,30-1
   mov ebx,offset PublicBufW
   mov edi,ebx
   mov edx,[ebx+4]
loopCompareW:
   add ebx,sizeof(PublicBufS)
   cmp edx,[ebx+4]
   jle  NextCompareW
   mov eax,ecx
   mov edi,ebx
   mov edx,[ebx+4]
NextCompareW:
   loop  loopCompareW
   mov ecx,eax
   mov eax,30
   sub eax,ecx
   mov ecx,AllWCharNum
   mov [edi+4],ecx
   xor ecx,ecx
   mov [edi+10],cx
   pop [edi]
   pop ebx
   pop ecx
   pop edx
   pop edi 
   ret
GetWBufNo  ENDP
;---------------------------------------------------------------------------
GetABufNo  PROC    ;eax为进程号,eax返回一个缓冲区号,找出访问频率最小的.并设置WirteCount和Pos域
   push edi
   push edx
   push ecx
   push ebx       
   push eax
   mov eax,10
   mov ecx,10-1
   mov ebx,offset PublicBufA
   mov edi,ebx
   mov edx,[ebx+4]
loopCompareA:
   add ebx,sizeof(PublicBufS)
   cmp edx,[ebx+4]
   jle  NextCompareA
   mov eax,ecx
   mov edi,ebx
   mov edx,[ebx+4]
NextCompareA:
   loop  loopCompareA
   mov ecx,eax
   mov eax,10
   sub eax,ecx
   mov ecx,AllACharNum
   mov [edi+4],ecx
   xor ecx,ecx
   mov [edi+10],cx
   pop [edi]
   pop ebx
   pop ecx
   pop edx
   pop edi 
   ret
GetABufNo  ENDP
;---------------------------------------------------------------------------
MainWork  PROC
  inc AllWCharNum
  add ecx,ecx
  cmp ecx,0ffh
  jl  NoLongerw
  mov ecx,0feh
NoLongerw:
  pushad
  cmp ProcessBufW.BufNo,-1
  ;查看ProcessBuf.BufNo是否为-1,如果=-1则调用GetWBufNo,得到一个空的缓冲区
  jnz HaveWBuf
GetWBuf:
  mov eax,ProcessBufW.ProcessHandle
  Call GetWBufNo
  mov ProcessBufW.BufNo,eax
HaveWBuf:
  mov eax,ProcessBufW.BufNo          
  mov ebx,sizeof(PublicBufS)
  mul ebx
  mov ebx,offset PublicBufW
  add ebx,eax         
  mov eax,[ebx]       ;ebx指向当前缓冲区管理队列
  cmp eax,ProcessBufW.ProcessHandle
  jnz GetWBuf
  mov eax,AllWCharNum
  mov [ebx+4],eax
  xor eax,eax
  mov ax,[ebx+10]
  mov edx,eax         ;当前缓冲区的字符数
  add eax,ecx
  cmp eax,255
  ja GetWBuf
  ;mov [ebx+8],eax
  push eax    ;当前字符数
  push ebx    ;存当前字符数
  mov eax,ProcessBufW.BufNo
  shl eax,8
  mov ebx,offset SaveBufferW
  add ebx,eax
  add ebx,edx
  mov edi,[ebp+7*4]
CopyW:
  mov al,[edi]
  mov [ebx],al
  inc ebx
  inc edi
  loop CopyW
  pop ebx
  pop eax
  mov [ebx+10],ax
  popad
  ret
MainWork  ENDP
;---------------------------------------------------------------------------
MyExtTextOutW PROC   ;从ExtTextOutW跳来
  push ebp
  mov ebp,esp
  push ecx
  mov ecx,[ebp+8*4]
  cmp ecx,0
  jz NoWChar
  call MainWork
NoWChar:
   pop ecx
   sub esp,1ch
   jmp dword ptr ExtTextOutWretAddr
MyExtTextOutW ENDP
;---------------------------------------------------------------------------
MyTextOutW2000 PROC ;从win2000中的TextOutW跳来
   push ebp
   mov ebp,esp
   push ecx
   push ebx
   push ecx
   mov ecx,[ebp+6*4]
   cmp ecx,0
   jz NoWChar1
   sub ebp,8
   call MainWork
   add ebp,8
NoWChar1:
   pop ecx
jmp dword ptr TextOutWretAddr
MyTextOutW2000 ENDP
;---------------------------------------------------------------------------
MyTextOutWXP PROC ;从winXP中的TextOutW跳来
   push ebp
   mov ebp,esp
   push ebx
   push esi
   push ecx
   mov ecx,[ebp+6*4]
   cmp ecx,0
   jz NoWChar1
   sub ebp,8
   call MainWork
   add ebp,8
NoWChar1:
   pop ecx
jmp dword ptr TextOutWretAddr
MyTextOutWXP ENDP
;---------------------------------------------------------------------------
MyExtTextOutA PROC ;从ExtTextOutA中跳来
  push ebp
  mov ebp,esp
  push ecx
  mov ecx,[ebp+8*4]
  cmp ecx,0
  jz NoAChar
  inc AllACharNum
  cmp ecx,0ffh
  jl  NoLongera
  mov ecx,0feh
NoLongera:
  pushad
  cmp ProcessBufA.BufNo,-1
  ;查看ProcessBuf.BufNo是否为-1,如果=-1则调用GetABufNo,得到一个空的缓冲区
  jnz HaveABuf
GetABuf:
  mov eax,ProcessBufA.ProcessHandle
  Call GetABufNo
  mov ProcessBufA.BufNo,eax
HaveABuf:
  mov eax,ProcessBufA.BufNo          
  mov ebx,sizeof(PublicBufS)
  mul ebx
  mov ebx,offset PublicBufA
  add ebx,eax         
  mov eax,[ebx]       ;ebx指向当缓冲区管理队列
  cmp eax,ProcessBufA.ProcessHandle
  jnz GetABuf
  mov eax,AllACharNum
  mov [ebx+4],eax
  xor eax,eax
  mov ax,[ebx+10]
  mov edx,eax         ;当前缓冲区的字符数
  add eax,ecx
  cmp eax,255
  ja GetABuf
  ;mov [ebx+8],eax
  push eax
  push ebx
  mov eax,ProcessBufA.BufNo
  shl eax,8
  mov ebx,offset SaveBufferA
  add ebx,eax
  add ebx,edx
  mov edi,[ebp+7*4]
CopyA:
  mov al,[edi]
  mov [ebx],al
  inc ebx
  inc edi
  loop CopyA
  pop ebx
  pop eax
  mov [ebx+10],ax
  popad
NoAChar:
   pop ecx
push byte ptr 0
jmp dword ptr ExtTextOutAretAddr
MyExtTextOutA ENDP
;---------------------------------------------------------------------------
MyDllMain proc hInstDLL:dword, reason:dword, unused:dword
    .if reason == DLL_PROCESS_ATTACH
        call GetCurrentProcessId
        mov ProcessBufW.ProcessHandle,eax
        mov ProcessBufA.ProcessHandle,eax
        mov eax,-1
        mov ProcessBufW.BufNo,eax       ;没有使用缓冲区
        mov ProcessBufA.BufNo,eax       ;没有使用缓冲区
        invoke GetSystemDirectory ,ADDR SystemPath ,MAX_PATH
        invoke lstrcat, ADDR SystemPath,ADDR gdi32
        invoke GetModuleHandle,ADDR SystemPath
        cmp eax,0
        jz NoLoadGDI32
        mov gdiModuleHandle,eax
        ;获取ExtTextOutW的地址
        invoke GetProcAddress,gdiModuleHandle,ADDR ExtTextOutWName
        mov ExtTextOutWAddr,eax
        add eax,6
        mov ExtTextOutWretAddr,eax   ;修改了6字节代码,所以返回到ExtTextOutW+6
        ;获取TextOutW的地址
        invoke GetProcAddress,gdiModuleHandle,ADDR TextOutWName
        mov TextOutWAddr,eax
        add eax,5
        mov TextOutWretAddr,eax
        ;获取ExtTextOutA的地址
        invoke GetProcAddress,gdiModuleHandle,ADDR ExtTextOutAName
        mov ExtTextOutAAddr,eax
        add eax,5
        mov ExtTextOutAretAddr,eax    ;修改了5字节代码,所以返回到ExtTextOutA+5
        ;修改ExtTextOutW的代码
        invoke VirtualProtect,ExtTextOutWAddr,8,PAGE_EXECUTE_READWRITE,ADDR pflOldProtect
        mov ebx,ExtTextOutWAddr
        mov al,0e9h
        mov [ebx],al
        mov eax,MyExtTextOutW
        sub eax,ExtTextOutWAddr
        sub eax,5
        mov [ebx+1],eax
        mov al,90h
        mov [ebx+5],al
        invoke VirtualProtect,ExtTextOutWAddr,8,pflOldProtect,ADDR temp
        ;修改TextOutW的代码
        invoke VirtualProtect,TextOutWAddr,8,PAGE_EXECUTE_READWRITE,ADDR pflOldProtect
        mov ebx,TextOutWAddr
        mov al,0e9h
        mov [ebx],al
        call GetVersion
        cmp ah,0
        jz is2000
        mov eax,MyTextOutWXP
        jmp xp2000
is2000: mov eax,MyTextOutW2000
xp2000: sub eax,TextOutWAddr
        sub eax,5
        mov [ebx+1],eax
        invoke VirtualProtect,TextOutWAddr,8,pflOldProtect,ADDR temp
        ;修改ExtTextOutA的代码
        invoke VirtualProtect,ExtTextOutAAddr,8,PAGE_EXECUTE_READWRITE,ADDR pflOldProtect
        mov ebx,ExtTextOutAAddr
        mov al,0e9h
        mov [ebx],al
        mov eax,MyExtTextOutA
        sub eax,ExtTextOutAAddr
        sub eax,5
        mov [ebx+1],eax
        invoke VirtualProtect,ExtTextOutAAddr,8,pflOldProtect,ADDR temp
NoLoadGDI32:
     .endif
      ret
MyDllMain Endp
      end MyDllMain

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -