SUCTF2019_signin

文章发布时间:

最后更新时间:

文章总字数:
713

预计阅读时间:
3 分钟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
__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 ( __gmpz_cmp(v6, v7) )
puts("GG!");
else
puts("TTTTTTTTTTql!");
return 0LL;
}

这一题涉及到的知识点非常多 所以写进博客记录一下

出现了不认识的系统函数 上网查阅一下其对应的作用

1
2
3
4
5
6
7
8
9
10
__gmpz_init_set_str 其实就是 mpz_init_set_str int mpz_init_set_str (mpz_t rop, const char *str, int base) 函数:

这三个参数分别是多精度整数变量,字符串,进制。 这个函数的作用就是将 str 字符数组以 base 指定的进制解读成数值并写入 rop 所指向的内存。
.
void mpz_powm (mpz_t rop, const mpz_t base, const mpz_t exp, const mpz_t mod) 函数:
其实就是计算 base 的 exp 次方,并对 mod 取模,最后将结果写入 rop 中, 这个运算的过程和RSA的加密过程一样。
.
接下来就是__gmpz_cmp函数,看这个函数名就知道这是比较函数。
mpz_cmp(b, c); //b 大于 c,返回 1;b
等于 c,返回 0;b 小于 c,返回-1*/

随后跟进一下sub_96A函数 看一下他对v8这个字符串进行了什么样的处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
size_t __fastcall sub_96A(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;
*(a2 + i) = word_202010[a1[v3] >> 4]; //除以16
*(a2 + i + 1LL) = word_202010[a1[v3++] & 0xF]; ///求余16
}
return result;
}

word_202010这个数组跟进一下 查看内容

1
0123456789abcdef

a2是v9 即一个空的数组 用来存放运算完的v8

看一下if的第一个语句 涉及到了>>右移运算符

(5条消息) 关于C/C++左移右移运算符的总结_pineapple-coder的博客-CSDN博客

这其实就是一个转16进制的算法 将这两个十六进制数分开存储

比如输入字符 ‘1’ ,它的整数是49,49除16的整数是3,余数是1,在word_202010下标中分别对应3和1,构成的31就是字符 ‘1’的ASCII的十六进制形式,只不过是分开的十六进制,3 1 共两个字节

程序主体部分到这里已经了解清楚了 接下来就是逆向RSA加密

e=65537

密文c=0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35

n=103461035900816914121390101299049044413950405173712170434161686539878160984549

浅析RSA算法 - 知乎 (zhihu.com)

首先我们需要分解出两个指数p q

利用工具得到

1
2
p=282164587459512124844245113950593348271
q=366669102002966856876605669837014229419

随后计算私匙

最后成功得到明文

1
suctf{Pwn_@_hundred_years}