77E600C8 dw 10Bh ; OptionalHeader.Magic
77E600C8 db 5 ; OptionalHeader.MajorLinkerVersion
77E600C8 db 0Ch ; OptionalHeader.MinorLinkerVersion
77E600C8 dd 59000h ; OptionalHeader.SizeOfCode
77E600C8 dd 73E00h ; OptionalHeader.SizeOfInitializedData
77E600C8 dd 0 ; OptionalHeader.SizeOfUninitializedData
77E600C8 dd 7A40h ; OptionalHeader.AddressOfEntryPoint
77E600C8 dd 1000h ; OptionalHeader.BaseOfCode
77E600C8 dd 5A000h ; OptionalHeader.BaseOfData
77E600C8 dd 77E60000h ; OptionalHeader.ImageBase
77E600C8 dd 1000h ; OptionalHeader.SectionAlignment
77E600C8 dd 200h ; OptionalHeader.FileAlignment
......
......
77E600C8 dd 1000h ; OptionalHeader.SectionAlignment
GetProcbaseAddress proc uses ebx esi FunAddr:DWORD
.if !FunAddr
;如果 FunAddr = 0 随便 Call 一下,pop eax 就是当前的地址
call $ + 5
pop eax
.else
;如果是某个函数的调用地址,函数调用地址一般有下面的格式:
; __stdcall MessageBoxA(x,x,x,x)
; MessageBoxA proc near
;FF 25 08 04 40 00 jmp ds:__imp__MessageBoxA
; MessageBoxA endp
;其中 FF 25 是 jmp 的操作码,后面的 00400408 是函数调用地址
;这样就容易理解下面的代码了。
mov eax, FunAddr
mov eax, [eax+2]
mov eax, [eax]
.endif
and eax, 0FFFF0000h
.repeat
.if word ptr [eax] != 'ZM'
xor esi, esi
sub eax, 1000h
.else
mov esi, [eax+IMAGE_DOS_HEADER.e_lfanew]
.endif
add esi, eax
.until dword ptr [esi] == 'EP'
ret
GetProcbaseAddress endp
77EB4230 ExportTable
77EB4230 dd 0 ; Characteristics
77EB4230 dd 41B04DB0h ; TimeDateStamp
77EB4230 dw 0 ; MajorVersion
77EB4230 dw 0 ; MinorVersion
77EB4230 dd offset NameStrBase ; Name
77EB4230 dd 1 ; Base
77EB4230 dd 33Dh ; NumberOfFunctions
77EB4230 dd 33Dh ; NumberOfNames
77EB4230 dd offset AddressOfFunctionsBase ; AddressOfFunctions
77EB4230 dd offset AddressOfNamesBase ; AddressOfNames
77EB4230 dd offset AddressOfNameOrdinalsBase ; AddressOfNameOrdinals
......
......
77EB8DC4 aRequestdevicew db 'RequestDeviceWakeup',0
77EB8DD8 aRequestwakeupl db 'RequestWakeupLatency',0
77EB8DED aResetevent db 'ResetEvent',0
77EB8DF8 aResetwritewatc db 'ResetWriteWatch',0
77EB8E08 aResumethread db 'ResumeThread',0
77EB8E15 aRtlfillmemory db 'RtlFillMemory',0
77EB8E23 RtlFillMemory db 'NTDLL.RtlFillMemory',0
77EB8E37 aRtlmovememory db 'RtlMoveMemory',0
77EB8E45 RtlMoveMemory db 'NTDLL.RtlMoveMemory',0
77EB8E59 aRtlunwind db 'RtlUnwind',0
77EB8E63 RtlUnwind db 'NTDLL.RtlUnwind',0
77EB8E73 aRtlzeromemory db 'RtlZeroMemory',0
77EB8E81 RtlZeroMemory db 'NTDLL.RtlZeroMemory',0
77EB8E95 aScrollconsoles db 'ScrollConsoleScreenBufferA',0
77EB8EB0 aScrollconsol_0 db 'ScrollConsoleScreenBufferW',0
77EB8ECB aSearchpatha db 'SearchPathA',0
......
......
GetDllBase proc uses ecx edx esi lpProcName:DWORD
;mov eax, large fs:18h
xor eax, eax
; masm32 在编译普通exe文件时,不支持 mov eax, fs:[18] 指令
; 因此写成如下格式,编译后等同 mov eax, fs:[18]
db 64h
mov eax, ds:18h ; TEB.Self
mov eax, [eax].TEB.Peb ; 取 PEB 表的地址
mov eax, [eax].PEB.Ldr ; 取 PEB_LDR_DATA 结构的地址
; PEB_LDR_DATA.InLoadOrderModuleList.Flink 指向 LDR_DATA_TABLE_ENTRY
add eax, PEB_LDR_DATA.InLoadOrderModuleList.Flink
; 这个结构形成一个链表
mov ecx, [eax].LDR_DATA_TABLE_ENTRY.InLoadOrderModuleList.Flink
Loop_SeachModule:
cmp ecx, eax
jz Exit
mov edx, ecx
; 获取下一个 LDR_DATA_TABLE_ENTRY 结构的地址
mov ecx, [ecx].LDR_DATA_TABLE_ENTRY.InLoadOrderModuleList.Flink
; 比较该内存地址是否为空,如果是,则出错
cmp [edx].LDR_DATA_TABLE_ENTRY.InMemoryOrderModuleList.Flink, 0
jz Loop_SeachModule
; 获取模块名的地址
lea esi, [edx].LDR_DATA_TABLE_ENTRY.BaseDllName.UNICODE_STRING.woLength
push eax
; 验证是否是我们需要的模块
invoke ComparAnsiStrUnicodeStr, lpProcName, esi
cmp eax, 1
pop eax
jnz Loop_SeachModule
; 如果是,取该模块的基地址
mov eax, [edx].LDR_DATA_TABLE_ENTRY.DllBase
jmp Exit1
Exit:
xor eax, eax
Exit1:
ret
GetDllBase endp
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: