首页
社区
课程
招聘
1
[原创]2019看雪CTF 晋级赛Q3 第8题-人妒英才
发表于: 2019-9-25 10:30 5868

[原创]2019看雪CTF 晋级赛Q3 第8题-人妒英才

2019-9-25 10:30
5868
start有一处PEB(02:BeingDebugged)反调试,直接跳过。程序有混淆,但可以带着分析程序。
1
2
3
4
5
6
7
8
9
10
11
k_is_9:0042F000 start           proc near
k_is_9:0042F000                 mov     byte ptr [ebp-5], 0
k_is_9:0042F004                 mov     eax, large fs:30h
k_is_9:0042F00A                 mov     al, [eax+2]
k_is_9:0042F00D                 mov     [ebp-5], al
k_is_9:0042F010                 movzx   eax, byte ptr [ebp-5]
k_is_9:0042F014                 test    eax, eax
k_is_9:0042F016
k_is_9:0042F016 loc_42F016:                             ; CODE XREF: start:loc_42F08A↓j
k_is_9:0042F016                 jnz     short loc_42F08A
k_is_9:0042F018                 jmp     sub_4110FF
程序的关键函数,根据界面提示搜索字串直接定位。 流程很明确获取输入,生成key,和目标字串进行比较检测。
1
2
3
4
5
6
7
8
9
10
11
k_is_9:0042F000 start           proc near
k_is_9:0042F000                 mov     byte ptr [ebp-5], 0
k_is_9:0042F004                 mov     eax, large fs:30h
k_is_9:0042F00A                 mov     al, [eax+2]
k_is_9:0042F00D                 mov     [ebp-5], al
k_is_9:0042F010                 movzx   eax, byte ptr [ebp-5]
k_is_9:0042F014                 test    eax, eax
k_is_9:0042F016
k_is_9:0042F016 loc_42F016:                             ; CODE XREF: start:loc_42F08A↓j
k_is_9:0042F016                 jnz     short loc_42F08A
k_is_9:0042F018                 jmp     sub_4110FF
程序的关键函数,根据界面提示搜索字串直接定位。 流程很明确获取输入,生成key,和目标字串进行比较检测。
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
int __usercall keyFunc@<eax>(int a1@<xmm0>)
{
  int v1; // edx
  int v2; // eax
  int v3; // eax
  int v4; // ecx
  int v5; // eax
  int v6; // eax
  int v7; // ecx
  int v8; // eax
  int v9; // eax
  int v10; // ecx
  _DWORD *v11; // eax
  int v12; // eax
  int v13; // ecx
  void *v14; // edx
  int v16; // [esp-1Ch] [ebp-1F8h]
  int v17; // [esp-8h] [ebp-1E4h]
  void *v18; // [esp-4h] [ebp-1E0h]
  char v19; // [esp+0h] [ebp-1DCh]
  struc_String *keyString_1; // [esp+10h] [ebp-1CCh]
  struc_String *keyString; // [esp+14h] [ebp-1C8h]
  int v22; // [esp+18h] [ebp-1C4h]
  char goalBuf[56]; // [esp+20h] [ebp-1BCh]
  char v24; // [esp+58h] [ebp-184h]
  int v25; // [esp+60h] [ebp-17Ch]
  char v26; // [esp+6Ch] [ebp-170h]
  char v27; // [esp+7Fh] [ebp-15Dh]
  struc_String sting; // [esp+88h] [ebp-154h]
  int *v29; // [esp+ACh] [ebp-130h]
  int v30; // [esp+B8h] [ebp-124h]
  int v31; // [esp+BCh] [ebp-120h]
  struc_String goalString; // [esp+188h] [ebp-54h]
  struc_String keyStringFromInput; // [esp+1ACh] [ebp-30h]
  int v34; // [esp+1CCh] [ebp-10h]
  int v35; // [esp+1D8h] [ebp-4h]
  int savedregs; // [esp+1DCh] [ebp+0h]
 
  G1.x = 11;
  G1.y = 4;
  v30 = j_timesPiont((struc_Point *)a1, &G1, times);
  v31 = v1;
  G2.x = v30;
  G2.y = v1;
  sub_4113B6((int)&keyStringFromInput, a1, byte_4252C2);
  v35 = 0;
  v2 = sub_411802(std::cout, "Ep =  y^2 = x^3 + 125*x  ");
  v3 = std::basic_ostream<char,std::char_traits<char>>::operator<<(v2, sub_411159);
  j_asmFun(v4, &v19 == &v19, v3, a1);
  v5 = sub_411802(std::cout, "Prime field p=127,base point G(11,4),publicK(120,41) please find private key k");
  v6 = std::basic_ostream<char,std::char_traits<char>>::operator<<(v5, sub_411159);
  j_asmFun(v7, &v19 == &v19, v6, a1);
  v8 = sub_411802(std::cout, "input your flag:");
  v9 = std::basic_ostream<char,std::char_traits<char>>::operator<<(v8, sub_411159);
  j_asmFun(v10, &v19 == &v19, v9, a1);
  getInput(a1, std::cin, &keyStringFromInput);  // 获取输入
  v29 = &v16;
  v22 = sub_411447(&v16, a1, &keyStringFromInput);
  keyString = (struc_String *)calcuKey(a1, (int)&sting);// 根据输入生成key
  keyString_1 = keyString;
  stringCopy(&keyStringFromInput, a1, keyString);
  releaseString(&sting, a1);
  goalBuf[0] = 0x5E;     //目标结果字串
  goalBuf[1] = 0x26;
  goalBuf[2] = 0;
  goalBuf[3] = 0x13;
  goalBuf[4] = 94;
  goalBuf[5] = 38;
  goalBuf[6] = 86;
  goalBuf[7] = 94;
  goalBuf[8] = 94;
  goalBuf[9] = 38;
  goalBuf[10] = 45;
  goalBuf[11] = 121;
  goalBuf[12] = 94;
  goalBuf[13] = 38;
  goalBuf[14] = 4;
  goalBuf[15] = 5;
  goalBuf[16] = 94;
  goalBuf[17] = 38;
  goalBuf[18] = 90;
  goalBuf[19] = 116;
  goalBuf[20] = 94;
  goalBuf[21] = 38;
  goalBuf[22] = 49;
  goalBuf[23] = 73;
  goalBuf[24] = 94;
  goalBuf[25] = 38;
  goalBuf[26] = 8;
  goalBuf[27] = 41;
  goalBuf[28] = 94;
  goalBuf[29] = 38;
  goalBuf[30] = 94;
  goalBuf[31] = 55;
  goalBuf[32] = 94;
  goalBuf[33] = 38;
  goalBuf[34] = 53;
  goalBuf[35] = 2;
  goalBuf[36] = 94;
  goalBuf[37] = 38;
  goalBuf[38] = 12;
  goalBuf[39] = 92;
  goalBuf[40] = 94;
  goalBuf[41] = 38;
  goalBuf[42] = 98;
  goalBuf[43] = 50;
  goalBuf[44] = 94;
  goalBuf[45] = 38;
  goalBuf[46] = 57;
  goalBuf[47] = 41;
  goalBuf[48] = 94;
  goalBuf[49] = 38;
  goalBuf[50] = 16;
  goalBuf[51] = 51;
  goalBuf[52] = 94;
  goalBuf[53] = 38;
  goalBuf[54] = 102;
  goalBuf[55] = 18;
  v18 = j_getThis_0((int)&v27);
  v11 = sub_4112C1(&v26, (int)goalBuf, (int)&v24);
  createString(&goalString, a1, *v11, v11[1], (int)v18);
  if ( stringCmp((int)&keyStringFromInput, a1, (int)&goalString) )// key 验证
    sub_41186B("try again", v19);
  else
    sub_41186B("Congratulations~~", v19);
  v12 = system("pause");
  j_asmFun(v13, &v19 == &v19, v12, a1);
  v25 = 0;
  releaseString(&goalString, a1);
  v35 = -1;
  releaseString(&keyStringFromInput, a1);
  v18 = v14;
  v17 = v25;
  sub_411677((int)&savedregs, (int)&dword_41BC54);
  return j_asmFun((unsigned int)&savedregs ^ v34, 1, v17, a1);
}

分析核心的key生成函数

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
int __usercall keyFunc@<eax>(int a1@<xmm0>)
{
  int v1; // edx
  int v2; // eax
  int v3; // eax
  int v4; // ecx
  int v5; // eax
  int v6; // eax
  int v7; // ecx
  int v8; // eax
  int v9; // eax
  int v10; // ecx
  _DWORD *v11; // eax
  int v12; // eax
  int v13; // ecx
  void *v14; // edx
  int v16; // [esp-1Ch] [ebp-1F8h]
  int v17; // [esp-8h] [ebp-1E4h]
  void *v18; // [esp-4h] [ebp-1E0h]
  char v19; // [esp+0h] [ebp-1DCh]
  struc_String *keyString_1; // [esp+10h] [ebp-1CCh]
  struc_String *keyString; // [esp+14h] [ebp-1C8h]
  int v22; // [esp+18h] [ebp-1C4h]
  char goalBuf[56]; // [esp+20h] [ebp-1BCh]
  char v24; // [esp+58h] [ebp-184h]
  int v25; // [esp+60h] [ebp-17Ch]
  char v26; // [esp+6Ch] [ebp-170h]
  char v27; // [esp+7Fh] [ebp-15Dh]
  struc_String sting; // [esp+88h] [ebp-154h]
  int *v29; // [esp+ACh] [ebp-130h]
  int v30; // [esp+B8h] [ebp-124h]
  int v31; // [esp+BCh] [ebp-120h]
  struc_String goalString; // [esp+188h] [ebp-54h]
  struc_String keyStringFromInput; // [esp+1ACh] [ebp-30h]
  int v34; // [esp+1CCh] [ebp-10h]
  int v35; // [esp+1D8h] [ebp-4h]
  int savedregs; // [esp+1DCh] [ebp+0h]
 
  G1.x = 11;
  G1.y = 4;
  v30 = j_timesPiont((struc_Point *)a1, &G1, times);
  v31 = v1;
  G2.x = v30;
  G2.y = v1;
  sub_4113B6((int)&keyStringFromInput, a1, byte_4252C2);
  v35 = 0;
  v2 = sub_411802(std::cout, "Ep =  y^2 = x^3 + 125*x  ");
  v3 = std::basic_ostream<char,std::char_traits<char>>::operator<<(v2, sub_411159);
  j_asmFun(v4, &v19 == &v19, v3, a1);
  v5 = sub_411802(std::cout, "Prime field p=127,base point G(11,4),publicK(120,41) please find private key k");
  v6 = std::basic_ostream<char,std::char_traits<char>>::operator<<(v5, sub_411159);
  j_asmFun(v7, &v19 == &v19, v6, a1);
  v8 = sub_411802(std::cout, "input your flag:");
  v9 = std::basic_ostream<char,std::char_traits<char>>::operator<<(v8, sub_411159);
  j_asmFun(v10, &v19 == &v19, v9, a1);
  getInput(a1, std::cin, &keyStringFromInput);  // 获取输入
  v29 = &v16;
  v22 = sub_411447(&v16, a1, &keyStringFromInput);
  keyString = (struc_String *)calcuKey(a1, (int)&sting);// 根据输入生成key
  keyString_1 = keyString;
  stringCopy(&keyStringFromInput, a1, keyString);
  releaseString(&sting, a1);
  goalBuf[0] = 0x5E;     //目标结果字串
  goalBuf[1] = 0x26;
  goalBuf[2] = 0;
  goalBuf[3] = 0x13;
  goalBuf[4] = 94;
  goalBuf[5] = 38;
  goalBuf[6] = 86;
  goalBuf[7] = 94;
  goalBuf[8] = 94;
  goalBuf[9] = 38;
  goalBuf[10] = 45;
  goalBuf[11] = 121;
  goalBuf[12] = 94;
  goalBuf[13] = 38;
  goalBuf[14] = 4;
  goalBuf[15] = 5;
  goalBuf[16] = 94;
  goalBuf[17] = 38;
  goalBuf[18] = 90;
  goalBuf[19] = 116;
  goalBuf[20] = 94;
  goalBuf[21] = 38;
  goalBuf[22] = 49;
  goalBuf[23] = 73;
  goalBuf[24] = 94;
  goalBuf[25] = 38;
  goalBuf[26] = 8;
  goalBuf[27] = 41;
  goalBuf[28] = 94;
  goalBuf[29] = 38;
  goalBuf[30] = 94;
  goalBuf[31] = 55;
  goalBuf[32] = 94;
  goalBuf[33] = 38;
  goalBuf[34] = 53;
  goalBuf[35] = 2;
  goalBuf[36] = 94;
  goalBuf[37] = 38;
  goalBuf[38] = 12;
  goalBuf[39] = 92;
  goalBuf[40] = 94;
  goalBuf[41] = 38;
  goalBuf[42] = 98;
  goalBuf[43] = 50;
  goalBuf[44] = 94;
  goalBuf[45] = 38;
  goalBuf[46] = 57;
  goalBuf[47] = 41;
  goalBuf[48] = 94;
  goalBuf[49] = 38;
  goalBuf[50] = 16;
  goalBuf[51] = 51;
  goalBuf[52] = 94;
  goalBuf[53] = 38;
  goalBuf[54] = 102;
  goalBuf[55] = 18;
  v18 = j_getThis_0((int)&v27);
  v11 = sub_4112C1(&v26, (int)goalBuf, (int)&v24);
  createString(&goalString, a1, *v11, v11[1], (int)v18);
  if ( stringCmp((int)&keyStringFromInput, a1, (int)&goalString) )// key 验证
    sub_41186B("try again", v19);
  else
    sub_41186B("Congratulations~~", v19);
  v12 = system("pause");
  j_asmFun(v13, &v19 == &v19, v12, a1);
  v25 = 0;
  releaseString(&goalString, a1);
  v35 = -1;
  releaseString(&keyStringFromInput, a1);
  v18 = v14;
  v17 = v25;
  sub_411677((int)&savedregs, (int)&dword_41BC54);
  return j_asmFun((unsigned int)&savedregs ^ v34, 1, v17, a1);
}
生成函数的依据是椭圆曲线方程,用输入字串的每个字符和字符的index进行倍点运算。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 for ( i = 0; ; ++i )
  {
    len = getInpuKeyLen((int)sting, a1);        // 获取key长度
    if ( i >= len )
      break;
    index = i;
    oneKey = *(char *)getKeyByIndex((int)sting, a1, i);
    pointPair_1 = (struc_PointPair *)timesPiontByOneKey(a1, &pointPair, index, oneKey);
    copyPoint_1(&pointPair_2, a1, pointPair_1);
    j_addZuobiao2Buf_0(a1, (struc_String *)&resultStr, pointPair_2.p1_x);
    j_addZuobiao2Buf_0(a1, (struc_String *)&resultStr, pointPair_2.p1_y);
    j_addZuobiao2Buf_0(a1, (struc_String *)&resultStr, pointPair_2.p2_x);
    j_addZuobiao2Buf_0(a1, (struc_String *)&resultStr, pointPair_2.p2_y);
  }
运算过程如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 for ( i = 0; ; ++i )
  {
    len = getInpuKeyLen((int)sting, a1);        // 获取key长度
    if ( i >= len )
      break;
    index = i;
    oneKey = *(char *)getKeyByIndex((int)sting, a1, i);
    pointPair_1 = (struc_PointPair *)timesPiontByOneKey(a1, &pointPair, index, oneKey);
    copyPoint_1(&pointPair_2, a1, pointPair_1);
    j_addZuobiao2Buf_0(a1, (struc_String *)&resultStr, pointPair_2.p1_x);
    j_addZuobiao2Buf_0(a1, (struc_String *)&resultStr, pointPair_2.p1_y);
    j_addZuobiao2Buf_0(a1, (struc_String *)&resultStr, pointPair_2.p2_x);
    j_addZuobiao2Buf_0(a1, (struc_String *)&resultStr, pointPair_2.p2_y);
  }
运算过程如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int __usercall timesPiontByOneKey_0@<eax>(struc_Point *a1@<xmm0>, struc_PointPair *result, int index, int onekey)
{
  int y1AfterTimes; // edx
  int y2AfterTimes; // edx
  struc_Point p1; // [esp+100h] [ebp-20h]
  struc_Point p2; // [esp+110h] [ebp-10h]
  int v9; // [esp+11Ch] [ebp-4h]
  int savedregs; // [esp+120h] [ebp+0h]
 
  p2.x = j_timesPiont(a1, &G1, 17);             // G1(11,4)->(0x5e,0x26)
  p2.y = y1AfterTimes;
  p1.x = index * j_timesPiont(a1, &G2, 17) % 127;// G2(14,91)->(0x56,0x5A) 
  p1.y = onekey * y2AfterTimes % 127;
  copyPoint(result, (int)a1, (int)&p2, (int)&p1);
  sub_411677((int)&savedregs, (int)&dword_417788);
  return j_asmFun((unsigned int)&savedregs ^ v9, 1, (int)result, (int)a1);
}
程序中有连个G点,G1(11,4),G2(14,91);根据G1,G2分别生成P1和P2两个点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int __usercall timesPiontByOneKey_0@<eax>(struc_Point *a1@<xmm0>, struc_PointPair *result, int index, int onekey)
{
  int y1AfterTimes; // edx
  int y2AfterTimes; // edx
  struc_Point p1; // [esp+100h] [ebp-20h]
  struc_Point p2; // [esp+110h] [ebp-10h]
  int v9; // [esp+11Ch] [ebp-4h]
  int savedregs; // [esp+120h] [ebp+0h]
 
  p2.x = j_timesPiont(a1, &G1, 17);             // G1(11,4)->(0x5e,0x26)
  p2.y = y1AfterTimes;
  p1.x = index * j_timesPiont(a1, &G2, 17) % 127;// G2(14,91)->(0x56,0x5A) 
  p1.y = onekey * y2AfterTimes % 127;
  copyPoint(result, (int)a1, (int)&p2, (int)&p1);
  sub_411677((int)&savedregs, (int)&dword_417788);
  return j_asmFun((unsigned int)&savedregs ^ v9, 1, (int)result, (int)a1);
}
程序中有连个G点,G1(11,4),G2(14,91);根据G1,G2分别生成P1和P2两个点。
完成计算后分别将带你的坐标p.x,p.y保存。

[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!

收藏
免费 1
支持
分享
赞赏记录
参与人
雪币
留言
时间
PLEBFE
为你点赞~
2023-1-22 03:19
最新回复 (0)
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册