张三的程序

张三的程序.exe

code1:shift+f12

image

code2:点击写出日志在C盘根目录生成flag.txt

image

So_easy

So_easy_re.exe

64位程序用ida打开,main函数发现

image

base64解码

image

JRE

Reverse.class

jadx打开

image

python脚本

1
2
3
4
5
str = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65]
flag=''
for i in range(0,len(str)):
flag += chr((str[i]-ord('@'))^32)0
print(flag)

上上签

image

remain

shangsahngqian.zip

走出迷宫的数字就是flag

image

ida分析main函数,也有密码

image

flag:flag{66666666622224484444422}

CHARS

CHARS.zip

发现一串字符串

image

ascii解码之后 }esrever_ot_ysae_s’tI{galf

1
2
3
4
5
6
python脚本
a=[125,101,115,114,101,118,101,114,95,111,116,95,121,115,97,101,95,115,39,116,73,123,103,97,108,102]
flag=''
for i in range(0,len(a)):
flag+=chr(a[i])
print(flag[::-1])

ManyCheck

ManyCheck.zip

三层验证,前两层拉入ida看或者直接用计算器算出结果:77、55、49

第三层根据ida里的算法,直接写个for循环就出来了:1198089844

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <bits/stdc++.h>
using namespace std;
int main()
{
for (int v1 = 0; v1 <= 1718896489; v1++)
{
int v2 = 16;
int v3 = (v1 >> (32 - v2)) | (v1 << v2);
if (v3 == 1718896489)
printf("%d", v1);
}
return 0;
}

see what you see

attachment_2.zip

查看字符串就可以看到flag

image

flag:qsnctf{I_Am_a_loser}

Mobile01

Mobile01.zip

程序安装打开之后就有flag

29b2c91322930fc7cda6bc992f28d18

flag:qsnctf{so_easy_Mobile_test_for_you}

ezandroid

关键函数

image

跟踪得到值

image

python解密

1
2
3
4
5
6
str = [404, 220, 436, 368, 220, 436, 412, 452, 432, 200, 412]
flag=''
for i in range(0,len(str)):
flag+=chr(str[i]>>2^3)
print(flag)

用户名:ccadwjlyah 密码:f4n_4ndro1d

登录成功

image

flag:DASCTF{1df456_34hjfk_y3o5c_99gh34_3ndro1d}

……

exe

1
https://bbs.qsnctf.com/thread-363-1-1.html

flag{re_is_so_easy}

Puzzle

puzzle.zip

1
https://www.moxinwangluo.cn/Moxin/20354.html

mfc

challenge.zip

  1. 使用查壳工具查壳,得知题目是MFC应用,没有加壳
  2. 利用IDA反编译程序,如果程序需要验证flag,那么必须先获取输入的文本,在Import界面搜索text,利用交叉引用找到关键函数,分析关键验证函数
  3. 分析得知,程序使用了异或算法对输入加密,然后与密文比对。
  4. 手动提取密文的十六进制,异或回去即可
1
2
3
4
c = [0xe1, 0xeb, 0xe6, 0xe0, 0xfc, 0xb6, 0xe1, 0xe3, 0xb2, 0xb6, 0xb7, 0xbe, 0xe2, 0xbe, 0xb1, 0xb2, 0xb2, 0xb6, 0xb6,
0xe2, 0xe2, 0xb3, 0xb0, 0xb3, 0xe2, 0xb2, 0xe3, 0xe3, 0xe2, 0xb3, 0xb7, 0xb7, 0xb0, 0xe6, 0xb0, 0xb6, 0xe1, 0xfa]
for i in c:
print(chr(i ^ 0x87), end='')

得到flag flag{1fd5109e965511ee474e5dde4007a71f}

Ez_pycode_dis

file.txt

字节码格式

常见的python字节码指令:
[mw_shl_code=applescript,false]
LOAD_CONST:加载常量,比如数值、字符串。用于传递给函数作为参数
BUILD_LIST: 创建一个列表
LOAD_FAST:用于读取值,用于计算或者函数调用传参等。
STORE_FAST:用于保存值到局部变量。
SETUP_LOOP 用于开始一个循环
BINARY_RSHIFT:用于右移(>>)
BINARY_LSHIFT:用于左移(<<)
BINARY_OR:用于位或(|)
BINARY_AND:用于位与(&)
BINARY_XOR: 用于异或[/mw_shl_code]
分析字节码得到源码

1
2
3
4
5
6
keys1='welcome_to_qsnctf_u_will_have_a_good_time!'
keys2=[6,22,2,0,27,11,30,109,76,86,106,92,17,15,6,76,94,102,23,105,70,68,84,85,104,12,89,79,82,62,4,108,3,66,91,84,59,18,93,9,3,92]
flag=''
for i in range(len(keys1)):
flag+=chr(ord(keys1[i])^keys2[i])
print(flag)

运行得到flag

人民的名义-抓捕赵德汉1-200

reverse.jar

(8条消息) XCTF_MOBILE15_人民的名义-抓捕赵德汉1-200_大雄_RE的博客-CSDN博客

Super Mario Bros

根据图片可以猜到是一个Python的exe,反编译得到源码,然后做个简单异或即可

1
2
3
4
5
6
enc = [10, 9, 23, 2, 23, 109, 15, 7, 4, 3, 58, 71, 22, 51, 82, 93, 20, 92, 93, 28, 41, 3, 25, 78, 0, 44, 16]
key = 'level num'
flag =''
for i in range(len(enc)):
flag += chr(ord(key[i%9])^enc[i])
print(flag)

flag{Mario_1s_r3a11y_funnY}

变形金刚

2019KCTF 晋级赛Q1 | 第二题点评及解题思路 (kanxue.com)

LiHua’s checkme

[LiHuas_checkme 1.txt](/image/CTF/青少年CTFReverse合集/LiHuas_checkme 1-20230331163951-4meqymk.txt)

1
2
3
flag=[114433,114459,114449,114438,114452,114473,114480,114530,114531,114487,114528,114483,114531,114484,114559,114530,114539,114532,114486,114559,114534,114484,114486,114538,114559,114538,114484,114539,114535,114559,114533,114487,114529,114538,114538,114486,114532,114539,114534,114539,114531,114531,114479]
for i in range(len(str)):
print(chr(flag[i]^114514),end='')

GO_Re

[gore.zip](/image/CTF/青少年CTFReverse合集/gore 1-20230222094316-d0dwdmm.zip)

代码比较混乱,细看之后找到

image

加密函数,猜测 v1 为是输入的值

经过加密之后与 v11 进行比较

分析加密函数

image

调试得到 v27

1
2
3
V27=[243,79,85,235,242,11,136,210,70,121,193,114,95,140,200,114,59,213,194,165,130,41,234,220,20,176,3,159,72,73,88,84]

V11= [0x9f,0x29,0x32,0x8a,0xc3,0x70,0xbc,0xea,0x20,0x40,0xf1,0x17,0x69,0xe8,0xfd,0x40,0x3,0xe6,0xa3,0x97,0xb7,0x1e,0xd3,0xbf,0x24,0x83,0x32,0xab,0x79,0x28,0x25,0x37]

多次尝试之后发现需要两个字节一起两两交换输出 flag

脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
v27=[243,79,85,235,242,11,136,210,70,121,193,114,95,140,200,114,59,213,194,165,130,41,234,220,20,176,3,159,72,73,88,84]
v11= [0x9f,0x29,0x32,0x8a,0xc3,0x70,0xbc,0xea,0x20,0x40,0xf1,0x17,0x69,0xe8,0xfd,0x40,0x3,0xe6,0xa3,0x97,0xb7,0x1e,0xd3,0xbf,0x24,0x83,0x32,0xab,0x79,0x28,0x25,0x37]
flag=''
for i in range(len(v11)):
v11[i]^=v27[i]
for i in range(0,len(v11),2):
t=v11[i]
v11[i]=v11[i+1]
v11[i+1]=t
for i in range(len(v11)):
flag+=chr(v11[i])
print(flag)

# flag{1849fe0d625382a75c93041a1c

babyUPX

查壳后发现是upx的壳,正常手动脱壳发现脱不掉,猜测可能是魔改壳。打开010进行手动恢复。
打开010后检查两个地方。

image

可以发现第一部分是没有问题的,UPX0,UPX1和UPX2都没有缺少,但是在下面的3.96._PX!就出现了字符缺失。(正常upx壳为3.96.UPX!)因此我们把缺少的字符补回去即可。修改后正常脱壳,直接拖入ida即可。

首先看到主函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main()
{
__int64 v0; // rax
__int64 v1; // rax
signed int v3; // [esp+28h] [ebp-14h]
signed int i; // [esp+2Ch] [ebp-10h]

__main();
gets(str);
v3 = strlen(str);
for ( i = 0; i < v3; ++i )
{
v0 = task(str[i], table[i]);
v1 = Task(v0, i); // v0^i
if ( !check(v1, i) )
{
printf("Worry!");
exit(0);
}
}
printf("Congratulations!");
return 0;
}

加密逻辑比较简单,那么我们看看具体的加密函数。

1.task函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
__int64 __cdecl task(__int64 a, __int64 b)
{
__int64 v2; // rax
__int64 ans; // [esp+20h] [ebp-18h]

ans = 1LL;
while ( (b != 0) + HIDWORD(b) > 0 ) // a=str,b=table
{
if ( (b & 1) != 0 )
ans *= a;
v2 = a * a;
HIDWORD(v2) += 2 * a * HIDWORD(a); // fastpow函数
a = v2;
b >>= 1;
}
return ans;
}

【这个函数里的HIDWORD在c++中无法运用,在建立自定义函数的时候需要自行进行修改。其次就是函数的类型为**_int64**,这与int不同(int是32位的,如果类型错误会导致一部分字符的丢失】
那么我们对于task函数的自定义脚本就可以写为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__int64  task(__int64 a, __int64 b)
{
// rax
__int64 ans; // [esp+20h] [ebp-18h]
__int64 v2;
ans = 1LL;
while (b) // a=str,b=table
{
if ( b & 1 )
ans *= a;
v2=a*a;
a=v2;
b >>= 1;
}
return ans;
}

【一定要注意参数的类型必须对应】
这里用到的参数一个是str,是我们输入的字符串,一个是table,可以点击查看获取。【点击table我们会发现一个比较不同的表达,例如 2 dup (5),这就表示 25,我们可以通过导出的 initialized C variable形式进行对比查验。】

2.Task函数。这个函数我们点击会发现只有一个参数的异或操作,那么我们写脚本时直接写参数异或即可。

3.Check语句。
我们点击Check语句后得到如下:

1
2
3
4
__int64 __cdecl check(__int64 A, __int64 l)
{
return A == __PAIR64__(HIDWORD(C[l]), C[l]); // c为flag
}

这里的PAIR64我目前没有查到什么有用的信息,那么点击C数组查看一下,看到是一些比较长的16进制数,根据判断语句猜测可能就是加密后形成的flag。也就是说str经过两个函数加密处理后存入v1,如果v1C一一对应,那么str就是我们需要的正确flag输出。

一般遇到需要逆向求输入的字符串时,可以考虑进行字符串爆破。
解密脚本如下:

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
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<string>
#include<cstring>
#include<list>
#include<stdlib.h>
#include <windowsx.h>
#include<windows.h>
using namespace std;
typedef int status;
typedef int selemtype;
using namespace std;

__int64 C[50] = {
0x000018AE1AAE0A3B, 0x000000007B908FE8, 0x0000000050794631, 0x0000000002F7B103,
0x0000077D75E13584, 0x00018360FF1E2E56, 0x000000049A6B9006, 0x0000000000000C47,
0x0000000000000A98, 0x000000000002AE09, 0x000000C1F1001E4B, 0x00000000000F424B,
0x0009E04F46B4000C, 0x00000057006F5D48, 0x000000E8D4A5100E, 0x0000618298AE6CC2,
0x00000000008BA0B1, 0x00133DFA38000011, 0x00000F4B13936533, 0x0000309F10210013,
0x0000000529194FBD, 0x0000000272736800, 0x00000088B0000016, 0x00000000003E9206,
0x0016909EF9A7B2E1, 0x000000CE40520859, 0x0000000023DD1783, 0x000000000002255B,
0x00000000000007F5, 0x00002386F26FC11D, 0x000000049A6B901E, 0x0000000023DD1786,
0x00000137BE2959A0, 0x0000000010D63AD0, 0x0000009DE93ECE73, 0x00001E39A5057DA2,
0x000041C21CB8E124, 0x00000000000245A8, 0x0000000339014807, 0x00000005C5E45267,//42
0x0006F05B59D3B228, 0x00D3C21BCECCED88, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000
};
__int64 table[50] =
{
7,
5,
5,
4,
7,
7,
6,
2,
2,
3,
6,
3,
9,
7,
6,
7,
4,
9,
8,
8,
6,
5,
7,
4,
9,
6,
5,
3,
2,
8,
6,
5,
7,
5,
7,
8,
8,
3,
6,
6,
9,
8,
0,
0,
0,
0,
0,
0,
0,
0
};
__int64 task(__int64 a, __int64 b)
{
// rax
__int64 ans; // [esp+20h] [ebp-18h]
__int64 v2;
ans = 1LL;
while (b) // a=str,b=table
{
if ( b & 1 )
ans *= a;
v2=a*a;
a=v2;
b >>= 1;
}
return ans;
}
int main()
{
__int64 v0;__int64 v1;
for(int i=0;i<50;i++)
{
for(char str=0;str<127;str++)
{
v0=task(str,table[i]);
v1=v0^i;
if(v1==C[i])
{
cout << str ;
//cout << i;
//cout << " ";//这两句用于判断是否有字符丢失
}

}
}
}

粗心的小红

image​​

image

qsnctf{d52557e8-3a19-4b4a-9347-8badeb89f0e2}