逆向攻防世界CTF系列48-Signin.md
直接定位
输入,然后跟踪96A
一个整数一个余数你会发现这是把输入字符变成两个分开的十六进制存储起来,比如输入字符 ‘1’ ,它的整数是49,49除16的整数是3,余数是1,在byte_202010下标中分别对应3和1,构成的31就是字符 '1’的ASCII的十六进制形式,只不过是分开的十六进制,3 1 共两个字节。
__gmpz_init_set_str猜测就是赋值,查了一下:
就是将字符串"ad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35" 看做是一个十六进制数,将其保存到v7中,v7中的值为数字类型的十六进制数ad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35 。
__gmpz_powm,查了一下:
void mpz_powm (mpz_t rop, const mpz_t base, const mpz_t exp, const mpz_t mod) [Function]
Set rop to base^exp mod mod.
其实就是计算 base 的 exp 次方,并对 mod 取模,最后将结果写入 rop 中
rop = (base ^ exp) % mod
v7 = (v6v5) % v4,求v6
有点难解
ad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35需要转成10进制
78510953323073664022480086884088868606008442004646066020022844860080426088640
做不出来了,看wp,是RSA(现学一下)
RSA算法:
其中e就是v5,C是v7,n是v4
所以__gmpz_powm是加密,我们要求d,p,q,m
首先要分解N得PQ
分解:
网站:http://www.factordb.com/index.php
P = 282164587459512124844245113950593348271
Q = 366669102002966856876605669837014229419
有了P、Q和E,我们就可以计算出欧拉函数,然后我们就可以通过欧拉函数φ(N)和公钥E计算出私钥D。
使用python的gmpy2库计算私钥。(E * D % φ(N) = 1)
先解出d
d = 91646299298871237857836940212608056141193465208586711901499120163393577626813
再解密
import libnum
from Crypto.Util.number import long_to_bytesq = 282164587459512124844245113950593348271
p = 366669102002966856876605669837014229419
e = 65537
c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
n = 103461035900816914121390101299049044413950405173712170434161686539878160984549# invmod(a, n) - 求a对于n的模逆,这里逆向加密过程中计算ψ(n)=(p-1)(q-1),对ψ(n)保密,也就是对应根据e*d=1 mod ψ(n),求出d
d = libnum.invmod(e, (p - 1) * (q - 1))
m = pow(c, d, n)
string = long_to_bytes(m) # 获取m明文,要转成字符串
# print(ex(m)[2:].decode('hex'))
print(string)
在Python中,long_to_bytes函数是一个常用于将长整型(long)数值转换为字节序列(bytes)的函数。这个函数在加密和解密操作中特别有用,因为它允许将数值转换为可以在网络上传输或存储在文件中的格式。
个常用于将长整型(long)数值转换为字节序列(bytes)的函数。这个函数在加密和解密操作中特别有用,因为它允许将数值转换为可以在网络上传输或存储在文件中的格式。