使用汇编取得PE文件导入的DLL名称和函数名称

小弟我原是C程序,最近迷上汇编,先拿PE文件做练手,写了一段程序,用于PE文件入的DLL以及相函数信息,有不足之处请指教。

的解 释请 参考代 中的相 。(不要骂我懒,其实我不忙。)
 
; 小弟用的是 RadASM2.2.1.1+ masm32 进行编辑和编译
; 感谢 Iczelion 提供如此详尽的 PE 文件讲解。
.386
.model flat,stdcall
include /masm32/include/windows.inc
include /masm32/include/user32.inc
include /masm32/include/kernel32.inc
include /masm32/include/comdlg32.inc
 
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/comdlg32.lib
 
ERROR_INFO_LEN equ             1024
 
MyMain proto :DWORD, :DWORD
RVAToOffset proto dwMapAddr:DWORD, dwRVA:DWORD
 
.data
        dwRet                   DWORD                   0
        hFile                     HANDLE                  INVALID_HANDLE_VALUE
        hFileMap               HANDLE                  0
        lpMapAddr             LPVOID                   0
        szErrorInfo             db                           "This file is a not PE file", 0
        szSuccessInfo       db                           "This file is a PE file", 0
        szHInfo                  db                          "PE info", 0
        wVirtualAddress      DWORD                   0
 
        ofn                        OPENFILENAME        <>
        FilterString            db                      "Executable Files (*.exe, *.dll)",0,"*.exe;*.dll",0
                                    db                      "All Files",0,"*.*",0,0
        szFormatStr           db                      "%d(0x%08X)",0
        szStrFormatStr       db                      "%s", 0DH, 0AH, 0
       szNameBuf             db                      ERROR_INFO_LEN dup (0)
        szSectionFormatInfo      db                  "SectionName = %s V.Size = %d V.Address = 0x%08X Raw Size = %d Raw Offset = 0x%08X Characteristics = 0x%08X", 0
   
.data?
        hModelIns               HINSTANCE                ?
        szCommLine           LPSTR                        ?
        buffer                     db                                512 dup(?)
        szOutInfo               BYTE                           ERROR_INFO_LEN dup(0)
 
.code
My_Start_Lable:
        invoke GetModuleHandle,NULL
        mov hModelIns, eax
       
        invoke GetCommandLine
        mov szCommLine, eax
       
        invoke MyMain, hModelIns, szCommLine
        mov dwRet, eax
        invoke ExitProcess, 0
 
; 自定义入口函数
MyMain proc hInst:HINSTANCE, CmdLine:LPSTR
       
        ; 定义临时变量
        LOCAL bRet[1]:BYTE
        LOCAL wSecCon:WORD
        LOCAL wSecConTem:WORD
        LOCAL szAddr:DWORD
        LOCAL dwFunCon:DWORD
       
        mov bRet, 0
        mov wSecCon, 0
        mov wSecConTem, 0
        mov szAddr, 0
        mov dwFunCon, 0
       
        mov ofn.lStructSize,SIZEOF ofn
        mov ofn.lpstrFilter, OFFSET FilterString
        mov ofn.lpstrFile, OFFSET buffer
        mov ofn.nMaxFile,512
        mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY
        ; 使用打开对话框打开一个 PE 文件
        invoke GetOpenFileName, ADDR ofn
        ; 打开指定的 PE 文件,为之后的内存映射做准备
        invoke CreateFile, ADDR buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
        ; 返回值判断(是不是只要是 WindowsAPI ,函数的返回值都使用 eax ?请大虾指教)
        mov hFile, eax
       
        .if hFile == INVALID_HANDLE_VALUE
                jmp END_MyMain
        .endif
        ; 创建内存映射
        invoke CreateFileMapping, hFile, NULL, PAGE_READONLY, 0, 0, NULL
        mov hFileMap, eax
       
        .if hFileMap == 0
                jmp END_MyMain
        .endif
       
        invoke MapViewOfFile, hFileMap, FILE_MAP_READ, 0, 0, 0
        mov lpMapAddr, eax
       
        mov edi, lpMapAddr
        assume edi:ptr IMAGE_DOS_HEADER
        ; 判断 DOS 头的合法性
        .if [edi].e_magic != IMAGE_DOS_SIGNATURE
                jmp END_MyMain
        .endif
       
        add edi, [edi].e_lfanew
        assume edi:ptr IMAGE_NT_HEADERS
        ; 判断 PE 文件的合法性
        .if [edi].Signature != IMAGE_NT_SIGNATURE
                jmp END_MyMain
        .endif
       
        mov dx, [edi].FileHeader.NumberOfSections
        mov wSecCon, dx
       
        invoke wsprintf, addr szOutInfo, addr szFormatStr, wSecCon, wSecCon
        ; 定位到节表
        add edi, sizeof IMAGE_NT_HEADERS       
        mov esi, edi
        assume esi:ptr IMAGE_SECTION_HEADER
       
        mov dx, wSecCon
        mov wSecConTem, dx
; 取得节表信息
get_section_info:
       
        invoke RtlZeroMemory, addr szOutInfo, sizeof szOutInfo
       
        invoke wsprintf, addr szOutInfo, addr szSectionFormatInfo, addr [esi].Name1, [esi].Misc.VirtualSize, [esi].VirtualAddress, [esi].SizeOfRawData, [esi].PointerToRawData, [esi].Characteristics
       
        add esi, sizeof IMAGE_SECTION_HEADER
        assume esi:ptr IMAGE_SECTION_HEADER
       
        DEC wSecConTem
        .if wSecConTem > 0
                jmp get_section_info
        .endif
       
; 取得导入的 DLL 信息
        mov edi, lpMapAddr
        assume edi:ptr IMAGE_DOS_HEADER
        add edi, [edi].e_lfanew
        assume edi:ptr IMAGE_NT_HEADERS
        add edi, sizeof IMAGE_NT_HEADERS
        sub edi, sizeof IMAGE_DATA_DIRECTORY * 15
        assume edi:ptr IMAGE_DATA_DIRECTORY
 
        invoke RVAToOffset, lpMapAddr, [edi].VirtualAddress
        .if eax == 0
                jmp END_MyMain
        .endif
       
        mov edi, eax
        add edi, lpMapAddr
        assume edi:ptr IMAGE_IMPORT_DESCRIPTOR
       
OUTPUT_IMPORT_INFO_BEGIN:
        mov esi, [edi].OriginalFirstThunk
        .if [edi].OriginalFirstThunk == 0
                .if [edi].FirstThunk == 0
                        jmp OUTPUT_IMPORT_INFO_END                     
                .endif
                mov esi, [edi].FirstThunk
        .endif
        ; 取得当前导入的 DLL 名称
        invoke RtlZeroMemory, addr szOutInfo, sizeof szOutInfo
        invoke RVAToOffset, lpMapAddr, [edi].Name1
        add eax, lpMapAddr
        invoke wsprintf, addr szOutInfo, addr szStrFormatStr, eax
 
        invoke RVAToOffset, lpMapAddr, esi
        mov esi, eax
        add esi, lpMapAddr
; 取得当前 DLL 所有导入的函数名称
GET_FUNCTIOM_BEGIN:
        .if dword ptr [esi] == NULL
                jmp GET_FUNCTIOM_END
        .endif
       
        invoke RVAToOffset, lpMapAddr, dword ptr[esi]
        add eax, lpMapAddr
        mov szAddr, eax
 
        invoke RtlZeroMemory, addr szNameBuf, sizeof szNameBuf
        mov edx, szAddr
        assume edx:ptr IMAGE_IMPORT_BY_NAME
        invoke wsprintf, addr szNameBuf, addr szStrFormatStr, addr [edx].Name1
        invoke lstrcat, addr szOutInfo, addr szNameBuf
       
        add esi, sizeof IMAGE_THUNK_DATA
        jmp GET_FUNCTIOM_BEGIN
GET_FUNCTIOM_END:
 
        invoke MessageBox, NULL, addr szOutInfo, addr szHInfo, MB_OK
 
        add edi, sizeof IMAGE_IMPORT_DESCRIPTOR
        jmp OUTPUT_IMPORT_INFO_BEGIN
OUTPUT_IMPORT_INFO_END:
        ; 显示当前 DLL 和函数名称
        invoke MessageBox, NULL, addr szOutInfo, addr szHInfo, MB_OK
 
        mov bRet, TRUE 
       
        invoke MessageBox, NULL, addr szSuccessInfo, addr szHInfo, MB_OK
END_MyMain:
       
        .if bRet != TRUE
                invoke GetLastError
                invoke MessageBox, NULL, addr szErrorInfo, addr szHInfo, MB_OK
        .endif
 
        .if hFile != INVALID_HANDLE_VALUE
                invoke CloseHandle, hFile
                mov hFile, INVALID_HANDLE_VALUE
        .endif
       
        .if hFileMap != 0
                .if lpMapAddr != 0
                        invoke UnmapViewOfFile, lpMapAddr
                        mov lpMapAddr, 0
                .endif
               
                invoke CloseHandle, hFileMap
                mov hFileMap, 0
        .endif
       
        ret
MyMain endp
 
; 此函数将相对虚拟地址( RVA )转换为文件偏移
RVAToOffset PROC dwMapAddr:DWORD, dwRVA:DWORD
        xor eax, eax
        xor ebx, ebx
        xor ecx, ecx
        xor edx, edx
       
        mov ebx, dwMapAddr
        assume ebx:ptr IMAGE_DOS_HEADER
        add ebx, [ebx].e_lfanew
        assume ebx:ptr IMAGE_NT_HEADERS
        mov cx, [ebx].FileHeader.NumberOfSections
        add ebx, sizeof IMAGE_NT_HEADERS
       
        mov edx, dwRVA
       
SET_RVA:
        assume ebx:ptr IMAGE_SECTION_HEADER
       
        .if edx >= [ebx].VirtualAddress
                mov eax, [ebx].VirtualAddress
                add eax, [ebx].SizeOfRawData
                .if edx < eax
                        mov eax, [ebx].VirtualAddress
                        sub edx, eax
                        add edx, [ebx].PointerToRawData
                        mov eax, edx
                        ret
                .endif
        .endif
        add ebx, sizeof IMAGE_SECTION_HEADER
        loop SET_RVA
        mov eax, 0
        ret
RVAToOffset endp
 
end My_Start_Lable
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值