-
-
[原创] KCTF2020 秋季赛 第二题 异常信号
-
2020-12-15 00:10 6019
-
程序直接打开就是一个巨大的函数,trace一下看看,有看到
1 2 3 4 | ~~ 1120 ~~ Cabinet.dll!Decompress arg 0 : 0x00c14a38 arg 1 : 0x000500ba and return to module id : 0 , offset: 0x59026 |
又回头看看有一个space的段没有内容,那大概是运行的时候把什么东西解压到这个space段?
那就运行一下,然后Attach。在几个Crackme的线程上打上断点,走几步,就可以看到space填充好内容了。这个时候把程序dump下来看看,找到主要逻辑 sub_2312B0。
算法逻辑最核心是要求找到一个长度为12的数组,然后数字之间两两的差都不同,最大数字是不超过90,最小的是0,还有一些小的限制。
然后写个脚本加点小限制条件来爆破一下。
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 | #include<stdio.h> int diff[ 100 ]; int is_valid( int * arr, int len ) { for ( int i = 0 ; i < = 90 ; i + + ) { diff[i] = 0 ; } for ( int j = 0 ; j < len ; j + + ) { for ( int k = 0 ; k < len ; k + + ) { if (arr[j] > arr[k]) { if (diff[arr[j] - arr[k]] = = 0 ) { diff[arr[j] - arr[k]] = 1 ; } else { return 0 ; } } } } return 1 ; } int arr[ 20 ]; int max_d = 35 ; int main() { for ( int i0 = 0 ; i0 < 90 ; i0 + + ) { for ( int i1 = i0 + 1 ; i1 < 90 ; i1 + + ) { if (i1 - i0 > max_d) break ; arr[ 1 ] = i1; if (!is_valid(arr, 2 )) continue ; / * if (i1 = = 2 ) { printf( "----\n" ); } * / for ( int i2 = i1 + 1 ; i2 < 90 ; i2 + + ) { if (i2 - i1 > max_d) break ; arr[ 2 ] = i2; if (!is_valid(arr, 3 )) continue ; for ( int i3 = i2 + 1 ; i3 < 90 ; i3 + + ) { if (i3 - i2 > max_d) break ; arr[ 3 ] = i3; if (!is_valid(arr, 4 )) continue ; for ( int i4 = i3 + 1 ; i4 < 90 ; i4 + + ) { if (i4 - i3 > max_d) break ; arr[ 4 ] = i4; if (!is_valid(arr, 5 )) continue ; for ( int i5 = i4 + 1 ; i5 < 90 ; i5 + + ) { if (i5 - i4 > max_d) break ; arr[ 5 ] = i5; if (!is_valid(arr, 6 )) continue ; for ( int i6 = i5 + 1 ; i6 < 90 ; i6 + + ) { if (i6 - i5 > max_d) break ; arr[ 6 ] = i6; if (!is_valid(arr, 7 )) continue ; for ( int i7 = i6 + 1 ; i7 < 90 ; i7 + + ) { if (i7 - i6 > max_d) break ; arr[ 7 ] = i7; if (!is_valid(arr, 8 )) continue ; for ( int i8 = i7 + 1 ; i8 < 90 ; i8 + + ) { if (i8 - i7 > max_d) break ; arr[ 8 ] = i8; if (!is_valid(arr, 9 )) continue ; for ( int i9 = i8 + 1 ; i9 < 90 ; i9 + + ) { if (i9 - i8 > max_d) break ; arr[ 9 ] = i9; if (!is_valid(arr, 10 )) continue ; for ( int i10 = i9 + 1 ; i10 < 90 ; i10 + + ) { if (i10 - i9 > max_d) break ; arr[ 10 ] = i10; if (!is_valid(arr, 11 )) continue ; / * for ( int z = 0 ; z < 11 ; z + + ) { printf( "%d, " , arr[z]); } puts(""); * / for ( int i11 = i10 + 1 ; i11 < 90 ; i11 + + ) { if (i11 - i10 > max_d) break ; arr[ 11 ] = i11; if (!is_valid(arr, 12 )) continue ; for ( int z = 0 ; z < 12 ; z + + ) { printf( "%d " , arr[z]); } return 0 ; } } } } } } } } } } } } return 0 ; } |
跑出结果
1 | 0 2 6 24 29 40 43 55 68 75 76 85 |
然后套上题目的随机数逻辑,就可以得到最终答案。
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
赞赏
他的文章
看原图