吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2286|回复: 11
收起左侧

[CTF] 【2025春节】解题领红包二到八题writeup

  [复制链接]
SGFvamll 发表于 2025-2-14 15:54

来吾爱三年了,没有发过任何帖子,但默默从萌新成长为了略通拳脚的师傅。
趁着好不容易春节回家前几天有空,刷了些题蹭吾爱币。现在继续发题解蹭积分(x

2

这个题我一开始认真逆向了题目的一部分逻辑,感慨吾爱的简单题也还是有点难度的(C++且无调试符号)。直到我看到后面的加密、比较操作时,我才反应过来哪里不对劲:加密是对我原以为的密文做的(所以其实是解密),而比较的目标是选手输入的明文,故而可以直接调试到解密结束,在栈上翻到 flag。

2

2

3

作为安卓苦手,这个题一开始让我感觉有点难于下手,就差把wuaipojie2025包下的每个类逐一点过去了。

最后在 MainActivity->FoldPagerAdapter->FoldFragment2 找到了一串神秘的 base64 以及“恳求”我寻找flag的任务提示:

3-1

3-1

跟着 base64 ,跟进两重调用后:

3-2

3-2

提示 xxtea,点进去看也确实是 xxtea 。剩下的就交给赛博厨师了。

3-3

3-3

这是第二段 flag ,在 FoldFragment2.onViewCreated.gestureDetector.1#onScroll 里还有一段:flag{

不能习惯没有 jni 的 android 题。

4

先看jni_onload,果然有动态注册:

4-1

4-1

4-2

4-2

上来一堆检测,但没细看,只关注了下检测的结果导致v9a还是aa

4-3

4-3

aaa两个函数差不多,都是跟进密钥生成扩展密钥流,扩展密钥流和明文异或得到密文。所以加密过程其实只是一个异或,没细看密钥生成的逻辑(E5220函数)。

题目友好地给出了x86架构的lib库,非常照顾我这个至今没有android真机调试环境的选手。

重打包-安装过程记得遇到过一些问题,根据adb install的报错搜索下就能解决。

调试输入0x13个字符串1,dump出密文b'\x1fz\xdf\xf9\xd1\xa4\xb9v\x81C*Yq\xe1;\xb5FA\xbb'。明密文异或即得扩展密钥流,再和密文异或得到flag。

ct1 = b'\x1fz\xdf\xf9\xd1\xa4\xb9v\x81C*Yq\xe1;\xb5FA\xbb'
pt1 = b"1" * 0x13

ct = bytes(reversed(bytes.fromhex('F75942B63AE26B0C72079872ECF89BAF8F2748')))

pt = bytes([a^b^c for a, b, c in zip(ct1, pt1, ct)])
print(pt, len(pt))

(忘了真实函数是a还是aa了,总之都试下肯定就有了)

得到:flag{md5(uid+2025)},我想到了如下一些可能:

import hashlib
print("flag{" + hashlib.md5(str(uid+2025).encode()).hexdigest() + "}")
print("flag{" + hashlib.md5(str(uid+2025).encode()).hexdigest().upper() + "}")
print("flag{" + hashlib.md5(int.to_bytes(uid+2025, 4, 'little')).hexdigest() + "}")
print("flag{" + hashlib.md5(int.to_bytes(uid+2025, 4, 'little')).hexdigest().upper() + "}")
print("flag{" + hashlib.md5(int.to_bytes(uid+2025, 4, 'big')).hexdigest() + "}")
print("flag{" + hashlib.md5(int.to_bytes(uid+2025, 4, 'big')).hexdigest().upper() + "}")
print("flag{" + hashlib.md5(str(uid).encode()+b'2025').hexdigest() + "}")
print("flag{" + hashlib.md5(str(uid).encode()+b'2025').hexdigest().upper() + "}")

嗯,这一步它卡了我一天(一天只能交三次 flag )。

5

动调了一路的一题。

die查出一个没见过的壳,网上没搜到有用的材料,于是开始调试这个壳。

发现到伪C代码208行这里跳转到 OEP 。跳转前调了 TlsCallback。也可以看到跳转前修改了 TlsCallBack 的代码。

5-1

5-1

TlsCallBack 恢复后的长这样,调了 140012038 处函数指针数组内的函数。

5-2

5-2

其中第二个函数利用ZwSetInformationThread反调。注意到程序还 patch 了跳转到ZwSetInformationThread的桩函数,

00007FFDD876D680 < | 90                         | nop                                         |
00007FFDD876D681   | FF25 00000000              | jmp qword ptr ds:[7FFDD876D687]             |
00007FFDD876D687   | 3013                       | xor byte ptr ds:[rbx],dl                    |
00007FFDD876D689   | 34 98                      | xor al,98                                   |
00007FFDD876D68B   | 6E                         | outsb                                       |
00007FFDD876D68C   | 0100                       | add dword ptr ds:[rax],eax                  |
00007FFDD876D68E   | 0001                       | add byte ptr ds:[rcx],al                    |
00007FFDD876D690   | 75 03                      | jne ntdll.7FFDD876D695                      |
00007FFDD876D692   | 0F05                       | syscall                                     |
00007FFDD876D694   | C3                         | ret                                         |

patch 为:

00007FFDD876D680 < | 90                         | nop                                         |
00007FFDD876D681   | FF25 00000000              | jmp qword ptr ds:[7FFDD876D687]             |
00007FFDD876D687   | 3013                       | xor byte ptr ds:[rbx],dl                    |
00007FFDD876D689   | 34 98                      | xor al,98                                   |
00007FFDD876D68B   | 6E                         | outsb                                       |
00007FFDD876D68C   | 0100                       | add dword ptr ds:[rax],eax                  |
00007FFDD876D68E   | 0001                       | add byte ptr ds:[rcx],al                    |
00007FFDD876D690   | 85D2                       | test edx,edx                                |
00007FFDD876D692   | 79 02                      | jns ntdll.7FFDD876D696                      |
00007FFDD876D694   | F7D2                       | not edx                                     |
00007FFDD876D696   | EB 1A                      | jmp ntdll.7FFDD876D6B2                      |

00007FFDD876D6B2   | 0F05                       | syscall                                     |
00007FFDD876D6B4   | C3                         | ret                                         |

主要修改是增加了一条not edx。同时注意到调用ZwSetInformationThread前,程序的第二个参数已经被作为一次取反(正常应该是17,程序实际调用参数为-17)。所以这条not edx的目的是恢复参数。

这里多此一举的目的是实现反-反-反调试。众所周知,ZwSetInformationThread可以实现反调。因而 ScyllaHide 实现了ZwSetInformationThread的反-反调试。实现方式为 patch ZwSetInformationThread的桩函数。实际上,最原始版本的桩函数为(上面给出的 patch 前版本实际是程序 patch 前、 ScyllaHide patch 后):

00007FFDD876D680 < | 4C:8BD1                    | mov r10,rcx                                 |
00007FFDD876D683   | B8 0D000000                | mov eax,D                                   | D:'\r'
00007FFDD876D688   | F60425 0803FE7F 01         | test byte ptr ds:[7FFE0308],1               |
00007FFDD876D690   | 75 03                      | jne ntdll.7FFDD876D695                      |
00007FFDD876D692   | 0F05                       | syscall                                     |
00007FFDD876D694   | C3                         | ret                          |

ScyllaHide patch 使其跳转到 00000214C4371330 ,并检测第二个参数是否为 17,如不是,恢复正常执行。程序对第二个参数取反的操作正是为了绕过 ScyllaHide 的检测。

00000214C4371330   | 48:8BC4                     | mov rax,rsp                                 |
00000214C4371333   | 48:8958 08                  | mov qword ptr ds:[rax+8],rbx                |
00000214C4371337   | 48:8968 10                  | mov qword ptr ds:[rax+10],rbp               |
00000214C437133B   | 48:8970 18                  | mov qword ptr ds:[rax+18],rsi               |
00000214C437133F   | 48:8978 20                  | mov qword ptr ds:[rax+20],rdi               |
00000214C4371343   | 41:56                       | push r14                                    |
00000214C4371345   | 48:83EC 20                  | sub rsp,20                                  |
00000214C4371349   | 41:8BF1                     | mov esi,r9d                                 |
00000214C437134C   | 4D:8BF0                     | mov r14,r8                                  |
00000214C437134F   | 8BEA                        | mov ebp,edx                                 |
00000214C4371351   | 48:8BF9                     | mov rdi,rcx                                 |
00000214C4371354   | 83FA 11                     | cmp edx,11                                  |
00000214C4371357   | 75 24                       | jne 214C437137D                             |
00000214C4371359   | 45:85C9                     | test r9d,r9d                                |
00000214C437135C   | 75 1F                       | jne 214C437137D                             |
00000214C437135E   | 48:83F9 FE                  | cmp rcx,FFFFFFFFFFFFFFFE                    |
00000214C4371362   | 74 15                       | je 214C4371379                              |
00000214C4371364   | 6548:8B0425 30000000        | mov rax,qword ptr gs:[30]                   |
00000214C437136D   | 8B58 40                     | mov ebx,dword ptr ds:[rax+40]               |
00000214C4371370   | E8 FB1D0000                 | call 214C4373170                            |
00000214C4371375   | 3BD8                        | cmp ebx,eax                                 |
00000214C4371377   | 75 04                       | jne 214C437137D                             |
00000214C4371379   | 33C0                        | xor eax,eax                                 |
00000214C437137B   | EB 11                       | jmp 214C437138E                             |
00000214C437137D   | 44:8BCE                     | mov r9d,esi                                 |
00000214C4371380   | 4D:8BC6                     | mov r8,r14                                  |
00000214C4371383   | 8BD5                        | mov edx,ebp                                 |
00000214C4371385   | 48:8BCF                     | mov rcx,rdi                                 |
00000214C4371388   | FF15 62630000               | call qword ptr ds:[214C43776F0]             |
00000214C437138E   | 48:8B5C24 30                | mov rbx,qword ptr ss:[rsp+30]               |
00000214C4371393   | 48:8B6C24 38                | mov rbp,qword ptr ss:[rsp+38]               |
00000214C4371398   | 48:8B7424 40                | mov rsi,qword ptr ss:[rsp+40]               |
00000214C437139D   | 48:8B7C24 48                | mov rdi,qword ptr ss:[rsp+48]               |
00000214C43713A2   | 48:83C4 20                  | add rsp,20                                  |
00000214C43713A6   | 41:5E                       | pop r14                                     |
00000214C43713A8   | C3                          | ret                                         |

直接 patch 调用 ZwSetInformationThread 的函数组织好返回值跳到末尾即可绕过这处反调。

回到脱壳后的 main 函数,程序先调用sub_140007940创建了几个线程,然后调用DialogBoxParamW创建了一个窗口。跟入DialogBox的 handle 函数(sub_140009EC0),它尾调用到sub_140009240,这里基本是响应用户请求,构造消息发给其它线程处理,并通过 ConditionVariable 唤醒线程。

接下来看线程入口函数sub_140007B50,基本一个大循环:等待指定的 ConditionVariable 被唤醒、调用某结构体特点偏移的处理函数、继续 sleep 直到下一次被唤醒。

140007C4D处下断点,跟入找到每个消息的处理函数。发现sub_140008A80对用户输入作check,是一个核心函数。期内又构造了四个消息请求由其它线程处理核心的加解密逻辑,依次实现如下功能:

  1. unhex 密码;
  2. 解密并 unpad 密码,得到的 20 字节视为这样一个结构体: 8 bytes time | 8 bytes uid | 4 bytes hash;
  3. 对解密得到的 20 字节的前 16 字节作哈希操作,最终得到 4 字节哈希结果 H;
  4. 获取由当前时间计算得到的量(半小时更新一次):T = (time() // 1800) * 1800;

最终 check 逻辑:检查输入结构体中的时间和 T 是否相同,输入结构体中的 uid 和 DialogBox 里用户 uid 是否相同,输入结构体里的哈希和计算得到 H 是否相同。

hash 算法为魔改版 md5,魔改点为在填充时给msg_len_in_bits值加了2。

EXP:


import time
from arc4 import ARC4

def p64(v):
    return int.to_bytes(v, 8, "little")
def p32(v):
    return int.to_bytes(v, 4, "little")
def toi32arr(data):
    return [int.from_bytes(data[i:i+4], "little") for i in range(0, len(data), 4)]
def fri32arr(data):
    return b"".join([int.to_bytes(a, 4, "little") for a in data])

def create_msg(t, u, p):
    return p64(t) + p64(u) + p32(p) + b"\x04" * 4

rc4_key = lambda c: int.to_bytes(c, 8, "little") + bytes.fromhex('E87964BA0EF1B4A8A175E934E143DFBAF08755F4C18D5AA6')

def enc(data):
    assert len(data) % 8 == 0
    mask = (1<<32)-1
    inpall = toi32arr(data)
    for i in range(len(data) // 8):
        inp = inpall[i*2:i*2+2]
        key = ARC4(rc4_key(i+1)).encrypt(b"\x00"*16)
        key = toi32arr(key)
        acc = 0
        for _ in range(12):
            acc -= 0xb979379e
            acc &= mask
            inp[1] += (inp[0] - acc) ^ (key[1] + (inp[0] >> 5)) ^ (key[0] + 16 * inp[0])
            inp[1] &= mask
            inp[0] += (inp[1] - acc) ^ (key[3] + (inp[1] >> 5)) ^ (key[2] + 16 * inp[1])
            inp[0] &= mask
        assert acc == 0x4E516498
        inpall[i*2:i*2+2] = inp
    return fri32arr(inpall)

# https://github.com/Utkarsh87/md5-hashing/blob/master/md5.py
from md5 import *

def epad(msg):
    msg_len_in_bits = (8*len(msg)) & 0xffffffffffffffff
    msg.append(0x80)
    while len(msg)%64 != 56:
          msg.append(0)
    msg_len_in_bits += 2    # !!!
    msg += msg_len_in_bits.to_bytes(8, byteorder='little') # little endian convention
    return msg

t = int((time.time() // 1800) * 1800)
uid = 0

salt = bytes.fromhex('3532706F6A6965203230323520E788B1E9A39EE79A84E78CAB00')
m = salt + create_msg(t, uid, 0)[:0x10] * 10
m = epad(bytearray(m))
processed_msg = processMessage(m)
digest = int.to_bytes(processed_msg, 16, "little")
p = digest[15] + (digest[11] << 8) + (digest[7] << 16) + (digest[3] << 24)

m = create_msg(t, uid, p)
m = enc(m)
print(m.hex())

6

这个题 windows 版应该可以直接用 upx 脱壳。里面是一个简单的 vm , vm 的 opcode 指令数目也不多。我的解法是用 R1+Python 重新实现了一遍 vm ,打印 trace ,然后一点点看 trace 完成逆向。

输入 flag 括号内的每段先 base36 解码,然后和 uid 一起算了一个哈希(看到其它wp说是crc32),要求哈希是一个指定常量。很容易逆向求得一组输入:

EXP:

def fc128(a0, a1):
    a0 &= 0xff
    v1 = a0 ^ a1
    for i in range(7, -1, -1):
        f = v1 & 1
        v1 >>= 1
        v1 ^= 0xedb88320 if f else 0
    return v1

def fc0b6(uid):
    # 202552pojieafdm2025
    v1 = 0xffffffff
    v1 = fc128(0x32, v1)
    v1 = fc128(0x30, v1)
    v1 = fc128(0x32, v1)
    v1 = fc128(0x35, v1)
    # print(hex(v1))
    v2 = v1
    v2 = fc128(uid >> 24, v2)
    v2 = fc128(0x35, v2)
    v2 = fc128(0x32, v2)
    v2 = fc128(0x70, v2)
    v2 = fc128(0x6f, v2)
    v2 = fc128(0x6a, v2)
    v2 = fc128(0x69, v2)
    v2 = fc128(0x65, v2)
    # print(hex(v2))
    v2 = fc128(uid >> 16, v2)
    v2 = fc128(0x61, v2)
    v2 = fc128(0x66, v2)
    v2 = fc128(0x64, v2)
    v2 = fc128(0x6d, v2)
    # print(hex(v2))
    v2 = fc128(uid >> 8, v2)
    v2 = fc128(0x32, v2)
    v2 = fc128(0x30, v2)
    v2 = fc128(0x32, v2)
    v2 = fc128(0x35, v2)
    # print(hex(v2))
    v2 = fc128(uid, v2)
    # print(hex(v2))
    return ((~v2) & 0xffffffff) | 0x80808080

def fc089p(data):
    return data[:5] == b"flag{" and data[0x1c] == b"}"[0]

def fc003(tab, inp, off, k):
    vv = 0
    for i in range(5):
        v = tab[inp[off + i]]
        assert v != 0
        vv *= 0x24
        vv += v - 1
    if vv >> 25:
        vv += 1
        vv %= (off & 0xff) + k * 0x13541
    else:
        vv |= 1
    return vv

tab = bytearray(b"\x00"*0x100)
tab[0x30:0x38] = int.to_bytes(0x40C132115100A09, 8, 'little')
tab[0x38:0x40] = int.to_bytes(0x1C11, 8, 'little')
tab[0x40:0x48] = int.to_bytes(0x623020D200F0300, 8, 'little')
tab[0x48:0x50] = int.to_bytes(0x12081916010E141B, 8, 'little')
tab[0x50:0x58] = int.to_bytes(0x51A071E0B24171F, 8, 'little')
tab[0x58:0x60] = int.to_bytes(0x221D18, 8, 'little')

def fc089(uid, passwd):
    kk = fc0b6(uid)
    v = 0
    for i in range(4):
        v |= fc003(tab, passwd, 5 + 6 * i, kk & 0xff)
        kk >>= 8
    v -= 1
    v &= 0xffffffff
    return v ^ 0xc15303fb

def rfc089(uid, expected):
    kk = fc0b6(uid)
    # print(hex(kk))
    v = expected ^ 0xc15303fb
    v += 1
    v &= 0xffffffff
    # print(hex(v))
    flag = b"flag{"
    for i in range(4):
        off = 5 + 6 * i
        k = kk & 0xff
        m = (off & 0xff) + k * 0x13541
        e = (((1 << 25) // m) + 1) * m
        e -= 1
        ans = []
        for j in range(5):
            ans.append(tab.index((e % 0x24) + 1))
            e //= 0x24
        flag += bytes(reversed(ans)) + b"-"
        kk >>= 8
    return flag[:-1] + b"}"

uid = 0
expected = 0x3EACFC04
inp = rfc089(uid, expected)
print(inp)
r = fc089(uid, inp)
print(hex(r), r == expected)

7

First 数组里有两个有用的初始化函数。作了简单的反调和字符串解密。反调函数很容易识别并 patch 掉,字符串解密也容易静态实现。

实现一些字符串解密的 ida 脚本:

import ida_bytes
def patch_add(addr, size, value):
    org = ida_bytes.get_bytes(addr, size)
    p = bytes([(a+value)&0xff for a in org])
    ida_bytes.patch_bytes(addr, p)
    print(f"done {hex(addr)} {hex(size)} {value}")

patch_add(0x140026ad0, 8, 0x10)
patch_add(0x140026ac4, 6, 0x10)
patch_add(0x140026aac, 6, 0x10)
patch_add(0x140026A30, 0x11, 0x10)
patch_add(0x140026A80, 0x29, 0x10)
patch_add(0x140026B28, 0x11, 0x10)
patch_add(0x140026B40, 13, 0x10)
patch_add(0x140026AB8, 11, 0x10)

第二个有用的初始化函数里面修改了main函数的地址,真实地址为1400017A0

刚开始做这题时,并没有认真看sub_1400013B0函数。发现只需要输入和程序由时间戳生成而来的一些常量满足一些简单的算数关系即可。通过trace获取生成的量,构造满足条件的输入后本地就过了,但远程连挂了三组(没错,又要等第二天了)。

后面认真看了下sub_1400013B0函数,发现是椭圆曲线的点加操作,初始化函数里也是在初始化一个阶小于200的非退化的椭圆曲线。于是猜测对输入数据实际上还有一些额外的要求。将输入的最后两个数(用作椭圆曲线的a、p参数改成和题目生成的一样),再去构造剩余输入,就过了。

EXP:

A = [
(0xFFFFFFFFFFFFE12E, 0x237),
# ......
]

a, p = 0x40, 0x80F
b = A[0][1]
A = [a for a, _ in A]
print('001001'*16 + ("%06d"%a) + ("%06d"%p))

uid = 0

import time
t = (int(time.time()) // 60) * 60 // 10
t ^= uid
t = str(t * t)[:0x10]
print(t)

key = ""
for i, c in enumerate(t):
    v = (ord(c) * b) - (A[i] - (1 << 64))
    print(v)
    key += "%06d"%v
print(key + ("%06d"%a) + ("%06d"%p))

后记:

第一天连挂三组时,站短戳了出题人,但奈何我只能发两条短消息,沟通完全没起到效果。然后搜出了出题人的邮箱,继续发邮件追问。出题人没有看邮箱的习惯,但好在过了第一天12点后,我利用新的提交flag机会试出了出题人的意图。后面补发邮件说明情况后没再继续纠结这回事。

8

一个不支持 x86 的 Android APP ,native 层加了不弱的 MBA 混淆,我能逆吗,我逆不动。

2/5 放题后小看了一会,在研究怎么装 unidbg 环境。ubuntu+vscode+maven,跑官方 test 报各种错,因为有活马上到DDL了,遂放弃。直到元宵那天晚上才腾出手了继续做题,这次切到 windows 直接解决了 unidbg 的环境问题。

虽然有 mba 混淆,但不影响在 JNI_OnLoad->sub_13260 里面找到 RegisterNatives。

通过追踪输入数据(GetStringUTFChars),可以大致看出sub_18A00在作加密算法的初始化(输入不参与),sub_18454在作加密。加密函数大致有如下结构:

// xxx
x = sub_16CA0(a1, x, 0LL)
x = sub_16CA0(a1+128, x, 1LL)
x = sub_16CA0(a1+256, x, 0LL)

x为8字节,很难不让我联想到 3des 。经过进一步比对基本确认。

剩下两个问题:

  1. sub_184A8对输入作了什么;
  2. 3des 的密钥是否能恢复(程序里只有扩展密钥,虽然已经够了,但如果能恢复密钥,一方面是验证了它确实是des,另一方面也更方便写代码)。

关于1,我真没猜出来,只看出是逐字节加密的(看其它wp说是bit倒序)。于是用 unidbg trace 打了个表:

    private void buildmap() {
        Module module = emulator.getMemory().findModule(moduleName);
        long target = module.base + 0x184A8;
        for (long i = 0; i< 0x100; i += 1) {
            Number result = emulator.eFunc(target, i << 56);
             System.out.print("(" + Long.toHexString(i) + "," + Long.toHexString(result.longValue()) + "),");
        }
    }

关于2,可以用Stark/des_keyschedule基于trace的任意一组明密文+第一轮密钥爆破出原始密钥。

最终 exp:

from Crypto.Cipher import DES

key1 = bytes.fromhex('2bd7449f82c5b200')
key2 = bytes.fromhex('952d48114881ff48')
key3 = key1

ciphers = [
    DES.new(key1, DES.MODE_ECB),
    DES.new(key2, DES.MODE_ECB),
    DES.new(key3, DES.MODE_ECB)
]

def tdes_enc(ciphers, pt):
    x = pt
    x = ciphers[0].encrypt(x)
    x = ciphers[1].decrypt(x)
    x = ciphers[2].encrypt(x)
    return x

def tdes_dec(ciphers, ct):
    x = ct
    x = ciphers[2].decrypt(x)
    x = ciphers[1].encrypt(x)
    x = ciphers[0].decrypt(x)
    return x

bmap = dict([(0x0,0x0),(0x1,0x80),(0x2,0x40),(0x3,0xc0),(0x4,0x20),(0x5,0xa0),(0x6,0x60),(0x7,0xe0),(0x8,0x10),(0x9,0x90),(0xa,0x50),(0xb,0xd0),(0xc,0x30),(0xd,0xb0),(0xe,0x70),(0xf,0xf0),(0x10,0x8),(0x11,0x88),(0x12,0x48),(0x13,0xc8),(0x14,0x28),(0x15,0xa8),(0x16,0x68),(0x17,0xe8),(0x18,0x18),(0x19,0x98),(0x1a,0x58),(0x1b,0xd8),(0x1c,0x38),(0x1d,0xb8),(0x1e,0x78),(0x1f,0xf8),(0x20,0x4),(0x21,0x84),(0x22,0x44),(0x23,0xc4),(0x24,0x24),(0x25,0xa4),(0x26,0x64),(0x27,0xe4),(0x28,0x14),(0x29,0x94),(0x2a,0x54),(0x2b,0xd4),(0x2c,0x34),(0x2d,0xb4),(0x2e,0x74),(0x2f,0xf4),(0x30,0xc),(0x31,0x8c),(0x32,0x4c),(0x33,0xcc),(0x34,0x2c),(0x35,0xac),(0x36,0x6c),(0x37,0xec),(0x38,0x1c),(0x39,0x9c),(0x3a,0x5c),(0x3b,0xdc),(0x3c,0x3c),(0x3d,0xbc),(0x3e,0x7c),(0x3f,0xfc),(0x40,0x2),(0x41,0x82),(0x42,0x42),(0x43,0xc2),(0x44,0x22),(0x45,0xa2),(0x46,0x62),(0x47,0xe2),(0x48,0x12),(0x49,0x92),(0x4a,0x52),(0x4b,0xd2),(0x4c,0x32),(0x4d,0xb2),(0x4e,0x72),(0x4f,0xf2),(0x50,0xa),(0x51,0x8a),(0x52,0x4a),(0x53,0xca),(0x54,0x2a),(0x55,0xaa),(0x56,0x6a),(0x57,0xea),(0x58,0x1a),(0x59,0x9a),(0x5a,0x5a),(0x5b,0xda),(0x5c,0x3a),(0x5d,0xba),(0x5e,0x7a),(0x5f,0xfa),(0x60,0x6),(0x61,0x86),(0x62,0x46),(0x63,0xc6),(0x64,0x26),(0x65,0xa6),(0x66,0x66),(0x67,0xe6),(0x68,0x16),(0x69,0x96),(0x6a,0x56),(0x6b,0xd6),(0x6c,0x36),(0x6d,0xb6),(0x6e,0x76),(0x6f,0xf6),(0x70,0xe),(0x71,0x8e),(0x72,0x4e),(0x73,0xce),(0x74,0x2e),(0x75,0xae),(0x76,0x6e),(0x77,0xee),(0x78,0x1e),(0x79,0x9e),(0x7a,0x5e),(0x7b,0xde),(0x7c,0x3e),(0x7d,0xbe),(0x7e,0x7e),(0x7f,0xfe),(0x80,0x1),(0x81,0x81),(0x82,0x41),(0x83,0xc1),(0x84,0x21),(0x85,0xa1),(0x86,0x61),(0x87,0xe1),(0x88,0x11),(0x89,0x91),(0x8a,0x51),(0x8b,0xd1),(0x8c,0x31),(0x8d,0xb1),(0x8e,0x71),(0x8f,0xf1),(0x90,0x9),(0x91,0x89),(0x92,0x49),(0x93,0xc9),(0x94,0x29),(0x95,0xa9),(0x96,0x69),(0x97,0xe9),(0x98,0x19),(0x99,0x99),(0x9a,0x59),(0x9b,0xd9),(0x9c,0x39),(0x9d,0xb9),(0x9e,0x79),(0x9f,0xf9),(0xa0,0x5),(0xa1,0x85),(0xa2,0x45),(0xa3,0xc5),(0xa4,0x25),(0xa5,0xa5),(0xa6,0x65),(0xa7,0xe5),(0xa8,0x15),(0xa9,0x95),(0xaa,0x55),(0xab,0xd5),(0xac,0x35),(0xad,0xb5),(0xae,0x75),(0xaf,0xf5),(0xb0,0xd),(0xb1,0x8d),(0xb2,0x4d),(0xb3,0xcd),(0xb4,0x2d),(0xb5,0xad),(0xb6,0x6d),(0xb7,0xed),(0xb8,0x1d),(0xb9,0x9d),(0xba,0x5d),(0xbb,0xdd),(0xbc,0x3d),(0xbd,0xbd),(0xbe,0x7d),(0xbf,0xfd),(0xc0,0x3),(0xc1,0x83),(0xc2,0x43),(0xc3,0xc3),(0xc4,0x23),(0xc5,0xa3),(0xc6,0x63),(0xc7,0xe3),(0xc8,0x13),(0xc9,0x93),(0xca,0x53),(0xcb,0xd3),(0xcc,0x33),(0xcd,0xb3),(0xce,0x73),(0xcf,0xf3),(0xd0,0xb),(0xd1,0x8b),(0xd2,0x4b),(0xd3,0xcb),(0xd4,0x2b),(0xd5,0xab),(0xd6,0x6b),(0xd7,0xeb),(0xd8,0x1b),(0xd9,0x9b),(0xda,0x5b),(0xdb,0xdb),(0xdc,0x3b),(0xdd,0xbb),(0xde,0x7b),(0xdf,0xfb),(0xe0,0x7),(0xe1,0x87),(0xe2,0x47),(0xe3,0xc7),(0xe4,0x27),(0xe5,0xa7),(0xe6,0x67),(0xe7,0xe7),(0xe8,0x17),(0xe9,0x97),(0xea,0x57),(0xeb,0xd7),(0xec,0x37),(0xed,0xb7),(0xee,0x77),(0xef,0xf7),(0xf0,0xf),(0xf1,0x8f),(0xf2,0x4f),(0xf3,0xcf),(0xf4,0x2f),(0xf5,0xaf),(0xf6,0x6f),(0xf7,0xef),(0xf8,0x1f),(0xf9,0x9f),(0xfa,0x5f),(0xfb,0xdf),(0xfc,0x3f),(0xfd,0xbf),(0xfe,0x7f),(0xff,0xff),])
rmap = {}
for k, v in bmap.items():
    rmap[v] = k

if __name__ == '__main__':
    ct = bytes.fromhex('15317A952E8B1A7CE65DFC6235E1434B5D943FE93A104683')
    pt = b""
    for i in range(0, len(ct), 8):
        tpt = tdes_dec(ciphers, bytes(reversed(ct[i:i+8])))
        pt += tpt
    pt = bytes([rmap[i] for i in pt])
    print(pt)

免费评分

参与人数 8吾爱币 +9 热心值 +8 收起 理由
Tkazer + 1 + 1 谢谢@Thanks!
ioyr5995 + 1 + 1 我很赞同!
风子09 + 1 + 1 用心讨论,共获提升!
solly + 3 + 1 用心讨论,共获提升!
Command + 1 + 1 用心讨论,共获提升!
正己 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
QaQ355 + 1 + 1 热心回复!
是不二的七七啊 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

爱飞的猫 发表于 2025-2-18 06:41

die查出一个没见过的壳,网上没搜到有用的材料,于是开始调试这个壳。

其实就是 UPX,改了下入口、区段名和抹掉 UPX 头,欸嘿。

风子09 发表于 2025-2-16 09:49
本帖最后由 风子09 于 2025-2-16 09:50 编辑

拿到exp
都不知道怎么运行,只能问ai
第七题
得到结果
001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001000064002063
3000947341784547
36807
35106
35106
35106
40209
37374
39075
36807
37374
35673
39075
39642
37374
37941
37374
39075
036807035106035106035106040209037374039075036807037374035673039075039642037374037941037374039075000064002063


第七题(14) D:\54>python flag74.py
b'\xacL\n\xf6V\x96\xa2\x12\x86\n\x0e\x9ev\xa2\xee\x9a\xcc\x86NL\x0cL\xac\x84'

(14) D:\54>python flag75.py
ac4c0af65696a212860a0e9e76a2ee9acc864e4c0c4cac84

提交也是错误!
是不二的七七啊 发表于 2025-2-15 00:45
Ysanky 发表于 2025-2-15 12:58
厉害厉害
C1earWind 发表于 2025-2-16 21:57
学习学习
initialheart 发表于 2025-2-18 13:53
做题2我就把那个LCG整个还原实现出来了然后发现怎么搞都不对
后面没时间做了没做了 结果原来是对密文解密对明文比较
709394Jim 发表于 2025-2-21 17:58
厉害,学习学习。。。。
Knm 发表于 2025-2-22 11:27
精品文章,慢慢学习
Abner123 发表于 2025-2-27 22:54
感谢分享~~~
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-1 09:17

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表