Skip to content

Latest commit

 

History

History
547 lines (513 loc) · 16.3 KB

File metadata and controls

547 lines (513 loc) · 16.3 KB

User

int __fastcall main(int argc, const char **argv, const char **envp)
{
  _QWORD *v4; // rcx
  __int64 v5; // rdx
  __int64 v6; // rdx
  _QWORD *v7; // rcx
  __int64 v8; // rdx
  __int64 v9; // rdx
  _QWORD *v10; // rcx
  __int64 v11; // rdx
  __int64 v12; // rdx
  int v13; // eax
  int i; // [rsp+0h] [rbp-30A0h]
  int v15; // [rsp+4h] [rbp-309Ch]
  int j; // [rsp+8h] [rbp-3098h]
  int k; // [rsp+Ch] [rbp-3094h]
  int v18; // [rsp+10h] [rbp-3090h]
  int m; // [rsp+14h] [rbp-308Ch]
  int v20; // [rsp+18h] [rbp-3088h]
  int ii; // [rsp+1Ch] [rbp-3084h]
  int c; // [rsp+20h] [rbp-3080h]
  int v23; // [rsp+24h] [rbp-307Ch]
  size_t v24; // [rsp+28h] [rbp-3078h] BYREF
  size_t n; // [rsp+30h] [rbp-3070h] BYREF
  size_t v26; // [rsp+38h] [rbp-3068h] BYREF
  size_t v27; // [rsp+40h] [rbp-3060h] BYREF
  size_t v28; // [rsp+48h] [rbp-3058h] BYREF
  FILE *stream; // [rsp+50h] [rbp-3050h]
  FILE *v30; // [rsp+58h] [rbp-3048h]
  __int64 v31; // [rsp+60h] [rbp-3040h]
  size_t v32; // [rsp+68h] [rbp-3038h]
  size_t v33; // [rsp+70h] [rbp-3030h]
  size_t v34; // [rsp+78h] [rbp-3028h]
  __int64 v35; // [rsp+80h] [rbp-3020h] BYREF
  __int64 v36; // [rsp+88h] [rbp-3018h]
  __int64 v37; // [rsp+90h] [rbp-3010h]
  __int64 v38; // [rsp+98h] [rbp-3008h] BYREF
  __int64 s1; // [rsp+A0h] [rbp-3000h] BYREF
  __int64 v40; // [rsp+A8h] [rbp-2FF8h]
  __int64 v41; // [rsp+B0h] [rbp-2FF0h]
  __int64 v42; // [rsp+B8h] [rbp-2FE8h] BYREF
  __int64 s2; // [rsp+C0h] [rbp-2FE0h] BYREF
  __int64 v44; // [rsp+C8h] [rbp-2FD8h]
  __int64 v45; // [rsp+D0h] [rbp-2FD0h]
  __int64 v46; // [rsp+D8h] [rbp-2FC8h] BYREF
  _QWORD v47[4]; // [rsp+E0h] [rbp-2FC0h] BYREF
  __int64 v48; // [rsp+100h] [rbp-2FA0h] BYREF
  __int64 v49; // [rsp+108h] [rbp-2F98h]
  __int64 v50; // [rsp+110h] [rbp-2F90h]
  __int64 v51; // [rsp+118h] [rbp-2F88h]
  _BYTE v52[1008]; // [rsp+120h] [rbp-2F80h] BYREF
  _BYTE src[1008]; // [rsp+510h] [rbp-2B90h] BYREF
  _BYTE v54[1008]; // [rsp+900h] [rbp-27A0h] BYREF
  char v55[944]; // [rsp+CF0h] [rbp-23B0h] BYREF
  char s[2016]; // [rsp+10E0h] [rbp-1FC0h] BYREF
  _BYTE dest[2016]; // [rsp+18C0h] [rbp-17E0h] BYREF
  _BYTE v58[2032]; // [rsp+20B0h] [rbp-FF0h] BYREF
  _BYTE v59[2040]; // [rsp+28A0h] [rbp-800h] BYREF
  unsigned __int64 v60; // [rsp+3098h] [rbp-8h]

  v60 = __readfsqword(0x28u);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  printf("Initial data: ");
  if ( !fgets(s, 2002, _bss_start) )
  {
    fwrite("Invalid input\n", 1uLL, 0xEuLL, stderr);
    return 1;
  }
  trim_newline(s);
  if ( (unsigned int)hex_to_bin(s, (__int64)v52, &v24) )
    goto LABEL_47;
  SHA256(v52, v24, &v35);
  s1 = v35;
  v40 = v36;
  v41 = v37;
  v42 = v38;
  s2 = v35;
  v44 = v36;
  v45 = v37;
  v46 = v38;
  for ( i = 0; i <= 99; ++i )
  {
    printf("Round %d\n", i + 1);
    printf("Salt 1: ");
    if ( !fgets(s, 2002, _bss_start) )
      goto LABEL_47;
    trim_newline(s);
    if ( (unsigned int)hex_to_bin(s, (__int64)src, &n) )
      goto LABEL_47;
    printf("Salt 2: ");
    if ( !fgets(s, 2002, _bss_start) )
      goto LABEL_47;
    trim_newline(s);
    if ( (unsigned int)hex_to_bin(s, (__int64)v54, &v26) )
      goto LABEL_47;
    printf("Salt 3: ");
    if ( !fgets(s, 2002, _bss_start) )
      goto LABEL_47;
    trim_newline(s);
    if ( (unsigned int)hex_to_bin(s, (__int64)v55, &v27) )
      goto LABEL_47;
    printf("Salt 4: ");
    if ( !fgets(s, 2002, _bss_start) )
      goto LABEL_47;
    trim_newline(s);
    if ( (unsigned int)hex_to_bin(s, (__int64)v59, &v28) )
      goto LABEL_47;
    if ( n != v27 || v26 != v28 )
    {
      fwrite("Length should be equal\n", 1uLL, 0x17uLL, stderr);
      return 1;
    }
    v33 = n + v26 + 32;
    memcpy(dest, src, n);
    v4 = &dest[n];
    v5 = v40;
    *v4 = s1;
    v4[1] = v5;
    v6 = v42;
    v4[2] = v41;
    v4[3] = v6;
    memcpy(&dest[n + 32], v54, v26);
    SHA256(dest, v33, &s1);
    v34 = v27 + v28 + 32;
    memcpy(v58, v55, v27);
    v7 = &v58[v27];
    v8 = v44;
    *v7 = s2;
    v7[1] = v8;
    v9 = v46;
    v7[2] = v45;
    v7[3] = v9;
    memcpy(&v58[v27 + 32], v59, v28);
    SHA256(v58, v34, &s2);
    if ( !memcmp(&s1, &s2, 0x20uLL) )
    {
      fwrite("Hash should be different\n", 1uLL, 0x19uLL, stderr);
      return 1;
    }
  }
  if ( memcmp(&v42, &v46, 8uLL) || memcmp(&v42, &v38, 8uLL) )
  {
    puts("Wrong answer");
    return 1;
  }
  stream = fopen("flag2", "r");
  if ( !stream )
    goto LABEL_27;
  while ( 1 )
  {
    c = fgetc(stream);
    if ( c == -1 )
      break;
    putchar(c);
  }
  fclose(stream);
  printf("Magic data: ");
  if ( !fgets(s, 2002, _bss_start) || (trim_newline(s), (unsigned int)hex_to_bin(s, (__int64)src, &n)) )
  {
LABEL_47:
    fwrite("Invalid input\n", 1uLL, 0xEuLL, stderr);
    return 1;
  }
  SHA256(src, n, v47);
  v15 = 0;
  for ( j = 0; j <= 99; ++j )
  {
    printf("How many rounds for path %d: ", j + 1);
    if ( !fgets(s, 2002, _bss_start) )
      goto LABEL_47;
    trim_newline(s);
    v31 = strtol(s, (char **)&v26, 10);
    if ( *(_BYTE *)v26 || v31 <= 0 || v31 > 100 )
    {
      fwrite("Invalid number of rounds\n", 1uLL, 0x19uLL, stderr);
      return 1;
    }
    v48 = v47[0];
    v49 = v47[1];
    v50 = v47[2];
    v51 = v47[3];
    dword_1370500 = v31;
    for ( k = 0; v31 > k; ++k )
    {
      printf("Round %d\n", k + 1);
      printf("Salt 1: ");
      if ( !fgets(s, 2002, _bss_start) )
        goto LABEL_47;
      trim_newline(s);
      if ( (unsigned int)hex_to_bin(s, (__int64)v54, &v27) )
        goto LABEL_47;
      printf("Salt 2: ");
      if ( !fgets(s, 2002, _bss_start) )
        goto LABEL_47;
      trim_newline(s);
      if ( (unsigned int)hex_to_bin(s, (__int64)v55, &v28) )
        goto LABEL_47;
      memcpy((char *)&path + 2016 * k, v54, v27);
      *((_QWORD *)&unk_133F568 + 252 * k) = v27;
      memcpy((char *)&path + 2016 * k + 1008, v55, v28);
      qword_133F958[252 * k] = v28;
      v32 = v27 + v28 + 32;
      memcpy(v59, v54, v27);
      v10 = &v59[v27];
      v11 = v49;
      *v10 = v48;
      v10[1] = v11;
      v12 = v51;
      v10[2] = v50;
      v10[3] = v12;
      memcpy(&v59[v27 + 32], v55, v28);
      SHA256(v59, v32, &v48);
    }
    if ( memcmp(&v48, &v35, 0x20uLL) )
    {
      fwrite("Hash does not match\n", 1uLL, 0x14uLL, stderr);
      return 1;
    }
    v18 = 0;
    for ( m = 0; m < v15; ++m )
    {
      if ( dword_363E0[50402 * m] == dword_1370500 )
      {
        v20 = 1;
        for ( ii = 0; ii < dword_1370500; ++ii )
        {
          if ( *((_QWORD *)&unk_5448 + 25201 * m + 252 * ii) != *((_QWORD *)&unk_133F568 + 252 * ii)
            || memcmp(
                 (char *)&paths + 201608 * m + 2016 * ii,
                 (char *)&path + 2016 * ii,
                 *((_QWORD *)&unk_133F568 + 252 * ii))
            || *((_QWORD *)&unk_5838 + 25201 * m + 252 * ii) != qword_133F958[252 * ii]
            || memcmp(
                 (char *)&paths + 201608 * m + 2016 * ii + 1008,
                 (char *)&path + 2016 * ii + 1008,
                 qword_133F958[252 * ii]) )
          {
            v20 = 0;
            break;
          }
        }
        if ( v20 )
        {
          v18 = 1;
          break;
        }
      }
    }
    if ( v18 )
    {
      fwrite("Duplicate path\n", 1uLL, 0xFuLL, stderr);
      return 1;
    }
    v13 = v15++;
    memcpy((char *)&paths + 201608 * v13, &path, (size_t)&unk_31388);
  }
  v30 = fopen("flag3", "r");
  if ( !v30 )
  {
LABEL_27:
    fwrite("Can't open file\n", 1uLL, 0x10uLL, stderr);
    return 1;
  }
  while ( 1 )
  {
    v23 = fgetc(v30);
    if ( v23 == -1 )
      break;
    putchar(v23);
  }
  fclose(v30);
  return 0;
}

请把这段反编译得到的程序写成等价的 Python 代码

o1-preview

Below is the equivalent Python code for the decompiled C program:

import sys
import hashlib

def hex_to_bin(s):
    try:
        data = bytes.fromhex(s)
        return data
    except ValueError:
        return None

def read_salt(n):
    print("Salt %d: " % n, end='')
    s = sys.stdin.readline()
    if not s:
        print("Invalid input", file=sys.stderr)
        exit(1)
    s = s.strip('\n')
    data = hex_to_bin(s)
    if data is None:
        print("Invalid input", file=sys.stderr)
        exit(1)
    return data

def main():
    # Initial data
    print("Initial data: ", end='')
    s = sys.stdin.readline()
    if not s:
        print("Invalid input", file=sys.stderr)
        return 1
    s = s.strip('\n')
    data = hex_to_bin(s)
    if data is None:
        print("Invalid input", file=sys.stderr)
        return 1
    hash1 = hashlib.sha256(data).digest()
    hash_s1 = hash1
    hash_s2 = hash1

    # First loop of 100 rounds
    for i in range(100):
        print("Round %d" % (i+1))
        Salt1 = read_salt(1)
        Salt2 = read_salt(2)
        Salt3 = read_salt(3)
        Salt4 = read_salt(4)
        if len(Salt1) != len(Salt3) or len(Salt2) != len(Salt4):
            print("Length should be equal", file=sys.stderr)
            return 1
        data1 = Salt1 + hash_s1 + Salt2
        hash_s1 = hashlib.sha256(data1).digest()
        data2 = Salt3 + hash_s2 + Salt4
        hash_s2 = hashlib.sha256(data2).digest()
        if hash_s1 == hash_s2:
            print("Hash should be different", file=sys.stderr)
            return 1
    # After 100 rounds, check the last 8 bytes
    if hash_s1[24:32] != hash_s2[24:32] or hash_s1[24:32] != hash1[24:32]:
        print("Wrong answer")
        return 1
    # Open and print 'flag2'
    try:
        with open('flag2', 'r') as f:
            for line in f:
                print(line, end='')
    except FileNotFoundError:
        print("Can't open file", file=sys.stderr)
        return 1
    # Magic data
    print("Magic data: ", end='')
    s = sys.stdin.readline()
    if not s:
        print("Invalid input", file=sys.stderr)
        return 1
    s = s.strip('\n')
    data = hex_to_bin(s)
    if data is None:
        print("Invalid input", file=sys.stderr)
        return 1
    temp_hash = hashlib.sha256(data).digest()
    paths = []
    # Second loop of 100 paths
    for j in range(100):
        print("How many rounds for path %d: " % (j+1), end='')
        s = sys.stdin.readline()
        if not s:
            print("Invalid input", file=sys.stderr)
            return 1
        s = s.strip('\n')
        try:
            num_rounds = int(s)
            if num_rounds <= 0 or num_rounds > 100:
                raise ValueError
        except ValueError:
            print("Invalid number of rounds", file=sys.stderr)
            return 1
        path_salts = []
        temp_temp_hash = temp_hash
        for k in range(num_rounds):
            print("Round %d" % (k+1))
            Salt1 = read_salt(1)
            Salt2 = read_salt(2)
            path_salts.append( (Salt1, Salt2) )
            data = Salt1 + temp_temp_hash + Salt2
            temp_temp_hash = hashlib.sha256(data).digest()
        if temp_temp_hash != hash1:
            print("Hash does not match", file=sys.stderr)
            return 1
        # Check for duplicates
        duplicate = False
        for previous_path in paths:
            if len(previous_path) != len(path_salts):
                continue
            is_same = True
            for (prev_salt1, prev_salt2), (salt1, salt2) in zip(previous_path, path_salts):
                if prev_salt1 != salt1 or prev_salt2 != salt2:
                    is_same = False
                    break
            if is_same:
                duplicate = True
                break
        if duplicate:
            print("Duplicate path", file=sys.stderr)
            return 1
        paths.append(path_salts)
    # Open and print 'flag3'
    try:
        with open('flag3', 'r') as f:
            for line in f:
                print(line, end='')
    except FileNotFoundError:
        print("Can't open file", file=sys.stderr)
        return 1

if __name__ == '__main__':
    main()

This Python script performs the same operations as the provided C code. Here's a brief explanation:

  • It reads an initial hex-encoded input and computes its SHA256 hash.
  • It then goes through 100 rounds where it reads four salts per round, performs checks, and updates the hash values.
  • After the rounds, it checks certain conditions on the hashes.
  • It opens and prints the contents of flag2.
  • It reads a magic data input, computes its hash, and then processes 100 paths. Each path consists of multiple rounds where salts are read and hashes are computed.
  • It checks for duplicate paths and hash mismatches.
  • Finally, it opens and prints the contents of flag3.

Please ensure you have the flag2 and flag3 files in the same directory as the script for it to work correctly.

User

请写得尽可能简洁,错误处理可以直接忽略,写成 assert 即可。

o1-preview

以下是简化后的 Python 代码:

import sys
import hashlib

def hex_to_bin(s):
    return bytes.fromhex(s.strip())

def read_input(prompt):
    print(prompt, end='')
    return sys.stdin.readline().strip()

def read_salt(n):
    s = read_input(f"Salt {n}: ")
    return hex_to_bin(s)

def main():
    # 初始数据
    s = read_input("Initial data: ")
    data = hex_to_bin(s)
    hash1 = hashlib.sha256(data).digest()
    hash_s1 = hash_s2 = hash1

    # 第一部分,100轮迭代
    for i in range(100):
        print(f"Round {i+1}")
        Salt1 = read_salt(1)
        Salt2 = read_salt(2)
        Salt3 = read_salt(3)
        Salt4 = read_salt(4)
        assert len(Salt1) == len(Salt3) and len(Salt2) == len(Salt4), "Length should be equal"
        data1 = Salt1 + hash_s1 + Salt2
        hash_s1 = hashlib.sha256(data1).digest()
        data2 = Salt3 + hash_s2 + Salt4
        hash_s2 = hashlib.sha256(data2).digest()
        assert hash_s1 != hash_s2, "Hash should be different"
    # 检查最后的8字节
    assert hash_s1[-8:] == hash_s2[-8:] == hash1[-8:], "Wrong answer"

    # 输出 flag2 文件内容
    with open('flag2', 'r') as f:
        print(f.read(), end='')

    # Magic data
    s = read_input("Magic data: ")
    data = hex_to_bin(s)
    temp_hash = hashlib.sha256(data).digest()
    paths = []

    # 第二部分,100个路径
    for j in range(100):
        num_rounds = int(read_input(f"How many rounds for path {j+1}: "))
        assert 0 < num_rounds <= 100, "Invalid number of rounds"
        path_salts = []
        temp_temp_hash = temp_hash
        for k in range(num_rounds):
            print(f"Round {k+1}")
            Salt1 = read_salt(1)
            Salt2 = read_salt(2)
            path_salts.append( (Salt1, Salt2) )
            data = Salt1 + temp_temp_hash + Salt2
            temp_temp_hash = hashlib.sha256(data).digest()
        assert temp_temp_hash == hash1, "Hash does not match"
        assert path_salts not in paths, "Duplicate path"
        paths.append(path_salts)

    # 输出 flag3 文件内容
    with open('flag3', 'r') as f:
        print(f.read(), end='')

if __name__ == '__main__':
    main()

这个简化的 Python 脚本按照以下步骤执行:

  1. 从标准输入读取初始数据,转换为二进制,并计算其 SHA256 哈希值,得到 hash1
  2. 初始化 hash_s1hash_s2hash1
  3. 进行第一部分的 100 轮迭代,每轮:
    • 读取 4 个盐值(Salt 1 到 Salt 4),并转换为二进制。
    • 确保 Salt1Salt3 的长度相等,Salt2Salt4 的长度相等。
    • 使用 Salt1hash_s1Salt2 计算新的 hash_s1
    • 使用 Salt3hash_s2Salt4 计算新的 hash_s2
    • 确保新的 hash_s1hash_s2 不相等。
  4. 在完成第一部分后,检查 hash_s1hash_s2hash1 的最后 8 个字节是否相等。
  5. 打开并输出名为 flag2 的文件内容。
  6. 读取 Magic data,计算其 SHA256 哈希值,得到 temp_hash
  7. 进行第二部分的 100 条路径处理,每条路径:
    • 读取该路径的轮数 num_rounds
    • 进行 num_rounds 轮迭代,每轮:
      • 读取 2 个盐值(Salt 1 和 Salt 2),并转换为二进制。
      • 使用 Salt1temp_temp_hashSalt2 计算新的 temp_temp_hash
    • 确保最终的 temp_temp_hashhash1 相等。
    • 确保路径不重复。
  8. 打开并输出名为 flag3 的文件内容。

注意:

  • 所有的错误处理都使用 assert,以简化代码。
  • 输入和输出均通过标准输入/输出完成。
  • 请确保在运行脚本的目录下存在 flag2flag3 文件。

希望这段代码能够满足您的需求。