首页
社区
课程
招聘
[原创]KCTF2022秋季赛 第二题 盗贼作乱 题解
2022-11-30 12:26 8013

[原创]KCTF2022秋季赛 第二题 盗贼作乱 题解

2022-11-30 12:26
8013

CM2022


 

根据调试,确定函数的功能

 

首先通过第一个if条件进入while 1循环后,进入第一个函数调试,会发现程序会有一个大数结构

1
2
3
4
struct bignum{
    int len;
    uint8_t data[32];
}

那么前面的函数的功能也可以据此bignum推测出来了。

 

此时main函数的比较部分整理出来如下:

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
if ( v3 > 0
   && (v6 = v4 - v3, v4 - v3 > 0)
   && frombase62(first, &a2, v3, table) > 0
   && frombase62(&second, &v10[v3], v6 - 1, table) > 0
   && (frombase62(&example, "IRtzloZ6iuB", strlen("IRtzloZ6iuB"), table),
       init(firstop, 0),
       init(secondop, 0),
       compare((char *)first, (char *)&second) < 0)
   && compare((char *)first, (char *)&example) < 0
   && compare((char *)&second, (char *)&example) < 0 )
 {
   v7 = 0;
   while ( 1 )
   {
     i = v7 + 1;
     plus(firstop, firstop, first);
     plus(secondop, secondop, &second);
     mod((unsigned int *)firstop, (char *)firstop, (char *)&example);
     mod((unsigned int *)secondop, (char *)secondop, (char *)&example);
     init(&firststageNumber, 1);
     sub(&firststageNumber, firstop, &firststageNumber);
     if ( !compare((char *)&firststageNumber, (char *)first) )
     {
       ++succ;
       sbf1(&firststageNumber, &firststageNumber, first);// sbf1唯一的作用就是当i==32时,succ+=4
     }
     init(&secondStageNumber, 1);
     plus(&secondStageNumber, secondop, &secondStageNumber);
     if ( !compare((char *)&secondStageNumber, (char *)&second) )
     {
       ++succ;
       sbf2(&secondStageNumber, (char *)&example, (char *)&second);// sbf2唯一的作用就是当i==32时,succ+=4
     }
     if ( succ == 10 )
       break;
     v7 = i;
     if ( i >= 2097152 )
       goto LABEL_20;
   }
   sub_40284A((int)aSuccess);
   return 0;
 }

难搞的是sbf1sbf2函数,因为此函数多次引用了main函数里面的全局变量,而且包含多个if条件,在乘法计算完后有这些操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
arrAnd(&firststageNumber, firstop, secondop);
    if ( compare((char *)&firststageNumber, (char *)&secondStageNumber) > 0 && succ > 0 )
    {
      maybe_div2(&firststageNumber, &firststageNumber, i);
      plus(&secondStageNumber, first, second);
      sub(&firststageNumber, &firststageNumber, &secondStageNumber);
    }
    init(&firststageNumber, 4);
    shlarg3(&secondStageNumber, &firststageNumber, 3);
    if ( succ > 0
      && *(int *)((char *)&examplerawNumber + (unsigned __int8)SecondStageNumber) == (unsigned __int8)SecondStageNumber )// i == 32
    {
      plus(&firststageNumber, &firststageNumber, &secondStageNumber);
      v13 = GetModImm(&firststageNumber, i);
      *((_BYTE *)&examplerawNumber + *((unsigned __int8 *)&firststageNumber + 4)) += 4;
      shlarg3(&firststageNumber, &firststageNumber, v13);
      sub(&secondStageNumber, &firststageNumber, &secondStageNumber);
    }

而这些函数里面又有类似sbf1的操作

 

理性分析一下会发现一个问题:
sbf1sbf2函数改了哪些变量呢?

 

改了图里的firststagenumbersecondstageNumber

 

这两个变量在执行compare 比较之前会被重新赋值,没有问题

 

还有在特殊条件下有一个条件会改example->data的值

 

这个example->data是前面用来取模的数

 

这个特殊条件又是写死的。

 

example->data + 32 == 32时,即在内存布局中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.data:0040A9D0 example         dd 0                    ; DATA XREF: sub+AD↑o
.data:0040A9D0                                         ; ArrOr+FF↑o ...
.data:0040A9D4 examplerawNumber dd 8 dup(0)            ; DATA XREF: sbf1+1B9↑r
.data:0040A9D4                                         ; sbf1+1FD↑o ...
.data:0040A9F4 i               dd 0                    ; DATA XREF: compare:loc_4016D0↑r
.data:0040A9F4                                         ; compare+65↑r ...
.data:0040A9F8 succ            dd 0                    ; DATA XREF: compare+7B↑r
.data:0040A9F8                                         ; plus+D0↑r ...
.data:0040A9FC ; signed int firstop[9]
.data:0040A9FC firstop         dd 0, 8 dup(?)          ; DATA XREF: ArrOr+83↑o
.data:0040A9FC                                         ; sbf1+118↑o ...
.data:0040AA20 ; signed int secondop[9]
.data:0040AA20 secondop        db ?                    ; DATA XREF: arrAnd+89↑o
.data:0040AA20                                         ; arrAnd+11A↑o ...

i == 32时,example->data + 36 (succ) += 4;

 

说人话即是

 

计算方程

1
2
32 * X - 1 % 10000000000000000000 = X
32 * X + 1 % 10000000000000000000 = X

的两个解

 

这里直接z3解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from z3 import *
magic = 0x8AC7230489E80000
 
Input1 = Int("Input1")
Input2 = Int("Input2")
s = Solver()
s.add(Input1 < Input2)
s.add(Input2 < magic)
 
s.add(32 * Input1 % magic - 1 == Input1)
s.add(32 * Input2 % magic + 1 == Input2)
print(magic)
print(s.check())
print(s.model())
# [Input2 = 6129032258064516129, Input1 = 3870967741935483871]
# 用cyberchef 转换一下
print("4bx4XreZxSZ"[::-1])
print("7Il21x7Pvyj"[::-1])
# ZSxZerX4xb4-jyvP7x12lI7

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞2
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回