B1g_Mac
Last updated
Last updated
Here's a zip file. You can also find the file in /problems/b1g-mac_0_ac4b0dbedcd3b0f0097a5f056e04f97a.
Unzip b1g_mac.zip
with unzip b1g_mac.zip
to get a folder called test
(with 18 images inside) and a main.exe
executable file.
Running the main.exe
file produces No flag found, please make sure this is run on the server
, which is an interesting error message because this file cannot be run on the shell server since it is a Windows executable and the shell server runs Linux.
Creating a fake flag file with echo picoCTF{fake_flag} > flag.txt
and rerunning the program results in the following:
Since something happened lets see if the files are any different by re-extracting the test directory from the zip file and comparing it to the contents of the current test directory: diff -r test/ test_original/
. Nothing appears to have changed. Lets reset the test
directory and delete the "new" folder in case it actually changed something.
Reverse the binary file using Ghidra (cheat sheet). Open it and in the symbol tree click on main. The decompiled main function will show on the left.
The program opens the flag file, reads 18 characters, initializes some globals and then calls _listdir
(after printing "Work is done!"
which is strange because nothing much is done before that message is printed). _listdir
function:
_listdir
is a recursive function which iterates over files in the folder (it was called with the folder "./test"
by the main function) and, if param_1
if 0, it calls _hideInFile for every other file (only the 'Copy'
files). If param_1
is set to 1, _decodeBytes
is called on the file instead.
Right click _listdir
and go to "References > Find references to _listdir". One of the three options is an uncalled function labeled _decode
:
The _decode
function uses the same _folderName
global variable as the main function. We can call _decode_
using the debugger after _folderName
gets initialized in the main function.
Get location in main right after initializing _folderName
: 0x00401bda
Get address of _decode
: 0x00401afe
Debugger and Get Flag 1. Linux (winedbg
- did not work): Open in GDB with winedbg main.exe
then set a breakpoint at 0x00401bda
with break *0x00401bda
(the *
means "address" instead of function) then next
then set $eip = 0x00401afe
then next
and get the flag. 2. Windows (x32dbg
- Successful): It is important that the file times in the zip are not changed. On Windows, use 7-zip
to open and extract these files without modifying their file times. The built-in to Windows extraction option does not work. Run x96dbg
from x64dbg and select x32dbg
. Then open main.exe
in x32dbg
and run SetBPX 00401bda
to set a breakpoint at 0x00401bda
. Next, click through "run" until this breakpoint is reached. When the breakpoint is hit, run EIP=00401afe
to change the EIP
to _decode
. "Run" one more time and get the flag.
_hideInFile
function:
We can see that the function is using GetFileTime
and SetFileTime
, and this also explains the challenge name (MAC stands for "Modification, Access, Creation"). The Windows user interface shows us the date and H:M:S, but NTFS file systems have a resolution of 100 Nanoseconds for these fields (The FILETIME
structure represents the time in 100-nanosecond intervals since January 1, 1601). More info about how the flag was encoded and how to write a script to decode it: Dvd848 (Archive) and AMACB (Archive)
picoCTF{M4cTim35!}