Tuesday, April 2, 2019

Sunshine CTF 2019 - The Whole Pkg

Description

I’ve stored all of my wrestling strategies in a state-of-the-art secret vault. I even wrote it in nodeJS, can’t get more cutting edge than that!

Author: dmaria

Strategy_Vault-win.exe


Write-up

The application showed options to list and read files, but the important file, flag.txt, was not permitted to be read.

C:\Users\user\Downloads>Strategy_Vault-win.exe
Strategy Vault
***********************Options: ***********************
1. List Files
2. Print File Contents
3. Exit
Selection : 2
*************************************************************
************************READ FILES***************************
*************************************************************
Which file would you like to read:
1. costume_shops.txt
2. finishing_moves.txt
3. flag.txt
4. sourcing_weapons.txt
5. weapons.txt
*************************************************************
************************READ FILES***************************
*************************************************************
File number: 3
File contents:
You do not have permission to view this file

The Strategy_Vault-win.exe file was a pkg compiled node.js application. It was an exe that would run at any Windows, even without node.js installed, as node.js binary was inside the file.

Our rev guys tried for hours (many hours) do the reversing of the binary but nothing seemed possible.

As I am a web guy I tried to decompile the file to get the JavaScript assets, but nothing was working. I read that the JavaScript files are compiled to V8 snapshot, so it was in binary format. I tried to run the binary with --print-bytecode, but the argument was being passed to app.js file, not to the node binary (aka ignored).

So I found this text at the bottom of the binary while reading it using a file editor:

{"C:\\snapshot\\source\\app.js":{"0":[0,6624],"3":[6624,70]},"C:\\snapshot\\source\\package.json":{"1":[6694,327],"3":[7021,69]},"C:\\snapshot\\source\\files\\costume_shops.txt":{"1":[7090,3872],"3":[10962,70]},"C:\\snapshot\\source\\files\\finishing_moves.txt":{"1":[11032,7072],"3":[18104,70]},"C:\\snapshot\\source\\files\\flag.txt":{"1":[18174,96],"3":[18270,68]},"C:\\snapshot\\source\\files\\sourcing_weapons.txt":{"1":[18338,5440],"3":[23778,70]},"C:\\snapshot\\source\\files\\weapons.txt":{"1":[23848,5216],"3":[29064,70]},"C:\\snapshot\\source\\asciiart.txt":{"1":[29134,1428],"3":[30562,70]},"C:\\snapshot\\source\\node_modules\\readline-sync\\package.json":{"1":[30632,1740],"3":[32372,70]},"C:\\snapshot\\source\\node_modules\\readline-sync\\lib\\readline-sync.js":{"0":[32442,64536],"1":[96978,44083],"3":[141061,71]},"C:\\snapshot\\source":{"2":[141132,63],"3":[141195,67]},"C:\\snapshot\\source\\node_modules\\readline-sync\\lib\\encrypt.js":{"1":[141262,569],"3":[141831,69]},"C:\\snapshot\\source\\node_modules\\readline-sync\\lib\\read.cs.js":{"1":[141900,3674],"3":[145574,70]},"C:\\snapshot\\source\\node_modules\\readline-sync\\lib\\read.ps1":{"1":[145644,3862],"3":[149506,70]},"C:\\snapshot\\source\\node_modules\\readline-sync\\lib\\read.sh":{"1":[149576,4214],"3":[153790,70]},"C:\\snapshot\\source\\node_modules\\readline-sync\\LICENSE-MIT":{"1":[153860,1050],"3":[154910,70]},"C:\\snapshot\\source\\node_modules\\readline-sync\\README-Deprecated.md":{"1":[154980,2175],"3":[157155,70]},"C:\\snapshot\\source\\files":{"2":[157225,91],"3":[157316,67]},"C:\\snapshot\\source\\node_modules\\readline-sync":{"2":[157383,59],"3":[157442,67]},"C:\\snapshot\\source\\node_modules\\readline-sync\\lib":{"2":[157509,67],"3":[157576,67]},"C:\\snapshot":{"2":[157643,10],"3":[157653,67]},"C:\\snapshot\\source\\node_modules":{"2":[157720,17],"3":[157737,67]}}
,
"C:\\snapshot\\source\\app.js"

I thought: maybe this last line is about the entrypoint.

In pkg the C:\\snapshot folder (or /snapshot in Linux) is inside the file, so I created a folder with the same number of bytes to not break the app (if you change the entrypoint to something with different number of bytes it would break the app). I just swapped the inverted the directories source and snapshot.

C:\\source\\snapshot\\app.js

console.log("Hello, world!")

And this was the result:

C:\Users\admin\Downloads>Strategy_Vault-win.exe
Hello, world!

Nice. I quickly changed my code to read the flag.txt inside the file:

const fs = require("fs")
var data = fs.readFileSync("C:\\snapshot\\source\\files\\flag.txt").toString("utf8")
console.log(data)

Unfortunately it was ciphered:

C:\Users\admin\Downloads>Strategy_Vault-win.exe
3c2077411a749dff9d91d6dfde7a571c44f477d5c7c6b4fa2a2c98a33037d3963751b8b4abd7a30ee31366059fc9422c

I checked the contents of other files and they were ciphered as well. I know it was ciphered because of references to aes-cbc-128 inside the code and the number of bytes (divisible by 16).

After some failures I came with the idea of change the name of files inside the last JSON. So when I asked the app to get costume_shops.txt in fact it was getting flag.txt for me. I swapped these two values and returned the original entrypoint.

So the start of the last JSON goes from:

{"C:\\snapshot\\source\\app.js":{"0":[0,6624],"3":[6624,70]},"C:\\snapshot\\source\\package.json":{"1":[6694,327],"3":[7021,69]},"C:\\snapshot\\source\\files\\costume_shops.txt":{"1":[7090,3872],"3":[10962,70]},"C:\\snapshot\\source\\files\\finishing_moves.txt":{"1":[11032,7072],"3":[18104,70]},"C:\\snapshot\\source\\files\\flag.txt":{"1":[18174,96],"3":[18270,68]}

to:

{"C:\\snapshot\\source\\app.js":{"0":[0,6624],"3":[6624,70]},"C:\\snapshot\\source\\package.json":{"1":[6694,327],"3":[7021,69]},"C:\\snapshot\\source\\files\\flag.txt":{"1":[7090,3872],"3":[10962,70]},"C:\\snapshot\\source\\files\\finishing_moves.txt":{"1":[11032,7072],"3":[18104,70]},"C:\\snapshot\\source\\files\\costume_shops.txt":{"1":[18174,96],"3":[18270,68]}

Same number of bytes, so it will no break the app.

I ran the program again and asked for the costume_shops.txt file.

C:\Users\user\Downloads>Strategy_Vault-win.exe
Strategy Vault
***********************Options: ***********************
1. List Files
2. Print File Contents
3. Exit
Selection : 2
*************************************************************
************************READ FILES***************************
*************************************************************
Which file would you like to read:
1. costume_shops.txt
2. finishing_moves.txt
3. flag.txt
4. sourcing_weapons.txt
5. weapons.txt
*************************************************************
************************READ FILES***************************
*************************************************************
File number: 1
File contents:
sun{n0d3j5_15_7h3_wh0l3_p4ck463}

Flag

sun{n0d3j5_15_7h3_wh0l3_p4ck463}

Capture the Flag , Reverse Engineering , Writeup