ICZelion PE TUTCN7

zhaozj2021-02-11  252

PE Tutorial 7: Export Table (Export Table)

The last lesson we have learned that the dynamic join is about the knowledge of the table, and now there is another part, that is, the introduction table.

theory:

When the PE loader performs a program, it puts the associated DLLs into the address space of the process. Then find the real function address in the related dlls to correct the main program according to the introduction function information of the main program. The PE loader searches for the extraction functions in DLLs.

DLL / EXE To take a function to use other DLL / EXEs, there are two implementation methods: through the function name or only by the number of orders. For example, a DLL is to be a function named "getsysconfig", if it is introduced by a function name, then other DLLS / EXES must call this function, it must pass the function name, it is getSysconfig. Another way is to lead the order. What is the number of orders? The number is the only 16-digit number that specifies a function in the DLL, which is unique in the DLL pointed to. For example, in the above example, the DLL can select by the number of sequences, assuming is 16, then other DLLS / EXES must call this function to call parameters as getProcAddress in this value. This is the so-called order only.

We do not advocate only the method of leading the function, which will bring problems on DLL maintenance. Once the DLL upgrade / modification, the programmer cannot change the number of functions, otherwise calling the DLL will not work.

Now let's start learning to lead the structure. Like the introduction table, you can find the location of the extracted table through the data directory. Here, the extraction table is the first member of the data directory, but also as image_export_directory. There are 11 members in this structure, commonly used in the table below.

The true name of the Field NamemeningNAME module. The domain is required because the file name may change. In this case, the PE loader will use this internal name. The NBase base, plus the number of orders is the index value of the function address array. The total number of functions / symbols taken by the NumberOffunctions module. NumberOfNames numbers passing through the names of the name. This value is not the total number of functions / symbols arising from the module, which is given by NumberOffunctions above. The domain can be 0, indicating that the module may only be drawn by the number. If the module does not bring any function / symbols at all, the RVA of the data directory is 0. A RVAS array pointing to all functions / symbols in the AddressOffunctions module, the domain is to point to the RVA array. In short, all functions of all functions in the module are saved in an array, and the domain points to the first address of this array. AddressOfNames Similar to the previous domain, there is a RVAS array pointing to all function names, which is to point to the RVAs array. AddressOfNameRDINALSRVA, pointing to 16-bit arrays that contain the number of related functions in the above addressOfNames array.

The above may not be able to fully understand the table, the following brief introduction will help you.

The design of the table is designed to facilitate the PE loader. First, the module must save all the addresses of the extracted function for the PE loader query. The module saves this information in the array pointing to the AddressOffunctions domain, and the number of array elements is stored in the NumberOffunctions domain. Therefore, if the module leads to 40 functions, addressoffunctions points to the array must have 40 elements, while the NumberOffunctions value is 40. Now if some functions are introduced through the name, the module must also retain this information in the file. The RVAs of these names are stored in a population for the PE loader query. The array is directed by addressofNames, and NumberOfNames contains the number of names. Consider the working mechanism of the PE loader, it knows the function name and wants to get the address of these functions. So far, modules have two modules: name arrays and address arrays, but there is no contact between the two. So we also need some contact function names and its address of Dongdong. The PE reference indicates the index of the address array as a join, so the PE loader finds the matching name in the name array, it also acquires an index of the corresponding elements in the address table. These indexes are stored in another array (last) that is pointed to by the AddressOfNameRDinals domain. Since the array is a function of contacting the name and address, the number of elements must be the same as the name number, for example, there is only one related address, which is not necessarily: each address can have several names. Congratulations. So we give the same address "alias". In order to connect, the name array and index array must be used in parallel, for example, the first element of the index array must contain the index of the first name, and so on. AddressOfnames AddressOfNameRDINALS |

RVA of Name 1RVA of Name 2RVA of Name 3RVA of Name 4 ... RVA of Name N

<-> <-> <-> <-> ... <->

Index of Name 1Index of name 2Index of name 3index of name 4 ... index of name n

Next, one or two examples have explained the problem. If we have an introduction function name and want to get the address here, you can do this:

Positioned to Pe Header. Read the virtual address from the data directory read. Location extraction table acquires the number of names (NUMBEROFNAMES). Parallel Traversing the array matching name points to AddressOfNames and AddressOfNameordinals. If you find a matching name in the array pointing to AddressOfNames, extract the index value from the array points to AddressOfNameRDINALS. For example, if the RVA of the matching name is found to store the 77th element of the AddressOfNames array, the 77 elements of the AddressOfNameRinal array are extracted as the index value. If you traverse the NumberOfNames elements, you have no name you want. The value extracted from the AddressOfNameRDinals array as an index of the Addressoffunctions array. That is, if the value is 5, you must read the fifth element of the AddressOffunctions array, this value is RVA to be function.

Now we turn attention to the NBase member of the image_export_directory structure. You already know the AddressOffunctions array contains the address of all extraction symbols in the module. When the PE loader indexs the array query function address, let us imagine such a situation if the programmer sets the starting number number 200 in the .def file, which means that at least 200 elements of the Addressoffunctions array, even this As far as 200 elements are not used, they must exist because the PE loader can index the correct address. This method is very bad, so I designated the NBASE domain to solve this problem. If the programmer specifies that the starting number is 200, the NBase value is 200. When the PE loader reads the NBase domain, it knows that the start of 200 elements do not exist, which can correctly index the AddressOffunctions array after the NBase value is reduced. With NBASE, saving 200 empty elements. Note NBase does not affect the value of the AddressOfNameRDinals array. Although "AddressOfNameOrDinals" is named, the array actually contains an index of the addressoffunctions array, not what is the number.

The role of NBASE is discussed, we continue to come to the next example. Suppose we only have the order of the function, so how to get the function address, you can do this:

Positioned to Pe Header. Read the virtual address from the data directory read. The positioning extraction table acquires the NBase value. The NBase value is reduced to point to the index of the AddressOffunctions array. Comparing this value with NumberOffunctions, it is not equal to the latter. The RVA in the AddressOffunctions array can be obtained by the above index.

It can be seen that the function address is easier than the function name. There are no need to traverse AddressOfNames and AddressOfNameordinals two arrays. However, comprehensive performance must be balanced with the simple extent of module maintenance.

In short, if you want to get the function address through the name, you need to traverse AddressOfNames and AddressOfNameOrDinals two arrays. If you use a function order, you can directly index the AddressOffunctions array after you lose the NBase value.

If a function is taken out by name, the name or order can be used in GetProcAddress. But what is the function of the function only? Take a look now. "A function is only used by the order" means that the function does not have a related item in the addressofNames and AddressOfNameRinal arrays. Remember two domains, numberoffunctions and numberofnames. These two domains can clearly show sometimes some functions have no name. The number of functions is at least the number of names, and there is no name of the function by the number. For example, if there are 70 functions but only 40 in the AddressOfNames array, this means that 30 functions in the module are only led by the number. Now how do we find functions that are introduced only by the order? This is not easy, such as the exclusion method, such as the array items of Addressoffunctions do not have correlation points in the addressofNameRinal array, indicating that the function RVA is only drawn only by the number.

Example:

This example is similar to an example of class. However, while displaying some member information of Image_export_Directory structure, RVAs, orders, and names of the lead function are listed. Note This example does not list functions taken only by the number of orders.

.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 IDD_MAINDLG equ 101 IDC_EDIT equ 1000 IDM_OPEN equ 40001 IDM_EXIT equ 40003 DlgProc proto: DWORD,: DWORD,: DWORD,: DWORD ShowExportFunctions Proto: DWORD Showthefunctions Proto: DWORD,: DWORD APPENDTEXT Proto: DWORD,: DWORD

SEH struct PrevLink dd? CurrentHandler dd? SafeOffset dd? PrevEsp dd? PrevEbp dd? SEH ends .data AppName db "PE tutorial no.7", 0 ofn OPENFILENAME <> FilterString db "Executable Files (* .exe, * .dll) ", 0," *. EXE; *. DLL ", 0 DB" All Files ", 0," *. * ", 0, 0 FileOpenenError DB" Cannot Open THE FILE, 0 FileOpenMappingerRor DB "Cannot Open THE File for membort mapping ", 0 Filemappinger DB" Cannot Map The File Into Memory ", 0 NOTVALIDPE DB" this file is not a valid pe ", 0 NoExportTable DB" no export information in this file ", 0 CRLF DB 0DH, 0AH, 0 ExportTable DB 0DH, 0AH, "====== [image_export_directory] =======", 0DH, 0AH DB "Name of the module:% s", 0DH, 0AH DB "NBASE:% Lu", 0DH, 0AH DB "Numberoffunctions:% Lu", 0DH, 0AH DB "NumberOfnames:% Lu", 0DH, 0AH DB "Addressoffunctions:% lx", 0DH, 0AH DB "AddressOfnames:% lx", 0DH, 0AH DB "AddressOfnameRINALS :% lx ", 0DH, 0AH, 0 Header DB" RVA Ord. Name ", 0DH, 0AH DB "--------------------------------------------", 0 Template DB "% LX% U% S", 0 .data? Buffer DB 512 DUP (?) HFFER DD? HMApping DD? PMApping DD? Validpe Dd? .Code Start: Invoke GetModuleHandle, Null Invoke Dialogboxparam, Eax, IDD_MAINDLG, NULL, addr DlgProc, 0 invoke ExitProcess, 0 DlgProc proc hDlg: DWORD, uMsg: DWORD, wParam: DWORD, lParam: DWORD .if uMsg == WM_INITDIALOG invoke SendDlgItemMessage, hDlg, IDC_EDIT, EM_SETLIMITTEXT, 0,0 .elseif uMsg == WM_Close Invoke Enddialog, HDLG, 0 .ELSEIF UMSG =

= WM_COMMAND .if lParam == 0 mov eax, wParam .if ax == IDM_OPEN invoke ShowExportFunctions, hDlg .else; IDM_EXIT invoke SendMessage, hDlg, WM_CLOSE, 0,0 .endif .endif .else mov eax, FALSE ret .endif mov eax, TRUE ret DlgProc endp 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 ValidPE, FALSE mov eax, ExceptionContinueExecution ret SEHHandler endp ShowExportFunctions proc uses edi hDlg: DWORD LOCAL seh: sEH 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 invoke GetOpenFileName, ADDR ofn .if eax == True Invoke Createfile, AddR Buffer, Generic_Read, Fi LE_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 associum 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 MOV EDI, PMAPPING Assume EDI: Ptr Image_dos_Header .IF [EDI] .e_magic ==

IMAGE_DOS_SIGNATURE add edi, [edi] .e_lfanew assume edi: ptr IMAGE_NT_HEADERS .if [edi] .Signature == IMAGE_NT_SIGNATURE mov ValidPE, TRUE .else mov ValidPE, FALSE .endif .else mov ValidPE, FALSE .endif FinalExit: push seh.PrevLink pop fs: [0] .if ValidPE == TRUE invoke ShowTheFunctions, hDlg, edi .else invoke MessageBox, 0, addr NotValidPE, addr AppName, MB_OK MB_ICONERROR .endif invoke UnmapViewOfFile, pMapping .else invoke MessageBox, 0, addr FileMappingError, addr AppName, MB_OK MB_ICONERROR .endif invoke CloseHandle, hMapping .else invoke MessageBox, 0, addr FileOpenMappingError, addr AppName, MB_OK MB_ICONERROR .endif invoke CloseHandle, hFile .else invoke MessageBox, 0, addr FileOpenError, addr AppName, MB_OK MB_ICONERROR .endif.ndif rett showex portFunctions endp AppendText proc hDlg: DWORD, pText: DWORD invoke SendDlgItemMessage, hDlg, IDC_EDIT, EM_REPLACESEL, 0, pText invoke SendDlgItemMessage, hDlg, IDC_EDIT, EM_REPLACESEL, 0, addr CRLF invoke SendDlgItemMessage, hDlg, IDC_EDIT, EM_SETSEL, -1,0 ret AppendText endp RVAToFileMap PROC uses edi esi edx ecx pFileMap: DWORD, RVA: DWORD mov esi, pFileMap assume esi: ptr IMAGE_DOS_HEADER add esi, [esi] .e_lfanew assume esi: ptr IMAGE_NT_HEADERS mov edi, RVA; edi == RVA mov edx, ESI Add Edx, SizeOf Image_NT_HEADERS MOV CX, [ESI] .fileHeader.Numberofsections Movzx ECX, CX Assume Edx: Ptr Image_section_Header .While ECX> 0 .IF EDI> =

[edx] .virtualaddress MOV EAX, [EDX] .virtualAddress Add Eax, [EDX] .SizeOfrawData .IF EDI

Mov Eax, [EDX] .virtualAddress

Sub EDI, EAX

MOV EAX, [EDX] .pointertorawdata

Add Eax, EDI

Add Eax, Pfilemap

RET

.endif

.endif

Add Edx, SizeOf Image_SECTION_HEADER

Dec ECX

.endw

Assume Edx: Nothing

Assume ESI: Nothing

Mov Eax, EDI

RET

RVATOFILEMAP ENDP

Showthefunctions Proc Uses ESI ECX EBX HDLG: DWORD, PNTHDR: DWORD

Local Temp [512]: BYTE

Local NumberOfNames: DWORD

Local Base: DWORD

Mov Edi, PNTHDR

Assume EDI: PTR Image_NT_HEADERS

Mov Edi, [EDI] .optionalheader.DataDirectory.VirtualAddress

.IF EDI == 0

Invoke Messagebox, 0, Addr NoExportTable, Addr Appname, MB_OK MB_ICONERROR

RET

.endif

Invoke setdlgitemtext, hdlg, idc_edit, 0

Invoke AppendText, HDLG, AddR Buffer

Invoke rvatofilemap, pmapping, edi

Mov Edi, EAX

Assume EDI: PTR image_export_directory

MOV EAX, [EDI] .Numberoffunctions

Invoke rvatofilemap, pmapping, [edi] .nname

invoke wsprintf, addr temp, addr ExportTable, eax, [edi] .nBase, [edi] .NumberOfFunctions, [edi] .NumberOfNames, [edi] .AddressOfFunctions, [edi] .AddressOfNames, [edi] .AddressOfNameOrdinals

Invoke appendtext, hdlg, addr temp

Invoke appendtext, hdlg, addr header

Push [EDI] .NumberOfnames

Pop NumberOfnames

Push [EDI] .nbase

POP Base

Invoke rvatofilemap, pmapping, [edi] .addressofnames

Mov ESI, EAX

Invoke rvatofilemap, pmapping, [edi] .addressofnameordinals

MOV EBX, EAX

Invoke Ratofilemap, Pmapping, [EDI] .addressoffunctions

Mov Edi, EAX

.While NumberOfnames> 0

Invoke RVATOFILEMAP, PMAPPING, DWORD PTR [ESI]

MOV DX, [EBX]

Movzx EDX, DX

MOV ECX, EDX

SHL EDX, 2

Add Edx, EDI

Add Ecx, Base

Invoke WSPrintf, Addr Temp, Addr Template, DWORD PTR [EDX], ECX, EAX

Invoke appendtext, hdlg, addr temp

Dec numberofnamesadd ESI, 4

Add ebx, 2

.endw

RET

Showthefunctions Endp

End Start

analysis:

mov edi, pNTHdr assume edi: ptr IMAGE_NT_HEADERS mov edi, [edi] .OptionalHeader.DataDirectory.VirtualAddress .if edi == 0 invoke MessageBox, 0, addr NoExportTable, addr AppName, MB_OK MB_ICONERROR ret .endif

After the program is verified, it is positioned to the data directory acquisition of the virtual address. If the virtual address is 0, the file does not contain an extraction symbol.

mov eax, [edi] .NumberOfFunctions invoke RVAToFileMap, pMapping, [edi] .nName invoke wsprintf, addr temp, addr ExportTable, eax, [edi] .nBase, [edi] .NumberOfFunctions, [edi] .NumberOfNames, [edi] .Addressoffunctions, [edi] .addressofnames, [edi] .addressofnameordinals invoke appendtext, hdlg, Addr Temp

Show some important information about the image_export_directory structure in the editing control.

Push [EDI] .NumberOfnames Pop NumberOfNames Push [EDI] .nbase Pop Base

Because we have to enumerate all function names, you must know the number of names in the table. NBASE sent to the address when converting the AddressOffunctions array index.

invoke RVAToFileMap, pMapping, [edi] .AddressOfNames mov esi, eax invoke RVAToFileMap, pMapping, [edi] .AddressOfNameOrdinals mov ebx, eax invoke RVAToFileMap, pMapping, [edi] .AddressOfFunctions mov edi, eax

Store the address of the three arrays to ESI, EBX, EDI. Ready to start access.

.While NumberOfnames> 0

Until all the names were processed.

Invoke RVATOFILEMAP, PMAPPING, DWORD PTR [ESI]

Since ESI points to an array containing the name string RVAS, [ESI] contains the RVA of the current name, you need to convert it into a virtual address, which is used by WSPrintf.

MOV DX, [EBX] Movzx EDX, DX MOV ECX, EDX Add ECX, BASE

EBX points to the order array, the value is the word type. So let's first convert it into a double word. At this time, the EDX and ECX contain an index that points to the AddressOffunctions array. We use EDX as an index value, and add ECX to NBASE to get the order value of the function. =

SHL EDX, 2 Add Edx, EDI

The index takes 4 (each element in the addressoffunctions array is 4-byte size) and then adds a number of group head addresses so that EDX is the RVA of the desired function.

Invoke WSPrintf, Addr Temp, Addr Template, DWORD PTR [EDX], ECX, EAX Invoke AppendText, HDLG, Addr Temp

Display the RVA, order, and name of the function in the editing control.

Dec NumberOfnames Add ESI, 4 Add EBX, 2 .Endw Current Pointer, the current pointer of the ADDRESSOFNAMES, and AddressOfNameRDinals, continue to traverse until all the names are completed.

Translation: IAMGUFENG [ICZelion's Win32 Assembly Home] [Luoyunbin's Win32 ASM Page]

转载请注明原文地址:https://www.9cbs.com/read-4643.html

New Post(0)