要获取一个文件的长度,我们可以使用API函数 GetFileSize()。
对于PE格式的文件,我们还可以利用PE文件头中的信息来获取文件长度,方法是:optional header中的 SizeOfHeaders值 + 所有节表中SizeOfRawData值 = 文件长度
PE文件格式说明可参考:Iczelion的PE教程
http://www.google.cn/search?complete=1&hl=zh-CN&newwindow=1&q=Iczelion%E7%9A%84PE%E6%95%99%E7%A8%8B&btnG=Google+%E6%90%9C%E7%B4%A2&meta=cr%3DcountryCN&aq=f
下面的代码也是在PE教程中的演示代码上修改而来。
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; FileName: FileSize.asm
; Function: Select a PE file and display it's size with it's PE file head info
; Author: Puple Endurer
;
; log
; -----------------------------------------------
; 2008-04-09 Created!
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.386
.model flat, stdcall
option casemap:none
include /masm32/include/windows.inc
include /masm32/include/kernel32.inc
include /masm32/include/comdlg32.inc
include /masm32/include/user32.inc
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/comdlg32.lib
d_UseSEH equ 0
SEH struct
PrevLink dd ? ; the address of the previous seh structure
CurrentHandler dd ? ; the address of the exception handler
SafeOffset dd ? ; The offset where it's safe to continue execution
PrevEsp dd ? ; the old value in esp
PrevEbp dd ? ; The old value in ebp
SEH ends
GetPeFileSize proto :LPSTR
IsPeFileMap proto :DWORD
CountSectionSize proto :dword, :dword
CountPeFileSize proto :HANDLE
.data
g_szAppName db "PE File Size", 0
g_stOfn OPENFILENAME <>
g_szFilterString db "*.exe, *.dll", 0, "*.exe;*.dll", 0
db "*.*", 0, "*.*", 0, 0
g_szFileOpenError db "未能打开文件以读", 0
g_szFileOpenMappingError db "未能打开文件用于内存映射", 0
g_szFileMappingError db "未能映射文件到内存", 0
g_szFileInValidPE db "非"
g_szFileValidPE db "有效PE文件", 0
g_szTmpFileSize db "文件长度为 %d 字节", 0
;.data?
g_buffer512 db 512 dup(?)
g_dwValidPE dd ?
.code
start proc
mov g_stOfn.lStructSize, SIZEOF g_stOfn
mov g_stOfn.lpstrFilter, OFFSET g_szFilterString
mov g_stOfn.lpstrFile, OFFSET g_buffer512
mov g_stOfn.nMaxFile, 512
mov g_stOfn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR g_stOfn
.if eax==TRUE
invoke GetPeFileSize, OFFSET g_buffer512
invoke MessageBox, 0, eax, addr g_szAppName, MB_OK
.endif
invoke ExitProcess, 0
start endp
GetPeFileSize proc lpszFileSpec: LPSTR
local hFile, hMapping, pMapping: dword
invoke CreateFile, lpszFileSpec, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
.if eax != INVALID_HANDLE_VALUE
mov hFile, eax
invoke CreateFileMapping, hFile, NULL, PAGE_READONLY, 0, 0, 0
.if eax != NULL
mov hMapping, eax
invoke MapViewOfFile, hMapping, FILE_MAP_READ, 0, 0, 0
.if eax != NULL
mov pMapping, eax
invoke IsPeFileMap, eax
.if g_dwValidPE==TRUE
invoke CountPeFileSize, pMapping
invoke wsprintf, addr g_buffer512, addr g_szTmpFileSize, eax
;invoke MessageBox, NULL, addr g_buffer512, addr g_buffer512, NULL
push offset g_buffer512 ;g_szFileValidPE
.else
push offset g_szFileInValidPE
.endif
.else
push offset g_szFileMappingError
.endif
invoke CloseHandle, hMapping
.else
push offset g_szFileOpenMappingError
.endif
invoke CloseHandle, hFile
pop eax
.else
mov eax, offset g_szFileOpenError
.endif
ret
GetPeFileSize endp
IsPeFileMap proc pMapping: DWORD
if d_UseSEH eq 1
local seh: SEH
endif ; d_UseSEH
mov g_dwValidPE, FALSE
mov edi, pMapping
if d_UseSEH eq 1
assume fs:nothing
push fs:[0]
pop seh.PrevLink
mov seh.CurrentHandler, offset SEHHandler
mov seh.SafeOffset, offset FinalExit
lea eax, seh
mov fs:[0], eax
mov seh.PrevEsp, esp
mov seh.PrevEbp, ebp
endif ; d_UseSEH
assume edi: ptr IMAGE_DOS_HEADER
.if [edi].e_magic==IMAGE_DOS_SIGNATURE
add edi, (IMAGE_DOS_HEADER ptr [edi]).e_lfanew ;add edi, [edi].e_lfanew
assume edi:ptr IMAGE_NT_HEADERS
.if [edi].Signature==IMAGE_NT_SIGNATURE
mov g_dwValidPE, TRUE
.endif
.endif
FinalExit:
ret
IsPeFileMap endp
; Input: dwNumberOfSections -- number of sections
; pSectionTabBeginAddr -- the begion address of the first section table
; Output: eax = all sections size
CountSectionSize proc dwNumberOfSections: dword, pSectionTabBeginAddr: dword
mov edi, dwNumberOfSections
mov esi, pSectionTabBeginAddr
xor eax, eax
.while (edi > 0)
add eax, (IMAGE_SECTION_HEADER ptr [esi]).SizeOfRawData
dec edi
add esi, sizeof IMAGE_SECTION_HEADER
.endw
ret
CountSectionSize endp
; Input: pMapping--the pointer to pe file mapping
; Output: eax = file size
CountPeFileSize proc pMapping: HANDLE
mov edi, pMapping
add edi, (IMAGE_DOS_HEADER ptr [edi]).e_lfanew
movzx eax, (IMAGE_NT_HEADERS ptr [edi]).FileHeader.NumberOfSections
test eax, eax
.if !ZERO?
push edi
add edi, sizeof IMAGE_NT_HEADERS
invoke CountSectionSize, eax, edi
pop edi
.endif
add eax, (IMAGE_NT_HEADERS ptr [edi]).OptionalHeader.SizeOfHeaders
ret
CountPeFileSize endp
if d_UseSEH eq 1
SEHHandler proc uses edx pExcept:DWORD, pFrame:DWORD, pContext:DWORD, pDispatch:DWORD
mov edx, pFrame
assume edx:ptr SEH
mov eax, pContext
assume eax:ptr CONTEXT
push [edx].SafeOffset
pop [eax].regEip
push [edx].PrevEsp
pop [eax].regEsp
push [edx].PrevEbp
pop [eax].regEbp
mov g_dwValidPE, FALSE
mov eax, ExceptionContinueExecution
ret
SEHHandler endp
endif ;d_UseSEH
end
start