程序段中的变量
Windows应用程序捆绑核心编程 张争秋 清华大学出版社 page189中使用一个子文件定义了一个汇编子程序
;文件:attach.asm.
;常量定义.
.const
;代码段开始.
.code
;以“_”开头,并以 API 函数名相接的,是用来贮存通过 GetProcAddress 得到的 API 线形地址.
attach_start equ $
OEP dd 0
hLibUser32 dd ?
_GetProcAddress dd 0
_LoadLibrary dd 0
_FreeLibrary dd 0
_ExitProcess dd 0
_MessageBox dd 0
szLibUser32 db "user32", 0
szProcLoadLibrary db "LoadLibraryA", 0
szProcFreeLibrary db "FreeLibrary", 0
szProcExitProcess db "ExitProcess", 0
szProcMessageBox db "MessageBoxA", 0
_szAppTitle db "Shellcode Test", 0
_szShowText db "Shellcode Done!",0
;真正的代码开始.
attach_code_start equ $
call Attachment
;-----------------------------------------------------------------------------
;附加段的子程序处理模块.
Attachment proc
;以下是经典的查找 kernel32.dll 的基地址的代码.
pop ebp
sub ebp, offset Attachment
mov eax, [esp]
and eax, 0FFFF0000h
@@chk:
cmp dword ptr [eax], 00905A4Dh
je @@fnd
sub eax, 1000h
jmp @@chk
@@fnd:
;以下的涉及到 PE 格式的操作.
push ebp
push ebx
push esi
push edi
mov ebp, eax
add eax, [eax][IMAGE_DOS_HEADER.e_lfanew]
mov edi, [eax][IMAGE_NT_HEADERS.OptionalHeader.DataDirectory]
add edi, ebp
mov esi, [edi][IMAGE_EXPORT_DIRECTORY.AddressOfNames]
add esi, ebp
;在 kernel32.dll 里面查找 GetProcAddress 的API 的线形地址.
xor edx, edx
@@name:
mov eax, [esi]
add eax, ebp
@@chgp: ; GetProcAddress()
cmp dword ptr [eax+00h], "PteG" ; GetP
jne @@next
cmp dword ptr [eax+04h], "Acor" ; rocA
jne @@next
cmp dword ptr [eax+08h], "erdd" ; ddre
jne @@next
cmp word ptr [eax+0Ch], "ss" ; ss
jne @@next
mov eax, [edi][IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals]
add eax, ebp
movzx ebx, word ptr [edx*2+eax]
mov eax, [edi][IMAGE_EXPORT_DIRECTORY.AddressOfFunctions]
add eax, ebp
mov eax, [ebx*4+eax]
add eax, ebp
; 找到GetProcAddress 的线形地址并保存.
mov [_GetProcAddress], eax
@@next:
add esi, 4
inc edx
cmp edx, [edi][IMAGE_EXPORT_DIRECTORY.NumberOfNames]
jne @@name
;下面的是通过 GetProcAddress 获得一些API 的线形地址,并储存起来,供后面使用.
_call [_GetProcAddress], ebp, offset szProcFreeLibrary
mov [_FreeLibrary], eax
_call [_GetProcAddress], ebp, offset szProcExitProcess
mov [_ExitProcess], eax
_call [_GetProcAddress], ebp, offset szProcLoadLibrary
mov [_LoadLibrary], eax
;载入 user32.dll ,并储存它的句柄.
_call eax, offset szLibUser32
mov [hLibUser32], eax
_call [_GetProcAddress], [hLibUser32], offset szProcMessageBox
mov [_MessageBox], eax
;调用加壳函数
_call ShellFunc
;返回原程序入口点
mov eax, dword ptr [OEP]
jmp eax
_call [_FreeLibrary], [hLibUser32]
_call [_ExitProcess], 0
Attachment endp
;-----------------------------------------------------------------------------
;计算加壳代码的长度.
attach_size equ $ - offset attach_start
我有一个疑问:
(1)变量 hLibUser32 dd ? 怎么被定义在程序段中,不是说程序段中的变量是不能修改的吗 ??
但是语句 mov [hLibUser32], eax 却对其赋值?