MCPcopy Create free account
hub / github.com/Binject/universal / LoadLibraryDlopen

Function LoadLibraryDlopen

loader_darwin.go:164–298  ·  view source on GitHub ↗

LoadLibraryDlopen - loads a single library using dlopen and resolves all exported symbols using dlsym. This function writes to a temporary file and then loads the file into memory, and unlinks it. This is similar to what NSLinkModule does nowadays.

(name string, image *[]byte)

Source from the content-addressed store, hash-verified

162// file and then loads the file into memory, and unlinks it.
163// This is similar to what NSLinkModule does nowadays.
164func LoadLibraryDlopen(name string, image *[]byte) (*Library, error) {
165 var (
166 dlopenAddr uint64
167 dlSymAddr uint64
168 dyldAddress uint64
169 )
170
171 machoFile, err := macho.NewFile(bytes.NewReader(*image))
172 if err != nil {
173 return nil, err
174 }
175
176 // We use the shared library cache to find the libdyld.dylib wrapper loaded into our process.
177 // Once we have the address of the libdyld.dylib wrapper, we can parse it in memory using debug/macho (thanks Awgh)
178 // and find the exports we're interested in: dlopen and dlsym.
179 // This part of the code is a port from the awesome work of usiegl00: https://github.com/usiegl00/metasploit-framework/blob/osx-stage-monterey/external/source/shellcode/osx/stager/main.c#L159-L183
180 sharedRegionStart, err := syscallSharedRegionCheckNp()
181 if err != nil {
182 return nil, err
183 }
184 dyldCacheheader := (*DyldCacheHeader)(unsafe.Pointer(uintptr(sharedRegionStart)))
185
186 imagesCount := dyldCacheheader.ImagesCountOld
187 if imagesCount == 0 {
188 imagesCount = dyldCacheheader.ImagesCount
189 }
190 imagesOffset := dyldCacheheader.ImagesOffsetOld
191 if imagesOffset == 0 {
192 imagesOffset = dyldCacheheader.ImagesOffset
193 }
194 sharedFileMapping := (*SharedFileMapping)(unsafe.Pointer(uintptr(sharedRegionStart + uint64(dyldCacheheader.MappingOffset))))
195
196 dyldCacheImageInfo := (*DyldCacheImageInfo)(unsafe.Pointer(uintptr(sharedRegionStart + uint64(imagesOffset))))
197 for i := uint32(0); i < imagesCount; i++ {
198 pathFileOffset := sharedRegionStart + uint64(dyldCacheImageInfo.PathFileOffset)
199 dylibPath := readCString(pathFileOffset)
200 if dylibPath == LIB_DYLD_PATH {
201 dyldAddress = dyldCacheImageInfo.Address
202 break
203 }
204 dyldCacheImageInfo = (*DyldCacheImageInfo)(unsafe.Pointer(uintptr(sharedRegionStart+uint64(imagesOffset)) + uintptr(i)*unsafe.Sizeof(DyldCacheImageInfo{})))
205 }
206
207 offset := sharedRegionStart - sharedFileMapping.Address
208 dyldAddress += offset
209
210 rawr := rawreader.New(uintptr(dyldAddress), MaxInt)
211 dyldFile, err := macho.NewFileFromMemory(rawr)
212 if err != nil {
213 return nil, err
214 }
215 exports := dyldFile.Exports()
216
217 for _, export := range exports {
218 if export.Name == "_dlopen" {
219 dlopenAddr = export.VirtualAddress + offset
220 }
221 if export.Name == "_dlsym" {

Callers 1

LoadLibraryImplFunction · 0.85

Calls 4

readCStringFunction · 0.85
machoCodeSignFunction · 0.85
CallMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…