You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何ZipCrypto Key2暴力破解出现大量误报?代码问题排查

问题

尝试利用CRC首字节与加密头最后一字节暴力破解ZipCrypto的Key2以测试耗时,却得到了2000余个无效的“有效密钥”。根据APPNOTE规范,Key2用于解密字节,由CRC32生成,是32位值,范围应为2147483648至4294967296。

本次测试参数:

  • 密码:> 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;
}

请问为何会出现大量误报,代码中存在什么问题?


问题分析与解决
  • 校验逻辑过于薄弱:仅验证单个解密字节等于CRC首字节(0x77),单字节匹配的概率为1/256。32位Key2范围包含2^31个可能值,理论上会产生约800万个匹配结果,你得到2000余个误报只是因为线程停止逻辑未拦截所有匹配,本质是单字节校验的误报率极高。必须校验完整CRC值或更多明文特征才能过滤无效密钥。

  • Key2范围理解错误:APPNOTE规范中Key2是32位无符号整数,范围应为0到4294967295,而非2147483648到4294967296。你仅遍历了高31位的一半,漏掉了低31位的所有可能值,既可能错过正确Key2,当前误报也都是错误范围内的无效匹配。

  • 线程停止逻辑存在竞态条件:stop作为volatile布尔值,多线程同时检测和设置时,可能有多个线程在stop被设置前进入匹配分支,导致多个无效密钥被打印。需用互斥锁保护stop的读写,或使用原子操作确保只有第一个匹配线程终止其他线程。

  • decrypt_byte函数实现错误:ZipCrypto解密时,Key2会随解密过程更新(每次解密字节后用CRC32算法更新),你直接用原始Key2计算解密字节,未模拟该更新过程,导致解密结果本身错误,即使匹配0x77也是无效的。正确逻辑应为:用候选Key2解密第一个加密字节得到明文,再用明文更新Key2,继续解密后续字节直至验证完整CRC或更多特征。

  • 加密字节选择错误:你使用的0xF2需确认是加密数据的第一个字节。Zip本地文件头中,加密数据从filename字段后开始,若提取的字节位置错误,解密结果对应无效位置,自然产生大量误报。

内容的提问来源于stack exchange,提问作者terry franklin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 17:19:50