0%

刮开有奖-[GXYCTF2019]luck_guy-findit-简单注册机-[BJDCTF2020]JustRE

@TOC

刮开有奖

运行发现有点劣质的刮奖卡片的感觉
在这里插入图片描述
查壳无壳32位ida打开
ctrl+F搜索主函数只看到这个
在这里插入图片描述
在这里插入图片描述
于是shift+F12查看字符串发现这个
在这里插入图片描述
双击过去交叉引用发现是函数DialogFunc刚好对应主函数里调用的函数完美
在这里插入图片描述
最后有个判断然后得出结果,所以看一下v7之类的是什么
在这里插入图片描述
可以知道输入的String是8个字符,然后v7-v17经过了函数sub_4010F0的处理
看一下这个函数

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
int __cdecl sub_4010F0(int a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx

result = a3;
for ( i = a2; i <= a3; a2 = i )
{
v5 = 4 * i;
v6 = *(_DWORD *)(4 * i + a1);
if ( a2 < result && i < result )
{
do
{
if ( v6 > *(_DWORD *)(a1 + 4 * result) )
{
if ( i >= result )
break;
++i;
*(_DWORD *)(v5 + a1) = *(_DWORD *)(a1 + 4 * result);
if ( i >= result )
break;
while ( *(_DWORD *)(a1 + 4 * i) <= v6 )
{
if ( ++i >= result )
goto LABEL_13;
}
if ( i >= result )
break;
v5 = 4 * i;
*(_DWORD *)(a1 + 4 * result) = *(_DWORD *)(4 * i + a1);
}
--result;
}
while ( i < result );
}
LABEL_13:
*(_DWORD *)(a1 + 4 * result) = v6;
sub_4010F0(a1, a2, i - 1);
result = a3;
++i;
}
return result;
}

参数齐全很清晰,可以改一下数组然后用C语言跑出来

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
#include<stdio.h>
void main()
{
int v7[11];
int sub_4010F0(int a1[], int a2, int a3);
v7[0] = 90;
v7[1] = 74;
v7[2] = 83;
v7[3] = 69;
v7[4] = 67;
v7[5] = 97;
v7[6] = 78;
v7[7] = 72;
v7[8] = 51;
v7[9] = 110;
v7[10] = 103;
sub_4010F0(v7, 0, 10);
for(int i=0;i<11;i++)
{
printf("%d ",v7[i]);
}
}

int __cdecl sub_4010F0(int a1[], int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx
result = a3; // result = 10
for ( i = a2; i <= a3; a2 = i ) // i=0;i<=10;a2=i
{
v5 = i;
v6 = a1[i]; // 遍历a1对应地址的元素
if ( a2 < result && i < result ) // a2<10 并且 i<10
{
do
{
if ( v6 > a1[result] ) // 如果a1[i] > a1[result]
{
if ( i >= result )
break; // 如果i>=result则退出循环
++i; // 给i+1
a1[v5] = a1[result]; // 让a1[1] = a1[result]
if ( i >= result )
break; // 如果i>=result则退出循环 重复
while ( a1[i] <= v6 ) // 当a1[i] <= v6 此循环一定成立
{
if ( ++i >= result ) // 如果i = result - 1
goto LABEL_13;
}
if ( i >= result )
break;
v5 = i;
a1[result] = a1[i];
}
--result; // result减一
}
while ( i < result );
}
LABEL_13:
a1[result] = v6; // 让a1[result] = 之前的a1[i]
sub_4010F0(a1, a2, i - 1); // 进行递归……
result = a3;
++i;
}
return result;
}

运行结果:
在这里插入图片描述
可以使用Python改成字符

1
2
3
4
5
arr = [51,67,69,72,74,78,83,90,97,103,110]
x = ""
for i in range(0, len(arr)):
x+=chr(arr[i])
print(x)

在这里插入图片描述

这就是新的v7到v17的值3CEHJNSZagn
我们回到函数DialogFunc,接着往后面看
在这里插入图片描述
双击v23,v25之类的发现都会跳到这里
在这里插入图片描述
可知v23为string[5],快捷键N依次修改
在这里插入图片描述
后面的if判断有v4,v5,这里可以看到v4,v5经过了函数sub_4010001的处理,分析sub_401000函数

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
// a1 为 v26的地址   a2 为 v26的长度
_BYTE *__cdecl sub_401000(int *a1, int a2)
{
int v2; // eax
int v3; // esi
size_t v4; // ebx
_BYTE *v5; // eax
_BYTE *v6; // edi
int v7; // eax
_BYTE *v8; // ebx
int v9; // edi
signed int v10; // edx
int v11; // edi
signed int v12; // eax
signed int v13; // esi
_BYTE *result; // eax
_BYTE *v15; // [esp+Ch] [ebp-10h]
_BYTE *v16; // [esp+10h] [ebp-Ch]
int v17; // [esp+14h] [ebp-8h]
int v18[4]; // [esp+18h] [ebp-4h]

v2 = a2 / 3;
v3 = 0;
if ( a2 % 3 > 0 )
++v2;
v4 = 4 * v2 + 1; // v4为长度
//
// 当进行编码的数据长度是3的倍数时,len=strlen(str_in)/3*4;
// 当进行编码的数据长度不是3的倍数时,len=(strlen(str_in)/3+1)*4;
// 为Base64加密
v5 = malloc(v4);
v6 = v5; // v6指向分配的动态内存空间
v15 = v5; // v15指向分配的动态内存空间
if ( !v5 )
exit(0); // 动态分配内存失败,退出
memset(v5, 0, v4); // 给分配的v5清零
v7 = a2;
v8 = v6; // v8指向分配的动态内存空间
v16 = v6; // v16指向分配的动态内存空间
if ( a2 > 0 )
{
while ( 1 )
{
v9 = 0;
v10 = 0;
v18[0] = 0;
do
{
if ( v3 >= v7 )
break;
++v10;
v9 = *(a1 + v3++) | (v9 << 8); // 将v9左移8位,然后与v9各个位二进制求或
}
while ( v10 < 3 );
v11 = v9 << 8 * (3 - v10); // v9向左移8的倍数位
v12 = 0;
v17 = v3;
v13 = 18;
do
{
if ( v10 >= v12 )
{
*(v18 + v12) = (v11 >> v13) & 63;
v8 = v16;
}
else
{
*(v18 + v12) = 64;
}
*v8++ = byte_407830[*(v18 + v12)];
v13 -= 6;
++v12;
v16 = v8;
}
while ( v13 > -6 );
v3 = v17;
if ( v17 >= a2 )
break;
v7 = a2;
}
v6 = v15;
}
result = v6;
*v8 = 0;
return result;
}

再看byte_407830的值,刚好是
在这里插入图片描述
符合base64加密规律
所以将
在这里插入图片描述
base64解密为jMp和WP1

再推上面的
在这里插入图片描述
而且是8位
所以对比可知道string = “UJWP1jMp”

flag:flag{UJWP1jMp}

[GXYCTF2019]luck_guy

在这里插入图片描述
ida64
在这里插入图片描述
将用户输入的字符串存到v4中,然后作为函数patch_me()的参数
在这里插入图片描述
查看函数get_flag()
在这里插入图片描述
取0~199的随机数,case1 case4 case5才是有效路径,并且需要按照一定顺序才能得出结果。
根据判断顺序应该为case4 case5 case1
flag是由f1和f2拼接而成,f1已知,f2在case4中,但是f2形式不太对,观察case5的代码,是对长度为8的字符串进行操作,f2(0x7F666F6067756369两位一划分)的长度正好也是8,猜测用来与f1进行拼接形成flag的字符串是f2进行了case5操作后的数据。
分一下f2,再考虑小端序存储,

1
f2=[0x7F,0x66,0x6F,0x60,0x67,0x75,0x63,0x69][::-1]

写脚本

1
2
3
4
5
6
7
8
9
flag="GXY{do_not_"
f2=[0x7F,0x66,0x6F,0x60,0x67,0x75,0x63,0x69][::-1]
for j in range(8):
if j%2==1 :
s=chr(f2[j]-2)
else:
s=chr(f2[j]-1)
flag+=s
print (flag)

解出来是GXY{do_not_hate_me}

由于题目要求,所以最后的flag是:flag{do_not_hate_me}

findit

题目叙述的有点好笑,看题
在这里插入图片描述
APK逆向,上JEB,看主函数有一段可疑的字符串
在这里插入图片描述
第五个数据是“{”的asscii,最后一个是“}”的ascii,所以这串数据很可能和flag有关,用脚本跑出字符串。

1
2
3
4
5
6
7
8
9
10
a=[ 0x70,0x76,0x6B,0x71,0x7B,0x6D,0x31,
0x36,0x34,0x36,0x37,0x35,0x32,0x36,
0x32,0x30,0x33,0x33,0x6C,0x34,0x6D,
0x34,0x39,0x6C,0x6E,0x70,0x37,0x70,
0x39,0x6D,0x6E,0x6B,0x32,0x38,0x6B,
0x37,0x35,0x7D]
s=''
for i in a:
s+=chr(i)
print(s)

pvkq{m164675262033l4m49lnp7p9mnk28k75}

跑出来是上面这个,观察一下特别像凯撒
f->p 10位 后面都是flag移动10位是pvkq
使用在线工具移动一下

flag{c164675262033b4c49bdf7f9cda28a75}

简单注册机

APK逆向,上JEB
在这里插入图片描述
tab键反编译,核心代码为这一部分
在这里插入图片描述
按照JAVA代码写Python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
str=['d','d','2','9','4','0','c','0','4','4','6','2','b','4','d','d','7','c','4','5','0','5','2','8','8','3','5','c','c','a','1','5']

str[2]=chr(ord(str[2])+ord(str[3])-50)
str[4]=chr( ord(str[2])+ord(str[5])-0x30 )
str[30]=chr( ord(str[0x1f])+ord(str[9])-0x30)
str[14]=chr( ord(str[27])+ord(str[28])-97 )

for i in range(16):
x=str[0x1f-i]
str[0x1f-i]=str[i]
str[i]=x

for i in str:
print (i,end="")

在这里插入图片描述
flag:flag{59acc538825054c7de4b26440c0999dd}

[BJDCTF2020]JustRE

在这里插入图片描述
ida打开,搜素main函数价值不大,搜索字符串,发现一个类似flag的字符串在这里插入图片描述
交叉引用过去看函数
在这里插入图片描述
第14行代码,sprintf补齐,查看aBjdDD2069a4579
在这里插入图片描述
刚好补充19999 和 0
flag是:flag{1999902069a45792d233ac}