https://buuoj.cn/challenges#[SUCTF2019]SignIn

exeinfo: NOT Win EXE - .o - ELF [ 64bit obj. Shared obj file - CPU : AMD x86-64 - OS/ABI: unspecified ]

定位到 main 函数

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  char v4[16]; // [rsp+0h] [rbp-4A0h] BYREF
  char v5[16]; // [rsp+10h] [rbp-490h] BYREF
  char v6[16]; // [rsp+20h] [rbp-480h] BYREF
  char v7[16]; // [rsp+30h] [rbp-470h] BYREF
  char v8[112]; // [rsp+40h] [rbp-460h] BYREF
  char v9[1000]; // [rsp+B0h] [rbp-3F0h] BYREF
  unsigned __int64 v10; // [rsp+498h] [rbp-8h]
 
  v10 = __readfsqword(0x28u);
  puts("[sign in]");
  printf("[input your flag]: ");
  __isoc99_scanf("%99s", v8);
  sub_96A(v8, v9);
  __gmpz_init_set_str(v7, "ad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35", 16LL);
  __gmpz_init_set_str(v6, v9, 16LL);
  __gmpz_init_set_str(v4, "103461035900816914121390101299049044413950405173712170434161686539878160984549", 10LL);
  __gmpz_init_set_str(v5, "65537", 10LL);
  __gmpz_powm(v6, v6, v5, v4);
  if ( (unsigned int)__gmpz_cmp(v6, v7) )
    puts("GG!");
  else
    puts("TTTTTTTTTTql!");
  return 0LL;
}

__gmpz_init_set_str 函数非常奇怪,网上一查知道这是一个字符串进制数转成数字的函数

官方文档: https://gmplib.org/ https://gmplib.org/manual/Assigning-Integers#index-mpz_005fset_005fstr

Function: int mpz_set_str (mpz_t rop, const char *str, int base)

Set the value of rop from str, a null-terminated C string in base base. White space is allowed in the string, and is simply ignored.

The base may vary from 2 to 62, or if base is 0, then the leading characters are used: 0x and 0X for hexadecimal, 0b and 0B for binary, 0 for octal, or decimal otherwise.

For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. For bases 37 to 62, upper-case letters represent the usual 10.. 35 while lower-case letters represent 36.. 61.

This function returns 0 if the entire string is a valid number in base base. Otherwise it returns −1.

https://gmplib.org/manual/Integer-Exponentiation#index-mpz_005fpowm_005fui

Function: void mpz_powm (mpz_t rop, const mpz_t base, const mpz_t exp, const mpz_t mod)

Set rop to (base raised to exp) modulo mod.

Negative exp is supported if the inverse base-1 mod mod exists (see mpz_invert in Number Theoretic Functions). If an inverse doesn’t exist then a divide by zero is raised.

其实就是 公钥密码学算法类型综述 里面的 rsa 加密

下载yafu 运行

factor(10346103590081691412139010129904904441395040517371217043416168653)

或者在线分解:

http://www.factordb.com/index.php?query=103461035900816914121390101299049044413950405173712170434161686539878160984549

得到

> .\yafu-x64.exe "factor(103461035900816914121390101299049044413950405173712170434161686539878160984549)"
 
 
fac: factoring 103461035900816914121390101299049044413950405173712170434161686539878160984549
fac: using pretesting plan: normal
fac: no tune info: using qs/gnfs crossover of 95 digits
div: primes less than 10000
fmt: 1000000 iterations
rho: x^2 + 3, starting 1000 iterations on C78
rho: x^2 + 2, starting 1000 iterations on C78
rho: x^2 + 1, starting 1000 iterations on C78
pm1: starting B1 = 150K, B2 = gmp-ecm default on C78
ecm: 30/30 curves on C78, B1=2K, B2=gmp-ecm default
ecm: 74/74 curves on C78, B1=11K, B2=gmp-ecm default
ecm: 161/161 curves on C78, B1=50K, B2=gmp-ecm default, ETA: 0 sec
 
starting SIQS on c78: 103461035900816914121390101299049044413950405173712170434161686539878160984549
 
==== sieving in progress (1 thread):   36224 relations needed ====
====           Press ctrl-c to abort and save state           ====
32701 rels found: 17655 full + 15046 from 172381 partial, (3391.97 rels/sec)
 
SIQS elapsed time = 61.3158 seconds.
Total factoring time = 71.3922 seconds
 
 
***factors found***
 
P39 = 282164587459512124844245113950593348271
P39 = 366669102002966856876605669837014229419
 
ans = 1

按照 rsa 加密方法走一遍计算私钥就可以了

RSA加密

脚本

import gmpy2  
import binascii  
  
E = 65537  
N = 103461035900816914121390101299049044413950405173712170434161686539878160984549  
C = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35  
  
p = 282164587459512124844245113950593348271  
q = 366669102002966856876605669837014229419  
  
phi = (p - 1) * (q - 1)  
D = gmpy2.invert(E, phi)  
M = pow(C, D, N)  
  
print(binascii.unhexlify(hex(M)[2:]).decode())

这行代码是在做什么的呢?它首先将整数 M 转换为十六进制字符串,然后去掉前两个字符(这两个字符是 ‘0x’,表示这是一个十六进制数)。然后,它使用 binascii.unhexlify 函数将这个十六进制字符串转换为二进制数据。最后,它使用 decode 方法将这个二进制数据解码为一个字符串。

suctf{Pwn_@_hundred_years}