看雪CTF第十題

__int64 sub_140006F50()
{
  __int64 v0; // r8@1
  __int64 v1; // r9@1
  signed __int64 len; // rax@1
  __int64 v3; // r8@4
  __int64 i; // rdx@4
  char anscii; // cl@5
  char v6; // al@9
  int v7; // eax@14
  const char *v8; // rcx@14
  char rp_rsa_zhishu(n); // [sp+20h] [bp-18h]@12

  print_140006EA0("=========================================================================\n");
  print_140006EA0("                     看雪CTF2017 CrackMe by 海風月影\n\n");
  print_140006EA0(&unk_14004BF18);
  input_140006F00((__int64)&unk_14004BF2C, (__int64)input_key, v0, v1);
  print_140006EA0(&unk_14004BF30);
  len = -1i64;
  do
    ++len;
  while ( input_key[len] );
  if ( (_DWORD)len == 70 )                      // 長度70
  {
    v3 = 0i64;
    i = 0i64;
    while ( 1 )
    {
      anscii = input_key[i];
      if ( (unsigned __int8)(anscii - 48) > 9u && (unsigned __int8)(anscii - 65) > 031u )// 檢查輸入字符是否數字或大寫字母
        break;
      if ( ++i >= 70 )
      {
        *(_DWORD *)input_key_before6 = *(_DWORD *)input_key;// 輸入的前6位字符串  rsa_e
        *(_WORD *)input_key_before6_4 = *(_WORD *)_input_key_4_;
        do
        {
          v6 = input_key[v3 + 6];
          input_key_after6[v3++] = v6;          // 輸入的第6位後的64位字符串  rsa_q
        }
        while ( v6 );                           // 初始化rop,並賦值rop = str,其中str是一個表示base進制整數的字符數組
        mpz_init_set_str(&rp_rsa_e, input_key_before6, 16i64);// mpz_init_set_str (mpz_t r, const char *sp, int base)
        mpz_init_set_str(&rp_rsa_p, input_key_after6, 16i64);// mpz_init_set_str (mpz_t r, const char *sp, int base)
        if ( mpz_probab_prime_p(&rp_rsa_p, 500i64) )// mpz_probab_prime_p (const mpz_t n, int reps)
        {                                       // 檢測n是否爲素數。該函數首先對n進行試除,而後使用米勒-拉賓素性檢測對n進行測試,reps表示進行檢測的次數。若是n爲素數,返回2;若是n可能爲素數,返回1;若是n爲合數,返回0。
          if ( mpz_probab_prime_p(&rp_rsa_e, 500i64) )
          {                                     // 初始化rop,並將其值設置爲op
            mpz_init_set_ui(&rp_rsa_q, 0i64);   // mpz_init_set_ui (mpz_t r, unsigned long int x)
            mpz_init_set_str(
              &rp_rsa_n,
              "6248BC3AB92A33B000FDB88568F19727F92F79EB68FF6AD73203EFD20A3E331BE941C7AA288095F33BC4B255FD983114D480EFFBEE"
              "2E313E6218A57F9CCC8189",
              16i64);
            mpz_init_set_str(
              &rp_rsa_d,
              "2476A7F02588913F228923E1F36F963F29708C07B117396817A6B94C336FC77FF7D381925EB40CFED8FBE894570155E41569B4EC69"
              "B26CB0320105A29651CB4B",
              16i64);
            mpz_init_set_ui(&rp_rsa_zhishu(n), 0i64);// 置 r 爲 n mod d
            mpz_mod(&rp_rsa_zhishu(n), &rp_rsa_n, &rp_rsa_p);// mpz_mod (mpz_t r, const mpz_t n, const mpz_t d)
            if ( !(unsigned int)mpz_cmp_si((__int64)&rp_rsa_zhishu(n), 0i64) )// mpz_cmp_si (const mpz_t a, const mpz_t b)
            {
              // 置 q 爲 n/d。 只有預先知道 d 是整除 n 的, 這些函數才返回正確的結果。
              // 這裏使用的程序比其餘的除法函數的快得多, 當確知整除發生時它是最好的選
              // 擇, 例如化簡有理數爲最小項時
              mpz_divexact(&rp_rsa_q, &rp_rsa_n, &rp_rsa_p);// mpz_divexact (mpz_t q, const mpz_t n, const mpz_t d)
              // 比較 op1 和 op2。 若 op1 > op2 則返回正值, 若 op1 = op2 則返回 0, 若 op1 <
              // op2 則返回負值。
              // 須要注意的是 mpz_cmp_ui 和 mpz_cmp_si 是宏, 它們可能對參數估值一次以
              // 上。
              if ( mpz_cmp(&rp_rsa_p, &rp_rsa_q) <= 0 )// mpz_cmp (const mpz_t a, const mpz_t b)
              {
                // N = (p-1)*(q-1)
                mpz_sub_ui(&rp_rsa_p, (__int64)&rp_rsa_p, 1ui64);// mpz_sub_ui (mpz_t r, const mpz_t a, unsigned long b)
                mpz_sub_ui(&rp_rsa_q, (__int64)&rp_rsa_q, 1ui64);
                mpz_mul(&rp_rsa_zhishu(n), &rp_rsa_p, &rp_rsa_q);// mpz_mul (mpz_t r, const mpz_t u, const mpz_t v)
                // 計算 op1 模 op2 的逆, 並將結果置於 rop。 若是逆存在則返回非 0 值, 且 rop 滿
                // 足 0 ? rop < op2。 若是逆不存在, 那麼返回 0, 此時 rop 是無心義的

                // e的 φ(n)-1 次方,就是e的模反元素。
                mpz_invert((__int64)&rp_rsa_zhishu(n), (__int64)&rp_rsa_e, (__int64)&rp_rsa_zhishu(n));// mpz_invert (mpz_t r, const mpz_t u, const mpz_t m)
                v7 = mpz_cmp(&rp_rsa_d, &rp_rsa_zhishu(n));
                v8 = "註冊成功!!!\n\n";
                if ( !v7 )
                  goto LABEL_16;
              }
            }
          }
        }
        break;
      }
    }
  }
  v8 = "註冊失敗\n\n";
LABEL_16:
  print_140006EA0(v8);
  sub_14002D1B4("pause");
  return 0i64;
}

分析發現這是RSA算法,提供了N和D,輸入e和p進行匹配。其計算公式以下:算法

q=n/p
N = (p-1)*(q-1)
d1 = invert(e,N)
d1 == d?

其中的invert是求模反元素的函數調用。數組

相關文章
相關標籤/搜索