extremecoders-re / pyinstxtractor

PyInstaller Extractor
GNU General Public License v3.0
2.82k stars 604 forks source link

problem when finding cookie pos #23

Closed baosj0 closed 3 years ago

baosj0 commented 3 years ago

it should be like this, not a fixed pos. search_end should be start of signature info or file end.

bootloader code: pyi_archive.c
static int
pyi_arch_find_cookie(ARCHIVE_STATUS *status, int search_end)
{
    int search_start = search_end - SEARCH_SIZE;
    char buf[SEARCH_SIZE];
    char * search_ptr = buf + SEARCH_SIZE - sizeof(COOKIE);

    if (fseek(status->fp, search_start, SEEK_SET)) {
        return -1;
    }

    /* Read the entire search space */
    if (fread(buf, SEARCH_SIZE, 1, status->fp) < 1) {
        return -1;
    }

    /* Search for MAGIC within search space */

    while(search_ptr >= buf) {
        if(0 == strncmp(MAGIC, search_ptr, strlen(MAGIC))) {
            /* MAGIC found - Copy COOKIE to status->cookie */
            memcpy(&status->cookie, search_ptr, sizeof(COOKIE));

            /* From the cookie, calculate the archive start */
            status->pkgstart = search_start + sizeof(COOKIE) + (search_ptr - buf) - ntohl(status->cookie.len);

            return 0;
        }
        search_ptr--;
    }

    return -1;
}

your scripts may fail due to several tailing junk bytes while bootloader still works.

extremecoders-re commented 3 years ago

It uses a fixed position to locate the cookie as older versions of PyInstaller does so.

From: https://github.com/pyinstaller/pyinstaller/blob/39b02fe5e7563431115f9812f757a21bbcc78837/bootloader/common/pyi_archive.c#L174-L186

static int pyi_arch_check_cookie(ARCHIVE_STATUS *status, int filelen)
{
    if (fseek(status->fp, filelen-(int)sizeof(COOKIE), SEEK_SET))
        return -1;

    /* Read the Cookie, and check its MAGIC bytes */
    if (fread(&(status->cookie), sizeof(COOKIE), 1, status->fp) < 1)
        return -1;
    if (strncmp(status->cookie.magic, MAGIC, strlen(MAGIC)))
        return -1;

  return 0;
}

But modern versions of PyInstaller does search for the cookie instead of using a hardcoded position like your code snippet. Will update PyInstxtractor. Thanks for notifying!

baosj0 commented 3 years ago

in fact , there is searching action too. in your reply file: line 254~

    if (pyi_arch_check_cookie(status, filelen) < 0)
    {
        VS("LOADER: %s does not contain an embedded package\n", status->archivename);
#ifndef WIN32
    return -1;
#else
        filelen = findDigitalSignature(status);
        if (filelen < 1)
            return -1;
        /* The digital signature has been aligned to 8-bytes boundary.
           We need to look for our cookie taking into account some
           padding. */
        for (i = 0; i < 8; ++i)
        {
            if (pyi_arch_check_cookie(status, filelen) >= 0)
                break;
            --filelen;
        }
        if (i == 8)
        {
            VS("LOADER: %s does not contain an embedded package, even skipping the signature\n", status->archivename);
            return -1;
        }
        VS("LOADER: package found skipping digital signature in %s\n", status->archivename);
#endif
    }

it is a fixed pos when it's not for windows.

extremecoders-re commented 3 years ago

Resolved in latest commit. Feel free to reopen if this persists.