github.com/saferwall/pe@v1.5.2/exports_test.go (about)

     1  // Copyright 2018 Saferwall. All rights reserved.
     2  // Use of this source code is governed by Apache v2 license
     3  // license that can be found in the LICENSE file.
     4  
     5  package pe
     6  
     7  import (
     8  	"testing"
     9  )
    10  
    11  type TestExport struct {
    12  	entryCount int
    13  	entryIndex int
    14  	name       string
    15  	imgExpDir  ImageExportDirectory
    16  	expFunc    ExportFunction
    17  }
    18  
    19  func TestExportDirectory(t *testing.T) {
    20  
    21  	tests := []struct {
    22  		in  string
    23  		out TestExport
    24  	}{
    25  		{
    26  			getAbsoluteFilePath("test/kernel32.dll"),
    27  			TestExport{
    28  				entryCount: 1633,
    29  				entryIndex: 0,
    30  				name:       "KERNEL32.dll",
    31  				imgExpDir: ImageExportDirectory{
    32  					TimeDateStamp:         0x38B369C4,
    33  					Name:                  0x0009E1D2,
    34  					Base:                  0x1,
    35  					NumberOfFunctions:     0x661,
    36  					NumberOfNames:         0x661,
    37  					AddressOfFunctions:    0x0009A208,
    38  					AddressOfNames:        0x0009BB8C,
    39  					AddressOfNameOrdinals: 0x0009D510,
    40  				},
    41  				expFunc: ExportFunction{
    42  					Ordinal:      0x1,
    43  					FunctionRVA:  0x0009E1F7,
    44  					NameRVA:      0x0009E1DF,
    45  					Name:         "AcquireSRWLockExclusive",
    46  					Forwarder:    "NTDLL.RtlAcquireSRWLockExclusive",
    47  					ForwarderRVA: 0x9CBF7,
    48  				},
    49  			},
    50  		},
    51  		{
    52  			getAbsoluteFilePath("test/mfc140u.dll"),
    53  			TestExport{
    54  				entryCount: 14103,
    55  				entryIndex: 0,
    56  				name:       "KERNEL32.dll",
    57  				imgExpDir: ImageExportDirectory{
    58  					TimeDateStamp:      0x5b8f7bca,
    59  					Name:               0x3e2e0c,
    60  					Base:               0x100,
    61  					NumberOfFunctions:  0x371d,
    62  					AddressOfFunctions: 0x3d5198,
    63  				},
    64  				expFunc: ExportFunction{
    65  					Ordinal:     0x100,
    66  					FunctionRVA: 0x275fa0,
    67  				},
    68  			},
    69  		},
    70  		// {
    71  		// 	// TODO: ThreadSanitizer failed to allocate 0x000048000000 (1207959552) in Github CI
    72  		// 	getAbsoluteFilePath("test/0b1d3d3664915577ab9a32188d29bbf3542b86c7b9ce333e245496c3018819f1"),
    73  		// 	TestExport{
    74  		// 		entryCount: 7728638,
    75  		// 		entryIndex: 0,
    76  		// 		name:       "",
    77  		// 		imgExpDir: ImageExportDirectory{
    78  		// 			Characteristics:       0xac0000,
    79  		// 			TimeDateStamp:         0xac0000,
    80  		// 			MinorVersion:          0xac,
    81  		// 			Name:                  0xac0000,
    82  		// 			Base:                  0xac0000,
    83  		// 			NumberOfFunctions:     0xac0000,
    84  		// 			NumberOfNames:         0xac0000,
    85  		// 			AddressOfFunctions:    0xac0000,
    86  		// 			AddressOfNames:        0xac0000,
    87  		// 			AddressOfNameOrdinals: 0xac0000,
    88  		// 		},
    89  		// 		expFunc: ExportFunction{
    90  		// 			Ordinal:     0xac0000,
    91  		// 			FunctionRVA: 0xac0000,
    92  		// 			NameRVA:     0xac0000,
    93  		// 		},
    94  		// 	},
    95  		// },
    96  	}
    97  
    98  	for _, tt := range tests {
    99  		t.Run(tt.in, func(t *testing.T) {
   100  			ops := Options{Fast: true}
   101  			file, err := New(tt.in, &ops)
   102  			if err != nil {
   103  				t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
   104  			}
   105  
   106  			err = file.Parse()
   107  			if err != nil {
   108  				t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err)
   109  			}
   110  
   111  			var va, size uint32
   112  
   113  			if file.Is64 {
   114  				oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
   115  				dirEntry := oh64.DataDirectory[ImageDirectoryEntryExport]
   116  				va = dirEntry.VirtualAddress
   117  				size = dirEntry.Size
   118  			} else {
   119  				oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
   120  				dirEntry := oh32.DataDirectory[ImageDirectoryEntryExport]
   121  				va = dirEntry.VirtualAddress
   122  				size = dirEntry.Size
   123  			}
   124  
   125  			err = file.parseExportDirectory(va, size)
   126  			if err != nil {
   127  				t.Fatalf("parseExportDirectory(%s) failed, reason: %v", tt.in, err)
   128  			}
   129  
   130  			export := file.Export
   131  			if len(export.Functions) != tt.out.entryCount {
   132  				t.Fatalf("export functions count assertion failed, got %v, want %v",
   133  					len(export.Functions), tt.out.entryCount)
   134  			}
   135  
   136  			imgExpDir := export.Struct
   137  			if imgExpDir != tt.out.imgExpDir {
   138  				t.Fatalf("image export directory assertion failed, got %v, want %v",
   139  					imgExpDir, tt.out.imgExpDir)
   140  			}
   141  
   142  			if len(export.Functions) > 0 {
   143  				expFunc := export.Functions[tt.out.entryIndex]
   144  				if expFunc != tt.out.expFunc {
   145  					t.Fatalf("export entry assertion failed, got %v, want %v", expFunc, tt.out.expFunc)
   146  				}
   147  			}
   148  		})
   149  	}
   150  }