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
and0X
for hexadecimal,0b
and0B
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)
或者在线分解:
得到
> .\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 加密方法走一遍计算私钥就可以了
脚本
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}