要获取一个文件的长度,我们可以使用API函数 GetFileSize()。
对于PE格式的文件,我们还可以利用PE文件头中的信息来获取文件长度,方法是:optional header中的 SizeOfHeaders值 + 所有节表中SizeOfRawData值 = 文件长度
PE文件格式说明可参考:Iczelion的PE教程
下面的代码也是在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