PicoCTF-2019 Writeup
  • HHousen PicoCTF-2019 Writeup
  • Binary Exploitation
    • L1im1tL355
    • messy-malloc
    • OverFlow 2
    • CanaRy
    • NewOverFlow-1
    • NewOverFlow-2
    • sice_cream
    • seed-sPRiNG
    • leap-frog
    • GoT
    • rop64
    • rop32
    • Ghost_Diary
    • zero_to_hero
    • Challenge Name
    • Heap overflow
    • slippery-shellcode
    • AfterLife
    • SecondLife
    • stringzz
  • Cryptography
    • la cifra de
    • b00tl3gRSA2
    • b00tl3gRSA3
    • AES-ABC
    • john_pollard
    • b00tl3gRSA2
    • waves over lambda
  • Forensics
    • What Lies Within
    • m00nwalk
    • shark on wire 1
    • shark on wire 2
    • Glory of the Garden
    • pastaAAA
    • Investigative Reversing 0
    • Investigative Reversing 1
    • extensions
    • investigation_encoded_1
    • Investigative Reversing 2
    • investigation_encoded_2
    • Investigative Reversing 3
    • like1000
    • Investigative Reversing 4
    • WebNet0
    • B1g_Mac
    • m00nwalk 2
    • WebNet1
    • WhitePages
    • So Meta
    • c0rrupt
  • Web Exploitation
    • Java Script Kiddie 2
    • Empire1
    • Empire2
    • cereal hacker 1
    • Empire3
    • cereal hacker 2
    • Java Script Kiddie
    • JaWT Scratchpad
    • Irish-Name-Repo 1
    • Irish-Name-Repo 2
    • Irish-Name-Repo 3
  • Reverse Engineering
    • Time's Up, Again!
    • Forky
    • droids0
    • Challenge Name
    • droids1
    • droids2
    • droids3
    • reverse_cipher
    • droids4
    • B1ll_Gat35
    • Time's Up
    • Time's Up, For the Last Time!
    • asm1
    • asm2
    • asm3
    • asm4
  • Challenge Name
Powered by GitBook
On this page
  • Problem
  • Solution
  • Flag

Was this helpful?

Edit on Git
  1. Reverse Engineering

Forky

PreviousTime's Up, Again!Nextdroids0

Last updated 4 years ago

Was this helpful?

Problem

In this program, identify the last integer value that is passed as parameter to the function doNothing(). The binary is also found in /problems/forky_5_4f100885e708548a54f8c5668f9821c1 on the shell server.

Solution

  1. Reverse the binary file using (). main() function:

     /* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */
    
     undefined4 main(void)
    
     {
     int *piVar1;
    
     piVar1 = (int *)mmap((void *)0x0,4,3,0x21,-1,0);
     *piVar1 = 1000000000;
     fork();
     fork();
     fork();
     fork();
     *piVar1 = *piVar1 + 0x499602d2;
     doNothing(*piVar1);
     return 0;
     }

    doNothing() function:

     void doNothing(void)
    
     {
     __x86.get_pc_thunk.ax();
     return;
     }
  2. So this program recursively forks itself and calls doNothing(). We need to identify last integer value that is passed as parameter to doNothing().

  3. The first process forks itself, creating 2 child processes. Those two children fork, creating 4 child processes. We have now executed 2 of the 4 calls to fork(). We fork the 4 children, doubling again to create 8 child processes. Now we only have 1 call to fork() left. We fork the 8 children, resulting in 16 child processes. More info about fork() on . The diagram below shows this happening (each 0 is a process):

     +
     |
     +-----------------------------------+
     |                                   |
     +-----------------+                 +-----------------+
     |                 |                 |                 |
     +--------+        +--------+        +--------+        +--------+
     |        |        |        |        |        |        |        |
     +---+    +---+    +---+    +---+    +---+    +---+    +---+    +---+  
     |   |    |   |    |   |    |   |    |   |    |   |    |   |    |   |  
     O   O    O   O    O   O    O   O    O   O    O   O    O   O    O   O
  4. Therefore, all we need to do is calculate 1000000000 + (16 * 0x499602d2). The program creates 16 processes, each of which adds 0x499602d2 to the initial value 1000000000.

  5. Run the calculation using python: python -c "from numpy import int32;print(int32(1000000000) + int32(16)*int32(0x499602d2))" to get -721750240. Here, we use the numpy.int32 datatype (generic unsigned integer) since it overflows just like in C. More info on () and ().

  6. Another way to use python to compute the answer is to use ctypes:

     import ctypes
     ctypes.c_int32(0x3B9ACA00 + 16*0x499602D2)
     c_int(-721750240)

Flag

picoCTF{-721750240}

Program
Ghidra
cheat sheet
GeeksforGeeks
this blog post from Loïc Pefferkorn
Archive
this StackOverflow answer
Archive