为什么我在 PKZIP 解密密钥验证中收到更多 256 误报?

问题描述 投票:0回答:1

我一直在尝试使用CRC的第一个字节和加密标头的最后一个字节来暴力破解ZipCryptoKey2,看看需要多长时间,但我得到了超过2000的有效密钥。 从APPNOTE中,Key2用于解密字节,Key2CRC32的结果,这意味着它是一个32位值,应该在21474836482147483648范围内找到*2.

此测试流的密码是

1234

CRC 是

77D7DCDE

然后直播:

50 4B 03 04 14 00 01 00 08 00 68 99 6D 58 DE DC D7 77 CB 82 07 00 0F B1 0A 00 09 00 00 00 6B 65 79 73 30 2E 74 78 74 50 3F 83 D5 C7 D4 69 6E 9B B9 E9 F2 DD 16 D5 EA 5B 41 F9 BC 59 6E 34 E8 2F 2B 49 4E DD 90 3E D8 65 5E 21 42 E6 8C 8C AD 8E

这是代码示例:

#ifdef LINUX

#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

typedef pthread_t thread;
typedef pthread_mutex_t mutex;

static inline void mutex_init(mutex *m)
{
    int res = pthread_mutex_init(m, NULL);
    assert(res == 0);
}

static inline void mutex_lock(mutex *m)
{
    int res = pthread_mutex_lock(m);
    assert(res == 0);
}

static inline void mutex_unlock(mutex *m)
{
    int res = pthread_mutex_unlock(m);
    assert(res == 0);
}

static thread spawn_thread(void *(f)(void *), void *arg)
{
    thread t;
    int res = pthread_create(&t, NULL, f, (void *)arg);
    if (res != 0)
        return (thread)NULL;
    return t;
}

static void join_thread(thread t)
{
    pthread_join(t, NULL);
}

static size_t num_threads(void)
{
    return (size_t)sysconf(_SC_NPROCESSORS_ONLN);
}


static uint64_t get_time(void)
{
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
}

#endif


unsigned char decrypt_byte(size_t Key2) {
    uint32_t dkey = Key2;
    unsigned short temp = dkey | 2;
    return (temp * (temp ^ 1)) >> 8;
}


static bool bytecheck(const unsigned char dat)
{
    unsigned char targ = 0x77;//first byte of my Checksum
    
    if(dat == targ)
       {
            return true;
        }
    return false;
}


struct info
{
    unsigned char buffer;
    size_t start;
    size_t end;
};

// Stop when a thread finds a solution.
static volatile bool stop = false;
static void *worker(void *arg);

static thread spawn_worker( size_t start, size_t end, unsigned char buffer)
{
    struct info *info = (struct info *)malloc(sizeof(struct info));
    assert(info != NULL);
    info->start = start;
    info->end = end;
    info->buffer = buffer;
    thread t = spawn_thread(worker, info);
    if (t == (thread)NULL)
    {
        fprintf(stderr, "error: failed to spawn thread");
        exit(EXIT_FAILURE);
    }
    return t;
}
static void *worker(void *arg)
{
    struct info *info = (struct info *)arg;
    size_t start = info->start;
    size_t end = info->end;
    unsigned char buf = info->buffer;
    free(info);
    for(size_t i =start; i < end+1; i++)
    {
        if (stop)
            return NULL;
        unsigned char res = decrypt_byte(i);
        unsigned char C = buf ^ res;

        if (bytecheck(C))
        {
            printf("%zu\n",i);
            stop = true;
            return NULL;
        }
    }

}

//gcc ben.c -pg --std=gnu99 -lz -lm -lpthread -o zipcr

int main()
{

    size_t NUM_WORKERS = num_threads();
    printf("threads = %lu\n", NUM_WORKERS);
    uint64_t t0 = get_time();
    size_t tap = 2147483648;
    size_t port = tap / NUM_WORKERS;
    thread ts[NUM_WORKERS];
    for (size_t i = 0; i < NUM_WORKERS; i++)
        {
            size_t start = tap+ (i*port);
            size_t end = start+port;
            unsigned char buffer = 0xF2;
            ts[i] = spawn_worker(start, end,buffer);
        }
        for (size_t i = 0; i < NUM_WORKERS; i++)
            join_thread(ts[i]);
    uint64_t t1 = get_time();
    printf("\ntime = %lums\n", t1 - t0);

return 0;
}

为什么我收到这么多误报,我的代码出了什么问题?

c deflate crc32 pkzip
1个回答
0
投票

所有这些都归结为:

#include <stdio.h>

int main(void) {
    size_t tap = 2147483648;
    for (size_t i = tap; i < 2 * tap + 1; i++) {
        unsigned short temp = i | 2;
        unsigned char ch = 0xf2 ^ ((temp * (temp ^ 1)) >> 8);
        if (ch == 0x77)
            printf("%zu\n", i);
    }
    return 0;
}

除了我删除了“停止”,以便打印所有结果。 (顺便说一句,这在我的机器上运行大约两秒钟,所以我不明白所有线程的意义是什么。)

这会打印 8388608 个结果,这是迭代次数的 1/256(减一)。正是您在检查随机生成的一个字节时所期望的。这里没有什么奇怪的。你在期待什么?

然而,在 231 情况下运行它(由于某种原因加上 1 个)是没有意义的,因为查询的输入只有 16 位(短)!或者在

| 2
之后实际上只有 15 位。您只需要 32768 次迭代即可探索函数的整个域。

© www.soinside.com 2019 - 2024. All rights reserved.