终于,来到了难度4!

easyCpp

0x00

​ 发现是64位的ELF。

image-20221123183717660

​ 一步步分析:

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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
[1] __fastcall在寄存器中放入不大于4字节的参数,故性能较高,适用于需要高性能的场合。
[2] 1LL 代表 long long 1
*/
__int64 __fastcall fib(int a1)
{
int v2;

if ( !a1 || a1 == 1 )
return 1LL;
v2 = fib(a1 - 1);
return v2 + (unsigned int)fib(a1 - 2);
}


/*
[1] _cdecl 是C Declaration的缩写,表示C语言默认的函数调用方法:
所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。
被调用函数无需要求调用者传递多少参数,调用者传递过多或者过少的参数,
甚至完全不同的参数都不会产生编译阶段的错误。
[2] argc指定从命令行传递给程序的参数数量。因为程序名被认为是一个参数,所以 argc 至少为 1。
argv是具体的参数。
envp是系统的环境变量,很少有介绍的。"名称=值"的形式,以NULL结束。
*/
int __cdecl main(int argc, const char **argv, const char **envp)
{
/*
__int64表示64 bit的整数
int为4字节(32位)
_DWORD为4字节(32位)
*/
__int64 v3;
__int64 v4;
__int64 v5;
__int64 v6;
__int64 v7;
__int64 v8;
__int64 v9;
__int64 v10;
int v11;
int v12;
int v13;
int v14;
int v15;
int v16;
int v18;
int v17;
int v19;
unsigned int *v20;
int i;
int j;
char v24[32];
char v25[32];
char v26[32];
char v27[32];
char v28[32];
__int64 v29[4];
__int64 v30[4];
_DWORD v31[18];
unsigned __int64 v32;

/*
[1] __readfsqword从相对于FS段开头的偏移量(0x28u)的位置读内存。
[2] FS段寄存器Windows用来存储一些进程信息的。
[3] std::vector<int>::vector相当于初始化值为int的vector
第一个参数表示要分配的对象
第二个参数表示初始vector的大小
第三个参数为初始填充的值
*/
v32 = __readfsqword(0x28u);
std::vector<int>::vector(v24, argv, envp);
std::vector<int>::vector(v25, argv, v3);
std::vector<int>::vector(v26, argv, v4);
std::vector<int>::vector(v27, argv, v5);
std::vector<int>::vector(v28, argv, v6);

/*
[1] std::vector<int>::push_back(arg1, arg2) 表示在vector末尾添加新元素
第一个参数表示要添加的vector
第二个参数表示添加的元素
[2] LODWORD 表示64位元素的第32位
*/
for (i = 0; i <= 15; ++i)
{
scanf("%d", &v31[i]);
std::vector<int>::push_back(v25, &v31[i]);
}
for (j = 0; j <= 15; ++j)
{
LODWORD(v30[0]) = fib(j);
std::vector<int>::push_back(v24, v30);
}
std::vector<int>::push_back(v26, v31);

/*
[1] std::back_inserter为容器构造一个迭代类型std::back_insert_iterator
参数:支持 push_back 操作的容器
返回值:std::back_insert_iterator,可用于将元素添加到容器的末尾
[2] std::vector<int>::end指向vector的末尾
参数:某个vector
std::vector<int>::begin类似
[3] __gnu_cxx::__normal_iterator指的是迭代器适配器是"正常"的,
因为它不会改变其迭代器参数的任何运算符的语义。
[3] std::transform(first1, last1, d_first, unary_op)
作用:将某个可迭代的对象进行转换
[first1,last1]:要转换的第一个元素范围
d_first:目标范围的开始
unary_op:应用的函数
[4] std::accumulate(first, last, init)
作用:计算可迭代的对象的和+init
[first1,last1]:要求和的元素范围
init:和的初始值
[5] std::vector<int>::~vector()
把vector取消掉
*/
v7 = std::back_inserter<std::vector<int>>(v26);
v8 = std::vector<int>::end(v25);
v30[0] = std::vector<int>::begin(v25);
v9 = __gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator+(v30, 1LL);
std::transform<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>,main::{lambda(int)#1}>(
v9,
v8,
v7,
v31
);
std::vector<int>::vector(v29, v8, v10);
LODWORD(v8) = std::vector<int>::end(v26);
v11 = std::vector<int>::begin(v26);
std::accumulate<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::vector<int>,main::{lambda(std::vector<int>,int)#2}>(
(unsigned int)v30,
v11,
v8,
(unsigned int)v29,
v12,
v13
);
std::vector<int>::operator=(v27, v30);
std::vector<int>::~vector(v30);
std::vector<int>::~vector(v29);
if((unsigned __int8)std::operator!=<int,std::allocator<int>>(v27, v24) )
{
puts("You failed!");
exit(0);
}
v14 = std::back_inserter<std::vector<int>>(v28);
v15 = std::vector<int>::end(v25);
v16 = std::vector<int>::begin(v25);
std::copy_if<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>,main::{lambda(int)#3}>(
v16,
v15,
v14,
v17,
v18,
v19
);
puts("You win!");
printf("Your flag is:flag{");
v29[0] = std::vector<int>::begin(v28);
v30[0] = std::vector<int>::end(v28);
while ((unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int>>(v29, v30) )
{
v20 = (unsigned int *)__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator*(v29);
std::ostream::operator<<(&std::cout, *v20);
__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator++(v29);
}
putchar(125);
std::vector<int>::~vector(v28);
std::vector<int>::~vector(v27);
std::vector<int>::~vector(v26);
std::vector<int>::~vector(v25);
std::vector<int>::~vector(v24);
return 0;
}

​ 没咋搞懂,动态调也没看出来,搜了一下要补以下C++的逆向知识。(上述工作耗费了2day

0x01

​ 先看https://blog.csdn.net/larry_zeng1/article/details/93027422

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
#include <iostream>
#include <vector>

using namespace std;
int main()
{
vector<int> test;
//创建一个vector,并且将5个数值压入容器
for(int i=0; i<5; i++)
test.push_back(i);
getchar();

//输出容器大小
cout << test.size();
getchar();

//删除容器中最后的一个元素
test.pop_back();
getchar();

//判断容器是否为空,若非空,删除一个元素
if(!test.empty())
test.pop_back();
getchar();

//重新设置容器大小并赋值
test.resize(5, 2);
getchar();

//创建一个新容器,并判断新容器跟旧容器是否相等
vector<int> test1(5,2);
if(test1 == test)
cout << "Right!" << endl;
getchar();

//将区间[first,last)的元素赋值到当前的vector容器中,或者赋n个值为x的元素到vector容器中,这个容器会清除掉vector容器中以前的内容
test1.assign(test.begin(), test.end());
getchar();
test.clear();
getchar();

return 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
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rax
__int64 v4; // rax
__int64 v5; // rbx
__int64 v6; // rax
int i; // [rsp+Ch] [rbp-64h]
char v9; // [rsp+10h] [rbp-60h]
char v10; // [rsp+30h] [rbp-40h]
int v11; // [rsp+54h] [rbp-1Ch]
char v12; // [rsp+5Bh] [rbp-15h]
int v13; // [rsp+5Ch] [rbp-14h]

//用上一节的知识,这里创建了一个vector
std::vector<int,std::allocator<int>>::vector(&v10, argv, envp);
for ( i = 0; i <= 4; ++i )
//这里相当于v10.push_back(i)
std::vector<int,std::allocator<int>>::push_back(&v10, &i);
getchar();

//求v10的大小,相当于v3 = v10.size();
v3 = std::vector<int,std::allocator<int>>::size(&v10);
//相当于cout<<v3;
std::ostream::operator<<(&std::cout, v3);
getchar();

//相当于v10.pop_back();
std::vector<int,std::allocator<int>>::pop_back(&v10);
getchar();

//相当于if(!v10.empty())
// v10.pop_back();
if ( (unsigned __int8)std::vector<int,std::allocator<int>>::empty(&v10) ^ 1 )
std::vector<int,std::allocator<int>>::pop_back(&v10);
getchar();

//这个resize有没有发觉很像上一节的构造函数,第一个参数为一个char变量的地址,第二个为容器初始大小,第三个为初始数据的地址
//相当于v10.resize(5,2);
v11 = 2;
std::vector<int,std::allocator<int>>::resize(&v10, 5LL, &v11);
getchar();

//这里就是上一节的那个构造函数了,相当于vector<int>v9(5,2);
std::allocator<int>::allocator(&v12);
v13 = 2;
std::vector<int,std::allocator<int>>::vector(&v9, 5LL, &v13, &v12);
std::allocator<int>::~allocator(&v12);
//这里判断两个容器是否相等,相当于v9 == v10
if ( (unsigned __int8)std::operator==<int,std::allocator<int>>(&v9, &v10) )
{
v4 = std::operator<<<std::char_traits<char>>(&std::cout, "Right!");
std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
}
getchar();

//这两句又出现了吧,end跟begin,这几句很常用,能识别就行
v5 = std::vector<int,std::allocator<int>>::end(&v10);
v6 = std::vector<int,std::allocator<int>>::begin(&v10);

//将下面句子简化可以看出他就是v9.assign(v6,v5);
//其实就是v9.assign(v10.begin(), v10.end());
//具体怎么简化的话,你就看::,不要看模板,那只是类型的问题
std::vector<int,std::allocator<int>>::assign<__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>,void>(
&v9,
v6,
v5);
getchar();

//清空容器元素,相当于v10.clear();
std::vector<int,std::allocator<int>>::clear(&v10);
getchar();

//析构函数
std::vector<int,std::allocator<int>>::~vector(&v9);
std::vector<int,std::allocator<int>>::~vector(&v10);
return 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
109
110
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v3;
__int64 v4;
__int64 v5;
__int64 v6;
__int64 v7;
__int64 v8;
int v9;
int v10;
int v11;
int v12;
int v13;
int v14;
int v15;
int v16;
unsigned int *v17;
int i;
int j;
char fib_results[32];
char input_address[32];
char input_0_addr[32];
char v24[32];
char v25[32];
__int64 v26[4];
__int64 v27[4];
_DWORD input[18];
unsigned __int64 v29;

v29 = __readfsqword(0x28u);
std::vector<int>::vector((__int64)fib_results);
std::vector<int>::vector((__int64)input_address);
std::vector<int>::vector((__int64)input_0_addr);
std::vector<int>::vector((__int64)v24);
std::vector<int>::vector((__int64)v25);
// input_address.push_back(input[i])
for ( i = 0; i <= 15; ++i )
{
scanf("%d", &input[i]);
std::vector<int>::push_back((__int64)input_address, (__int64)&input[i]);
}
// fib_results.push_back(fib(i))
for ( j = 0; j <= 15; ++j )
{
LODWORD(v27[0]) = fib(j);
std::vector<int>::push_back((__int64)fib_results, (__int64)v27);
}
// input_0_addr.push_back(input[0])
std::vector<int>::push_back((__int64)input_0_addr, (__int64)input);
// 创建容器指针 v4 指向 input_0_addr
v4 = std::back_inserter<std::vector<int>>(input_0_addr);
v5 = std::vector<int>::end(input_address);
v27[0] = std::vector<int>::begin(input_address);
v6 = __gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator+(v27, 1LL);
// input[i] = input[0] + input[i], i!= 0
// input[0] = input[0]
std::transform<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>,main::{lambda(int)#1}>(
v6, // input_address.begin() + 4
v5, // input_address.end()
v4,
(__int64)input);
// 对 input 进行逆序化
std::vector<int>::vector((__int64)v26);
v7 = std::vector<int>::end(input_0_addr);
v8 = std::vector<int>::begin(input_0_addr);

std::accumulate<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::vector<int>,main::{lambda(std::vector<int>,int)#2}>(
(__int64)v27, // input.begin()
v8, // input.begin()
v7, // input.end()
(__int64)v26, // null pointer
v9,
v10,
v3);
std::vector<int>::operator=((__int64)v24, (__int64)v27);
std::vector<int>::~vector(v27);
std::vector<int>::~vector(v26);
if ( (unsigned __int8)std::operator!=<int,std::allocator<int>>((__int64)v24, (__int64)fib_results) )
{
puts("You failed!");
exit(0);
}
v11 = std::back_inserter<std::vector<int>>(v25);
v12 = std::vector<int>::end(input_address);
v13 = std::vector<int>::begin(input_address);
std::copy_if<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>,main::{lambda(int)#3}>(
v13,
v12,
v11,
v14,
v15,
v16);
puts("You win!");
printf("Your flag is:flag{");
v26[0] = std::vector<int>::begin(v25);
v27[0] = std::vector<int>::end(v25);
while ( (unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int>>(v26, v27) )
{
v17 = (unsigned int *)__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator*(v26);
std::ostream::operator<<(&std::cout, *v17);
__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator++(v26);
}
putchar(125);
std::vector<int>::~vector(v25);
std::vector<int>::~vector(v24);
std::vector<int>::~vector(input_0_addr);
std::vector<int>::~vector(input_address);
std::vector<int>::~vector(fib_results);
return 0;
}

​ 分析到std::transform时,点进去看看,发现有:

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
/*
相当于input的每个元素,除第一个元素外,都加Input[0]。
*/

__int64 __fastcall std::transform<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>,main::{lambda(int)#1}>(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
unsigned int *v4;
__int64 v5;
__int64 v7;
__int64 v8;
__int64 v9;
__int64 v10;
int v11;
unsigned __int64 v12;

v10 = a1; // input_address.begin() + 4
v9 = a2; // input_address.end()
v8 = a3; // 指向 input_0_addr
v7 = a4; // input
v12 = __readfsqword(0x28u);
while ( (unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int>>(&v10, &v9) ) // 遍历
{
// v4 = v10
v4 = (unsigned int *)__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator*(&v10);
// v11 = *v7 + *v4
v11 = main::{lambda(int)#1}::operator()(&v7, *v4);
// v5 = &v8
v5 = std::back_insert_iterator<std::vector<int>>::operator*(&v8);
// v11 存到 v5 中去
std::back_insert_iterator<std::vector<int>>::operator=(v5, &v11);
// v10 += 4
__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator++(&v10);
// v8 ++
std::back_insert_iterator<std::vector<int>>::operator++(&v8);
}
return v8;
}

​ 再来分析std::accumulate函数:

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
int64 __fastcall std::accumulate<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::vector<int>,main::{lambda(std::vector<int>,int)#2}>(__int64 a1, __int64 a2, __int64 a3, __int64 a4, int a5, int a6, char a7)
{
unsigned int v7;
__int64 v10;
__int64 v11;
__int64 v12;
char v13[32];
char v14[24];
unsigned __int64 v15;

v12 = a1; // input.begin()
v11 = a2; // input.begin()
v10 = a3; // input.end()
v15 = __readfsqword(0x28u);
while ( (unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int>>(&v11, &v10) ) // 遍历
{
// v7 = v11
v7 = *(_DWORD *)__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator*(&v11);
// v13 = a4
std::vector<int>::vector(v13, a4);
/*
每一次执行到这一行时:
round 0: v14 = []
a7 = ""
v13 = []
v7 = &input[0]
round 1: v14 = [input[0]]
a7 = ""
v13 = [input[0]]
v7 = &input[1]
round 2: v14 = [input[1], input[0]]
a7 = ""
v13 = [input[1], input[0]]
v7 = &input[2]
*/
main::{lambda(std::vector<int>,int)#2}::operator()(v14, &a7, v13, v7);
// a4 = v14
std::vector<int>::operator=(a4, (__int64)v14);
std::vector<int>::~vector(v14);
std::vector<int>::~vector(v13);
// v11 += 4
__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator++(&v11);
}
// v12 = a4
std::vector<int>::vector(v12, a4);
return v12;
}

​ 其中有一个main::{lambda(std::vector<int>,int)#2}::operator(),此函数为:

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
__int64 __fastcall main::{lambda(std::vector<int>,int)#2}::operator()(__int64 a1, __int64 a2, __int64 a3, int a4)
{
__int64 v4;
__int64 v5;
__int64 v6;
int v8;
__int64 v9;
__int64 v10;
__int64 v11;
unsigned __int64 v12;
v11 = a1; // v11 = [], [input[0]]
v10 = a2; // v10 = "", ""
v9 = a3; // v9 = [], [input[0]]
v8 = a4; // v8 = &input[0], &input[1]
v12 = __readfsqword(0x28u);
std::vector<int>::vector(a1);
// a1.push_back(v8)
std::vector<int>::push_back(a1, (__int64)&v8);
v4 = std::back_inserter<std::vector<int>>(v11);
v5 = std::vector<int>::end(v9);
v6 = std::vector<int>::begin(v9);
std::copy<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>>(
v6, // v9.begin()
v5, // v9.end()
v4);
return v11;
}

​ 重点看其中的std::copy<__gnu_cxx::__normal_iterator<std::vector<int>>>,有:

1
2
3
4
5
6
7
8
9
10
11
12
__int64 __fastcall std::copy<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>>(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v3;
__int64 v4;

v3 = std::__miter_base<__gnu_cxx::__normal_iterator<int *,std::vector<int>>>(a2); // end
v4 = std::__miter_base<__gnu_cxx::__normal_iterator<int *,std::vector<int>>>(a1); // begin
return std::__copy_move_a2<false,__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>>(
v4, // begin
v3, // end
a3);
}

​ 其中又调用了std::__copy_move_a2,其中主要调用了std::__copy_move_a,里面又调用了std::__copy_move,再进去看:

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
/*
例如:
有数组A = [1,2,3],
输入为 a1 = A[0],a2 = A[2],a3 = 7
输出为 [7, 1, 2, 3]
*/
__int64 __fastcall std::__copy_move<false,false,std::random_access_iterator_tag>::__copy_m<int *,std::back_insert_iterator<std::vector<int>>>(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v3;
__int64 v5[2];
__int64 v6;
__int64 i;

v6 = a1; // begin
v5[1] = a2; // end
v5[0] = a3; // input[i]
// (a2-a1) >> 2 意思是他俩差了多少个元素,最小是4 byte。这是从高向低遍历。
for ( i = (a2 - a1) >> 2; i > 0; --i )
{
// v3 = v5
v3 = std::back_insert_iterator<std::vector<int>>::operator*((__int64)v5);
// v3.push_back(*v6)
std::back_insert_iterator<std::vector<int>>::operator=(v3, v6);
// v6 += 4
v6 += 4LL;
// v5 ++
std::back_insert_iterator<std::vector<int>>::operator++((__int64)v5);
}
return v5[0];
}

​ 看了好久,终于把std::accumulate函数的逆序看明白了。(太难了,,一会儿总结一波。。

​ 直接写脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
# @Time : 2022/11/24 15:44:43
# @Author: wd-2711
'''

def fib(a1):
if a1 <= 1:
return 1
v2 = fib(a1 - 1)
return v2 + fib(a1 - 2)

if __name__ == "__main__":
fib_list = []
for i in range(16):
fib_list.append(fib(i))
fib_list.reverse()
for i in range(len(fib_list[:-1])):
fib_list[i + 1] -= fib_list[0]
print(fib_list)

# [987, -377, -610, -754, -843, -898, -932, -953, -966, -974, -979, -982, -984, -985, -986, -986]
# 按顺序输入到此题中,输出flag{987-377-843-953-979-985}

0x02

​ 前面的题目分析,写的有点烂,再来归纳总结一下。最后输出为奇数的输入数字。

未命名文件 (1)

0x03

​ 其他师傅大多用的是动调。第一次做正经的cpp题目,感觉难度还是比较大的,主要是得细心分析,应该就没问题。

​ 自己又动调了一下,在下图红框所示打断点:

image-20221124213416616

​ 经过0x00与0x11的分析之后,输出变量为v30。

​ 点进去之后发现:

image-20221124213545981

​ 一开始动调就是卡到这里了,看了其他师傅的wp。他们是这样做的:

  1. v30是_int64 [4]的数组,所以对栈中的元素选中并进行分析,就会得到:

image-20221124213750434

  1. 点进去之后发现:

image-20221124213832404

​ 发现是逆序输出,结束!!

PS:还得多多练练动调技能,要不一开始咋没做出来呢。


getit

0x00

​ 发现是64位的ELF。

image-20221124201412821

​ 看了一眼,发现最后把生成的/tmp/flag.txt又删除掉,直接不让他删除,在remove上打断点,然后直接cat /tmp/flag.txt发现是:

image-20221124203230168

​ 竟然还被隐藏了,再回头仔细瞅瞅。

​ 直接在第一次strcpy(stream, "%s\n", u)中下断点,直接得到:SharifCTF{b70c59275fcfa8aebf2d5911223c6589}。是正确的。

​ 也可以脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
# @Time : 2022/11/24 20:35:57
# @Author: wd-2711
'''

if __name__ == "__main__":
s = "c61b68366edeb7bdce3c6820314b7498"
t = [0x53, 0x68, 0x61, 0x72, 0x69, 0x66, 0x43, 0x54, 0x46, 0x7B, 0x62, 0x37, 0x30, 0x63, 0x35, 0x39, 0x32, 0x37, 0x35, 0x66, 0x63, 0x66, 0x61, 0x38, 0x61, 0x65, 0x62, 0x66, 0x32, 0x64, 0x35, 0x39, 0x31, 0x31, 0x32, 0x32, 0x33, 0x63, 0x36, 0x35, 0x38, 0x39, 0x7D, 0x00]
p = [0x0000001E, 0x00000018, 0x00000019, 0x00000020, 0x00000028, 0x00000024, 0x0000001C, 0x00000011, 0x00000022, 0x00000027, 0x00000010, 0x00000021, 0x00000013, 0x0000001A, 0x00000005, 0x00000003, 0x0000001D, 0x0000001B, 0x0000001F, 0x00000004, 0x00000008, 0x0000000F, 0x00000025, 0x0000002A, 0x0000000E, 0x00000029, 0x00000002, 0x00000017, 0x00000015, 0x00000000, 0x0000000A, 0x00000014, 0x00000007, 0x0000000B, 0x00000001, 0x0000000D, 0x00000006, 0x00000026, 0x00000012, 0x00000023, 0x0000000C, 0x00000016, 0x00000009]
for i in range(len(s)):
v3 = 1 if i & 1 != 0 else -1
t[i + 10] = ord(s[i]) + v3

for i in range(len(t)):

​ easy money。

0x01

​ 为什么最后变成了**********呢?分析一波:

​ 在第二次循环下断点,记录每一轮时的参数值。

1
2
3
4
5
6
7
8
round0:

j --> 0
p --> [0x0000001E, 0x00000018, 0x00000019, 0x00000020, 0x00000028, 0x00000024, 0x0000001C, 0x00000011, 0x00000022, 0x00000027, 0x00000010, 0x00000021, 0x00000013, 0x0000001A, 0x00000005, 0x00000003, 0x0000001D, 0x0000001B, 0x0000001F, 0x00000004, 0x00000008, 0x0000000F, 0x00000025, 0x0000002A, 0x0000000E, 0x00000029, 0x00000002, 0x00000017, 0x00000015, 0x00000000, 0x0000000A, 0x00000014, 0x00000007, 0x0000000B, 0x00000001, 0x0000000D, 0x00000006, 0x00000026, 0x00000012, 0x00000023, 0x0000000C, 0x00000016, 0x00000009]
t --> [0x53, 0x68, 0x61, 0x72, 0x69, 0x66, 0x43, 0x54, 0x46, 0x7B, 0x62, 0x37, 0x30, 0x63, 0x35, 0x39, 0x32, 0x37, 0x35, 0x66, 0x63, 0x66, 0x61, 0x38, 0x61, 0x65, 0x62, 0x66, 0x32, 0x64, 0x35, 0x39, 0x31, 0x31, 0x32, 0x32, 0x33, 0x63, 0x36, 0x35, 0x38, 0x39, 0x7D, 0x00]
u --> '*******************************************'

round1:

​ 原来是把指针调整到开头直接用u覆盖了。。

知识点1:

[1]fseek

作用:为调节文件指针位置。

应用场景:当我们使用文件指针通过fwrite()函数向文件中输入数据,假设数据为字符串“麻辣香锅”,输入完毕后文件指针的指向位置实际上是“锅”的后面,相当于光标。此刻如果使用fread函数是无法正常读取文件内容的,原因是fread只能读取指针往后的内容。需要将文件指针前置,这时候就需要用到fseek函数。
使用:fseek(arg1, arg2, arg3)

参数详解:arg1:文件指针。arg2:偏移量。arg3:

image-20221124202436772

[2]fputc

image-20221124202710977


csaw2013reversing2

0x00

​ 发现是32位的PE。

​ 打开报:(它说是连接了一个debug信息,但是我这没有呀

image-20221126194408866

​ 运行了一下,发现:(乱码

image-20221126195514773

​ 程序主函数如下:

image-20221126201313127

​ 但是到不了这里,因为有IsDebuggerPresent()

​ 看一下sub_40100

image-20221126201422449

方法1:直接用动调,在if(!sub_1B102A() && !IsDebuggerPresent())上设置zf=1,直接跳过sDebuggerPresent()的判断,最后运行完sub_40100之后看lpMem,发现是:flag{reversing_is_not_that_hard!}

方法2:

​ 一直不知道传入a2a2的值,调试之后发现是0xbca0ccbb,又想了想,反正v3-(a2+2)会将a2抵消。计算result=((v3-(a2+2))>>2)+1=((a2+1+35+1-(a2+2))>>2)+1=9,直接循环9次。可以写脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
# @Time : 2022/11/26 20:15:24
# @Author: wd-2711
'''

if __name__ == "__main__":
init = [0xBB, 0xCC, 0xA0, 0xBC, 0xDC, 0xD1, 0xBE, 0xB8, 0xCD, 0xCF, 0xBE, 0xAE, 0xD2, 0xC4, 0xAB, 0x82, 0xD2, 0xD9, 0x93, 0xB3, 0xD4, 0xDE, 0x93, 0xA9, 0xD3, 0xCB, 0xB8, 0x82, 0xD3, 0xCB, 0xBE, 0xB9, 0x9A, 0xD7, 0xCC, 0xDD]
xordata = [0xBB, 0xAA, 0xCC, 0xDD]
ii = 0
for i in range(9):
for x in xordata:
try:
ff = init[ii] ^ x
except Exception as e:
print("over")
print(chr(ff), end = "")
ii += 1


# flag{reversing_is_not_that_hard!}

​ 忒简单了。

0x01

​ 看了其他师傅的wp,有的是直接跳到了弹窗部分,直接显示flag,感觉比较帅,试一试。他是直接从call ds:ExitProcess跳到callloc_1B10B9了。

image-20221126212057260

​ 调试之后,发现:

image-20221126212450620

image-20221126212728187

​ 妈的还是个坑!cao

​ 真实的MessageBoxA调用

image-20221126213021913

​ 虚假的MessageBoxA调用

image-20221126213107729

​ 不惯着他,直接添加指令(但是添加指令好像很麻烦,得扩展段的空间,直接屈服,老老实实跳吧)

​ 一个字,优雅。

image-20221126214058677

​ 这里就可以知道为什么调用第一个弹窗会失败了,因为第一个字符解码后为’\0’,直接截断,所以会输出空白。原来如此,所以才会有inc eax操作,学到了。题目简单,但是知识的确很多。

0x02

知识点1:win32的函数

函数名 作用
HeapCreate(arg1,arg2,arg3) 给进程创建堆。arg1为堆分配选项(不太重要),arg2为堆的初始大小,arg3为堆的最大大小,返回值为新创建的堆的引用。
HeapAlloc(arg1,arg2,arg3) 从堆中分配一块内存。arg1为堆的句柄,arg2为堆分配选项(不太重要),arg3为要分配的字节数,返回值为分配的内存块的指针。
IsDebuggerPresent() 确定调用进程是否正在调试器中调试,若未在调试器中运行,则返回值为零。
MessageBoxA(arg1,arg2,arg3,arg4) 显示一个对话框。arg1为创建的消息框的所有者窗口的句柄,arg2为要显示的消息,arg3为对话框标题,arg4为对话框的内容和行为(有几个按钮)。
HeapFree(arg1,arg2,arg3) 释放从堆中分配的内存块。arg1为要释放其内存块的堆的句柄,arg2不重要,arg3为要释放的内存块的指针。如果函数成功,则返回值为非零。
HeapDestroy() 销毁指定的堆对象。
ExitProcess(arg1) 结束调用进程及其所有线程。arg1为进程和所有线程的退出代码。

知识点2:ida使用:

  1. option->setup data types可以将数据由字节变为字/双字等。
  2. patch完字符后,如果要保存, IDA->edit->Patch program->Apply patches to input。

知识点3:C语言strlen函数不包含”\0”


no-strings-attached

0x00

​ 32位的ELF。运行了一下:

image-20221126222454113

​ 搜了一下是:越界访问了动态分配的内存。

​ 主函数为:

image-20221126221638268

image-20221126222653023

image-20221126223034004

image-20221126223451823

方法1:

​ 最简单的方法,动调直接看s2,但是前面运行的时候根本到不了Please enter authentication details:这一步,推测应该是wprintf(&unk_80489F8);访问了那个随机数rand()

​ 动调试了试,发现动调可以继续往下运行:

image-20221126225048795

​ 之后直接到s2 = (wchar_t *)decrypt((wchar_t *)&s, (wchar_t *)&dword_8048A90);,看s29447{you_are_an_international_mystery},轻松得到flag。

​ 但是运行到fgetws时,就直接卡住。(奇怪,在这里越界访问了动态分配的内存)

​ 还有一个奇怪的点就是,运行到prompt_authentication函数时,call _wprintf没及时打印出字符串,而是等到authenticatefgetws才打印出来。

image-20221127125209604

  1. 尝试直接跳过prompt_authentication函数,没有效果,应该不是_wprintf的问题。
  2. 尝试将下图的0x2000改成0x100,也不行。

image-20221127130456686

  1. 再仔细分析一下,正常能打印出来的_wprintf是这样的:

image-20221127131435824

prompt_authentication中的_wprintf是这样的:

image-20221127131802749

​ 突发奇想,ESP-18h是不是干扰了_wprintf的输出?直接判定字符串结尾了,输出为空?

​ 试一试。直接把sub esp 18h nop掉,还是打印不出来。又看了看,别的_wprintf也有sub esp 18h。最后,我终于知道了,因为Please enter authentication details:最后没有换行符(0Ah),最后加上换行符0Ah就OK啦。

​ 但是还是报错,只不过报错是在Please enter authentication details:这行之后了。

image-20221127175039702

​ 试验了一下,如果按如下方式改的话,就不会报错啦(我感觉应该是一开始给的空间太大了,堆空间溢出到了程序动态链接的地址中)。但是,输入正确的flag之后还是报Access Denied(看一看其他人的wp仔细研究一波)

方法2:

​ 接着分析一下decrypt(&s, &dword_8048A90)

image-20221127200257666

​ 很简单,直接上解密脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
# @Time : 2022/11/27 20:26:11
# @Author: wd-2711
'''

if __name__ == "__main__":
s = [0x0000143A, 0x00001436, 0x00001437, 0x0000143B, 0x00001480, 0x0000147A, 0x00001471, 0x00001478, 0x00001463, 0x00001466, 0x00001473, 0x00001467, 0x00001462, 0x00001465, 0x00001473, 0x00001460, 0x0000146B, 0x00001471, 0x00001478, 0x0000146A, 0x00001473, 0x00001470, 0x00001464, 0x00001478, 0x0000146E, 0x00001470, 0x00001470, 0x00001464, 0x00001470, 0x00001464, 0x0000146E, 0x0000147B, 0x00001476, 0x00001478, 0x0000146A, 0x00001473, 0x0000147B, 0x00001480]
dword_8048A90 = [0x00001401, 0x00001402, 0x00001403, 0x00001404, 0x00001405]
for id, ss in enumerate(s):
tmp = ss - dword_8048A90[id % 5]
print(chr(tmp), end = "")

0x01

​ 其他师傅wp写的都挺水的,还是我牛逼啊。哈哈

知识点1:宽字符是宽度始终为 16 位的多语言字符代码。 字符常量的类型是 char;对于宽字符,该类型是 wchar_t

知识点2:wprintf打印宽字符。

知识点3:

  1. setlocale(arg1,arg2)。设置或检索运行时区域设置。arg1受语言环境影响的类别,arg2语言环境说明符。

Hello, CTF

0x00

​ 32位的PE。扔进ida瞅了一眼,我感觉这难度4的有失难度4的水准,感觉比难度3简单。

image-20221127205141825

​ 其实就是输入字符串,对字符串做处理,然后与指定的字符串比较,我感觉这种题已经被做烂了。

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
# @Time : 2022/11/27 20:55:54
# @Author: wd-2711
'''

if __name__ == "__main__":
v13 = "437261636b4d654a757374466f7246756e"
for i in range(len(v13) // 2):
ii = v13[i*2:i*2 + 2]
print(chr(int(ii, 16)), end = "")

tar-tar-binks

0x00

image-20221127210342187

​ 两个文件,竟然是17年的题,唉后悔自己入门re太晚。libarchive.dylib占大头。

​ 搜了一下macOS系统的动态库使用dylib文件作为动态库,是64位的MAC OS X Mach-O

​ 我心想ida这么牛,应该能打开吧。

image-20221127211225564

​ 好多函数,不愧是链接库。

​ 对flag.tar进行解压显示文件损坏。解压这个文件花了我好长时间(1 day),他的文件头是正确的,一开始我猜测是校验和不对,但是网上搜索不到对应的脚本。之后我又猜测是不是加入了ustarmagic字段的元素,但是最终还是失败了。最终下载了一个修复工具DataNumen TAR Repair,就直接修好了。(无语住了,有时候工具真管用)

​ 用010editor看了一下,最初的tar文件头为:

image-20221128145654534

​ 修复后的文件头为:

image-20221128145727093

​ 是把mod,uid,gid,size,mtime,chksum改了,感觉确实是校验和的问题。(无奈自己太菜了,之后看看其他师傅的wp看看有没有计算校验和的脚本。)

​ 里面有一个flag.txt

1
F5D1,4D6B,ED6A,08A6,38DD,F7FA,609E,EBC4,E55F,E6D1,7C89,ED5B,0871,1A69,5D58,72DE,224B,3AA6,0845,7DD6,58FB,E9CC,0A2D,76B8,ED60,251A,1F6B,32CC,E78D,12FA,201A,E889,2D25,922A,4BC5,F5FF,F8E5,C79B,3A77,4BDB,EA11,5941,58BD,3A95,F5C9,A225,AD40,F8BD,095D,70B6,458C,E7A9,EA68,252F,094B,5E41,0969,6015,5ED5,F6E5,59B9,7CAF,66DF,265B,7837,57B4,7CAF,AED9,F707,6A3C,F8E5,F509,7C8B,0915,2235,336F,33E9,2D14,7C91,5804,83E5,E78D,F4EA,0874,ED6B,4B35,E839,57B4,E77C,EA68,2525,AD41,ED6F,3A4A,4BCC,6015,F440,0858,3AA6,7809,671D,0874,EA77,63AF,2E91,5845,F6C4,086D,7795,3939,57B4,7C89,82DC,32ED,B994,C7AF,9135,0E65,1B66,ED5B,3235,6577,5A80,3AD3,E776,1EE5,AD41,ED59,864C,70B4,3876,ED67,64D6,F8E5,F505,EAD9,7C9C,32ED,B994,B4EF,0C6C,F665,F5F5,9047,521A,E99E,EA68,252F,9D09,76B7,E776,1ED0,095D,0D4D,5D5A,087B,2005,1526,7E76,85AD,78B9,E8B6,782C,251C,32ED,7F68,EBE3,EA41,57FD,ED59,846D,7A05,B994,BB78,ED6A,08A6,38DD,3B5D,7E45,E839,738C,E9CC,0A2D,764A,609E,E8B6,EA68,2524,E6BB,7C9C,639F,3A95,0895,F40F,8328,EA69,7EE5,F8BD,7F7D,0D6D,70B6,458C,E8B6,EA68,251C,6065,B35F,C789,5845,7F7D,6D89,4C6E,A20E,60B5,7E45,ED59,F707,69EF,922A,4BC5,F6EF,8635,F4B9,57B4,7CF8,ED60,2510,095D,20AF,3545,F40F,8328,EA41,58A4,225D,7E7C,4BDB,F8BD,082C,EAE7,5D57,5D50,0914,E7C7,8624,7CF8,ED60,2511,7C8E,7159,8416,7EF9,E7E5,774A,3895,1EC9,7C90,09B9,58BD,5FF5,E99E,EA68,250A,224C,EA3D,73F5,7C89,53A6,3190,3B5D,1526,7DD5,666A,0919,225F,CDEF,79E1,7E7B,7E6B,082C,A277,E885,E8BB,E775,5FF7,EA68,251B,7FDF,589D,7A05,779A,8A5A,7C91,5D5C,32ED,F628,2195,F49A,0C77,EAE1,59B9,58BD,E570,E99E,EA3D,73F9,13AD,2BF5,225D,7F7D,70B6,4A9C,337A,1EC9,4D05,7E75,2578,ED59,38E5,1ECA,A210,3B5D,779A,8A6F,C790,2518,4B41,7C89,5D49,4D05,152D,73C5,79F9,4BED,913C,37C9,5D4D,53C8,0941,7C97,5D5B,346A,82D8,5F36,801F,C800

​ 其实不修复也能看到,可能我比较追求完美吧,嘿嘿。应该是加密后的密文,猜测是用dylib库内的某个函数加的密。

​ 在库中找到这样一个函数:

image-20221128151647718

​ 与文件结果很匹配,猜测就是打开一个文件,加密之后把结果以大写16进制写入了flag.txt

​ 追踪sub_101数组:

image-20221128154939180

​ 追踪a1

image-20221128154905013

​ 追踪sub_1023456

image-20221128155156042

​ 发现sub_1023458中的a1数组的元素始终在[0-39]之间。(可以遍历

​ 一开始写了一个遍历脚本,64线程,跑了1day,没跑出来。我的垃圾脚本如下:

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
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
# @Time : 2022/11/28 20:57:40
# @Author: wd-2711
'''

import time
import threading

flags = [""]

class myThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.circle_tb = [0x5F, 0x2D, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A]
self.sub_1023456_shifted = -1
self.pending = 1
self.v9 = [0 for i in range(3)]
self.sub_101 = []
self.flagEncrypted = [62929, 19819, 60778, 2214, 14557, 63482, 24734, 60356, 58719, 59089, 31881, 60763, 2161, 6761, 23896, 29406, 8779, 15014, 2117, 32214, 22779, 59852, 2605, 30392, 60768, 9498, 8043, 13004, 59277, 4858, 8218, 59529, 11557, 37418, 19397, 62975, 63717, 51099, 14967, 19419, 59921, 22849, 22717, 14997, 62921, 41509, 44352, 63677, 2397, 28854, 17804, 59305, 60008, 9519, 2379, 24129, 2409, 24597, 24277, 63205, 22969, 31919, 26335, 9819, 30775, 22452, 31919, 44761, 63239, 27196, 63717, 62729, 31883, 2325, 8757, 13167, 13289, 11540, 31889, 22532, 33765, 59277, 62698, 2164, 60779, 19253, 59449, 22452, 59260, 60008, 9509, 44353, 60783, 14922, 19404, 24597, 62528, 2136, 15014, 30729, 26397, 2164, 60023, 25519, 11921, 22597, 63172, 2157, 30613, 14649, 22452, 31881, 33500, 13037, 47508, 51119, 37173, 3685, 7014, 60763, 12853, 25975, 23168, 15059, 59254, 7909, 44353, 60761, 34380, 28852, 14454, 60775, 25814, 63717, 62725, 60121, 31900, 13037, 47508, 46319, 3180, 63077, 62965, 36935, 21018, 59806, 60008, 9519, 40201, 30391, 59254, 7888, 2397, 3405, 23898, 2171, 8197, 5414, 32374, 34221, 30905, 59574, 30764, 9500, 13037, 32616, 60387, 59969, 22525, 60761, 33901, 31237, 47508, 47992, 60778, 2214, 14557, 15197, 32325, 59449, 29580, 59852, 2605, 30282, 24734, 59574, 60008, 9508, 59067, 31900, 25503, 14997, 2197, 62479, 33576, 60009, 32485, 63677, 32637, 3437, 28854, 17804, 59574, 60008, 9500, 24677, 45919, 51081, 22597, 32637, 28041, 19566, 41486, 24757, 32325, 60761, 63239, 27119, 37418, 19397, 63215, 34357, 62649, 22452, 31992, 60768, 9488, 2397, 8367, 13637, 62479, 33576, 59969, 22692, 8797, 32380, 19419, 63677, 2092, 60135, 23895, 23888, 2324, 59335, 34340, 31992, 60768, 9489, 31886, 29017, 33814, 32505, 59365, 30538, 14485, 7881, 31888, 2489, 22717, 24565, 59806, 60008, 9482, 8780, 59965, 29685, 31881, 21414, 12688, 15197, 5414, 32213, 26218, 2329, 8799, 52719, 31201, 32379, 32363, 2092, 41591, 59525, 59579, 59253, 24567, 60008, 9499, 32735, 22685, 31237, 30618, 35418, 31889, 23900, 13037, 63016, 8597, 62618, 3191, 60129, 22969, 22717, 58736, 59806, 59965, 29689, 5037, 11253, 8797, 32637, 28854, 19100, 13178, 7881, 19717, 32373, 9592, 60761, 14565, 7882, 41488, 15197, 30618, 35439, 51088, 9496, 19265, 31881, 23881, 19717, 5421, 29637, 31225, 19437, 37180, 14281, 23885, 21448, 2369, 31895, 23899, 13418, 33496, 24374, 32799, 51200]

def sub_1023456(self, a1):
v4 = a1
if self.sub_1023456_shifted == -1:
if a1 == 126:
v4 = 0
for i in range(39):
if self.ctable[i] == v4:
self.pending = 0
return i
if self.ctable[i + 39] == v4:
self.pending = 1
self.sub_1023456_shifted = i
return 39
self.pending = 0
v5 = 37
else:
v2 = self.sub_1023456_shifted
self.sub_1023456_shifted = -1
self.pending = 0
v5 = v2
return v5

def sub_1023458(self, a1):
sum = a1[0] + 40 * a1[1] + 1600 * a1[2]
self.sub_101.append(sum)

def sub_1023457(self, a1, a2):
v6 = 3
i = -1
while i < a2:
i += 1
v5 = a1[i]
self.pending = 1
while self.pending:
v6 -= 1
self.v9[v6] = self.sub_1023456(v5)
if v6 == 0:
self.sub_1023458(self.v9)
v6 = 3
if v6 != 3:
while v6 != -1:
v6 -= 1
self.v9[v6] = 0
self.sub_1023458(self.v9)

def run(self):
global flags
while True:
threadLock1.acquire()
s = flags[0]
flags = flags[1:]
print("len: ", len(flags))
threadLock1.release()
ll = int(len(s)/1.5 + 2)
lll = int(ll / 2)
for i in range(32, 128):
for j in range(32, 128):
for k in range(32, 128):
s += chr(i) + chr(j) + chr(k)
s = [ord(ss) for ss in s]
self.sub_1023457(s, ll)
good = 1
for ii in range(lll):
# print(sub_101[ii], hex(int(flagEncrypted[ii], 16))[2:], ii)
if self.sub_101[ii] != int(self.flagEncrypted[ii], 16):
good = 0
break
s = "".join([chr(ss) for ss in s])
if good:
threadLock2.acquire()
flags.append(s)
threadLock2.release()
self.sub_101 = []
s = s[:-3]
if len(flags) == 1:
break

threadLock1 = threading.Lock()
threadLock2 = threading.Lock()
threads = []
for i in range(64):
th = myThread()
th.start()
threads.append(th)

for t in threads:
t.join()

print(flags)

​ 最终,仔细瞅了瞅sub_1023456,总结如下:

  1. 当输入字符为a-z0-9,返回ctable中对应的标号。
  2. 当输入字符为A-Z(!@#,.?/*)<>时,返回39与返回ctable中对应的标号-39
  3. 输入其他字符时,返回37。

​ 可以写脚本:

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
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
# @Time : 2022/11/29 09:59:51
# @Author: wd-2711
'''

from tqdm import tqdm

ctable = [0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x20, 0x0A, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x28, 0x21, 0x40, 0x23, 0x2C, 0x2E, 0x3F, 0x2F, 0x2A, 0x29, 0x3C, 0x3E, 0x00, 0x00]
flagEncrypted = "F5D1,4D6B,ED6A,08A6,38DD,F7FA,609E,EBC4,E55F,E6D1,7C89,ED5B,0871,1A69,5D58,72DE,224B,3AA6,0845,7DD6,58FB,E9CC,0A2D,76B8,ED60,251A,1F6B,32CC,E78D,12FA,201A,E889,2D25,922A,4BC5,F5FF,F8E5,C79B,3A77,4BDB,EA11,5941,58BD,3A95,F5C9,A225,AD40,F8BD,095D,70B6,458C,E7A9,EA68,252F,094B,5E41,0969,6015,5ED5,F6E5,59B9,7CAF,66DF,265B,7837,57B4,7CAF,AED9,F707,6A3C,F8E5,F509,7C8B,0915,2235,336F,33E9,2D14,7C91,5804,83E5,E78D,F4EA,0874,ED6B,4B35,E839,57B4,E77C,EA68,2525,AD41,ED6F,3A4A,4BCC,6015,F440,0858,3AA6,7809,671D,0874,EA77,63AF,2E91,5845,F6C4,086D,7795,3939,57B4,7C89,82DC,32ED,B994,C7AF,9135,0E65,1B66,ED5B,3235,6577,5A80,3AD3,E776,1EE5,AD41,ED59,864C,70B4,3876,ED67,64D6,F8E5,F505,EAD9,7C9C,32ED,B994,B4EF,0C6C,F665,F5F5,9047,521A,E99E,EA68,252F,9D09,76B7,E776,1ED0,095D,0D4D,5D5A,087B,2005,1526,7E76,85AD,78B9,E8B6,782C,251C,32ED,7F68,EBE3,EA41,57FD,ED59,846D,7A05,B994,BB78,ED6A,08A6,38DD,3B5D,7E45,E839,738C,E9CC,0A2D,764A,609E,E8B6,EA68,2524,E6BB,7C9C,639F,3A95,0895,F40F,8328,EA69,7EE5,F8BD,7F7D,0D6D,70B6,458C,E8B6,EA68,251C,6065,B35F,C789,5845,7F7D,6D89,4C6E,A20E,60B5,7E45,ED59,F707,69EF,922A,4BC5,F6EF,8635,F4B9,57B4,7CF8,ED60,2510,095D,20AF,3545,F40F,8328,EA41,58A4,225D,7E7C,4BDB,F8BD,082C,EAE7,5D57,5D50,0914,E7C7,8624,7CF8,ED60,2511,7C8E,7159,8416,7EF9,E7E5,774A,3895,1EC9,7C90,09B9,58BD,5FF5,E99E,EA68,250A,224C,EA3D,73F5,7C89,53A6,3190,3B5D,1526,7DD5,666A,0919,225F,CDEF,79E1,7E7B,7E6B,082C,A277,E885,E8BB,E775,5FF7,EA68,251B,7FDF,589D,7A05,779A,8A5A,7C91,5D5C,32ED,F628,2195,F49A,0C77,EAE1,59B9,58BD,E570,E99E,EA3D,73F9,13AD,2BF5,225D,7F7D,70B6,4A9C,337A,1EC9,4D05,7E75,2578,ED59,38E5,1ECA,A210,3B5D,779A,8A6F,C790,2518,4B41,7C89,5D49,4D05,152D,73C5,79F9,4BED,913C,37C9,5D4D,53C8,0941,7C97,5D5B,346A,82D8,5F36,801F,C800"

if __name__ == "__main__":
flagEncrypted = flagEncrypted.split(",")
Arr = []
for fi in tqdm(flagEncrypted):
for i in range(40):
for j in range(40):
for k in range(40):
tmp1 = i + 40 * j + 1600 * k
if int(fi, 16) == tmp1:
Arr.extend([k, j, i])
i = 0
flag = ""
for ind in Arr:
if ind == 39:
i = 39
continue
elif ind == 37:
flag += " "
i = 0
continue
else:
flag += chr(ctable[ind + i])
i = 0
continue
print(flag)
# Milos Raonic (born 1990) is a Canadian professional tennis player. He reached a career high world No. 4 singles ranking in May 2015, as ranked by the Association of Tennis Professionals (ATP). His career highlights include a Grand Slam final at the 2016 Wimbledon Championships and two Grand Slam semifinals at the 2014 Wimbledon Championships and 2016 Australian Open. He was the 2011 ATP Newcomer of the Year, and has been ranked continuously inside the top 20 since August 2012. Raonic is the first player born in the 1990s to win an ATP title, to be ranked in the top 10, and to qualify for the ATP World Tour Finals. He has eight ATP singles titles, all won on hard courts. He is frequently described as having one of the best serves among his contemporaries. Statistically, he is among the strongest servers in the Open Era, winning 91p of service games to rank third all time. Aided by his serve, he plays an all court style with an emphasis on short points.

​ 输出了一段话,看了好久不知道啥意思,为啥放在flag.txt里啊,不理解。

​ 之后我又试了试md5sha1sha256,都不是正确的flag。准备看wp了。

0x01

​ 看了一下,我真是草泥马。最后是md5加密,为啥我的不对,草泥马。

​ 吐槽一下,继续瞅瞅。

​ 最终,我发现一个很有意思的事情,我在线md5加密和python的md5加密不一样。仔细瞅了瞅,发现python对字符串encode之后,是这样的:

image-20221129111018274

​ 而在线md5无法输入\x00\x00,所以导致了不一样的问题。悔恨啊!

​ 但是,最终的结果更狗。最终md5是先把尾部的\x00\x00去掉,然后再加上\n,然后再md5。行吧,以后记得加\n

​ 上述脚本中加入,获得flag:

1
2
3
4
5
m = hashlib.md5()
m.update(flag.encode()[:-2] + b'\n')
print(m.hexdigest())

# 2c8cd31daeba8753815851f13e6370b3

​ 关于解压的问题,别的师傅根本没详细说,感觉他们可能以为这个太简单了?

搞了好久,其实就差最后一口气。

知识点1:Windows系统的动态库是DLL文件,Linux系统是so文件,macOS系统的动态库则使用dylib文件作为动态库。

知识点2:tar文件结构。tar程序是一个归档程序,它将文件存储在一个单独的归档文件中,而不进行压缩

https://blog.csdn.net/DisMisPres/article/details/94733424

知识点3:输出长话要试一试各种哈希算法,哈希算法结果也试一试大小写。而且加密的时候字符串一般都是先把尾部的\x00去掉,然后加上\n再哈希。


handcrafted-pyc

0x00

​ 这个题目的名字:手工制作pyc,文件后缀.py_bc552f58fe2709225ca0768c131dd14934a47305好长。exeinfope说是py文件。

​ 改成py文件之后瞅瞅。

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import marshal, zlib, base64

exec(
marshal.loads(
zlib.decompress(
base64.b64decode( 'eJyNVktv00AQXm/eL0igiaFA01IO4cIVCUGFBBJwqRAckLhEIQmtRfPwI0QIeio/hRO/hJ/CiStH2M/prj07diGRP43Hs9+MZ2fWMxbnP6mux+oK9xVMHPFViLdCTB0xkeKDFEFfTIU4E8KZq8dCvB4UlN3hGEsdddXU9QTLv1eFiGKGM4cKUgsFCNLFH7dFrS9poayFYmIZm1b0gyqxMOwJaU3r6xs9sW1ooakXuRv+un7Q0sIlLVzOCZq/XtsK2oTSYaZlStogXi1HV0iazoN2CV2HZeXqRQ54TlJRb7FUlKyUatISsdzo+P7UU1Gb1POdMruckepGwk9tIXQTftz2yBaT5JQovWvpSa6poJPuqgao+b9l5Aj/R+mLQIP4f6Q8Vb3g/5TB/TJxWGdZr9EQrmn99fwKtTvAZGU7wzS7GNpZpDm2JgCrr8wrmPoo54UqGampFIeS9ojXjc4E2yI06bq/4DRoUAc0nVnng4k6p7Ks0+j/S8z9V+NZ5dhmrJUM/y7JTJeRtnJ2TSYJvsFq3CQt/vnfqmQXt5KlpuRcIvDAmhnn2E0t9BJ3SvB/SfLWhuOWNiNVZ+h28g4wlwUp00w95si43rZ3r6+fUIEdgOZbQAsyFRRvBR6dla8KCzRdslar7WS+a5HFb39peIAmG7uZTHVm17Czxju4m6bayz8e7J40DzqM0jr0bmv9PmPvk6y5z57HU8wdTDHeiUJvBMAM4+0CpoAZ4BPgJeAYEAHmgAUgAHiAj4AVAGORtwd4AVgC3gEmgBBwCPgMWANOAQ8AbwBHgHuAp4D3gLuARwoGmNUizF/j4yDC5BWM1kNvvlxFA8xikRrBxHIUhutFMBlgQoshhPphGAXe/OggKqqb2cibxwuEXjUcQjccxi5eFRL1fDSbKrUhy2CMb2aLyepkegDWsBwPlrVC0/kLHmeCBQ=='
))))

知识补充:

​ 1. marsha1库。Python的marshal模块,顾名思义也是负责在Python数值与二进制字节对象之间进行转换的。但是,marshal模块仅供Python解析器内部用作对象的序列化不推荐开发人员使用该模块处理Python对象的序列化和反序列化(更推荐用pickle)。marshal模块不是通用的序列化/反序列化模块,而是以读写.pyc文件中的Python代码为目的设计的。marshal模块提供的函数可以读写二进制对象为Python数值。这里的二进制对象是Python字节定义的独特二进制格式,与所在机器的体系结构无关。

函数名 函数作用
load(file) 从文件读取Python数值并返回该值
loads(bytes) 将读入的字节对象转换为Python数值
dump(value, file) 将Python数值写入到文件
dumps(value) 将读入的Python数值转换为一个字节对象

​ 2. pyc文件。pyc文件是py文件编译后生成的字节码文件(byte code)。pyc文件经过python解释器最终会生成机器码运行。所以pyc文件是可以跨平台部署的,类似Java的.class文件。一般py文件改变后,都会重新生成pyc文件。

补充完毕!

​ 之后准备生成handcrafted.pyc文件,脚本如下:

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import marshal, zlib, base64

with open("handcrafted.pyc", "wb") as f:
marshal.dump(
zlib.decompress(
base64.b64decode( 'eJyNVktv00AQXm/eL0igiaFA01IO4cIVCUGFBBJwqRAckLhEIQmtRfPwI0QIeio/hRO/hJ/CiStH2M/prj07diGRP43Hs9+MZ2fWMxbnP6mux+oK9xVMHPFViLdCTB0xkeKDFEFfTIU4E8KZq8dCvB4UlN3hGEsdddXU9QTLv1eFiGKGM4cKUgsFCNLFH7dFrS9poayFYmIZm1b0gyqxMOwJaU3r6xs9sW1ooakXuRv+un7Q0sIlLVzOCZq/XtsK2oTSYaZlStogXi1HV0iazoN2CV2HZeXqRQ54TlJRb7FUlKyUatISsdzo+P7UU1Gb1POdMruckepGwk9tIXQTftz2yBaT5JQovWvpSa6poJPuqgao+b9l5Aj/R+mLQIP4f6Q8Vb3g/5TB/TJxWGdZr9EQrmn99fwKtTvAZGU7wzS7GNpZpDm2JgCrr8wrmPoo54UqGampFIeS9ojXjc4E2yI06bq/4DRoUAc0nVnng4k6p7Ks0+j/S8z9V+NZ5dhmrJUM/y7JTJeRtnJ2TSYJvsFq3CQt/vnfqmQXt5KlpuRcIvDAmhnn2E0t9BJ3SvB/SfLWhuOWNiNVZ+h28g4wlwUp00w95si43rZ3r6+fUIEdgOZbQAsyFRRvBR6dla8KCzRdslar7WS+a5HFb39peIAmG7uZTHVm17Czxju4m6bayz8e7J40DzqM0jr0bmv9PmPvk6y5z57HU8wdTDHeiUJvBMAM4+0CpoAZ4BPgJeAYEAHmgAUgAHiAj4AVAGORtwd4AVgC3gEmgBBwCPgMWANOAQ8AbwBHgHuAp4D3gLuARwoGmNUizF/j4yDC5BWM1kNvvlxFA8xikRrBxHIUhutFMBlgQoshhPphGAXe/OggKqqb2cibxwuEXjUcQjccxi5eFRL1fDSbKrUhy2CMb2aLyepkegDWsBwPlrVC0/kLHmeCBQ=='
)), f)

​ 然后使用uncompyle6将pyc转为py,报错:

image-20221202132050845

之后我们就要修复生成的handcrafted.pyc文件。

​ 学习完pyc文件分析后,对比并在文件开头加3个字节,并将开头四个字节改为03 F3 0D 0A,表示是python2.7。之后使用uncompyle6反编译仍然报错:

image-20221202145559527

​ 但是还是生成的python文件,瞅了瞅,里面写了一些opcode乱码。其实可以直接看到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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
# uncompyle6 version 3.8.0
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: <string>
# Compiled at: 1970-01-01 08:44:22


def main--- This code section failed: ---

L. 1 0 LOAD_GLOBAL 0 'chr'
3 LOAD_CONST 108
6 CALL_FUNCTION_1 1 None
9 LOAD_GLOBAL 0 'chr'
12 LOAD_CONST 108
15 CALL_FUNCTION_1 1 None
18 LOAD_GLOBAL 0 'chr'
21 LOAD_CONST 97
24 CALL_FUNCTION_1 1 None
27 LOAD_GLOBAL 0 'chr'
30 LOAD_CONST 67
33 CALL_FUNCTION_1 1 None
36 ROT_TWO
37 BINARY_ADD
38 ROT_TWO
39 BINARY_ADD
40 ROT_TWO
41 BINARY_ADD
42 LOAD_GLOBAL 0 'chr'
45 LOAD_CONST 32
48 CALL_FUNCTION_1 1 None
51 LOAD_GLOBAL 0 'chr'
54 LOAD_CONST 101
57 CALL_FUNCTION_1 1 None
60 LOAD_GLOBAL 0 'chr'
63 LOAD_CONST 109
66 CALL_FUNCTION_1 1 None
69 LOAD_GLOBAL 0 'chr'
72 LOAD_CONST 32
75 CALL_FUNCTION_1 1 None
78 ROT_TWO
79 BINARY_ADD
80 ROT_TWO
81 BINARY_ADD
82 ROT_TWO
83 BINARY_ADD
84 BINARY_ADD
85 LOAD_GLOBAL 0 'chr'
88 LOAD_CONST 121
91 CALL_FUNCTION_1 1 None
94 LOAD_GLOBAL 0 'chr'
97 LOAD_CONST 80
100 CALL_FUNCTION_1 1 None
103 LOAD_GLOBAL 0 'chr'
106 LOAD_CONST 32
109 CALL_FUNCTION_1 1 None
112 LOAD_GLOBAL 0 'chr'
115 LOAD_CONST 97
118 CALL_FUNCTION_1 1 None
121 ROT_TWO
122 BINARY_ADD
123 ROT_TWO
124 BINARY_ADD
125 ROT_TWO
126 BINARY_ADD
127 LOAD_GLOBAL 0 'chr'
130 LOAD_CONST 104
133 CALL_FUNCTION_1 1 None
136 LOAD_GLOBAL 0 'chr'
139 LOAD_CONST 116
142 CALL_FUNCTION_1 1 None
145 ROT_TWO
146 BINARY_ADD
147 LOAD_GLOBAL 0 'chr'
150 LOAD_CONST 32
153 CALL_FUNCTION_1 1 None
156 LOAD_GLOBAL 0 'chr'
159 LOAD_CONST 110
162 CALL_FUNCTION_1 1 None
165 LOAD_GLOBAL 0 'chr'
168 LOAD_CONST 111
171 CALL_FUNCTION_1 1 None
174 ROT_TWO
175 BINARY_ADD
176 ROT_TWO
177 BINARY_ADD
178 BINARY_ADD
179 BINARY_ADD
180 BINARY_ADD
181 LOAD_GLOBAL 0 'chr'
184 LOAD_CONST 116
187 CALL_FUNCTION_1 1 None
190 LOAD_GLOBAL 0 'chr'
193 LOAD_CONST 114
196 CALL_FUNCTION_1 1 None
199 LOAD_GLOBAL 0 'chr'
202 LOAD_CONST 105
205 CALL_FUNCTION_1 1 None
208 LOAD_GLOBAL 0 'chr'
211 LOAD_CONST 118
214 CALL_FUNCTION_1 1 None
217 ROT_TWO
218 BINARY_ADD
219 ROT_TWO
220 BINARY_ADD
221 ROT_TWO
222 BINARY_ADD
223 LOAD_GLOBAL 0 'chr'
226 LOAD_CONST 32
229 CALL_FUNCTION_1 1 None
232 LOAD_GLOBAL 0 'chr'
235 LOAD_CONST 108
238 CALL_FUNCTION_1 1 None
241 LOAD_GLOBAL 0 'chr'
244 LOAD_CONST 97
247 CALL_FUNCTION_1 1 None
250 LOAD_GLOBAL 0 'chr'
253 LOAD_CONST 117
256 CALL_FUNCTION_1 1 None
259 ROT_TWO
260 BINARY_ADD
261 ROT_TWO
262 BINARY_ADD
263 ROT_TWO
264 BINARY_ADD
265 BINARY_ADD
266 LOAD_GLOBAL 0 'chr'
269 LOAD_CONST 104
272 CALL_FUNCTION_1 1 None
275 LOAD_GLOBAL 0 'chr'
278 LOAD_CONST 99
281 CALL_FUNCTION_1 1 None
284 LOAD_GLOBAL 0 'chr'
287 LOAD_CONST 97
290 CALL_FUNCTION_1 1 None
293 LOAD_GLOBAL 0 'chr'
296 LOAD_CONST 109
299 CALL_FUNCTION_1 1 None
302 ROT_TWO
303 BINARY_ADD
304 ROT_TWO
305 BINARY_ADD
306 ROT_TWO
307 BINARY_ADD
308 LOAD_GLOBAL 0 'chr'
311 LOAD_CONST 110
314 CALL_FUNCTION_1 1 None
317 LOAD_GLOBAL 0 'chr'
320 LOAD_CONST 105
323 CALL_FUNCTION_1 1 None
326 ROT_TWO
327 BINARY_ADD
328 LOAD_GLOBAL 0 'chr'
331 LOAD_CONST 32
334 CALL_FUNCTION_1 1 None
337 LOAD_GLOBAL 0 'chr'
340 LOAD_CONST 33
343 CALL_FUNCTION_1 1 None
346 LOAD_GLOBAL 0 'chr'
349 LOAD_CONST 101
352 CALL_FUNCTION_1 1 None
355 ROT_TWO
356 BINARY_ADD
357 ROT_TWO
358 BINARY_ADD
359 BINARY_ADD
360 BINARY_ADD
361 BINARY_ADD
362 BINARY_ADD
363 LOAD_GLOBAL 0 'chr'
366 LOAD_CONST 97
369 CALL_FUNCTION_1 1 None
372 LOAD_GLOBAL 0 'chr'
375 LOAD_CONST 99
378 CALL_FUNCTION_1 1 None
381 LOAD_GLOBAL 0 'chr'
384 LOAD_CONST 32
387 CALL_FUNCTION_1 1 None
390 LOAD_GLOBAL 0 'chr'
393 LOAD_CONST 73
396 CALL_FUNCTION_1 1 None
399 ROT_TWO
400 BINARY_ADD
401 ROT_TWO
402 BINARY_ADD
403 ROT_TWO
404 BINARY_ADD
405 LOAD_GLOBAL 0 'chr'
408 LOAD_CONST 110
411 CALL_FUNCTION_1 1 None
414 LOAD_GLOBAL 0 'chr'
417 LOAD_CONST 105
420 CALL_FUNCTION_1 1 None
423 LOAD_GLOBAL 0 'chr'
426 LOAD_CONST 32
429 CALL_FUNCTION_1 1 None
432 LOAD_GLOBAL 0 'chr'
435 LOAD_CONST 110
438 CALL_FUNCTION_1 1 None
441 ROT_TWO
442 BINARY_ADD
443 ROT_TWO
444 BINARY_ADD
445 ROT_TWO
446 BINARY_ADD
447 BINARY_ADD
448 LOAD_GLOBAL 0 'chr'
451 LOAD_CONST 112
454 CALL_FUNCTION_1 1 None
457 LOAD_GLOBAL 0 'chr'
460 LOAD_CONST 114
463 CALL_FUNCTION_1 1 None
466 LOAD_GLOBAL 0 'chr'
469 LOAD_CONST 101
472 CALL_FUNCTION_1 1 None
475 LOAD_GLOBAL 0 'chr'
478 LOAD_CONST 116
481 CALL_FUNCTION_1 1 None
484 ROT_TWO
485 BINARY_ADD
486 ROT_TWO
487 BINARY_ADD
488 ROT_TWO
489 BINARY_ADD
490 LOAD_GLOBAL 0 'chr'
493 LOAD_CONST 101
496 CALL_FUNCTION_1 1 None
499 LOAD_GLOBAL 0 'chr'
502 LOAD_CONST 114
505 CALL_FUNCTION_1 1 None
508 ROT_TWO
509 BINARY_ADD
510 LOAD_GLOBAL 0 'chr'
513 LOAD_CONST 80
516 CALL_FUNCTION_1 1 None
519 LOAD_GLOBAL 0 'chr'
522 LOAD_CONST 32
525 CALL_FUNCTION_1 1 None
528 LOAD_GLOBAL 0 'chr'
531 LOAD_CONST 116
534 CALL_FUNCTION_1 1 None
537 ROT_TWO
538 BINARY_ADD
539 ROT_TWO
540 BINARY_ADD
541 BINARY_ADD
542 BINARY_ADD
543 BINARY_ADD
544 LOAD_GLOBAL 0 'chr'
547 LOAD_CONST 111
550 CALL_FUNCTION_1 1 None
553 LOAD_GLOBAL 0 'chr'
556 LOAD_CONST 104
559 CALL_FUNCTION_1 1 None
562 LOAD_GLOBAL 0 'chr'
565 LOAD_CONST 116
568 CALL_FUNCTION_1 1 None
571 LOAD_GLOBAL 0 'chr'
574 LOAD_CONST 121
577 CALL_FUNCTION_1 1 None
580 ROT_TWO
581 BINARY_ADD
582 ROT_TWO
583 BINARY_ADD
584 ROT_TWO
585 BINARY_ADD
586 LOAD_GLOBAL 0 'chr'
589 LOAD_CONST 32
592 CALL_FUNCTION_1 1 None
595 LOAD_GLOBAL 0 'chr'
598 LOAD_CONST 110
601 CALL_FUNCTION_1 1 None
604 ROT_TWO
605 BINARY_ADD
606 LOAD_GLOBAL 0 'chr'
609 LOAD_CONST 116
612 CALL_FUNCTION_1 1 None
615 LOAD_GLOBAL 0 'chr'
618 LOAD_CONST 121
621 CALL_FUNCTION_1 1 None
624 LOAD_GLOBAL 0 'chr'
627 LOAD_CONST 98
630 CALL_FUNCTION_1 1 None
633 ROT_TWO
634 BINARY_ADD
635 ROT_TWO
636 BINARY_ADD
637 BINARY_ADD
638 BINARY_ADD
639 LOAD_GLOBAL 0 'chr'
642 LOAD_CONST 100
645 CALL_FUNCTION_1 1 None
648 LOAD_GLOBAL 0 'chr'
651 LOAD_CONST 111
654 CALL_FUNCTION_1 1 None
657 LOAD_GLOBAL 0 'chr'
660 LOAD_CONST 99
663 CALL_FUNCTION_1 1 None
666 LOAD_GLOBAL 0 'chr'
669 LOAD_CONST 101
672 CALL_FUNCTION_1 1 None
675 ROT_TWO
676 BINARY_ADD
677 ROT_TWO
678 BINARY_ADD
679 ROT_TWO
680 BINARY_ADD
681 LOAD_GLOBAL 0 'chr'
684 LOAD_CONST 115
687 CALL_FUNCTION_1 1 None
690 LOAD_GLOBAL 0 'chr'
693 LOAD_CONST 101
696 CALL_FUNCTION_1 1 None
699 ROT_TWO
700 BINARY_ADD
701 LOAD_GLOBAL 0 'chr'
704 LOAD_CONST 33
707 CALL_FUNCTION_1 1 None
710 LOAD_GLOBAL 0 'chr'
713 LOAD_CONST 33
716 CALL_FUNCTION_1 1 None
719 LOAD_GLOBAL 0 'chr'
722 LOAD_CONST 33
725 CALL_FUNCTION_1 1 None
728 ROT_TWO
729 BINARY_ADD
730 ROT_TWO
731 BINARY_ADD
732 BINARY_ADD
733 BINARY_ADD
734 BINARY_ADD
735 BINARY_ADD
736 BINARY_ADD
737 LOAD_CONST None
740 NOP
741 JUMP_ABSOLUTE 759 'to 759'
744 LOAD_GLOBAL 1 'raw_input'
747 JUMP_ABSOLUTE 1480 'to 1480'
750 LOAD_FAST 0 'password'
753 COMPARE_OP 2 ==
756 JUMP_ABSOLUTE 767 'to 767'
759 ROT_TWO
760 STORE_FAST 0 'password'
763 POP_TOP
764 JUMP_BACK 744 'to 744'
767 POP_JUMP_IF_FALSE 1591 'to 1591'
770 LOAD_GLOBAL 0 'chr'
773 LOAD_CONST 99
776 CALL_FUNCTION_1 1 None
779 LOAD_GLOBAL 0 'chr'
782 LOAD_CONST 116
785 CALL_FUNCTION_1 1 None
788 LOAD_GLOBAL 0 'chr'
791 LOAD_CONST 105
794 CALL_FUNCTION_1 1 None
797 LOAD_GLOBAL 0 'chr'
800 LOAD_CONST 104
803 CALL_FUNCTION_1 1 None
806 ROT_TWO
807 BINARY_ADD
808 ROT_TWO
809 BINARY_ADD
810 ROT_TWO
811 BINARY_ADD
812 LOAD_GLOBAL 0 'chr'
815 LOAD_CONST 78
818 CALL_FUNCTION_1 1 None
821 LOAD_GLOBAL 0 'chr'
824 LOAD_CONST 123
827 CALL_FUNCTION_1 1 None
830 LOAD_GLOBAL 0 'chr'
833 LOAD_CONST 110
836 CALL_FUNCTION_1 1 None
839 LOAD_GLOBAL 0 'chr'
842 LOAD_CONST 111
845 CALL_FUNCTION_1 1 None
848 ROT_TWO
849 BINARY_ADD
850 ROT_TWO
851 BINARY_ADD
852 ROT_TWO
853 BINARY_ADD
854 BINARY_ADD
855 LOAD_GLOBAL 0 'chr'
858 LOAD_CONST 121
861 CALL_FUNCTION_1 1 None
864 LOAD_GLOBAL 0 'chr'
867 LOAD_CONST 32
870 CALL_FUNCTION_1 1 None
873 LOAD_GLOBAL 0 'chr'
876 LOAD_CONST 119
879 CALL_FUNCTION_1 1 None
882 LOAD_GLOBAL 0 'chr'
885 LOAD_CONST 111
888 CALL_FUNCTION_1 1 None
891 ROT_TWO
892 BINARY_ADD
893 ROT_TWO
894 BINARY_ADD
895 ROT_TWO
896 BINARY_ADD
897 LOAD_GLOBAL 0 'chr'
900 LOAD_CONST 99
903 CALL_FUNCTION_1 1 None
906 LOAD_GLOBAL 0 'chr'
909 LOAD_CONST 32
912 CALL_FUNCTION_1 1 None
915 LOAD_GLOBAL 0 'chr'
918 LOAD_CONST 117
921 CALL_FUNCTION_1 1 None
924 LOAD_GLOBAL 0 'chr'
927 LOAD_CONST 111
930 CALL_FUNCTION_1 1 None
933 ROT_TWO
934 BINARY_ADD
935 ROT_TWO
936 BINARY_ADD
937 ROT_TWO
938 BINARY_ADD
939 BINARY_ADD
940 BINARY_ADD
941 LOAD_GLOBAL 0 'chr'
944 LOAD_CONST 99
947 CALL_FUNCTION_1 1 None
950 LOAD_GLOBAL 0 'chr'
953 LOAD_CONST 32
956 CALL_FUNCTION_1 1 None
959 LOAD_GLOBAL 0 'chr'
962 LOAD_CONST 110
965 CALL_FUNCTION_1 1 None
968 LOAD_GLOBAL 0 'chr'
971 LOAD_CONST 97
974 CALL_FUNCTION_1 1 None
977 ROT_TWO
978 BINARY_ADD
979 ROT_TWO
980 BINARY_ADD
981 ROT_TWO
982 BINARY_ADD
983 LOAD_GLOBAL 0 'chr'
986 LOAD_CONST 105
989 CALL_FUNCTION_1 1 None
992 LOAD_GLOBAL 0 'chr'
995 LOAD_CONST 112
998 CALL_FUNCTION_1 1 None
1001 LOAD_GLOBAL 0 'chr'
1004 LOAD_CONST 109
1007 CALL_FUNCTION_1 1 None
1010 LOAD_GLOBAL 0 'chr'
1013 LOAD_CONST 111
1016 CALL_FUNCTION_1 1 None
1019 ROT_TWO
1020 BINARY_ADD
1021 ROT_TWO
1022 BINARY_ADD
1023 ROT_TWO
1024 BINARY_ADD
1025 BINARY_ADD
1026 LOAD_GLOBAL 0 'chr'
1029 LOAD_CONST 97
1032 CALL_FUNCTION_1 1 None
1035 LOAD_GLOBAL 0 'chr'
1038 LOAD_CONST 32
1041 CALL_FUNCTION_1 1 None
1044 LOAD_GLOBAL 0 'chr'
1047 LOAD_CONST 101
1050 CALL_FUNCTION_1 1 None
1053 LOAD_GLOBAL 0 'chr'
1056 LOAD_CONST 108
1059 CALL_FUNCTION_1 1 None
1062 ROT_TWO
1063 BINARY_ADD
1064 ROT_TWO
1065 BINARY_ADD
1066 ROT_TWO
1067 BINARY_ADD
1068 LOAD_GLOBAL 0 'chr'
1071 LOAD_CONST 100
1074 CALL_FUNCTION_1 1 None
1077 LOAD_GLOBAL 0 'chr'
1080 LOAD_CONST 110
1083 CALL_FUNCTION_1 1 None
1086 ROT_TWO
1087 BINARY_ADD
1088 LOAD_GLOBAL 0 'chr'
1091 LOAD_CONST 117
1094 CALL_FUNCTION_1 1 None
1097 LOAD_GLOBAL 0 'chr'
1100 LOAD_CONST 114
1103 CALL_FUNCTION_1 1 None
1106 LOAD_GLOBAL 0 'chr'
1109 LOAD_CONST 32
1112 CALL_FUNCTION_1 1 None
1115 ROT_TWO
1116 BINARY_ADD
1117 ROT_TWO
1118 BINARY_ADD
1119 BINARY_ADD
1120 BINARY_ADD
1121 BINARY_ADD
1122 BINARY_ADD
1123 LOAD_GLOBAL 0 'chr'
1126 LOAD_CONST 121
1129 CALL_FUNCTION_1 1 None
1132 LOAD_GLOBAL 0 'chr'
1135 LOAD_CONST 80
1138 CALL_FUNCTION_1 1 None
1141 LOAD_GLOBAL 0 'chr'
1144 LOAD_CONST 32
1147 CALL_FUNCTION_1 1 None
1150 LOAD_GLOBAL 0 'chr'
1153 LOAD_CONST 110
1156 CALL_FUNCTION_1 1 None
1159 ROT_TWO
1160 BINARY_ADD
1161 ROT_TWO
1162 BINARY_ADD
1163 ROT_TWO
1164 BINARY_ADD
1165 LOAD_GLOBAL 0 'chr'
1168 LOAD_CONST 110
1171 CALL_FUNCTION_1 1 None
1174 LOAD_GLOBAL 0 'chr'
1177 LOAD_CONST 111
1180 CALL_FUNCTION_1 1 None
1183 LOAD_GLOBAL 0 'chr'
1186 LOAD_CONST 104
1189 CALL_FUNCTION_1 1 None
1192 LOAD_GLOBAL 0 'chr'
1195 LOAD_CONST 116
1198 CALL_FUNCTION_1 1 None
1201 ROT_TWO
1202 BINARY_ADD
1203 ROT_TWO
1204 BINARY_ADD
1205 ROT_TWO
1206 BINARY_ADD
1207 BINARY_ADD
1208 LOAD_GLOBAL 0 'chr'
1211 LOAD_CONST 116
1214 CALL_FUNCTION_1 1 None
1217 LOAD_GLOBAL 0 'chr'
1220 LOAD_CONST 121
1223 CALL_FUNCTION_1 1 None
1226 LOAD_GLOBAL 0 'chr'
1229 LOAD_CONST 98
1232 CALL_FUNCTION_1 1 None
1235 LOAD_GLOBAL 0 'chr'
1238 LOAD_CONST 32
1241 CALL_FUNCTION_1 1 None
1244 ROT_TWO
1245 BINARY_ADD
1246 ROT_TWO
1247 BINARY_ADD
1248 ROT_TWO
1249 BINARY_ADD
1250 LOAD_GLOBAL 0 'chr'
1253 LOAD_CONST 100
1256 CALL_FUNCTION_1 1 None
1259 LOAD_GLOBAL 0 'chr'
1262 LOAD_CONST 111
1265 CALL_FUNCTION_1 1 None
1268 LOAD_GLOBAL 0 'chr'
1271 LOAD_CONST 99
1274 CALL_FUNCTION_1 1 None
1277 LOAD_GLOBAL 0 'chr'
1280 LOAD_CONST 101
1283 CALL_FUNCTION_1 1 None
1286 ROT_TWO
1287 BINARY_ADD
1288 ROT_TWO
1289 BINARY_ADD
1290 ROT_TWO
1291 BINARY_ADD
1292 BINARY_ADD
1293 BINARY_ADD
1294 LOAD_GLOBAL 0 'chr'
1297 LOAD_CONST 110
1300 CALL_FUNCTION_1 1 None
1303 LOAD_GLOBAL 0 'chr'
1306 LOAD_CONST 105
1309 CALL_FUNCTION_1 1 None
1312 LOAD_GLOBAL 0 'chr'
1315 LOAD_CONST 32
1318 CALL_FUNCTION_1 1 None
1321 LOAD_GLOBAL 0 'chr'
1324 LOAD_CONST 101
1327 CALL_FUNCTION_1 1 None
1330 ROT_TWO
1331 BINARY_ADD
1332 ROT_TWO
1333 BINARY_ADD
1334 ROT_TWO
1335 BINARY_ADD
1336 LOAD_GLOBAL 0 'chr'
1339 LOAD_CONST 117
1342 CALL_FUNCTION_1 1 None
1345 LOAD_GLOBAL 0 'chr'
1348 LOAD_CONST 111
1351 CALL_FUNCTION_1 1 None
1354 LOAD_GLOBAL 0 'chr'
1357 LOAD_CONST 121
1360 CALL_FUNCTION_1 1 None
1363 LOAD_GLOBAL 0 'chr'
1366 LOAD_CONST 32
1369 CALL_FUNCTION_1 1 None
1372 ROT_TWO
1373 BINARY_ADD
1374 ROT_TWO
1375 BINARY_ADD
1376 ROT_TWO
1377 BINARY_ADD
1378 BINARY_ADD
1379 LOAD_GLOBAL 0 'chr'
1382 LOAD_CONST 114
1385 CALL_FUNCTION_1 1 None
1388 LOAD_GLOBAL 0 'chr'
1391 LOAD_CONST 98
1394 CALL_FUNCTION_1 1 None
1397 LOAD_GLOBAL 0 'chr'
1400 LOAD_CONST 32
1403 CALL_FUNCTION_1 1 None
1406 LOAD_GLOBAL 0 'chr'
1409 LOAD_CONST 114
1412 CALL_FUNCTION_1 1 None
1415 ROT_TWO
1416 BINARY_ADD
1417 ROT_TWO
1418 BINARY_ADD
1419 ROT_TWO
1420 BINARY_ADD
1421 LOAD_GLOBAL 0 'chr'
1424 LOAD_CONST 105
1427 CALL_FUNCTION_1 1 None
1430 LOAD_GLOBAL 0 'chr'
1433 LOAD_CONST 97
1436 CALL_FUNCTION_1 1 None
1439 ROT_TWO
1440 BINARY_ADD
1441 LOAD_GLOBAL 0 'chr'
1444 LOAD_CONST 125
1447 CALL_FUNCTION_1 1 None
1450 LOAD_GLOBAL 0 'chr'
1453 LOAD_CONST 33
1456 CALL_FUNCTION_1 1 None
1459 LOAD_GLOBAL 0 'chr'
1462 LOAD_CONST 110
1465 CALL_FUNCTION_1 1 None
1468 ROT_TWO
1469 BINARY_ADD
1470 ROT_TWO
1471 BINARY_ADD
1472 BINARY_ADD
1473 BINARY_ADD
1474 BINARY_ADD
1475 BINARY_ADD
1476 BINARY_ADD
1477 JUMP_ABSOLUTE 2212 'to 2212'
1480 LOAD_GLOBAL 0 'chr'
1483 LOAD_CONST 97
1486 CALL_FUNCTION_1 1 None
1489 LOAD_GLOBAL 0 'chr'
1492 LOAD_CONST 112
1495 CALL_FUNCTION_1 1 None
1498 ROT_TWO
1499 BINARY_ADD
1500 LOAD_GLOBAL 0 'chr'
1503 LOAD_CONST 119
1506 CALL_FUNCTION_1 1 None
1509 LOAD_GLOBAL 0 'chr'
1512 LOAD_CONST 115
1515 CALL_FUNCTION_1 1 None
1518 LOAD_GLOBAL 0 'chr'
1521 LOAD_CONST 115
1524 CALL_FUNCTION_1 1 None
1527 ROT_TWO
1528 BINARY_ADD
1529 ROT_TWO
1530 BINARY_ADD
1531 BINARY_ADD
1532 LOAD_GLOBAL 0 'chr'
1535 LOAD_CONST 114
1538 CALL_FUNCTION_1 1 None
1541 LOAD_GLOBAL 0 'chr'
1544 LOAD_CONST 111
1547 CALL_FUNCTION_1 1 None
1550 ROT_TWO
1551 BINARY_ADD
1552 LOAD_GLOBAL 0 'chr'
1555 LOAD_CONST 32
1558 CALL_FUNCTION_1 1 None
1561 LOAD_GLOBAL 0 'chr'
1564 LOAD_CONST 58
1567 CALL_FUNCTION_1 1 None
1570 LOAD_GLOBAL 0 'chr'
1573 LOAD_CONST 100
1576 CALL_FUNCTION_1 1 None
1579 ROT_TWO
1580 BINARY_ADD
1581 ROT_TWO
1582 BINARY_ADD
1583 BINARY_ADD
1584 BINARY_ADD
1585 CALL_FUNCTION_1 1 None
1588 JUMP_BACK 750 'to 750'
1591 LOAD_GLOBAL 0 'chr'
1594 LOAD_CONST 111
1597 CALL_FUNCTION_1 1 None
1600 LOAD_GLOBAL 0 'chr'
1603 LOAD_CONST 114
1606 CALL_FUNCTION_1 1 None
1609 LOAD_GLOBAL 0 'chr'
1612 LOAD_CONST 87
1615 CALL_FUNCTION_1 1 None
1618 ROT_TWO
1619 BINARY_ADD
1620 ROT_TWO
1621 BINARY_ADD
1622 LOAD_GLOBAL 0 'chr'
1625 LOAD_CONST 112
1628 CALL_FUNCTION_1 1 None
1631 LOAD_GLOBAL 0 'chr'
1634 LOAD_CONST 32
1637 CALL_FUNCTION_1 1 None
1640 LOAD_GLOBAL 0 'chr'
1643 LOAD_CONST 103
1646 CALL_FUNCTION_1 1 None
1649 LOAD_GLOBAL 0 'chr'
1652 LOAD_CONST 110
1655 CALL_FUNCTION_1 1 None
1658 ROT_TWO
1659 BINARY_ADD
1660 ROT_TWO
1661 BINARY_ADD
1662 ROT_TWO
1663 BINARY_ADD
1664 BINARY_ADD
1665 LOAD_GLOBAL 0 'chr'
1668 LOAD_CONST 115
1671 CALL_FUNCTION_1 1 None
1674 LOAD_GLOBAL 0 'chr'
1677 LOAD_CONST 115
1680 CALL_FUNCTION_1 1 None
1683 LOAD_GLOBAL 0 'chr'
1686 LOAD_CONST 97
1689 CALL_FUNCTION_1 1 None
1692 ROT_TWO
1693 BINARY_ADD
1694 ROT_TWO
1695 BINARY_ADD
1696 LOAD_GLOBAL 0 'chr'
1699 LOAD_CONST 100
1702 CALL_FUNCTION_1 1 None
1705 LOAD_GLOBAL 0 'chr'
1708 LOAD_CONST 114
1711 CALL_FUNCTION_1 1 None
1714 LOAD_GLOBAL 0 'chr'
1717 LOAD_CONST 111
1720 CALL_FUNCTION_1 1 None
1723 LOAD_GLOBAL 0 'chr'
1726 LOAD_CONST 119
1729 CALL_FUNCTION_1 1 None
1732 ROT_TWO
1733 BINARY_ADD
1734 ROT_TWO
1735 BINARY_ADD
1736 ROT_TWO
1737 BINARY_ADD
1738 BINARY_ADD
1739 BINARY_ADD
1740 LOAD_GLOBAL 0 'chr'
1743 LOAD_CONST 46
1746 CALL_FUNCTION_1 1 None
1749 LOAD_GLOBAL 0 'chr'
1752 LOAD_CONST 46
1755 CALL_FUNCTION_1 1 None
1758 LOAD_GLOBAL 0 'chr'
1761 LOAD_CONST 46
1764 CALL_FUNCTION_1 1 None
1767 ROT_TWO
1768 BINARY_ADD
1769 ROT_TWO
1770 BINARY_ADD
1771 LOAD_GLOBAL 0 'chr'
1774 LOAD_CONST 101
1777 CALL_FUNCTION_1 1 None
1780 LOAD_GLOBAL 0 'chr'
1783 LOAD_CONST 108
1786 CALL_FUNCTION_1 1 None
1789 LOAD_GLOBAL 0 'chr'
1792 LOAD_CONST 80
1795 CALL_FUNCTION_1 1 None
1798 LOAD_GLOBAL 0 'chr'
1801 LOAD_CONST 32
1804 CALL_FUNCTION_1 1 None
1807 ROT_TWO
1808 BINARY_ADD
1809 ROT_TWO
1810 BINARY_ADD
1811 ROT_TWO
1812 BINARY_ADD
1813 BINARY_ADD
1814 LOAD_GLOBAL 0 'chr'
1817 LOAD_CONST 32
1820 CALL_FUNCTION_1 1 None
1823 LOAD_GLOBAL 0 'chr'
1826 LOAD_CONST 101
1829 CALL_FUNCTION_1 1 None
1832 LOAD_GLOBAL 0 'chr'
1835 LOAD_CONST 115
1838 CALL_FUNCTION_1 1 None
1841 LOAD_GLOBAL 0 'chr'
1844 LOAD_CONST 97
1847 CALL_FUNCTION_1 1 None
1850 ROT_TWO
1851 BINARY_ADD
1852 ROT_TWO
1853 BINARY_ADD
1854 ROT_TWO
1855 BINARY_ADD
1856 LOAD_GLOBAL 0 'chr'
1859 LOAD_CONST 32
1862 CALL_FUNCTION_1 1 None
1865 LOAD_GLOBAL 0 'chr'
1868 LOAD_CONST 121
1871 CALL_FUNCTION_1 1 None
1874 LOAD_GLOBAL 0 'chr'
1877 LOAD_CONST 114
1880 CALL_FUNCTION_1 1 None
1883 LOAD_GLOBAL 0 'chr'
1886 LOAD_CONST 116
1889 CALL_FUNCTION_1 1 None
1892 ROT_TWO
1893 BINARY_ADD
1894 ROT_TWO
1895 BINARY_ADD
1896 ROT_TWO
1897 BINARY_ADD
1898 BINARY_ADD
1899 BINARY_ADD
1900 BINARY_ADD
1901 LOAD_GLOBAL 0 'chr'
1904 LOAD_CONST 97
1907 CALL_FUNCTION_1 1 None
1910 LOAD_GLOBAL 0 'chr'
1913 LOAD_CONST 103
1916 CALL_FUNCTION_1 1 None
1919 LOAD_GLOBAL 0 'chr'
1922 LOAD_CONST 97
1925 CALL_FUNCTION_1 1 None
1928 ROT_TWO
1929 BINARY_ADD
1930 ROT_TWO
1931 BINARY_ADD
1932 LOAD_GLOBAL 0 'chr'
1935 LOAD_CONST 32
1938 CALL_FUNCTION_1 1 None
1941 LOAD_GLOBAL 0 'chr'
1944 LOAD_CONST 46
1947 CALL_FUNCTION_1 1 None
1950 LOAD_GLOBAL 0 'chr'
1953 LOAD_CONST 110
1956 CALL_FUNCTION_1 1 None
1959 LOAD_GLOBAL 0 'chr'
1962 LOAD_CONST 105
1965 CALL_FUNCTION_1 1 None
1968 ROT_TWO
1969 BINARY_ADD
1970 ROT_TWO
1971 BINARY_ADD
1972 ROT_TWO
1973 BINARY_ADD
1974 BINARY_ADD
1975 LOAD_GLOBAL 0 'chr'
1978 LOAD_CONST 32
1981 CALL_FUNCTION_1 1 None
1984 LOAD_GLOBAL 0 'chr'
1987 LOAD_CONST 111
1990 CALL_FUNCTION_1 1 None
1993 LOAD_GLOBAL 0 'chr'
1996 LOAD_CONST 68
1999 CALL_FUNCTION_1 1 None
2002 ROT_TWO
2003 BINARY_ADD
2004 ROT_TWO
2005 BINARY_ADD
2006 LOAD_GLOBAL 0 'chr'
2009 LOAD_CONST 32
2012 CALL_FUNCTION_1 1 None
2015 LOAD_GLOBAL 0 'chr'
2018 LOAD_CONST 116
2021 CALL_FUNCTION_1 1 None
2024 LOAD_GLOBAL 0 'chr'
2027 LOAD_CONST 111
2030 CALL_FUNCTION_1 1 None
2033 LOAD_GLOBAL 0 'chr'
2036 LOAD_CONST 110
2039 CALL_FUNCTION_1 1 None
2042 ROT_TWO
2043 BINARY_ADD
2044 ROT_TWO
2045 BINARY_ADD
2046 ROT_TWO
2047 BINARY_ADD
2048 BINARY_ADD
2049 BINARY_ADD
2050 LOAD_GLOBAL 0 'chr'
2053 LOAD_CONST 117
2056 CALL_FUNCTION_1 1 None
2059 LOAD_GLOBAL 0 'chr'
2062 LOAD_CONST 114
2065 CALL_FUNCTION_1 1 None
2068 LOAD_GLOBAL 0 'chr'
2071 LOAD_CONST 98
2074 CALL_FUNCTION_1 1 None
2077 ROT_TWO
2078 BINARY_ADD
2079 ROT_TWO
2080 BINARY_ADD
2081 LOAD_GLOBAL 0 'chr'
2084 LOAD_CONST 102
2087 CALL_FUNCTION_1 1 None
2090 LOAD_GLOBAL 0 'chr'
2093 LOAD_CONST 32
2096 CALL_FUNCTION_1 1 None
2099 LOAD_GLOBAL 0 'chr'
2102 LOAD_CONST 101
2105 CALL_FUNCTION_1 1 None
2108 LOAD_GLOBAL 0 'chr'
2111 LOAD_CONST 116
2114 CALL_FUNCTION_1 1 None
2117 ROT_TWO
2118 BINARY_ADD
2119 ROT_TWO
2120 BINARY_ADD
2121 ROT_TWO
2122 BINARY_ADD
2123 BINARY_ADD
2124 LOAD_GLOBAL 0 'chr'
2127 LOAD_CONST 101
2130 CALL_FUNCTION_1 1 None
2133 LOAD_GLOBAL 0 'chr'
2136 LOAD_CONST 99
2139 CALL_FUNCTION_1 1 None
2142 LOAD_GLOBAL 0 'chr'
2145 LOAD_CONST 114
2148 CALL_FUNCTION_1 1 None
2151 LOAD_GLOBAL 0 'chr'
2154 LOAD_CONST 111
2157 CALL_FUNCTION_1 1 None
2160 ROT_TWO
2161 BINARY_ADD
2162 ROT_TWO
2163 BINARY_ADD
2164 ROT_TWO
2165 BINARY_ADD
2166 LOAD_GLOBAL 0 'chr'
2169 LOAD_CONST 41
2172 CALL_FUNCTION_1 1 None
2175 LOAD_GLOBAL 0 'chr'
2178 LOAD_CONST 61
2181 CALL_FUNCTION_1 1 None
2184 LOAD_GLOBAL 0 'chr'
2187 LOAD_CONST 32
2190 CALL_FUNCTION_1 1 None
2193 LOAD_GLOBAL 0 'chr'
2196 LOAD_CONST 46
2199 CALL_FUNCTION_1 1 None
2202 ROT_TWO
2203 BINARY_ADD
2204 ROT_TWO
2205 BINARY_ADD
2206 ROT_TWO
2207 BINARY_ADD
2208 BINARY_ADD
2209 BINARY_ADD
2210 BINARY_ADD
2211 BINARY_ADD
2212 PRINT_ITEM
2213 PRINT_NEWLINE_CONT

Parse error at or near `None' instruction at offset -1


if __name__ == '__main__':
main()

​ 里面这么多chr函数,还有数字。写个脚本瞅瞅:

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
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
# @Time : 2022/12/02 15:04:51
# @Author: wd-2711
'''

if __name__ == "__main__":
result = ""
with open("output.txt", "r") as f:
ind = 0
while True:
line = f.readline()
if "LOAD_CONST" in line:
dd = line[44:].replace(" ", "").replace("\n", "")
if dd != "None":
# print(chr(int(dd, 10)), end = "")
result += chr(int(dd, 10))
ind += 1
if ind == 985:
break
result = result.split(" ")
for i in result:
print(i[::-1], end = " ")
#Call me Py tha virton inmachual cae! inI Preterpn ythot yon{Nhitc!!!esecodbytn cow cou aompian rundle Py bytthonn inecod youe br orsswpan!}air pWrod: Ple...wordassng ase agatry in. Do fbrunot =)orcete .

​ 输出有flag的样子了,但是看着很奇怪,还是老老实实反编译吧。

​ 唉,看看wp吧,没做过这种题鸭。(我就是fw

0x01

​ 看了一下其他师傅的wp,感觉自己还是能做出来的啊,都是没真正反编译成功,都是看字节码(自己没有耐心看了,这是我的问题。

​ 一开始吐血的是python2可以直接运行,我说python3咋运行不出来,但是又想自己在文件头前面加的是python2.7的头,瞬间觉得自己真傻逼。

image-20221202153714678

​ OK,事已至此,不具体看wp了,自己分析并写脚本好吧。

补充知识:python虚拟机

​ 1. ROT_TWO,python opcode,主要是交换两个变量的值:

1
2
3
4
5
6
7
TARGET(ROT_TWO) {           
PyObject *top = TOP();
PyObject *second = SECOND();
SET_TOP(second);
SET_SECOND(top);
FAST_DISPATCH();
}

​ 2. python字节码执行函数,例如有这样一个函数:my_function(my_var, 2)。它的执行过程是这样的:

1
2
3
4
5
6
//Python 将转换为一系列字节码指令:
1.一个LOAD_NAME指令,用于查找函数对象 my_function,并将其推送到计算栈的顶部
2.另一个 LOAD_NAME 指令去查找变量 my_var,并将其推送到计算栈的顶部
3.一个 LOAD_CONST 指令将一个整数 2 推送到计算栈的顶部
4.一个 CALL_FUNCTION 指令
//CALL_FUNCTION 指令有2个参数,它表示 Python 需要在堆栈顶部弹出两个位置参数; 然后函数将在它上面进行调用,并且它也同时被弹出。一旦 Python 具备了这些,它将在调用堆栈上分配一个新的帧,填充到函数调用的本地变量,然后运行该帧内的 my_function 的字节码。一旦运行完成,帧将从调用堆栈中弹出,在原始帧中,my_function 的返回值将被推入到计算栈的顶部。

​ 3. BINARY_ADD。来看看Python的a = b + c语句, 其汇编码为:

1
2
3
4
LOAD_NAME  0 (b)
LOAD_NAME 1 (c)
BINARY_ADD
STORE_NAME 2 (a)

​ 相当于把b,c以此压栈,最后add,把结果压栈,最后将栈顶元素给a。

​ 4.JUMP python opcode。

  • JUMP_FORWARD: 字节码中的相对跳转。获取要跳过的字节数。
  • JUMP_IF_FALSE_OR_POP, JUMP_IF_TRUE_OR_POP, JUMP_ABSOLUTE, POP_JUMP_IF_FALSE, 和 POP_JUMP_IF_TRUE 都在字节码中采用绝对跳转。

​ 5.FAST_DISPATCH的定义Python/ceval.c#L980-L1013。简要总结就是,当找到预测时,直接进行跳转,否则,回到switch开始部分。“每一个opcode都应该以goto error(当操作失败时)或者fast_dispatch/dispatch结尾”,同样值得注意的时,DISPATCH会执行一次对eval_breaker的原子检查,如果通过了,就会跳过冗长的main loop前置的操作。

​ 6.LOAD_FAST(var_num)将指向局部对象co_varnames[var_num]的引用推入栈顶。STORE_FAST (var_num)将TOS(堆栈顶部项)存放到局部对象 co_varnames[var_num]。

​ 7.LOAD_GLOBAL(namei)。加载名称为 co_names[namei] 的全局对象推入栈顶。

补充完毕!

​ 仔细分析了一波,关键在这里:

image-20221202160944738

​ 运行流程是这样:

1
2
3
4
1. 运行ROT_TWO之后取出栈顶元素给password。
2. 导入raw_input,如果导入失败就跳到1480。
3. 把password推到栈顶。
4. == 比较。

​ 写脚本:

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
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
# @Time : 2022/12/02 16:24:57
# @Author: wd-2711
'''

next_flag = -1
stack = []

def analyze(line):
global next_flag
global stack
if "LOAD_GLOBAL" in line and "chr" in line:
next_flag = 1
if "LOAD_CONST" in line and next_flag == 1:
tmp = chr(int(list(filter(None,line.split(" ")))[2], 10))
stack.append(tmp)
next_flag = -1
if "ROT_TWO" in line:
tmp = stack[-1]
stack[-1] = stack[-2]
stack[-2] = tmp
if "BINARY_ADD" in line:
TopStack = stack[-1]
TopStack1 = stack[-2]
stack = stack[:-2]
TopStack += TopStack1
stack.append(TopStack)



if __name__ == "__main__":
with open("output.txt", "r") as f:
idNum = 325
for i in range(idNum):
line = f.readline()
analyze(line)
print(stack[0][::-1])
# Call me a Python virtual machine! I can interpret Python bytecodes!!!

​ 直接输入:

image-20221202170257947

​ 得到flag:hitcon{Now you can compile and run Python bytecode in your brain!}

​ 当然,也可以在跳转之后运行咯,进行判断的时候其实栈中就一个元素,就是Call me a Python virtual machine! I can interpret Python bytecodes!!!

​ 分别对两个跳转进行分析:若在下图跳转:

image-20221202170839107

​ 则修改脚本为:

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
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
# @Time : 2022/12/02 16:24:57
# @Author: wd-2711
'''

next_flag = -1
stack = ["1"]

def analyze(line):
global next_flag
global stack
if "LOAD_GLOBAL" in line and "chr" in line:
next_flag = 1
if "LOAD_CONST" in line and next_flag == 1:
tmp = chr(int(list(filter(None,line.split(" ")))[2], 10))
stack.append(tmp)
next_flag = -1
if "ROT_TWO" in line:
tmp = stack[-1]
stack[-1] = stack[-2]
stack[-2] = tmp
if "BINARY_ADD" in line:
TopStack = stack[-1]
TopStack1 = stack[-2]
stack = stack[:-2]
TopStack += TopStack1
stack.append(TopStack)



if __name__ == "__main__":
with open("output.txt", "r") as f:
end = 968
begin = 696
for i in range(idNum):
line = f.readline()
if i < 696:
continue
print(line)
analyze(line)
print(stack[0][::-1])
# Wr1ng password... Please try again. Do not brute force. =)

​ 说明跳转过后是错误的分支。

​ 若不跳转,则将上述脚本改为end=648, begin=336,得到:hitcon{Now you can compile and run Python bytecode in your brain!}

​ 真鸡儿爽嘿嘿。

知识点1:py格式化文档

https://blog.csdn.net/qianbin3200896/article/details/90180980

知识点2:常用的pyc转py方法

 1. https://tool.lu/pyc/
 2. ``uncompyle6 -o xx.py xx.pyc``

知识点3:python -m xx.py意思是将xx.py当作模块处理。

知识点4:python 列表反转是xx.reverse();字符串反转是xx[::-1];list(filter(None, xx))自动去掉xx中为假的值。

0x02 附录:

output.txt如下:

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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
 L.   1         0  LOAD_GLOBAL           0  'chr'
3 LOAD_CONST 108
6 CALL_FUNCTION_1 1 None
9 LOAD_GLOBAL 0 'chr'
12 LOAD_CONST 108
15 CALL_FUNCTION_1 1 None
18 LOAD_GLOBAL 0 'chr'
21 LOAD_CONST 97
24 CALL_FUNCTION_1 1 None
27 LOAD_GLOBAL 0 'chr'
30 LOAD_CONST 67
33 CALL_FUNCTION_1 1 None
36 ROT_TWO
37 BINARY_ADD
38 ROT_TWO
39 BINARY_ADD
40 ROT_TWO
41 BINARY_ADD
42 LOAD_GLOBAL 0 'chr'
45 LOAD_CONST 32
48 CALL_FUNCTION_1 1 None
51 LOAD_GLOBAL 0 'chr'
54 LOAD_CONST 101
57 CALL_FUNCTION_1 1 None
60 LOAD_GLOBAL 0 'chr'
63 LOAD_CONST 109
66 CALL_FUNCTION_1 1 None
69 LOAD_GLOBAL 0 'chr'
72 LOAD_CONST 32
75 CALL_FUNCTION_1 1 None
78 ROT_TWO
79 BINARY_ADD
80 ROT_TWO
81 BINARY_ADD
82 ROT_TWO
83 BINARY_ADD
84 BINARY_ADD
85 LOAD_GLOBAL 0 'chr'
88 LOAD_CONST 121
91 CALL_FUNCTION_1 1 None
94 LOAD_GLOBAL 0 'chr'
97 LOAD_CONST 80
100 CALL_FUNCTION_1 1 None
103 LOAD_GLOBAL 0 'chr'
106 LOAD_CONST 32
109 CALL_FUNCTION_1 1 None
112 LOAD_GLOBAL 0 'chr'
115 LOAD_CONST 97
118 CALL_FUNCTION_1 1 None
121 ROT_TWO
122 BINARY_ADD
123 ROT_TWO
124 BINARY_ADD
125 ROT_TWO
126 BINARY_ADD
127 LOAD_GLOBAL 0 'chr'
130 LOAD_CONST 104
133 CALL_FUNCTION_1 1 None
136 LOAD_GLOBAL 0 'chr'
139 LOAD_CONST 116
142 CALL_FUNCTION_1 1 None
145 ROT_TWO
146 BINARY_ADD
147 LOAD_GLOBAL 0 'chr'
150 LOAD_CONST 32
153 CALL_FUNCTION_1 1 None
156 LOAD_GLOBAL 0 'chr'
159 LOAD_CONST 110
162 CALL_FUNCTION_1 1 None
165 LOAD_GLOBAL 0 'chr'
168 LOAD_CONST 111
171 CALL_FUNCTION_1 1 None
174 ROT_TWO
175 BINARY_ADD
176 ROT_TWO
177 BINARY_ADD
178 BINARY_ADD
179 BINARY_ADD
180 BINARY_ADD
181 LOAD_GLOBAL 0 'chr'
184 LOAD_CONST 116
187 CALL_FUNCTION_1 1 None
190 LOAD_GLOBAL 0 'chr'
193 LOAD_CONST 114
196 CALL_FUNCTION_1 1 None
199 LOAD_GLOBAL 0 'chr'
202 LOAD_CONST 105
205 CALL_FUNCTION_1 1 None
208 LOAD_GLOBAL 0 'chr'
211 LOAD_CONST 118
214 CALL_FUNCTION_1 1 None
217 ROT_TWO
218 BINARY_ADD
219 ROT_TWO
220 BINARY_ADD
221 ROT_TWO
222 BINARY_ADD
223 LOAD_GLOBAL 0 'chr'
226 LOAD_CONST 32
229 CALL_FUNCTION_1 1 None
232 LOAD_GLOBAL 0 'chr'
235 LOAD_CONST 108
238 CALL_FUNCTION_1 1 None
241 LOAD_GLOBAL 0 'chr'
244 LOAD_CONST 97
247 CALL_FUNCTION_1 1 None
250 LOAD_GLOBAL 0 'chr'
253 LOAD_CONST 117
256 CALL_FUNCTION_1 1 None
259 ROT_TWO
260 BINARY_ADD
261 ROT_TWO
262 BINARY_ADD
263 ROT_TWO
264 BINARY_ADD
265 BINARY_ADD
266 LOAD_GLOBAL 0 'chr'
269 LOAD_CONST 104
272 CALL_FUNCTION_1 1 None
275 LOAD_GLOBAL 0 'chr'
278 LOAD_CONST 99
281 CALL_FUNCTION_1 1 None
284 LOAD_GLOBAL 0 'chr'
287 LOAD_CONST 97
290 CALL_FUNCTION_1 1 None
293 LOAD_GLOBAL 0 'chr'
296 LOAD_CONST 109
299 CALL_FUNCTION_1 1 None
302 ROT_TWO
303 BINARY_ADD
304 ROT_TWO
305 BINARY_ADD
306 ROT_TWO
307 BINARY_ADD
308 LOAD_GLOBAL 0 'chr'
311 LOAD_CONST 110
314 CALL_FUNCTION_1 1 None
317 LOAD_GLOBAL 0 'chr'
320 LOAD_CONST 105
323 CALL_FUNCTION_1 1 None
326 ROT_TWO
327 BINARY_ADD
328 LOAD_GLOBAL 0 'chr'
331 LOAD_CONST 32
334 CALL_FUNCTION_1 1 None
337 LOAD_GLOBAL 0 'chr'
340 LOAD_CONST 33
343 CALL_FUNCTION_1 1 None
346 LOAD_GLOBAL 0 'chr'
349 LOAD_CONST 101
352 CALL_FUNCTION_1 1 None
355 ROT_TWO
356 BINARY_ADD
357 ROT_TWO
358 BINARY_ADD
359 BINARY_ADD
360 BINARY_ADD
361 BINARY_ADD
362 BINARY_ADD
363 LOAD_GLOBAL 0 'chr'
366 LOAD_CONST 97
369 CALL_FUNCTION_1 1 None
372 LOAD_GLOBAL 0 'chr'
375 LOAD_CONST 99
378 CALL_FUNCTION_1 1 None
381 LOAD_GLOBAL 0 'chr'
384 LOAD_CONST 32
387 CALL_FUNCTION_1 1 None
390 LOAD_GLOBAL 0 'chr'
393 LOAD_CONST 73
396 CALL_FUNCTION_1 1 None
399 ROT_TWO
400 BINARY_ADD
401 ROT_TWO
402 BINARY_ADD
403 ROT_TWO
404 BINARY_ADD
405 LOAD_GLOBAL 0 'chr'
408 LOAD_CONST 110
411 CALL_FUNCTION_1 1 None
414 LOAD_GLOBAL 0 'chr'
417 LOAD_CONST 105
420 CALL_FUNCTION_1 1 None
423 LOAD_GLOBAL 0 'chr'
426 LOAD_CONST 32
429 CALL_FUNCTION_1 1 None
432 LOAD_GLOBAL 0 'chr'
435 LOAD_CONST 110
438 CALL_FUNCTION_1 1 None
441 ROT_TWO
442 BINARY_ADD
443 ROT_TWO
444 BINARY_ADD
445 ROT_TWO
446 BINARY_ADD
447 BINARY_ADD
448 LOAD_GLOBAL 0 'chr'
451 LOAD_CONST 112
454 CALL_FUNCTION_1 1 None
457 LOAD_GLOBAL 0 'chr'
460 LOAD_CONST 114
463 CALL_FUNCTION_1 1 None
466 LOAD_GLOBAL 0 'chr'
469 LOAD_CONST 101
472 CALL_FUNCTION_1 1 None
475 LOAD_GLOBAL 0 'chr'
478 LOAD_CONST 116
481 CALL_FUNCTION_1 1 None
484 ROT_TWO
485 BINARY_ADD
486 ROT_TWO
487 BINARY_ADD
488 ROT_TWO
489 BINARY_ADD
490 LOAD_GLOBAL 0 'chr'
493 LOAD_CONST 101
496 CALL_FUNCTION_1 1 None
499 LOAD_GLOBAL 0 'chr'
502 LOAD_CONST 114
505 CALL_FUNCTION_1 1 None
508 ROT_TWO
509 BINARY_ADD
510 LOAD_GLOBAL 0 'chr'
513 LOAD_CONST 80
516 CALL_FUNCTION_1 1 None
519 LOAD_GLOBAL 0 'chr'
522 LOAD_CONST 32
525 CALL_FUNCTION_1 1 None
528 LOAD_GLOBAL 0 'chr'
531 LOAD_CONST 116
534 CALL_FUNCTION_1 1 None
537 ROT_TWO
538 BINARY_ADD
539 ROT_TWO
540 BINARY_ADD
541 BINARY_ADD
542 BINARY_ADD
543 BINARY_ADD
544 LOAD_GLOBAL 0 'chr'
547 LOAD_CONST 111
550 CALL_FUNCTION_1 1 None
553 LOAD_GLOBAL 0 'chr'
556 LOAD_CONST 104
559 CALL_FUNCTION_1 1 None
562 LOAD_GLOBAL 0 'chr'
565 LOAD_CONST 116
568 CALL_FUNCTION_1 1 None
571 LOAD_GLOBAL 0 'chr'
574 LOAD_CONST 121
577 CALL_FUNCTION_1 1 None
580 ROT_TWO
581 BINARY_ADD
582 ROT_TWO
583 BINARY_ADD
584 ROT_TWO
585 BINARY_ADD
586 LOAD_GLOBAL 0 'chr'
589 LOAD_CONST 32
592 CALL_FUNCTION_1 1 None
595 LOAD_GLOBAL 0 'chr'
598 LOAD_CONST 110
601 CALL_FUNCTION_1 1 None
604 ROT_TWO
605 BINARY_ADD
606 LOAD_GLOBAL 0 'chr'
609 LOAD_CONST 116
612 CALL_FUNCTION_1 1 None
615 LOAD_GLOBAL 0 'chr'
618 LOAD_CONST 121
621 CALL_FUNCTION_1 1 None
624 LOAD_GLOBAL 0 'chr'
627 LOAD_CONST 98
630 CALL_FUNCTION_1 1 None
633 ROT_TWO
634 BINARY_ADD
635 ROT_TWO
636 BINARY_ADD
637 BINARY_ADD
638 BINARY_ADD
639 LOAD_GLOBAL 0 'chr'
642 LOAD_CONST 100
645 CALL_FUNCTION_1 1 None
648 LOAD_GLOBAL 0 'chr'
651 LOAD_CONST 111
654 CALL_FUNCTION_1 1 None
657 LOAD_GLOBAL 0 'chr'
660 LOAD_CONST 99
663 CALL_FUNCTION_1 1 None
666 LOAD_GLOBAL 0 'chr'
669 LOAD_CONST 101
672 CALL_FUNCTION_1 1 None
675 ROT_TWO
676 BINARY_ADD
677 ROT_TWO
678 BINARY_ADD
679 ROT_TWO
680 BINARY_ADD
681 LOAD_GLOBAL 0 'chr'
684 LOAD_CONST 115
687 CALL_FUNCTION_1 1 None
690 LOAD_GLOBAL 0 'chr'
693 LOAD_CONST 101
696 CALL_FUNCTION_1 1 None
699 ROT_TWO
700 BINARY_ADD
701 LOAD_GLOBAL 0 'chr'
704 LOAD_CONST 33
707 CALL_FUNCTION_1 1 None
710 LOAD_GLOBAL 0 'chr'
713 LOAD_CONST 33
716 CALL_FUNCTION_1 1 None
719 LOAD_GLOBAL 0 'chr'
722 LOAD_CONST 33
725 CALL_FUNCTION_1 1 None
728 ROT_TWO
729 BINARY_ADD
730 ROT_TWO
731 BINARY_ADD
732 BINARY_ADD
733 BINARY_ADD
734 BINARY_ADD
735 BINARY_ADD
736 BINARY_ADD
737 LOAD_CONST None
740 NOP
741 JUMP_ABSOLUTE 759 'to 759'
744 LOAD_GLOBAL 1 'raw_input'
747 JUMP_ABSOLUTE 1480 'to 1480'
750 LOAD_FAST 0 'password'
753 COMPARE_OP 2 ==
756 JUMP_ABSOLUTE 767 'to 767'
759 ROT_TWO
760 STORE_FAST 0 'password'
763 POP_TOP
764 JUMP_BACK 744 'to 744'
767 POP_JUMP_IF_FALSE 1591 'to 1591'
770 LOAD_GLOBAL 0 'chr'
773 LOAD_CONST 99
776 CALL_FUNCTION_1 1 None
779 LOAD_GLOBAL 0 'chr'
782 LOAD_CONST 116
785 CALL_FUNCTION_1 1 None
788 LOAD_GLOBAL 0 'chr'
791 LOAD_CONST 105
794 CALL_FUNCTION_1 1 None
797 LOAD_GLOBAL 0 'chr'
800 LOAD_CONST 104
803 CALL_FUNCTION_1 1 None
806 ROT_TWO
807 BINARY_ADD
808 ROT_TWO
809 BINARY_ADD
810 ROT_TWO
811 BINARY_ADD
812 LOAD_GLOBAL 0 'chr'
815 LOAD_CONST 78
818 CALL_FUNCTION_1 1 None
821 LOAD_GLOBAL 0 'chr'
824 LOAD_CONST 123
827 CALL_FUNCTION_1 1 None
830 LOAD_GLOBAL 0 'chr'
833 LOAD_CONST 110
836 CALL_FUNCTION_1 1 None
839 LOAD_GLOBAL 0 'chr'
842 LOAD_CONST 111
845 CALL_FUNCTION_1 1 None
848 ROT_TWO
849 BINARY_ADD
850 ROT_TWO
851 BINARY_ADD
852 ROT_TWO
853 BINARY_ADD
854 BINARY_ADD
855 LOAD_GLOBAL 0 'chr'
858 LOAD_CONST 121
861 CALL_FUNCTION_1 1 None
864 LOAD_GLOBAL 0 'chr'
867 LOAD_CONST 32
870 CALL_FUNCTION_1 1 None
873 LOAD_GLOBAL 0 'chr'
876 LOAD_CONST 119
879 CALL_FUNCTION_1 1 None
882 LOAD_GLOBAL 0 'chr'
885 LOAD_CONST 111
888 CALL_FUNCTION_1 1 None
891 ROT_TWO
892 BINARY_ADD
893 ROT_TWO
894 BINARY_ADD
895 ROT_TWO
896 BINARY_ADD
897 LOAD_GLOBAL 0 'chr'
900 LOAD_CONST 99
903 CALL_FUNCTION_1 1 None
906 LOAD_GLOBAL 0 'chr'
909 LOAD_CONST 32
912 CALL_FUNCTION_1 1 None
915 LOAD_GLOBAL 0 'chr'
918 LOAD_CONST 117
921 CALL_FUNCTION_1 1 None
924 LOAD_GLOBAL 0 'chr'
927 LOAD_CONST 111
930 CALL_FUNCTION_1 1 None
933 ROT_TWO
934 BINARY_ADD
935 ROT_TWO
936 BINARY_ADD
937 ROT_TWO
938 BINARY_ADD
939 BINARY_ADD
940 BINARY_ADD
941 LOAD_GLOBAL 0 'chr'
944 LOAD_CONST 99
947 CALL_FUNCTION_1 1 None
950 LOAD_GLOBAL 0 'chr'
953 LOAD_CONST 32
956 CALL_FUNCTION_1 1 None
959 LOAD_GLOBAL 0 'chr'
962 LOAD_CONST 110
965 CALL_FUNCTION_1 1 None
968 LOAD_GLOBAL 0 'chr'
971 LOAD_CONST 97
974 CALL_FUNCTION_1 1 None
977 ROT_TWO
978 BINARY_ADD
979 ROT_TWO
980 BINARY_ADD
981 ROT_TWO
982 BINARY_ADD
983 LOAD_GLOBAL 0 'chr'
986 LOAD_CONST 105
989 CALL_FUNCTION_1 1 None
992 LOAD_GLOBAL 0 'chr'
995 LOAD_CONST 112
998 CALL_FUNCTION_1 1 None
1001 LOAD_GLOBAL 0 'chr'
1004 LOAD_CONST 109
1007 CALL_FUNCTION_1 1 None
1010 LOAD_GLOBAL 0 'chr'
1013 LOAD_CONST 111
1016 CALL_FUNCTION_1 1 None
1019 ROT_TWO
1020 BINARY_ADD
1021 ROT_TWO
1022 BINARY_ADD
1023 ROT_TWO
1024 BINARY_ADD
1025 BINARY_ADD
1026 LOAD_GLOBAL 0 'chr'
1029 LOAD_CONST 97
1032 CALL_FUNCTION_1 1 None
1035 LOAD_GLOBAL 0 'chr'
1038 LOAD_CONST 32
1041 CALL_FUNCTION_1 1 None
1044 LOAD_GLOBAL 0 'chr'
1047 LOAD_CONST 101
1050 CALL_FUNCTION_1 1 None
1053 LOAD_GLOBAL 0 'chr'
1056 LOAD_CONST 108
1059 CALL_FUNCTION_1 1 None
1062 ROT_TWO
1063 BINARY_ADD
1064 ROT_TWO
1065 BINARY_ADD
1066 ROT_TWO
1067 BINARY_ADD
1068 LOAD_GLOBAL 0 'chr'
1071 LOAD_CONST 100
1074 CALL_FUNCTION_1 1 None
1077 LOAD_GLOBAL 0 'chr'
1080 LOAD_CONST 110
1083 CALL_FUNCTION_1 1 None
1086 ROT_TWO
1087 BINARY_ADD
1088 LOAD_GLOBAL 0 'chr'
1091 LOAD_CONST 117
1094 CALL_FUNCTION_1 1 None
1097 LOAD_GLOBAL 0 'chr'
1100 LOAD_CONST 114
1103 CALL_FUNCTION_1 1 None
1106 LOAD_GLOBAL 0 'chr'
1109 LOAD_CONST 32
1112 CALL_FUNCTION_1 1 None
1115 ROT_TWO
1116 BINARY_ADD
1117 ROT_TWO
1118 BINARY_ADD
1119 BINARY_ADD
1120 BINARY_ADD
1121 BINARY_ADD
1122 BINARY_ADD
1123 LOAD_GLOBAL 0 'chr'
1126 LOAD_CONST 121
1129 CALL_FUNCTION_1 1 None
1132 LOAD_GLOBAL 0 'chr'
1135 LOAD_CONST 80
1138 CALL_FUNCTION_1 1 None
1141 LOAD_GLOBAL 0 'chr'
1144 LOAD_CONST 32
1147 CALL_FUNCTION_1 1 None
1150 LOAD_GLOBAL 0 'chr'
1153 LOAD_CONST 110
1156 CALL_FUNCTION_1 1 None
1159 ROT_TWO
1160 BINARY_ADD
1161 ROT_TWO
1162 BINARY_ADD
1163 ROT_TWO
1164 BINARY_ADD
1165 LOAD_GLOBAL 0 'chr'
1168 LOAD_CONST 110
1171 CALL_FUNCTION_1 1 None
1174 LOAD_GLOBAL 0 'chr'
1177 LOAD_CONST 111
1180 CALL_FUNCTION_1 1 None
1183 LOAD_GLOBAL 0 'chr'
1186 LOAD_CONST 104
1189 CALL_FUNCTION_1 1 None
1192 LOAD_GLOBAL 0 'chr'
1195 LOAD_CONST 116
1198 CALL_FUNCTION_1 1 None
1201 ROT_TWO
1202 BINARY_ADD
1203 ROT_TWO
1204 BINARY_ADD
1205 ROT_TWO
1206 BINARY_ADD
1207 BINARY_ADD
1208 LOAD_GLOBAL 0 'chr'
1211 LOAD_CONST 116
1214 CALL_FUNCTION_1 1 None
1217 LOAD_GLOBAL 0 'chr'
1220 LOAD_CONST 121
1223 CALL_FUNCTION_1 1 None
1226 LOAD_GLOBAL 0 'chr'
1229 LOAD_CONST 98
1232 CALL_FUNCTION_1 1 None
1235 LOAD_GLOBAL 0 'chr'
1238 LOAD_CONST 32
1241 CALL_FUNCTION_1 1 None
1244 ROT_TWO
1245 BINARY_ADD
1246 ROT_TWO
1247 BINARY_ADD
1248 ROT_TWO
1249 BINARY_ADD
1250 LOAD_GLOBAL 0 'chr'
1253 LOAD_CONST 100
1256 CALL_FUNCTION_1 1 None
1259 LOAD_GLOBAL 0 'chr'
1262 LOAD_CONST 111
1265 CALL_FUNCTION_1 1 None
1268 LOAD_GLOBAL 0 'chr'
1271 LOAD_CONST 99
1274 CALL_FUNCTION_1 1 None
1277 LOAD_GLOBAL 0 'chr'
1280 LOAD_CONST 101
1283 CALL_FUNCTION_1 1 None
1286 ROT_TWO
1287 BINARY_ADD
1288 ROT_TWO
1289 BINARY_ADD
1290 ROT_TWO
1291 BINARY_ADD
1292 BINARY_ADD
1293 BINARY_ADD
1294 LOAD_GLOBAL 0 'chr'
1297 LOAD_CONST 110
1300 CALL_FUNCTION_1 1 None
1303 LOAD_GLOBAL 0 'chr'
1306 LOAD_CONST 105
1309 CALL_FUNCTION_1 1 None
1312 LOAD_GLOBAL 0 'chr'
1315 LOAD_CONST 32
1318 CALL_FUNCTION_1 1 None
1321 LOAD_GLOBAL 0 'chr'
1324 LOAD_CONST 101
1327 CALL_FUNCTION_1 1 None
1330 ROT_TWO
1331 BINARY_ADD
1332 ROT_TWO
1333 BINARY_ADD
1334 ROT_TWO
1335 BINARY_ADD
1336 LOAD_GLOBAL 0 'chr'
1339 LOAD_CONST 117
1342 CALL_FUNCTION_1 1 None
1345 LOAD_GLOBAL 0 'chr'
1348 LOAD_CONST 111
1351 CALL_FUNCTION_1 1 None
1354 LOAD_GLOBAL 0 'chr'
1357 LOAD_CONST 121
1360 CALL_FUNCTION_1 1 None
1363 LOAD_GLOBAL 0 'chr'
1366 LOAD_CONST 32
1369 CALL_FUNCTION_1 1 None
1372 ROT_TWO
1373 BINARY_ADD
1374 ROT_TWO
1375 BINARY_ADD
1376 ROT_TWO
1377 BINARY_ADD
1378 BINARY_ADD
1379 LOAD_GLOBAL 0 'chr'
1382 LOAD_CONST 114
1385 CALL_FUNCTION_1 1 None
1388 LOAD_GLOBAL 0 'chr'
1391 LOAD_CONST 98
1394 CALL_FUNCTION_1 1 None
1397 LOAD_GLOBAL 0 'chr'
1400 LOAD_CONST 32
1403 CALL_FUNCTION_1 1 None
1406 LOAD_GLOBAL 0 'chr'
1409 LOAD_CONST 114
1412 CALL_FUNCTION_1 1 None
1415 ROT_TWO
1416 BINARY_ADD
1417 ROT_TWO
1418 BINARY_ADD
1419 ROT_TWO
1420 BINARY_ADD
1421 LOAD_GLOBAL 0 'chr'
1424 LOAD_CONST 105
1427 CALL_FUNCTION_1 1 None
1430 LOAD_GLOBAL 0 'chr'
1433 LOAD_CONST 97
1436 CALL_FUNCTION_1 1 None
1439 ROT_TWO
1440 BINARY_ADD
1441 LOAD_GLOBAL 0 'chr'
1444 LOAD_CONST 125
1447 CALL_FUNCTION_1 1 None
1450 LOAD_GLOBAL 0 'chr'
1453 LOAD_CONST 33
1456 CALL_FUNCTION_1 1 None
1459 LOAD_GLOBAL 0 'chr'
1462 LOAD_CONST 110
1465 CALL_FUNCTION_1 1 None
1468 ROT_TWO
1469 BINARY_ADD
1470 ROT_TWO
1471 BINARY_ADD
1472 BINARY_ADD
1473 BINARY_ADD
1474 BINARY_ADD
1475 BINARY_ADD
1476 BINARY_ADD
1477 JUMP_ABSOLUTE 2212 'to 2212'
1480 LOAD_GLOBAL 0 'chr'
1483 LOAD_CONST 97
1486 CALL_FUNCTION_1 1 None
1489 LOAD_GLOBAL 0 'chr'
1492 LOAD_CONST 112
1495 CALL_FUNCTION_1 1 None
1498 ROT_TWO
1499 BINARY_ADD
1500 LOAD_GLOBAL 0 'chr'
1503 LOAD_CONST 119
1506 CALL_FUNCTION_1 1 None
1509 LOAD_GLOBAL 0 'chr'
1512 LOAD_CONST 115
1515 CALL_FUNCTION_1 1 None
1518 LOAD_GLOBAL 0 'chr'
1521 LOAD_CONST 115
1524 CALL_FUNCTION_1 1 None
1527 ROT_TWO
1528 BINARY_ADD
1529 ROT_TWO
1530 BINARY_ADD
1531 BINARY_ADD
1532 LOAD_GLOBAL 0 'chr'
1535 LOAD_CONST 114
1538 CALL_FUNCTION_1 1 None
1541 LOAD_GLOBAL 0 'chr'
1544 LOAD_CONST 111
1547 CALL_FUNCTION_1 1 None
1550 ROT_TWO
1551 BINARY_ADD
1552 LOAD_GLOBAL 0 'chr'
1555 LOAD_CONST 32
1558 CALL_FUNCTION_1 1 None
1561 LOAD_GLOBAL 0 'chr'
1564 LOAD_CONST 58
1567 CALL_FUNCTION_1 1 None
1570 LOAD_GLOBAL 0 'chr'
1573 LOAD_CONST 100
1576 CALL_FUNCTION_1 1 None
1579 ROT_TWO
1580 BINARY_ADD
1581 ROT_TWO
1582 BINARY_ADD
1583 BINARY_ADD
1584 BINARY_ADD
1585 CALL_FUNCTION_1 1 None
1588 JUMP_BACK 750 'to 750'
1591 LOAD_GLOBAL 0 'chr'
1594 LOAD_CONST 111
1597 CALL_FUNCTION_1 1 None
1600 LOAD_GLOBAL 0 'chr'
1603 LOAD_CONST 114
1606 CALL_FUNCTION_1 1 None
1609 LOAD_GLOBAL 0 'chr'
1612 LOAD_CONST 87
1615 CALL_FUNCTION_1 1 None
1618 ROT_TWO
1619 BINARY_ADD
1620 ROT_TWO
1621 BINARY_ADD
1622 LOAD_GLOBAL 0 'chr'
1625 LOAD_CONST 112
1628 CALL_FUNCTION_1 1 None
1631 LOAD_GLOBAL 0 'chr'
1634 LOAD_CONST 32
1637 CALL_FUNCTION_1 1 None
1640 LOAD_GLOBAL 0 'chr'
1643 LOAD_CONST 103
1646 CALL_FUNCTION_1 1 None
1649 LOAD_GLOBAL 0 'chr'
1652 LOAD_CONST 110
1655 CALL_FUNCTION_1 1 None
1658 ROT_TWO
1659 BINARY_ADD
1660 ROT_TWO
1661 BINARY_ADD
1662 ROT_TWO
1663 BINARY_ADD
1664 BINARY_ADD
1665 LOAD_GLOBAL 0 'chr'
1668 LOAD_CONST 115
1671 CALL_FUNCTION_1 1 None
1674 LOAD_GLOBAL 0 'chr'
1677 LOAD_CONST 115
1680 CALL_FUNCTION_1 1 None
1683 LOAD_GLOBAL 0 'chr'
1686 LOAD_CONST 97
1689 CALL_FUNCTION_1 1 None
1692 ROT_TWO
1693 BINARY_ADD
1694 ROT_TWO
1695 BINARY_ADD
1696 LOAD_GLOBAL 0 'chr'
1699 LOAD_CONST 100
1702 CALL_FUNCTION_1 1 None
1705 LOAD_GLOBAL 0 'chr'
1708 LOAD_CONST 114
1711 CALL_FUNCTION_1 1 None
1714 LOAD_GLOBAL 0 'chr'
1717 LOAD_CONST 111
1720 CALL_FUNCTION_1 1 None
1723 LOAD_GLOBAL 0 'chr'
1726 LOAD_CONST 119
1729 CALL_FUNCTION_1 1 None
1732 ROT_TWO
1733 BINARY_ADD
1734 ROT_TWO
1735 BINARY_ADD
1736 ROT_TWO
1737 BINARY_ADD
1738 BINARY_ADD
1739 BINARY_ADD
1740 LOAD_GLOBAL 0 'chr'
1743 LOAD_CONST 46
1746 CALL_FUNCTION_1 1 None
1749 LOAD_GLOBAL 0 'chr'
1752 LOAD_CONST 46
1755 CALL_FUNCTION_1 1 None
1758 LOAD_GLOBAL 0 'chr'
1761 LOAD_CONST 46
1764 CALL_FUNCTION_1 1 None
1767 ROT_TWO
1768 BINARY_ADD
1769 ROT_TWO
1770 BINARY_ADD
1771 LOAD_GLOBAL 0 'chr'
1774 LOAD_CONST 101
1777 CALL_FUNCTION_1 1 None
1780 LOAD_GLOBAL 0 'chr'
1783 LOAD_CONST 108
1786 CALL_FUNCTION_1 1 None
1789 LOAD_GLOBAL 0 'chr'
1792 LOAD_CONST 80
1795 CALL_FUNCTION_1 1 None
1798 LOAD_GLOBAL 0 'chr'
1801 LOAD_CONST 32
1804 CALL_FUNCTION_1 1 None
1807 ROT_TWO
1808 BINARY_ADD
1809 ROT_TWO
1810 BINARY_ADD
1811 ROT_TWO
1812 BINARY_ADD
1813 BINARY_ADD
1814 LOAD_GLOBAL 0 'chr'
1817 LOAD_CONST 32
1820 CALL_FUNCTION_1 1 None
1823 LOAD_GLOBAL 0 'chr'
1826 LOAD_CONST 101
1829 CALL_FUNCTION_1 1 None
1832 LOAD_GLOBAL 0 'chr'
1835 LOAD_CONST 115
1838 CALL_FUNCTION_1 1 None
1841 LOAD_GLOBAL 0 'chr'
1844 LOAD_CONST 97
1847 CALL_FUNCTION_1 1 None
1850 ROT_TWO
1851 BINARY_ADD
1852 ROT_TWO
1853 BINARY_ADD
1854 ROT_TWO
1855 BINARY_ADD
1856 LOAD_GLOBAL 0 'chr'
1859 LOAD_CONST 32
1862 CALL_FUNCTION_1 1 None
1865 LOAD_GLOBAL 0 'chr'
1868 LOAD_CONST 121
1871 CALL_FUNCTION_1 1 None
1874 LOAD_GLOBAL 0 'chr'
1877 LOAD_CONST 114
1880 CALL_FUNCTION_1 1 None
1883 LOAD_GLOBAL 0 'chr'
1886 LOAD_CONST 116
1889 CALL_FUNCTION_1 1 None
1892 ROT_TWO
1893 BINARY_ADD
1894 ROT_TWO
1895 BINARY_ADD
1896 ROT_TWO
1897 BINARY_ADD
1898 BINARY_ADD
1899 BINARY_ADD
1900 BINARY_ADD
1901 LOAD_GLOBAL 0 'chr'
1904 LOAD_CONST 97
1907 CALL_FUNCTION_1 1 None
1910 LOAD_GLOBAL 0 'chr'
1913 LOAD_CONST 103
1916 CALL_FUNCTION_1 1 None
1919 LOAD_GLOBAL 0 'chr'
1922 LOAD_CONST 97
1925 CALL_FUNCTION_1 1 None
1928 ROT_TWO
1929 BINARY_ADD
1930 ROT_TWO
1931 BINARY_ADD
1932 LOAD_GLOBAL 0 'chr'
1935 LOAD_CONST 32
1938 CALL_FUNCTION_1 1 None
1941 LOAD_GLOBAL 0 'chr'
1944 LOAD_CONST 46
1947 CALL_FUNCTION_1 1 None
1950 LOAD_GLOBAL 0 'chr'
1953 LOAD_CONST 110
1956 CALL_FUNCTION_1 1 None
1959 LOAD_GLOBAL 0 'chr'
1962 LOAD_CONST 105
1965 CALL_FUNCTION_1 1 None
1968 ROT_TWO
1969 BINARY_ADD
1970 ROT_TWO
1971 BINARY_ADD
1972 ROT_TWO
1973 BINARY_ADD
1974 BINARY_ADD
1975 LOAD_GLOBAL 0 'chr'
1978 LOAD_CONST 32
1981 CALL_FUNCTION_1 1 None
1984 LOAD_GLOBAL 0 'chr'
1987 LOAD_CONST 111
1990 CALL_FUNCTION_1 1 None
1993 LOAD_GLOBAL 0 'chr'
1996 LOAD_CONST 68
1999 CALL_FUNCTION_1 1 None
2002 ROT_TWO
2003 BINARY_ADD
2004 ROT_TWO
2005 BINARY_ADD
2006 LOAD_GLOBAL 0 'chr'
2009 LOAD_CONST 32
2012 CALL_FUNCTION_1 1 None
2015 LOAD_GLOBAL 0 'chr'
2018 LOAD_CONST 116
2021 CALL_FUNCTION_1 1 None
2024 LOAD_GLOBAL 0 'chr'
2027 LOAD_CONST 111
2030 CALL_FUNCTION_1 1 None
2033 LOAD_GLOBAL 0 'chr'
2036 LOAD_CONST 110
2039 CALL_FUNCTION_1 1 None
2042 ROT_TWO
2043 BINARY_ADD
2044 ROT_TWO
2045 BINARY_ADD
2046 ROT_TWO
2047 BINARY_ADD
2048 BINARY_ADD
2049 BINARY_ADD
2050 LOAD_GLOBAL 0 'chr'
2053 LOAD_CONST 117
2056 CALL_FUNCTION_1 1 None
2059 LOAD_GLOBAL 0 'chr'
2062 LOAD_CONST 114
2065 CALL_FUNCTION_1 1 None
2068 LOAD_GLOBAL 0 'chr'
2071 LOAD_CONST 98
2074 CALL_FUNCTION_1 1 None
2077 ROT_TWO
2078 BINARY_ADD
2079 ROT_TWO
2080 BINARY_ADD
2081 LOAD_GLOBAL 0 'chr'
2084 LOAD_CONST 102
2087 CALL_FUNCTION_1 1 None
2090 LOAD_GLOBAL 0 'chr'
2093 LOAD_CONST 32
2096 CALL_FUNCTION_1 1 None
2099 LOAD_GLOBAL 0 'chr'
2102 LOAD_CONST 101
2105 CALL_FUNCTION_1 1 None
2108 LOAD_GLOBAL 0 'chr'
2111 LOAD_CONST 116
2114 CALL_FUNCTION_1 1 None
2117 ROT_TWO
2118 BINARY_ADD
2119 ROT_TWO
2120 BINARY_ADD
2121 ROT_TWO
2122 BINARY_ADD
2123 BINARY_ADD
2124 LOAD_GLOBAL 0 'chr'
2127 LOAD_CONST 101
2130 CALL_FUNCTION_1 1 None
2133 LOAD_GLOBAL 0 'chr'
2136 LOAD_CONST 99
2139 CALL_FUNCTION_1 1 None
2142 LOAD_GLOBAL 0 'chr'
2145 LOAD_CONST 114
2148 CALL_FUNCTION_1 1 None
2151 LOAD_GLOBAL 0 'chr'
2154 LOAD_CONST 111
2157 CALL_FUNCTION_1 1 None
2160 ROT_TWO
2161 BINARY_ADD
2162 ROT_TWO
2163 BINARY_ADD
2164 ROT_TWO
2165 BINARY_ADD
2166 LOAD_GLOBAL 0 'chr'
2169 LOAD_CONST 41
2172 CALL_FUNCTION_1 1 None
2175 LOAD_GLOBAL 0 'chr'
2178 LOAD_CONST 61
2181 CALL_FUNCTION_1 1 None
2184 LOAD_GLOBAL 0 'chr'
2187 LOAD_CONST 32
2190 CALL_FUNCTION_1 1 None
2193 LOAD_GLOBAL 0 'chr'
2196 LOAD_CONST 46
2199 CALL_FUNCTION_1 1 None
2202 ROT_TWO
2203 BINARY_ADD
2204 ROT_TWO
2205 BINARY_ADD
2206 ROT_TWO
2207 BINARY_ADD
2208 BINARY_ADD
2209 BINARY_ADD
2210 BINARY_ADD
2211 BINARY_ADD
2212 PRINT_ITEM
2213 PRINT_NEWLINE_CONT

Parse error at or near `None' instruction at offset -1


if __name__ == '__main__':
main()

mfc逆向-200

0x00

知识补充:

MFC是啥:MFC(Microsoft Foundation Classes),以C++类的形式封装了Windows的API,并且包含一个应用程序框架。其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类

补充完毕!

​ 查看了一下大小,1.8M,算是比较大的了。

​ 点开:

image-20221202173841105

image-20221202174116530

​ 发现是VMProtect的壳,32位程序。查了查资料,感觉这个还不好脱壳。

​ 最近学习状态不太好,准备看wp了。我真是废物!!

常见的壳:UPX(CTF用的多,垃圾壳),VMProtect(有虚拟机保护),ASProtect(应用最广),Armadillo(各种保护手段),EXECryptor(猛)。

0x01 fw的wp复现

​ 参考博客1:

https://blog.csdn.net/xiao__1bai/article/details/122244983

​ 首先,他没有重点关注vmp的脱壳。

知识补充:

​ 在mfc-study这一博客中也提到了。简单来说,mfc把监听的消息以及相应的处理函数放到了一个静态数组中,如果能找到这个数组,就容易做逆向分析工作。要在整个内存块中找出一个数组来并不容易,不过好在MFC框架为了方便其自身,定义了查表的接口:

1
virtual const AFX_MSGMAP* GetMessageMap() const;

​ 有很多工具可以实现这一点,例如窗口查看分析工具SPY++、专门的 MFC 内部分析工具XSPY等

​ 更详细的:

image-20221207130111187

补充完毕!

​ 那么,首先打开本题给出的exe文件,之后使用spy++定位窗口:

image-20221207130315346

​ 发现类名944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b

​ 之后,使用xspy找到此类的相关信息:

image-20221207130425005

​ 上图红框代表消息处理函数,其中要注意的是0464。其余函数的信息为:

image-20221207130615469

​ 可以写c脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 1.cpp : 定义控制台应用程序的入口点。
//注意是MFC运行。

#include "stdafx.h"
#include<stdio.h>
#include<string.h>
#include "windows.h"

int main()
{
HWND h = FindWindowA("944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b",NULL);
//HWND h = FindWindowA(NULL, "Flag就在控件里");
//HWND h = FindWindowA("944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b", "Flag就在控件里");
//这里用到两个关键函数,一个是获取窗口句柄函数,第二个就是根据句柄发送消息函数。获取句柄的FindWindowA中第一个可以传入类名,第二个可以传入标题,因为我们两个都有,所以任意一个都可以锁定程序窗口。
if(h)
{
SendMessage(h, 0x464, NULL, NULL);
//发送函数中第二个是区别其他消息的常量值,这里题目用了自定义常量值,所以我们要对应一致。
}
getchar();
// system("pause");
return 0;
}

​ 也可以用python写:

1
2
3
import win32gui
hwnd=win32gui.FindWindow(None,'Flag就在控件里')
win32gui.SendMessage(hwnd,0x464,None,None)

函数补充:

image-20221207132757822

image-20221207132940214

补充完毕!!

​ 发现得到:

image-20221207130802791

​ 直接用密码学综合工具:

image-20221207130821439

​ 得到flag为thIs_Is_real_kEy_hahaaa

0x02 总结

​ 其他人的博客差不多也是这么写的,但是真正没有脱vmp的,以后遇到再说吧,感觉是被vmp吓到了。

​ 找到了另一个exeinfope.exe的替代,detect it easy。有时候exeinfo不准,综合起来用更好。

知识点1:

​ 常用的VMProtect脱壳:https://github.com/lmy375/awesome-vmp/blob/master/README.md

知识点2:

​ stdafx.h在C++中起到的作用是头文件预编译,即把C++工程中使用的MFC头文件预先编译,以后该工程编译时,直接使用预编译的结果,以加快编译速度。C++编译器通过一个头文件stdafx.h来使用预编译头文件。stdafx.h并不是标准C++头文件,与项目的源代码文件存放在同一个文件文件夹下,通过#include”stdafx.h”引用。stdafx的英文全称为:Standard Application Framework Extensions(标准应用程序框架的扩展)。

​ 编译器通过一个头文件stdafx.h来使用预编译头文件。stdafx.h这个头文件名是可以在project的编译设置里指定的。编译器认为,所有在指令#include “stdafx.h”前的代码都是预编译的,它跳过#include “stdafx. h”指令,使用projectname.pch编译这条指令之后的所有代码

​ 因此,所有的MFC实现文件第一条语句都是:”#include “stdafx.h”。在它前面的所有代码将被忽略,所以其他的头文件应该在这一行后面被包含。否则,你将会得到“No such file or directory”这样让你百思不得其解的错误提示。


The_Maya_Society

0x00

​ 玛雅社会,有点小帅。

​ 给的文件目录结构为(tree /f > result.txt):

1
2
3
4
5
6
7
└─src
│ launcher
│ The Maya Society.html

└─The Maya Society_files
main.css
maya.png

​ launcher为64位的ELF。

​ 打开The Maya Society.html:

image-20221207134724841

​ 猜测这里的launcher就是给的那个文件。

image-20221208002416513

​ 之后,我就分析那个launcher文件,流程大概就是:

  1. 产生014dfa2ce4b0ef535ca0b0094f29f75c.fluxfingers.net,赋给dest变量。
  2. sub_56447D2018A4函数,主要是对上述网址发起DNS询问,返回两个双引号之间的结果v20
  3. v20交给sub_56447D2015E0处理(主要是类似于base64加密的功能),得到v19
  4. v19交给sub_56447D201858(异或操作),生成v18
  5. 最后v18是个函数,函数有一个参数就是v19

​ 一开始,我想着找到一个没有被引用的函数,找来找去只找到一个base64。明天再瞅瞅!

​ 明天又瞅了瞅,发现第1步产生的结果是变化的,变成了:05469fb88bbaa21271ae17f419011b34.fluxfingers.net。chatGPT太鸡儿牛了,一眼发现sub_56447D200B5A函数是md4。又问了问GPT的sub_55CA11A018A4,是返回ip地址。而sub_56447D2015Ebase64_decode函数。

​ 看了很久,还是不知道:((void (__fastcall *)(char *))v18)(v8);是啥意思,我一开始认为v18是某个函数的地址,但又找不到类似的函数。

​ 手足无措了,准备看wp。

​ 看了之后,首先,sub_56447D200B5A是md5,chatGPT搞错了。之后,他是把linux时间位跳到了玛雅末日那一天,即2012-12-21,这个的确需要脑洞。但是这个题是复现不出来的,因为题目太老了,对应的xxx.fluxfingers.net域名已经关闭。

最后,这道题就是构造好xxx.fluxfingers.net发送给服务器解析,获得一些东西,并使用Base64解密,并异或,最终得到flag。(官方flag:flag{e3a03c6f3fe91b40eaa8e71b41f0db12})

0x01 总结

​ 题目不重要,但这道题能学到很多,要总结。

0x1.1 如何判断base64与md5加密函数

md5加密函数:

​ 1. 2个64元素的数组。

​ 2. 4个起始寄存器。

image-20221208120442402

​ 3. md5加密512位的倍数,但是长度以64比特加在后面,所以内容占448比特。

image-20221208120645439

​ 4. md5算法具体实现:

image-20221208120737566

base64加密:

​ 语雀文档里写过。

base64解密:

image-20221208120903697

0x1.2 此题中爆破日期的方法

​ 当时也想过,能不能遍历日期?

思想是:写一个动态链接库,里面包含一个伪time函数,让launcher运行时调用伪time函数,获取我们指定的时间,另一方面,我们可以再使用一个bash脚本,来进行循环。

1
2
3
4
5
6
7
8
9
10
11
// faketime.c
// 把faketime.c 变成动态链接库
// gcc -c -fPIC faketime.c -o faketime.o
// gcc faketime.o -shared -o faketime.so
#include<stdio.h>
#include<stdlib.h>

int time(int * second)
{
return atoi(getenv("CURR_TIME"));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// victim.c
// 调用time库的受害者
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main(){
time_t timer;
struct tm *tp;
char s[104];

timer = time(0LL);
tp = localtime(&timer);
strftime(s, 0x63uLL, "%Y-%m-%d", tp);
printf("%s\n", s);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
# time.sh
# 对时间进行遍历
# LD_PRELOAD 是 Linux/Unix 系统的一个环境变量,它影响程序的运行时的链接(Runtime linker),它允许在程序运行前定义优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库(重点)。
#!/bin/bash

for((c=1325376000; c<=1356912000; c+=3600*24)) # 按天遍历(2012-01-01到2012-12-30)
do
CURR_TIME=$c
export CURR_TIME
export LD_PRELOAD=$(pwd)/faketime.so
result=`./victim`
echo "$result"
done

0x1.3 ((void (__fastcall )(char ))v18)(v8); 是啥意思

​ 看了看别人的wp,说是花指令动态函数,解题用不到,我服了。

0x1.4

​ 其实这道题,看完之后觉得不是特别难,只是之前没有掌握遍历的方法,但是最重要的是:看到题目,应该要想到世界末日,但是没想到,唉,脑洞问题,还得继续修炼呀。


What-does-this-button-do

0x00

​ 看到这个名字,肯定是mfc类似的东东,肯定要关注某个按钮,die看一下,发现是apk文件。

image-20221208135118927

​ 用jadx打开瞅瞅:

image-20221208140216515

​ 上述onCreateOptionsMenu是创建菜单,onCreateOptionsMenu是根据itemid来响应事件,都不是重要,重要的是OnCreate函数,大概意思就是如果输入密码为EYG3QMCS,就进入FlagActivity

​ 再来看FlagActivity

image-20221208140638149

​ 直接得到flag了,有点简单。。

​ 上脚本:

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
# @Time : 2022/12/08 14:30:43
# @Author: wd-2711
'''

flag = [102, 108, 97, 103, 123, 119, 52, 110, 110, 52, 95, 106, 52, 114, 95, 109, 121, 95, 100, 51, 120, 125]
for i in flag:
print(chr(i), end = "")
# flag{w4nn4_j4r_my_d3x}

​ 还有一种方法,直接把后缀改成.apk,放到mumu里,输入密码EYG3QMCS

image-20221208140935914

​ 简单。

0x01 补充

​ 看了其他大佬的wp,补充一下知识,关于android apk文件的结构:

image-20221208141221864

jadx与jeb都能对java 安卓进行反编译。jadx反编译能力较弱,抗干扰能力很弱,对于一些嵌套循环的反编译展示能力很差,jeb反编译能力极强,能够代码跟踪,添加备注,方法重命名等等。

JEB主要用来反编译apk文件的,jd-gui是用来反编译jar可执行文件的。

​ 感觉jeb更牛逼,和ida似的。

1
2
3
4
5
6
7
8
9
10
11
12
jeb 常用指令

1.n //重命名
2.Enter //双击跟踪
3.Esc //返回
4.Ctrl+Enter//前进
5.H //帮助
6.I //条目信息
7.X //交叉引用,Ctrl + X 源码交叉引用
8.;or C //注释
9.B //改变进制数
10.Tab //反编译

​ 有的师傅用dex2jar将classes.dex反编译成jar之后用jd-gui打开。试一试。

​ 首先把后缀改成.zip,然后解压,使用./d2j-dex2jar.bat classes.dex得到jar。之后放入jd-gui中,分析方法一样。


2ex

0x00

​ 我说我咋觉得以前做过,找了找,真让我找到了,以前做了一道2ex1的题目。当时是看的wp,这次不能看了奥。

​ 查了查die,是32位的mips。

​ 发现就是原题。。是个换码表的base64,是靠逆向嗅觉的。其实想想,2ex不看wp确实挺难的。

​ 复习一下换码表:

  1. 用新码表转成旧码表。
  2. 对结果进行base64解码。
1
2
3
4
5
6
7
8
9
10
11
12
13
# script 1
from base64 import b64decode
miwen = "_r-+_Cl5;vgq_pdme7#7eC0="
key1 = list("@,.1fgvw#`/2ehux$~\"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD")
base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
secret = ""
for i in miwen:
k = key1.index(i)
secret += base64[k]
print(secret)
print(len(secret))
print(b64decode(secret))
# flag{change53233}

留言

2022-11-23

© 2024 wd-z711

⬆︎TOP