极客巅峰2020

First Post:

Last Update:

Word Count:
2.8k

Read Time:
15 min

极客巅峰 2020

本来都可以进线下的, 但我二进制这边没有输出, 先来个中午时web历史辉煌一刻:

image_01

只怪自己太菜, 连累了队伍, 最后掉到后40了….

PWN

这次比赛两个盲打, 一个blind heap另一个不知道是啥题, 类似与抓的awd抓的流量包…还有一个是python 的溢出利用
这次的pwn只有个bheap有点思路, 其他两个pwn完全没思路, 但是一个也没弄出来, (菜~)。

bheap

​ bheap存在uaf漏洞, double free之后没有报错, 那可以猜想为libc.so.2.26 ~ libc.so.2.27, 且在本地写了个模拟了一个逻辑差不多的程序, 使用dup修改top chunk size 故意报错, 远程也是如此,也很肯定猜想是正确的. 比较麻烦的是如何泄漏libc, 且开辟的次数不能超过10次。若用dup打入IO_FILE泄漏Libc的话, 开辟次数非常多, 加上再次劫持mallo_hook或free_hook,次数就超过10次很多了, 这点问题就把我kill掉了….菜~等wp吧….

RE

virus

是一个简单的迷宫题.采用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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v5; // [esp+14h] [ebp-4Ch]
int v6; // [esp+3Ch] [ebp-24h]
int v7; // [esp+40h] [ebp-20h]
int v8; // [esp+44h] [ebp-1Ch]
int v9; // [esp+48h] [ebp-18h]
int v10; // [esp+4Ch] [ebp-14h]
size_t v11; // [esp+50h] [ebp-10h]
int len; // [esp+54h] [ebp-Ch]
int i; // [esp+58h] [ebp-8h]
int times; // [esp+5Ch] [ebp-4h]

__main();
puts("There is a long way to defeat it.");
scanf("%s", flag);
len = strlen(flag);
v6 = 0;
v7 = 0;
v8 = 0;
v9 = 0;
v10 = 0;
times = 0;
v11 = 0;
for ( i = 0; i < len; ++i )
{
if ( flag[i] == '-' )
{
v3 = times++;
*(&v6 + v3) = i; // length
}
if ( !times )
{
*(&v5 + i) = flag[i] - '0'; // check is number
if ( *(&v5 + i) > 9 || *(&v5 + i) < 0 )
return 0;
}
}
if ( times != 4 ) // 4
return 0;
v10 = len;
for ( i = 1; i <= times; ++i )
{
v11 = *(&v6 + i) - *(&v6 + i - 1) - 1;
if ( step[i] != v11 ) // check length
return 0;
strncpy(&road[0xC8 * i], &flag[*(&v6 + i - 1) + 1], v11);
}
for ( i = 0; i <= 3; ++i )
{
if ( check_flag((int)&global_map + 0xC8 * *(&v5 + i), *(&v5 + i), &road[200 * (i + 1)]) )
{
puts("How about try again?");
return 0;
}
if ( i == 3 )
printf("Great! We will defeat it!!! your flag is flag{%s}", flag);
}
return 0;
}

解释一下, 要求输入四个’-‘, 在输入’-‘之前必须为数字, 然后在对字符串的进行’-‘分割, ‘-’后面的长度分别为: 19, 25, 26, 28.这个从step[i] != v11所判断的, 如下:

1
2
3
4
5
6
7
8
9
.data:00403468 _step           dd 0                    ; DATA XREF: _main+13F↑r
.data:0040346C dd 19
.data:00403470 dd 25
.data:00403474 dd 26
.data:00403478 dd 28
.data:0040347C db 0
.data:0040347D db 0
.data:0040347E db 0
.data:0040347F db 0

通过以上逻辑, 输入的格式必须满足 -str1-str2-str3-str4

接着看check_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
bool __cdecl check_flag(int a1, int a2, char *a3)
{
bool result; // eax
signed int length; // [esp+10h] [ebp-18h]
int width; // [esp+14h] [ebp-14h]
int hight; // [esp+18h] [ebp-10h]
signed int i; // [esp+1Ch] [ebp-Ch]

length = strlen(a3);
hight = start[2 * a2];
width = dword_403444[2 * a2];
for ( i = 0; ; ++i )
{
result = i;
if ( i >= length )
break;
switch ( a3[i] )
{
case 'w':
--hight;
break;
case 's':
++hight;
break;
case 'a':
--width;
break;
case 'd':
++width;
break;
default:
return 1;
}
if ( width < 0 || width > 19 || hight < 0 || hight > 10 ) //迷宫宽度 20, 高度10
return 1;
if ( length - 1 == i )
return *(_BYTE *)(a1 + 20 * hight + width) != 'd';
if ( *(_BYTE *)(a1 + 20 * hight + width) != '.' )
return 1;
}
return result;
}

就是一个典型的迷宫了,使用wsad字符来控制.

那么我们所输入的就需要这四个字符来控制了, 先找一下迷宫的地图, 且进行宽度为20进行补齐如下:

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
|||||||||||||||.....
|||||||||||||||.....
|||||||||||||||.....
||s.........|||.....
|||||||||||.|||.....
||d||||||||.|||.....
||.||||||||.|||.....
||.||||||||.|||.....
||..........|||.....
|||||||||||||||.....
|||||||||||||||||||.
||s|||||||||||||d||.
||..|||||||||||..||.
|||..|||||||||..|||.
||||..|||||||..||||.
|||||..|||||..|||||.
||||||..|||..||||||.
|||||||..|..|||||||.
||||||||...||||||||.
|||||||||||||||||||.
|||||||||||||||.....
||.........s|||.....
||.||||||||||||.....
||.||||||||||||.....
||.||||||||||||.....
||.||||||||||||.....
||.||||||||||||.....
||.||||||||||||.....
||.........d|||.....
|||||||||||||||.....
|||||||||||||||.....
|||||||||||||||.....
|||||||||||||||.....
|||..........||.....
|||.||||||||.||.....
|||.||||||||.||.....
|||.||||||||.||.....
|||.||||||||.||.....
|||s||||||||d||.....
|||||||||||||||.....

从s出发到d结束, 那么四个迷宫分别步骤如下:

dddddddddsssssaaaaaaaaawww

sdsdsdsdsdsdsddwdwdwdwdwdwdw

aaaaaaaaasssssssddddddddd

wwwwwdddddddddsssss

当我输入 -dddddddddsssssaaaaaaaaawww-sdsdsdsdsdsdsddwdwdwdwdwdwdw-aaaaaaaaasssssssddddddddd-wwwwwdddddddddsssss发现, 在调用check_flag传入map参数执偏离原map很大的一个地址,且进入check_flag函数获取map中的值都是0,原来在输入步骤之前需要指定地图的顺序.

根据前面我们知道每个字符串的长度(19, 25, 26, 28)来指定:

那就是-wwwwwdddddddddsssss-aaaaaaaaasssssssddddddddd-dddddddddsssssaaaaaaaaawww-sdsdsdsdsdsdsddwdwdwdwdwdwdw

在确定一下迷宫的顺序为:

4312

那么输入的就是:

4312-wwwwwdddddddddsssss-aaaaaaaaasssssssddddddddd-dddddddddsssssaaaaaaaaawww-sdsdsdsdsdsdsddwdwdwdwdwdwdw

那么就出flag啦…

virus

fu!k_py

通过饭编译pyc文件

解密网站: http://www.llang.net/sudoku/calsudoku.html

或者:

1
uncompyle6 fu!k.pyc > fu!k.py
1
2
3
4
5
6
7
8
9
10
11
# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.8.3 (default, May 17 2020, 18:15:42)
# [GCC 10.1.0]
# Embedded file name: test233_ol.py
# Compiled at: 2020-03-20 13:22:50
(lambda __g, __print: [ [ (lambda __after: [ (lambda __after: (__print('Error len!'), (exit(), __after())[1])[1] if len(input) != 87 else __after())(lambda : [ [ [ [ (lambda __after: (__print('Error fmt!'), (exit(0), __after())[1])[1] if fmt1 != 'flag{' or fmt2 != '}' else __after())(lambda : (d.append(context[0:9]), (d.append(context[9:18]), (d.append(context[18:27]), (d.append(context[27:36]), (d.append(context[36:45]), (d.append(context[45:54]), (d.append(context[54:63]), (d.append(context[63:72]), (d.append(context[72:81]), [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[0][2] != '5' or d[0][3] != '3' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[1][0] != '8' or d[1][7] != '2' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[2][1] != '7' or d[2][4] != '1' or d[2][6] != '5' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[3][0] != '4' or d[3][5] != '5' or d[3][6] != '3' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[4][1] != '1' or d[4][4] != '7' or d[4][8] != '6' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[5][2] != '3' or d[5][3] != '2' or d[5][7] != '8' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[6][1] != '6' or d[6][3] != '5' or d[6][8] != '9' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[7][2] != '4' or d[7][7] != '3' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[8][5] != '9' or d[8][6] != '7' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check(h1) != 45 or check(h2) != 45 or check(h3) != 45 or check(h4) != 45 or check(h5) != 45 or check(h6) != 45 or check(h7) != 45 or check(h8) != 45 or check(h9) != 45 else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check(l1) != 45 or check(l2) != 45 or check(l3) != 45 or check(l4) != 45 or check(l5) != 45 or check(l6) != 45 or check(l7) != 45 or check(l8) != 45 or check(l9) != 45 else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check(k1) != 45 or check(k2) != 45 or check(k3) != 45 or check(k4) != 45 or check(k5) != 45 or check(k6) != 45 or check(k7) != 45 or check(k8) != 45 or check(k9) != 45 else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check1(h1) != 1 or check1(h2) != 1 or check1(h3) != 1 or check1(h4) != 1 or check1(h5) != 1 or check1(h6) != 1 or check1(h7) != 1 or check1(h8) != 1 or check1(h9) != 1 else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check1(l1) != 1 or check1(l2) != 1 or check1(l3) != 1 or check1(l4) != 1 or check1(l5) != 1 or check1(l6) != 1 or check1(l7) != 1 or check1(l8) != 1 or check1(l9) != 1 else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check1(k1) != 1 or check1(k2) != 1 or check1(k3) != 1 or check1(k4) != 1 or check1(k5) != 1 or check1(k6) != 1 or check1(k7) != 1 or check1(k8) != 1 or check1(k9) != 1 else __after())(lambda : (__print('Yes! You got it!'), __after())[1]))))))))))))))) for __g['k9'] in [context[60] + context[61] + context[62] + context[69] + context[70] + context[71] + context[78] + context[79] + context[80]] ][0] for __g['k8'] in [context[57] + context[58] + context[59] + context[66] + context[67] + context[68] + context[75] + context[76] + context[77]] ][0] for __g['k7'] in [context[54] + context[55] + context[56] + context[63] + context[64] + context[65] + context[72] + context[73] + context[74]] ][0] for __g['k6'] in [context[33] + context[34] + context[35] + context[42] + context[43] + context[44] + context[51] + context[52] + context[53]] ][0] for __g['k5'] in [context[30] + context[31] + context[32] + context[39] + context[40] + context[41] + context[48] + context[49] + context[50]] ][0] for __g['k4'] in [context[27] + context[28] + context[29] + context[36] + context[37] + context[38] + context[45] + context[46] + context[47]] ][0] for __g['k3'] in [context[6] + context[7] + context[8] + context[15] + context[16] + context[17] + context[24] + context[25] + context[26]] ][0] for __g['k2'] in [context[3] + context[4] + context[5] + context[12] + context[13] + context[14] + context[21] + context[22] + context[23]] ][0] for __g['k1'] in [context[0] + context[1] + context[2] + context[9] + context[10] + context[11] + context[18] + context[19] + context[20]] ][0] for __g['l9'] in [context[8] + context[17] + context[26] + context[35] + context[44] + context[53] + context[62] + context[71] + context[80]] ][0] for __g['l8'] in [context[7] + context[16] + context[25] + context[34] + context[43] + context[52] + context[61] + context[70] + context[79]] ][0] for __g['l7'] in [context[6] + context[15] + context[24] + context[33] + context[42] + context[51] + context[60] + context[69] + context[78]] ][0] for __g['l6'] in [context[5] + context[14] + context[23] + context[32] + context[41] + context[50] + context[59] + context[68] + context[77]] ][0] for __g['l5'] in [context[4] + context[13] + context[22] + context[31] + context[40] + context[49] + context[58] + context[67] + context[76]] ][0] for __g['l4'] in [context[3] + context[12] + context[21] + context[30] + context[39] + context[48] + context[57] + context[66] + context[75]] ][0] for __g['l3'] in [context[2] + context[11] + context[20] + context[29] + context[38] + context[47] + context[56] + context[65] + context[74]] ][0] for __g['l2'] in [context[1] + context[10] + context[19] + context[28] + context[37] + context[46] + context[55] + context[64] + context[73]] ][0] for __g['l1'] in [context[0] + context[9] + context[18] + context[27] + context[36] + context[45] + context[54] + context[63] + context[72]] ][0] for __g['h9'] in [context[72:81]] ][0] for __g['h8'] in [context[63:72]] ][0] for __g['h7'] in [context[54:63]] ][0] for __g['h6'] in [context[45:54]] ][0] for __g['h5'] in [context[36:45]] ][0] for __g['h4'] in [context[27:36]] ][0] for __g['h3'] in [context[18:27]] ][0] for __g['h2'] in [context[9:18]] ][0] for __g['h1'] in [context[0:9]] ][0])[1])[1])[1])[1])[1])[1])[1])[1])[1]) for __g['d'] in [[]] ][0] for __g['context'] in [input[5:-1]] ][0] for __g['fmt2'] in [input[(-1)]] ][0] for __g['fmt1'] in [input[0:5]] ][0])
for __g['input'] in [raw_input('Input your flag:')] ][0] if __name__ == '__main__' else __after())(lambda : None)
for __g['check1'], check1.__name__ in [(lambda arg: (lambda __l: [ (lambda __after: 0 if len(list(set(__l['arg']))) != 9 else 1)(lambda : None) for __l['arg'] in [arg] ][0])({}), 'check1')] ][0]
for __g['check'], check.__name__ in [(lambda arg: (lambda __l: [ sum(map(int, __l['arg'])) for __l['arg'] in [arg] ][0])({}), 'check')] ][0])(globals(), __import__('__builtin__', level=0).__dict__['print'])
# okay decompiling fu!k.pyc
  • d,l,h分别表示3x3块,列,行
  • 先判断列表的长度是否为9
  • check求和

是一个9x9的数独游戏,根据已知数据,求解未知就行

将一下生成的内容导入到数独求解器中求解即可.

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
# python script for sudoku

# 数独求解
# http://www.llang.net/sudoku/calsudoku.html
c = 0
d = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
]
d[0][2] = '5'
d[0][3] = '3'
d[1][0] = '8'
d[1][7] = '2'
d[2][1] = '7'
d[2][4] = '1'
d[2][6] = '5'
d[3][0] = '4'
d[3][5] = '5'
d[3][6] = '3'
d[4][1] = '1'
d[4][4] = '7'
d[4][8] = '6'
d[5][2] = '3'
d[5][3] = '2'
d[5][7] = '8'
d[6][1] = '6'
d[6][3] = '5'
d[6][8] = '9'
d[7][2] = '4'
d[7][7] = '3'
d[8][5] = '9'
d[8][6] = '7'

for i in d:
l = ''
for j in i:
l += str(j)
print(l)
1
2
3
4
5
6
7
8
9
10
11
logan@arch:~ » python exp.py
005300000
800000020
070010500
400005300
010070006
003200080
060500009
004000030
000009700
000000000

求得

1
145327698839654127672918543496185372218473956753296481367542819984761235521839764

即flag为flag{145327698839654127672918543496185372218473956753296481367542819984761235521839764}

打赏点小钱
支付宝 | Alipay
微信 | WeChat