首页
社区
课程
招聘
[原创]从Google CTF Fluffy 看Dart逆向
发表于: 2025-7-8 00:33 3856

[原创]从Google CTF Fluffy 看Dart逆向

2025-7-8 00:33
3856

之前遇到过Dart的逆向,但是关键逻辑不在libapp.so。这次做的Fluffy算是真的要去恩看Dart的逻辑,Dart的代码放入ida中的非常难看,很多native操作,通过这篇文章来总结我对Dart语言的一些特性的思考。

Dart中的对象中存入的指针,为了节省空间,并不是将所有地址都存入内存,而是只是将低32位的偏移存入内存,高32位的地址由x28保存。如果你打开ida,发现很多 var << 32 + var 之类的表达式,please just relax,这只是在拼接堆指针罢了。

在blutter还原的汇编注释也可见一斑:

首先Dart中一切皆为Object,但是实际Dart在也是有底层优化的。在Dart中最最常见的就是int类型。

共有两种类型:

举个例子:

smi与bigint的区别就在于,右移一位后是否为1

Dart的栈使用X15,而不是X29,

返回值使用的X0,但是寄存器传参是从X1开始的

Dart中的特殊寄存器如下:

X21用于多态调用,基于cid(class id)进行寻址

举个例子:

v29-1 指向object头部, 头部高20为class id,低12位为一些标志位用于GC等。v5指向X21

然后根据cid进行寻址。进行多态调用。

然后使用如下的函数签名,重新set call type将函数还原成原本的样子:

还原后:

好看很多,函数参数也清晰了。

还有一些细枝末节的东西,比如很多的内存0xb, 0xf偏移的内存访问,还有new 一个数组要经过 Arraystub, GrowArraystub等等,只要知道这些底层操作对用的高级操作就可以了。

blutter预处理后

接下来,就是摁看加调试(确定多态调用)

最后还原出加密逻辑

所以接下来要爆破4位pin和时间戳爆破。

接下来请欣赏,河豚鱼大人艺术般的爆破脚本。

(引用名人名句:爆,爆,爆,爆tmd —河豚鱼)

// 0x358708: DecompressPointer r2
    //     0x358708: add             x2, x2, HEAP, lsl #32
// 0x358708: DecompressPointer r2
    //     0x358708: add             x2, x2, HEAP, lsl #32
寄存器 用途 说明
X21 类型表指针(TypeTable / GDT) 用于类型跳转(vtable)调用、类 ID 映射等
X26 当前线程指针(Thread* thr GC、栈检查等使用
X27 常量池指针(ObjectPool* pp 用于加载常量、内联缓存等
X28 Heap 基地址 解压压缩指针
X15 虚拟栈指针 传递更多参数 / spill slot
_QWORD (__usercall *)@<X0>(DartObjectPool *pool@<X27>, DartThread *thread@<X26>, _QWORD *stack@<X15>, _QWORD@<X1>, _QWORD@<X2>, _QWORD@<X4>)
_QWORD (__usercall *)@<X0>(DartObjectPool *pool@<X27>, DartThread *thread@<X26>, _QWORD *stack@<X15>, _QWORD@<X1>, _QWORD@<X2>, _QWORD@<X4>)
static int saveSecret(unsigned char* res, const void* token, int token_len, int pin, const void* secret, int secret_len) {
    unsigned char* token_bytes = malloc(token_len);
    int token_bytes_len = b62decode(token_bytes, token, token_len);
    assert(token_bytes_len == 8);
    memcpy(res, secret, secret_len);
    for (int i = 0; i < pin; i++) {
        for (int j = 0; j < secret_len; j++) {
            res[j] = rol1(res[j] + token_bytes[j % token_bytes_len], j & 7);
        }
        unsigned char tmp = res[secret_len - 1];
        memmove(res + 1, res, secret_len - 1);
        res[0] = tmp;
        update_token_bytes(token_bytes, token_bytes_len, pin, i);
    }
    free(token_bytes);
    return b62encode(res, res, secret_len);
}
static void update_token_bytes(unsigned char* token_bytes, int token_bytes_len, int pin, int round) {
    unsigned char tmp = token_bytes[0];
    memmove(token_bytes, token_bytes + 1, token_bytes_len - 1);
    token_bytes[token_bytes_len - 1] = tmp;
    for (int j = 0; j < token_bytes_len; j++) {
        token_bytes[j] = ror1(token_bytes[j], (pin ^ ((round & 3) + 1)) & 7);
    }
}
static int saveSecret(unsigned char* res, const void* token, int token_len, int pin, const void* secret, int secret_len) {
    unsigned char* token_bytes = malloc(token_len);
    int token_bytes_len = b62decode(token_bytes, token, token_len);
    assert(token_bytes_len == 8);
    memcpy(res, secret, secret_len);
    for (int i = 0; i < pin; i++) {
        for (int j = 0; j < secret_len; j++) {
            res[j] = rol1(res[j] + token_bytes[j % token_bytes_len], j & 7);
        }
        unsigned char tmp = res[secret_len - 1];
        memmove(res + 1, res, secret_len - 1);
        res[0] = tmp;
        update_token_bytes(token_bytes, token_bytes_len, pin, i);
    }
    free(token_bytes);
    return b62encode(res, res, secret_len);
}
static void update_token_bytes(unsigned char* token_bytes, int token_bytes_len, int pin, int round) {
    unsigned char tmp = token_bytes[0];
    memmove(token_bytes, token_bytes + 1, token_bytes_len - 1);
    token_bytes[token_bytes_len - 1] = tmp;
    for (int j = 0; j < token_bytes_len; j++) {
        token_bytes[j] = ror1(token_bytes[j], (pin ^ ((round & 3) + 1)) & 7);
    }
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <gmp.h>
#include <openssl/sha.h>
#include <pthread.h>
#include <assert.h>
 
static unsigned char rol1(unsigned char x, int n) {
    return (x << n) | (x >> (8 - n));
}
 
static unsigned char ror1(unsigned char x, int n) {
    return (x >> n) | (x << (8 - n));
}
 
static void reverse_str(unsigned char* s, int n) {
    for (int i = 0, j = n - 1; i < j; i++, j--) {
        unsigned char tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
    }
}
 
static void bytes_to_long(mpz_t* res, const unsigned char* s, int n) {
    mpz_set_ui(*res, 0);
    for (int i = 0; i < n; i++) {
        mpz_mul_ui(*res, *res, 256);
        mpz_add_ui(*res, *res, s[i]);
    }
}
 
static int long_to_bytes(unsigned char* res, const mpz_t* v) {
    mpz_t t;
    mpz_init(t);
    mpz_set(t, *v);
    int l = 0;
    while (mpz_cmp_ui(t, 0)) {
        res[l++] = mpz_get_ui(t) & 0xff;
        mpz_fdiv_q_ui(t, t, 256);
    }
    mpz_clear(t);
    reverse_str(res, l);
    return l;
}
 
static const char* b62table = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static unsigned char b62table_r[256];
 
static void init_b62table() {
    for (int i = 0; i < strlen(b62table); i++) {
        b62table_r[b62table[i] & 0xff] = i;
    }
}
 
static int b62encode(unsigned char* res, const unsigned char* s, int n) {
    if (!b62table_r['z']) {
        init_b62table();
    }
    mpz_t v;
    mpz_init(v);
 
    bytes_to_long(&v, s, n);
    int l = 0;
    mpz_t mod;
    mpz_init(mod);
    while (mpz_cmp_ui(v, 0)) {
        mpz_mod_ui(mod, v, 62);
        res[l++] = b62table[mpz_get_ui(mod)];
        mpz_fdiv_q_ui(v, v, 62);
    }
    mpz_clear(mod);
    mpz_clear(v);
    reverse_str(res, l);
    res[l] = 0;
    return l;
}
 
static int b62decode(unsigned char* res, const unsigned char* s, int n) {
    if (!b62table_r['z']) {
        init_b62table();
    }
    mpz_t v;
    mpz_init(v);
    for (int i = 0; i < n; i++) {
        mpz_mul_ui(v, v, 62);
        mpz_add_ui(v, v, b62table_r[s[i]]);
    }
    int l = long_to_bytes(res, &v);
    mpz_clear(v);
    res[l] = 0;
    return l;
}
 
static int generate_token(char* res, time_t ts) {
    if (!ts) {
        ts = time(NULL);
    }
    char buffer[256];
    sprintf(buffer, "gctf25_%ld", ts);
    unsigned char hash[20];
    SHA1((unsigned char*) buffer, strlen(buffer), hash);
    return b62encode((unsigned char*) res, hash, 8);
}
 
static void update_token_bytes(unsigned char* token_bytes, int token_bytes_len, int pin, int round) {
    unsigned char tmp = token_bytes[0];
    memmove(token_bytes, token_bytes + 1, token_bytes_len - 1);
    token_bytes[token_bytes_len - 1] = tmp;
    for (int j = 0; j < token_bytes_len; j++) {
        token_bytes[j] = ror1(token_bytes[j], (pin ^ ((round & 3) + 1)) & 7);
    }
}
 
static int saveSecret(unsigned char* res, const void* token, int token_len, int pin, const void* secret, int secret_len) {
    unsigned char* token_bytes = malloc(token_len);
    int token_bytes_len = b62decode(token_bytes, token, token_len);
    assert(token_bytes_len == 8);
    memcpy(res, secret, secret_len);
    for (int i = 0; i < pin; i++) {
        for (int j = 0; j < secret_len; j++) {
            res[j] = rol1(res[j] + token_bytes[j % token_bytes_len], j & 7);
        }
        unsigned char tmp = res[secret_len - 1];
        memmove(res + 1, res, secret_len - 1);
        res[0] = tmp;
        update_token_bytes(token_bytes, token_bytes_len, pin, i);
    }
    free(token_bytes);
    return b62encode(res, res, secret_len);
}
 
static int restoreSecret(unsigned char* res, const void* token, int token_len, int pin, const void* encrypted, int encrypted_len) {
    unsigned char* token_bytes = malloc(0x18);
    int token_bytes_len = b62decode(token_bytes, token, token_len);
    int res_len = b62decode(res, encrypted, encrypted_len);
    unsigned char* token_bytes_list = malloc(pin * token_bytes_len);
    for (int i = 0; i < pin; i++) {
        memcpy(token_bytes_list + i * token_bytes_len, token_bytes, token_bytes_len);
        update_token_bytes(token_bytes, token_bytes_len, pin, i);
    }
    free(token_bytes);
 
    for (int i = pin - 1; i >= 0; i--) {
        unsigned char* _token_bytes = token_bytes_list + i * token_bytes_len;
        unsigned char tmp = res[0];
        for (int j = 0; j < res_len - 1; j++) {
            res[j] = res[j + 1];
        }
        res[res_len - 1] = tmp;
        for (int j = 0; j < res_len; j++) {
            res[j] = ror1(res[j], j & 7) - _token_bytes[j % token_bytes_len];
        }
    }
    free(token_bytes_list);
    return res_len;
}
 
static unsigned char restoreSecretWithPrecomputedAt(int index, const unsigned char* token_bytes_list, int token_bytes_len, int pin, const unsigned char* res_start, int res_len) {
    assert(index >= 0 && index < res_len);
 
    unsigned char c = res_start[(index + pin) % res_len];
    for (int i = pin - 1; i >= 0; i--) {
        const unsigned char* token_bytes = token_bytes_list + i * token_bytes_len;
        const int c_index = (index + i) % res_len;
        c = ror1(c, c_index & 7) - token_bytes[c_index % token_bytes_len];
    }
    return c;
}
 
static int restoreSecretWithPrecomputed(unsigned char* res, const unsigned char* token_bytes_list, int token_bytes_len, int pin, const unsigned char* res_start, int res_len) {
    memcpy(res, res_start, res_len);
    for (int i = pin - 1; i >= 0; i--) {
        const unsigned char* token_bytes = token_bytes_list + i * token_bytes_len;
        unsigned char tmp = res[0];
        memmove(res, res + 1, res_len - 1);
        res[res_len - 1] = tmp;
        for (int j = 0; j < res_len; j++) {
            // const int res_index = (j + pin - i) % res_len;
            // res[res_index] = ror1(res[res_index], j & 7) - token_bytes[j % token_bytes_len];
            res[j] = ror1(res[j], j & 7) - token_bytes[j % token_bytes_len];
        }
    }
    return res_len;
}
 
static int is_printable(const unsigned char* s, int n) {
    for (int i = 0; i < n; i++) {
        if (s[i] < 0x20 || s[i] >= 0x7f) {
            return 0;
        }
    }
    return 1;
}
 
static void bf_secret(int ts_lower_bound, int ts_upper_bound, const void* encrypted, int encrypted_len) {
/*
    char token[0x100];
    unsigned char* decrypted = malloc(encrypted_len);
    for (int ts = ts_upper_bound - 1; ts >= ts_lower_bound; ts--) {
        int token_len = generate_token(token, ts);
        for (int pin = 1; pin < 10000; pin++) {
            printf("\r%d, %d: ", ts, pin);
            int decrypted_len = restoreSecret(decrypted, token, token_len, pin, encrypted, encrypted_len);
            if (is_printable(decrypted, decrypted_len)) {
                printf("\r%d, %d: %s\n", ts, pin, (char*) decrypted);
            }
        }
    }
    free(decrypted);
*/
    unsigned char* res_start = malloc(encrypted_len);
    unsigned char* decrypted = malloc(encrypted_len);
    memset(decrypted, 0, encrypted_len);
    unsigned char* token_bytes = malloc(0x18);
    unsigned char* token_bytes_list = malloc(10000 * 0x10);
    int res_len = b62decode(res_start, encrypted, encrypted_len);
    char token[0x100];
    for (int ts = ts_upper_bound - 1; ts >= ts_lower_bound; ts--) {
        int token_len = generate_token(token, ts);
        for (int pin_start = 1; pin_start < 9; pin_start++) {
            // printf("\r%d, %d: ", ts, pin_start);
            int token_bytes_len = b62decode(token_bytes, (unsigned char*) token, token_len);
            for (int i = 0; i < 10000; i++) {
                memcpy(token_bytes_list + i * token_bytes_len, token_bytes, token_bytes_len);
                update_token_bytes(token_bytes, token_bytes_len, pin_start, i);
            }
            for (int pin = pin_start; pin < 10000; pin += 8) {
                if (restoreSecretWithPrecomputedAt(res_len - 1, token_bytes_list, token_bytes_len, pin, res_start, res_len) == '}') {
                    int decrypted_len = restoreSecretWithPrecomputed(decrypted, token_bytes_list, token_bytes_len, pin, res_start, res_len);
                    if (is_printable(decrypted, decrypted_len)) {
                        printf("\r%d, %d: %s\n", ts, pin, (char*) decrypted);
                        // exit(0);
                    }
                }
            }
        }
    }
    free(token_bytes_list);
    free(token_bytes);
    free(decrypted);
    free(res_start);
}
 
struct bf_secret_thread_struct {
    int id;
    int ts_lower_bound;
    int ts_upper_bound;
    const char* encrypted;
};
 
#define THREAD_COUNT 16
#define SECONDS_PER_THREAD 60 * 60
#define SECONDS_PRE_LOG 60
 
static void bf_secret_thread(struct bf_secret_thread_struct* arg) {
    printf("thread %d started (from %d to %d)\n", arg->id, arg->ts_lower_bound, arg->ts_upper_bound);
    // while (1) {
        const int ts_count = arg->ts_upper_bound - arg->ts_lower_bound;
        assert(ts_count % SECONDS_PRE_LOG == 0);
        const int log_count = ts_count / SECONDS_PRE_LOG;
        for (int i = 0; i < log_count; i++) {
            printf("thread %2d: %d / %d\n", arg->id, i, log_count);
            bf_secret(arg->ts_lower_bound + SECONDS_PRE_LOG * i, arg->ts_lower_bound + SECONDS_PRE_LOG * (i + 1), arg->encrypted, strlen(arg->encrypted));
        }
        printf("thread %d finished\n", arg->id);
        // prepare_next_arg(arg);
    // }
    free(arg);
}
 
int main() {
    /*
    unsigned char res[100];
    unsigned char res2[100];
    int l1 = b62encode(res, (unsigned char*) "0123456789abcdef", 16);
    printf("%d: %s\n", l1, (char*) res);
    int l2 = b62decode(res2, res, l1);
    printf("%d: %s\n", l2, (char*) res2);
    unsigned char res[100];
    generate_token(res, 1000);
    puts((char*) res);
 
    const int pin = 1000;
    const char* token = "aaaaaaaaaaa";
    const int token_len = strlen(token);
 
    unsigned char res[0x100];
    unsigned char res2[0x100];
    int l1 = saveSecret(res, token, token_len, pin, "0123456789abcdef", 16);
    printf("%d: %s\n", l1, (char*) res);
    int l2 = restoreSecret(res2, token, token_len, pin, res, l1);
    printf("%d: %s\n", l2, (char*) res2);
    */
 
    setbuf(stdout, NULL);
 
    /*
    const int lower_bound = 1691127420 + 60 + 8 * 60 * 60 - 12 * 60 * 60;
    const char* encrypted = "fmMf7mIMbHcPoQmLGx1CO0XVGBmhjTaYhB0";
 
    pthread_t threads[24];
    for (int i = 0; i < 24; i++) {
        struct bf_secret_thread_struct* s = malloc(sizeof(struct bf_secret_thread_struct));
        s->id = i;
        s->ts_upper_bound = lower_bound + i * 60 * 60;
        s->ts_lower_bound = s->ts_upper_bound - 10 * 60;
        s->encrypted = encrypted;
        assert(!pthread_create(threads + i,NULL, (void*) bf_secret_thread, s));
    }
    for (int i = 0; i < 24; i++) {
        assert(!pthread_join(threads[i], NULL));
    }
 
    puts("done");
    */
 
    /*
    const int upper_bound[] = {
        1691127420 + 60 + 6 * 60 * 60,
        1725706320 + 60 + 6 * 60 * 60,
        1741010820 + 60 + 6 * 60 * 60
    };
    const char* encrypted[] = {
        "fmMf7mIMbHcPoQmLGx1CO0XVGBmhjTaYhB0",
        "5O6WRgCajs3QSTyohnu2hldds18mjkx",
        "fgv99dOvazsvEESh7DPKbb3k0I3RW"
    };
 
    const int idx = 2;
    bf_secret(upper_bound[idx] - 10 * 60, upper_bound[idx], encrypted[idx], strlen(encrypted[idx]));
    */
 
    // const int upper_bound = 1741010820 + 60 + 8 * 60 * 60; // - THREAD_COUNT * SECONDS_PER_THREAD;
    // const char* encrypted = "fgv99dOvazsvEESh7DPKbb3k0I3RW";
 
    // pthread_t threads[THREAD_COUNT];
    // for (int i = 0; i < THREAD_COUNT; i++) {
    //     struct bf_secret_thread_struct* s = malloc(sizeof(struct bf_secret_thread_struct));
    //     s->id = i;
    //     s->ts_upper_bound = upper_bound - i * SECONDS_PER_THREAD;
    //     s->ts_lower_bound = s->ts_upper_bound - SECONDS_PER_THREAD;
    //     s->encrypted = encrypted;
    //     assert(!pthread_create(threads + i,NULL, (void*) bf_secret_thread, s));
    // }
    // for (int i = 0; i < THREAD_COUNT; i++) {
    //     assert(!pthread_join(threads[i], NULL));
    // }
 
    // puts("done");
 
    // bf_secret_string(1691127420 + 60 + 8 * 60 * 60, "fmMf7mIMbHcPoQmLGx1CO0XVGBmhjTaYhB0");
    // 1691149047, 8126: CTF{Ok4y_h4v3_u_0ptim1zed_
    // bf_secret_string(1725706320 + 60 + 8 * 60 * 60, "5O6WRgCajs3QSTyohnu2hldds18mjkx");
    // 1725727951, 5178: brUt3_f0rcE_0R_y0u_jUst
    // bf_secret_string(1741010820 + 60 + 8 * 60 * 60, "fgv99dOvazsvEESh7DPKbb3k0I3RW");
    //
 
    return 0;
}
 
// gcc ./main.c -o main -s -O3 -Wall -Wno-unused-function -lgmp -lcrypto && ./main
 
// CTF{Ok4y_h4v3_u_0ptim1zed_brUt3_f0rcE_0R_y0u_jUst
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <gmp.h>
#include <openssl/sha.h>
#include <pthread.h>
#include <assert.h>
 
static unsigned char rol1(unsigned char x, int n) {
    return (x << n) | (x >> (8 - n));
}
 
static unsigned char ror1(unsigned char x, int n) {
    return (x >> n) | (x << (8 - n));
}
 
static void reverse_str(unsigned char* s, int n) {
    for (int i = 0, j = n - 1; i < j; i++, j--) {
        unsigned char tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
    }
}
 
static void bytes_to_long(mpz_t* res, const unsigned char* s, int n) {
    mpz_set_ui(*res, 0);
    for (int i = 0; i < n; i++) {
        mpz_mul_ui(*res, *res, 256);
        mpz_add_ui(*res, *res, s[i]);
    }
}
 
static int long_to_bytes(unsigned char* res, const mpz_t* v) {
    mpz_t t;
    mpz_init(t);
    mpz_set(t, *v);
    int l = 0;
    while (mpz_cmp_ui(t, 0)) {
        res[l++] = mpz_get_ui(t) & 0xff;
        mpz_fdiv_q_ui(t, t, 256);
    }
    mpz_clear(t);
    reverse_str(res, l);
    return l;
}
 
static const char* b62table = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static unsigned char b62table_r[256];
 
static void init_b62table() {
    for (int i = 0; i < strlen(b62table); i++) {
        b62table_r[b62table[i] & 0xff] = i;
    }
}
 
static int b62encode(unsigned char* res, const unsigned char* s, int n) {
    if (!b62table_r['z']) {
        init_b62table();
    }
    mpz_t v;
    mpz_init(v);
 
    bytes_to_long(&v, s, n);
    int l = 0;
    mpz_t mod;
    mpz_init(mod);
    while (mpz_cmp_ui(v, 0)) {
        mpz_mod_ui(mod, v, 62);
        res[l++] = b62table[mpz_get_ui(mod)];
        mpz_fdiv_q_ui(v, v, 62);
    }
    mpz_clear(mod);
    mpz_clear(v);
    reverse_str(res, l);
    res[l] = 0;
    return l;
}
 
static int b62decode(unsigned char* res, const unsigned char* s, int n) {
    if (!b62table_r['z']) {
        init_b62table();
    }
    mpz_t v;
    mpz_init(v);
    for (int i = 0; i < n; i++) {
        mpz_mul_ui(v, v, 62);
        mpz_add_ui(v, v, b62table_r[s[i]]);
    }
    int l = long_to_bytes(res, &v);
    mpz_clear(v);
    res[l] = 0;
    return l;
}
 
static int generate_token(char* res, time_t ts) {
    if (!ts) {
        ts = time(NULL);
    }
    char buffer[256];
    sprintf(buffer, "gctf25_%ld", ts);
    unsigned char hash[20];
    SHA1((unsigned char*) buffer, strlen(buffer), hash);
    return b62encode((unsigned char*) res, hash, 8);
}
 
static void update_token_bytes(unsigned char* token_bytes, int token_bytes_len, int pin, int round) {
    unsigned char tmp = token_bytes[0];
    memmove(token_bytes, token_bytes + 1, token_bytes_len - 1);
    token_bytes[token_bytes_len - 1] = tmp;
    for (int j = 0; j < token_bytes_len; j++) {
        token_bytes[j] = ror1(token_bytes[j], (pin ^ ((round & 3) + 1)) & 7);
    }
}
 
static int saveSecret(unsigned char* res, const void* token, int token_len, int pin, const void* secret, int secret_len) {
    unsigned char* token_bytes = malloc(token_len);
    int token_bytes_len = b62decode(token_bytes, token, token_len);
    assert(token_bytes_len == 8);
    memcpy(res, secret, secret_len);
    for (int i = 0; i < pin; i++) {
        for (int j = 0; j < secret_len; j++) {
            res[j] = rol1(res[j] + token_bytes[j % token_bytes_len], j & 7);
        }
        unsigned char tmp = res[secret_len - 1];
        memmove(res + 1, res, secret_len - 1);
        res[0] = tmp;
        update_token_bytes(token_bytes, token_bytes_len, pin, i);
    }
    free(token_bytes);
    return b62encode(res, res, secret_len);
}
 
static int restoreSecret(unsigned char* res, const void* token, int token_len, int pin, const void* encrypted, int encrypted_len) {
    unsigned char* token_bytes = malloc(0x18);
    int token_bytes_len = b62decode(token_bytes, token, token_len);
    int res_len = b62decode(res, encrypted, encrypted_len);
    unsigned char* token_bytes_list = malloc(pin * token_bytes_len);
    for (int i = 0; i < pin; i++) {
        memcpy(token_bytes_list + i * token_bytes_len, token_bytes, token_bytes_len);
        update_token_bytes(token_bytes, token_bytes_len, pin, i);
    }
    free(token_bytes);
 
    for (int i = pin - 1; i >= 0; i--) {
        unsigned char* _token_bytes = token_bytes_list + i * token_bytes_len;
        unsigned char tmp = res[0];
        for (int j = 0; j < res_len - 1; j++) {
            res[j] = res[j + 1];
        }
        res[res_len - 1] = tmp;
        for (int j = 0; j < res_len; j++) {
            res[j] = ror1(res[j], j & 7) - _token_bytes[j % token_bytes_len];
        }
    }
    free(token_bytes_list);
    return res_len;
}
 

[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 2025-7-8 00:41 被SleepAlone编辑 ,原因:
收藏
免费 6
支持
分享
最新回复 (2)
雪    币: 16
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
1
2025-7-18 18:08
0
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
可以私聊吗
2025-8-1 00:17
0
游客
登录 | 注册 方可回帖
返回