解析
先查看一下,发现这是一个无壳64位的一个可执行文件,拖入ida中查看main函数。
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
char v4; // [rsp+0h] [rbp-4A0h]
char v5; // [rsp+10h] [rbp-490h]
char v6; // [rsp+20h] [rbp-480h]
char v7; // [rsp+30h] [rbp-470h]
char v8; // [rsp+40h] [rbp-460h]
char v9; // [rsp+B0h] [rbp-3F0h]
unsigned __int64 v10; // [rsp+498h] [rbp-8h]
v10 = __readfsqword(0x28u);
puts("[sign in]");
printf("[input your flag]: ", a2);
__isoc99_scanf("%99s", &v8);
sub_5623E300096A(&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;
}
看一下,sub_5623E300096A做了什么。
size_t __fastcall sub_5623E300096A(const char *a1, __int64 a2)
{
size_t result; // rax
int v3; // [rsp+18h] [rbp-18h]
int i; // [rsp+1Ch] [rbp-14h]
v3 = 0;
for ( i = 0; ; i += 2 )
{
result = strlen(a1);
if ( v3 >= result )
break;
*(_BYTE *)(a2 + i) = byte_5623E3202010[(char)(a1[v3] >> 4)];
*(_BYTE *)(a2 + i + 1LL) = byte_5623E3202010[a1[v3++] & 0xF];
}
return result;
}
发现是这些东西,但是看不懂,咱们开始动调,发现是获取你输入的ascii码是多少,之后一直在循环,直到获取完所有的。
我输入的是5个a,之后返回为6161616161,所以这个是在获取你的ascii码,之后跳了回来,看反编译
__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查了一下,这个是GUN高精度算法库里面的函数,官方文链接: 官方文档。
__gmpz_init_set_str(&v7, "ad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35", 16LL);
#v7保存ad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35以十六进制方式。
__gmpz_init_set_str(&v6, &v9, 16LL);
#v6保存转换为ascii的数值以十六进制
__gmpz_init_set_str(&v4, "103461035900816914121390101299049044413950405173712170434161686539878160984549", 10LL);
#v4保存103461035900816914121390101299049044413950405173712170434161686539878160984549以十进制
__gmpz_init_set_str(&v5, "65537", 10LL);
#v5保存65537以十进制
__gmpz_powm根据官方文档的解释进行对照是v6 ^v5%v4,之后返回值给v6,之后__gmpz_cmp比较v6和v7是否相等,看起来是一个RSA的题,咱们先分解大大整数n,分解出来p和q,
n = 103461035900816914121390101299049044413950405173712170434161686539878160984549
这里要用到一个工具是yafu,调用大佬文章链接: yafu
最后获得到了。
n = 103461035900816914121390101299049044413950405173712170434161686539878160984549
p = 282164587459512124844245113950593348271
q = 366669102002966856876605669837014229419
e = 65537
c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
现在需要求出来m和d的值,利用python的给,gmpy2库进行求解
脚本
import gmpy2
n = 103461035900816914121390101299049044413950405173712170434161686539878160984549
p = 282164587459512124844245113950593348271
q = 366669102002966856876605669837014229419
e = 65537
c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
d = gmpy2.invert(e, (p - 1) * (q - 1))
m = gmpy2.powmod(c, d, n)
print (hex(m)[2:])
求出来了是十六进制,之后转为字符串即可获得suctf{Pwn_@_hundred_years}