cant's dlopen after protect dylib under macOS 10.13

Issues related to VMProtect
flowercodec
Posts: 8
Joined: Fri Aug 17, 2018 9:59 am

cant's dlopen after protect dylib under macOS 10.13

Postby flowercodec » Fri Aug 17, 2018 10:19 am

Hi,

dlopen error message: initializer 0x768FAB does not point within __TEXT segment
It works fine under macOS 10.12 and before, How to fix this problem.

Thanks.

Apple's dylib loading process is open source
dyld-519.2.2(macOS 10.13 using this version) download url:
https://opensource.apple.com/tarballs/d ... 2.2.tar.gz

I found the error code from its open source code, at dyld-519.2.2\dyld3\MachOParser.cpp:2485.
diag.error("initializer 0x%0llX does not point within __TEXT segment", anInit);

Code: Select all

void MachOParser::forEachInitializer(Diagnostics& diag, void (^callback)(uint32_t offset)) const
{
    __block uint64_t textSegAddrStart = 0;
    __block uint64_t textSegAddrEnd   = 0;

    forEachSegment(^(const char* segName, uint32_t fileOffset, uint32_t fileSize, uint64_t vmAddr, uint64_t vmSize, uint8_t protections, bool& stop) {
        if ( strcmp(segName, "__TEXT") == 0 ) {
            textSegAddrStart = vmAddr;
            textSegAddrEnd   = vmAddr + vmSize;
            stop = true;
        }
    });
    if ( textSegAddrStart == textSegAddrEnd ) {
        diag.error("no __TEXT segment");
        return;
    }

    // if dylib linked with -init linker option, that initializer is first
    forEachLoadCommand(diag, ^(const load_command* cmd, bool& stop) {
        if ( cmd->cmd == LC_ROUTINES ) {
            const routines_command* routines = (routines_command*)cmd;
            uint64_t dashInit = routines->init_address;
            if ( (textSegAddrStart < dashInit) && (dashInit < textSegAddrEnd) )
                callback((uint32_t)(dashInit - textSegAddrStart));
            else
                diag.error("-init does not point within __TEXT segment");
        }
        else if ( cmd->cmd == LC_ROUTINES_64 ) {
            const routines_command_64* routines = (routines_command_64*)cmd;
            uint64_t dashInit = routines->init_address;
            if ( (textSegAddrStart < dashInit) && (dashInit < textSegAddrEnd) )
                callback((uint32_t)(dashInit - textSegAddrStart));
            else
                diag.error("-init does not point within __TEXT segment");
        }
    });

    // next any function pointers in mod-init section
    bool p64 = is64();
    unsigned pointerSize = p64 ? 8 : 4;
    forEachSection(^(const char* segmentName, const char* sectionName, uint32_t flags, const void* content, size_t size, bool illegalSectionSize, bool& stop) {
        if ( (flags & SECTION_TYPE) == S_MOD_INIT_FUNC_POINTERS ) {
            if ( (size % pointerSize) != 0 ) {
                diag.error("initializer section %s/%s has bad size", segmentName, sectionName);
                stop = true;
                return;
            }
            if ( illegalSectionSize ) {
                diag.error("initializer section %s/%s extends beyond the end of the segment", segmentName, sectionName);
                stop = true;
                return;
            }
            if ( ((long)content % pointerSize) != 0 ) {
                diag.error("initializer section %s/%s is not pointer aligned", segmentName, sectionName);
                stop = true;
                return;
            }
            if ( p64 ) {
                const uint64_t* initsStart = (uint64_t*)content;
                const uint64_t* initsEnd   = (uint64_t*)((uint8_t*)content + size);
                for (const uint64_t* p=initsStart; p < initsEnd; ++p) {
                    uint64_t anInit = *p;
                    if ( (anInit <= textSegAddrStart) || (anInit > textSegAddrEnd) ) {
                         diag.error("initializer 0x%0llX does not point within __TEXT segment", anInit);// It's here!
                         stop = true;
                         break;
                    }
                    callback((uint32_t)(anInit - textSegAddrStart));
                }
            }
            else {
                const uint32_t* initsStart = (uint32_t*)content;
                const uint32_t* initsEnd   = (uint32_t*)((uint8_t*)content + size);
                for (const uint32_t* p=initsStart; p < initsEnd; ++p) {
                    uint32_t anInit = *p;
                    if ( (anInit <= textSegAddrStart) || (anInit > textSegAddrEnd) ) {
                         diag.error("initializer 0x%0X does not point within __TEXT segment", anInit);
                         stop = true;
                         break;
                    }
                    callback(anInit - (uint32_t)textSegAddrStart);
                }
            }
        }
    });
}

Admin
Site Admin
Posts: 1504
Joined: Mon Aug 21, 2006 8:19 pm
Location: Russia, E-burg
Contact:

Re: cant's dlopen after protect dylib under macOS 10.13

Postby Admin » Mon Aug 20, 2018 4:05 am

It seems Apple added new crap in the latest dyld :))

flowercodec
Posts: 8
Joined: Fri Aug 17, 2018 9:59 am

Re: cant's dlopen after protect dylib under macOS 10.13

Postby flowercodec » Tue Aug 21, 2018 3:29 am

Hi Admin,
after protect dylib, I find sectname __mod_init_func, segname __TEXT1.(not found before protect)
I think this should be the reason why dlopen gave an error.
Is it possible to manually call some initialization through the VMP SDK (a new feature).
Then we can bypass "the new crap".
Or is there any other way to solve this problem?

Thanks.

Code: Select all

otool -l my.dylib
Section
  sectname __mod_init_func
   segname __TEXT1
      addr 0x000000000078a850
      size 0x00000000000002f0
    offset 7895120
     align 2^2 (4)
    reloff 0
    nreloc 0
     flags 0x00000009
 reserved1 0
 reserved2 0

Admin
Site Admin
Posts: 1504
Joined: Mon Aug 21, 2006 8:19 pm
Location: Russia, E-burg
Contact:

Re: cant's dlopen after protect dylib under macOS 10.13

Postby Admin » Tue Sep 04, 2018 8:03 am

Please try the 1013 build.

flowercodec
Posts: 8
Joined: Fri Aug 17, 2018 9:59 am

Re: cant's dlopen after protect dylib under macOS 10.13

Postby flowercodec » Wed Sep 05, 2018 1:21 am

Admin wrote:Please try the 1013 build.


Hi Admin,

I instal 1013 build version. it seem to be another problem.
dlopen error message: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB pointer rebase is in executable segment

I search dylib source code again, found the error code. at dyld-519.2.2\dyld3\MachOParser.cpp:2612, funcation name is "invalidRebaseState"
diag.error("%s pointer rebase is in executable segment", opcodeName);
opcodeName is "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB"

Thanks.

flowercodec
Posts: 8
Joined: Fri Aug 17, 2018 9:59 am

Re: cant's dlopen after protect dylib under macOS 10.13

Postby flowercodec » Thu Sep 06, 2018 3:47 am

Admin wrote:Please try the 1013 build.

I want to send the binary to you, is it sent to info@vmpsoft.com ?

Admin
Site Admin
Posts: 1504
Joined: Mon Aug 21, 2006 8:19 pm
Location: Russia, E-burg
Contact:

Re: cant's dlopen after protect dylib under macOS 10.13

Postby Admin » Thu Nov 08, 2018 5:29 pm

Please try the 1028 build.

flowercodec
Posts: 8
Joined: Fri Aug 17, 2018 9:59 am

Re: cant's dlopen after protect dylib under macOS 10.13

Postby flowercodec » Sat Nov 10, 2018 7:42 am

Admin wrote:Please try the 1028 build.


1028 build works fine.
I also test it under macOS 10.14.1, works fine too!
Thanks.

Is 1028 build is a stable version? So I can use it for my release application.

Admin
Site Admin
Posts: 1504
Joined: Mon Aug 21, 2006 8:19 pm
Location: Russia, E-burg
Contact:

Re: cant's dlopen after protect dylib under macOS 10.13

Postby Admin » Sun Nov 25, 2018 3:09 pm

Yes, it's stable.