【crackmes.one】———— mothlight
Language: c/c++ | Arch: x86-64 | Platform: Windows |Tech: keygenme,FNV-1a,djb2,CRC32,Base64,RC4,TEA

EXE info

程序行为

Behavior
它会提示你输入名称和序列号,并对长度和格式做了限定,接下来开始静态分析

验证逻辑分析

先看一下strings列表是否有作者文档里写的The moth lands. Lantern CMO{........}
strings
然而并没有,那就一步一步分析
进入到main函数
main function
这个程序的输入输出函数是通过WriteFile/ReadFile搭配GetStdHandle实现的
对main函数简单分析一下,发现主要逻辑在54行的if语句
main function2
条件中除了关于长度的判断还有一个函数,它的作用是把序列号四位一组转换成16进制数

stringTohex

stringTohex
图中三个子函数用于把三组字符串转换成十六进制
sub_4015C1
这里又有一个子函数,它是将char转为16进制

__int64 __fastcall sub_40153C(int n48)
{
  if ( n48 >= '0' && n48 <= '9' )
    return n48 - '0';
  if ( n48 >= 'A' && n48 <= 'F' ) //'A'的ASCII码为65,减去15得到10,也就是十六进制A,下面小写字母同理
    return (n48 - 55);
  if ( n48 < 'a' || n48 > 'f' )
    return 0xFFFFFFFFLL;
  return (n48 - 87);   //小写字母
}

关键代码是v5 = v3 | (16 * v5);第一眼可能看不懂,需要翻译一下。
从二进制角度看v5 * 16,这里需要把16转换成2^4,也就是把v5左移4位。
这四位就是0了,或运算就可以把v3搬到这四位,也就顺利完成了十六进制数拼接
最终,stringTohex做的事情就是把字符串"XXXX"转换为十六进制数0xXXXX存储\

回到if判断中,这个函数根据serial得到了三个值,下边sub_401336根据name也得到了三个值,那可想而知sub_4018EC的作用就是把这两组数比较并输出flag。

sub_401336

sub_401336
三个值对应三个算法,从上往下分别为FNV-1a,黄金分割旋转哈希,魔改的djb2。
需要注意一点n1836020840 = 'moth';中moth最终需要作为name传入程序,因为这个程序中出现最多的也是moth。

sub_4018EC

int __fastcall sub_4018EC(int n1, int n2, int n3, int sy, int sz, int sx)
{
  unsigned int v7; // eax
  int i; // [rsp+40h] [rbp-70h]
  int j; // [rsp+40h] [rbp-70h]
  __int64 lpBuffer_; // [rsp+44h] [rbp-6Ch] BYREF
  _BYTE Buffer[32]; // [rsp+4Ch] [rbp-64h] BYREF
  unsigned int v12[8]; // [rsp+6Ch] [rbp-44h] BYREF
  unsigned int v13[8]; // [rsp+8Ch] [rbp-24h] BYREF
  int v14; // [rsp+ACh] [rbp-4h]
  unsigned __int16 _n1; // [rsp+C0h] [rbp+10h]
  unsigned __int16 _n2; // [rsp+C8h] [rbp+18h]
  unsigned __int16 _n3; // [rsp+D0h] [rbp+20h]
  unsigned __int16 _sy; // [rsp+D8h] [rbp+28h]

  _n1 = n1;
  _n2 = n2;
  _n3 = n3;
  _sy = sy;
  v14 = sx ^ n3 | sz ^ n2 | sy ^ n1;
  if ( v14 != 0 )
    // "The moth circles and does not land.\r\n"
    return output(Format: Format);
  sub_4017DF(Y: sy, Z: sz, n3: sx, a4: v13, n32: 32);
  sub_4017DF(Y: _n1, Z: _n2, n3: _n3, a4: v12, n32: 32);
  for ( i = 0; i < 28; ++i )
    Buffer[i + 4] = *(v12 + i) ^ *(v13 + i) ^ byte_402000[i] ^ 0x6B;
  for ( j = 0; j < 4; ++j )
    Buffer[j] = *(&v12[7] + j) ^ *(&v13[7] + j) ^ byte_40201C[j] ^ 0x6B;
  v7 = sub_4017AD(Y: _sy, Z: sz, n3: sx);
  sub_401872(lpBuffer: &lpBuffer_, a2: v7);
  sub_401000(lpBuffer: &Buffer[4], n28: 0x1Cu);
  sub_401000(lpBuffer: &lpBuffer_, n28: 8u);
  return sub_401000(lpBuffer: Buffer, n28: 4u);
}

这个函数比较关键的就是前面的比较,只要不触发// "The moth circles and does not land.\r\n"分支后面程序就会自动生成flag了
关键在于v14 = sx ^ n3 | sz ^ n2 | sy ^ n1。异或是相异输出True,如果相同,则输出False。因此可以用这条性质得出 a ^ b == 0,当且仅当a == b。最终需要v14 == 0,也就是两组数需要对应相等。
到这里可以得出验证的逻辑了

验证逻辑

输入name      输出serial
   ↓              ↓
根据name生成   根据serial生成
  三个值         三个值
     \            /
      一一对应相等
           ↓
        输出flag
因此根据相等条件可以求解出序列号\

keygen

主要是根据name生成三个值的算法,只需要把sub_401336翻译为对应的编程语言即可,这里以python为例,不过需要注意与掩码做与运算以及运算符优先级的问题。
另外还需要注意name生成三个值和serial生成的三个值的对应关系,需要主动追踪调用链一一证实。
完整代码如下:

import sys

M = 0xFFFFFFFF


def check(c) -> int:
    if c < "a" or c > "z":
        return ord(c)
    else:
        return ord(c) - 32


def keygen(name: str, len: int) -> str:
    v12 = 0x811C9DC5
    n = 0x6D6F7468

    for c in name:
        v12 = 0x1000193 * ((check(c) ^ v12) & M) & M
    a3 = ((40503 * (v12 ^ 0x4D4C)) >> 16) & 0xFFFF

    for c in reversed(name):
        v6 = check(c)
        x = ((v6 + 32) ^ n) & M
        n = ((x >> 27) | (x << 5)) & M
        n = (n - 1640531527) & M
    a4 = ((v12 >> 16) ^ n) & 0xFFFF

    v10 = (check(name[0]) + (len << 8)) & M
    for k in range(len):
        v10 = (33 * ((k + 3) * check(name[k]) + v10) + 23) & M
    a5 = (v12 ^ v10 ^ 0x17A1) & 0xFFFF

    return f"ML-{a5:04X}-{a3:04X}-{a4:04X}"


if __name__ == "__main__":
    name = input("name> ").strip()
    if not (3 <= len(name) <= 20):
        sys.exit("name must be 3..20 chars (letters/digits/space/hyphen, >=1 letter)")
    serial = keygen(name, len(name))
    print(f"serial> {serial}")
posted on 2026-11-10 21:55  %HuTao%  阅读(4)  评论(0)    收藏  举报