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

    技术2022-05-11  56

    小弟我原是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(0xX)",0         szStrFormatStr       db                      "%s", 0DH, 0AH, 0        szNameBuf             db                      ERROR_INFO_LEN dup (0)         szSectionFormatInfo      db                  "SectionName = %s V.Size = %d V.Address = 0xX Raw Size = %d Raw Offset = 0xX Characteristics = 0xX", 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)