This repository has been archived by the owner on Jun 11, 2024. It is now read-only.
generated from BCACTF/chall-repo-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
11b23da
commit f91fd75
Showing
10 changed files
with
225 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
libscript_theory_addon.node |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
FROM rust:1.78-bullseye | ||
|
||
WORKDIR /addon | ||
|
||
COPY ./src/addon . | ||
|
||
RUN cargo build --release && \ | ||
mv ./target/release/libscript_theory_addon.so ./libscript_theory_addon.node |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
name: Script Theory | ||
categories: | ||
- rev | ||
value: 125 | ||
flag: | ||
file: ./src/flag.txt | ||
description: |- | ||
I rewrote some of my code in Rust to make it run faster. | ||
But where did my flag go? | ||
deploy: | ||
builder: | ||
build: . | ||
files: | ||
- src: ./src/program.js | ||
- src: ./output.txt | ||
- src: /addon/libscript_theory_addon.node | ||
dest: libscript_theory_addon.node | ||
container: builder | ||
authors: | ||
- Puhalenthi | ||
visible: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Encoded: DZwOdRBBOBaBxZ7SdUHDqORNCSzNt2SkBDa5NH9xsGIGz8ufVijMgucC8fht |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[package] | ||
name = "script-theory-addon" | ||
version = "1.0.0" | ||
edition = "2021" | ||
|
||
[lib] | ||
crate-type = ["cdylib"] | ||
|
||
[dependencies] | ||
chacha20 = "0.9.1" | ||
rand = "0.8.5" | ||
rand_chacha = "0.3.1" | ||
napi = "2.16.6" | ||
napi-derive = "2.16.4" | ||
|
||
[build-dependencies] | ||
napi-build = "2.1.3" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
fn main() { | ||
napi_build::setup(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
use rand::prelude::*; | ||
use rand_chacha::ChaCha20Rng; | ||
|
||
use chacha20::ChaCha20; | ||
use chacha20::cipher::KeyIvInit; | ||
use chacha20::cipher::StreamCipher; | ||
|
||
use napi::JsNumber; | ||
use napi::bindgen_prelude::*; | ||
|
||
use napi_derive::napi; | ||
|
||
pub const OIL_BASE: [u8; 30] = [ | ||
0x05, 0x14, 0x02, 0x74, 0xdd, 0xe3, 0x1c, 0xe1, 0xa7, 0xab, | ||
0x05, 0x7e, 0xae, 0x09, 0x1b, 0x18, 0x3a, 0x03, 0xae, 0x9d, | ||
0x8d, 0xd1, 0x4e, 0x93, 0x7e, 0x68, 0x27, 0xda, 0x79, 0x2a | ||
]; | ||
|
||
#[napi] | ||
fn bring_oil(value: JsNumber) -> Buffer { | ||
let mut rng = ChaCha20Rng::seed_from_u64(452890686835); | ||
|
||
let mut oil_key: [u8; 32] = [0; 32]; | ||
oil_key[0..30].copy_from_slice(&OIL_BASE); | ||
|
||
let sub = value.get_int32().unwrap() as u8; | ||
|
||
for i in 0..30 { | ||
oil_key[i] ^= rng.gen::<u8>(); | ||
|
||
if i % 2 == 0 { | ||
oil_key[i] = sub + 157 - oil_key[i]; | ||
} else { | ||
oil_key[30] += oil_key[i] % 10; | ||
} | ||
} | ||
|
||
oil_key[31] = oil_key[0] + (oil_key[1] % 3); | ||
|
||
return oil_key.to_vec().into(); | ||
} | ||
|
||
#[napi] | ||
fn diplomat_accurate(oil_key: Buffer, data: Buffer) -> Buffer { | ||
let n = [0x32; 12]; | ||
|
||
let key: Vec<u8> = oil_key.to_vec(); | ||
|
||
let mut cipher = ChaCha20::new(key.as_slice().into(), &n.into()); | ||
|
||
let mut plaintext = data.to_vec().clone(); | ||
|
||
cipher.apply_keystream(&mut plaintext); | ||
|
||
for byte in &mut plaintext { | ||
*byte = byte.reverse_bits(); | ||
} | ||
|
||
return plaintext.into(); | ||
} | ||
|
||
#[napi] | ||
fn bucket_terrace(shifter: Buffer, mut data: Buffer, magic: JsNumber) -> Buffer { | ||
for (i, byte) in shifter.iter().enumerate() { | ||
data[i] ^= byte ^ (magic.get_uint32().unwrap() as u8); | ||
} | ||
|
||
return data; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
bcactf{th3_uLt1maT3_L0cKb0X_ygIyaO6iacdU74Xt} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
const { readFileSync } = require('fs') | ||
|
||
const scriptTheory = require('./libscript_theory_addon.node') | ||
|
||
const data = readFileSync('flag.txt') | ||
|
||
const oilKey = scriptTheory.bringOil(data[0]) | ||
|
||
for (let i = 0; i < oilKey.length; i++) { | ||
oilKey[i] = Math.abs(oilKey[i] - i) | ||
} | ||
|
||
const initial = scriptTheory.diplomatAccurate(oilKey, data) | ||
|
||
const shifter = Buffer.alloc(initial.length) | ||
|
||
for (let i = 0; i < shifter.length; i++) { | ||
const sub = String(Math.abs(Math.E * i + 2 / 3 * 100)) | ||
shifter[i] = Number(sub.split('.')[1].slice(0, 2)) | ||
} | ||
|
||
const value = [...shifter].map(value => value ** 2).reduce((a, b) => { | ||
return Math.max(a + Math.sqrt(b) - 2, 1) | ||
}, 0) % 200 | ||
|
||
const bucket = scriptTheory.bucketTerrace(shifter, initial, value) | ||
|
||
console.log('Encoded: ' + bucket.toString('base64')) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
const scriptTheory = require('./libscript_theory_addon.node') | ||
const crypto = require('crypto') | ||
|
||
const ENCODED_FLAG = 'DZwOdRBBOBaBxZ7SdUHDqORNCSzNt2SkBDa5NH9xsGIGz8ufVijMgucC8fht' | ||
|
||
const computeShifterAndValue = length => { | ||
// these routines are extracted straight from program.js | ||
|
||
const shifter = Buffer.alloc(length) | ||
|
||
for (let i = 0; i < shifter.length; i++) { | ||
const value = String(Math.abs(Math.E * i + 2 / 3 * 100)) | ||
shifter[i] = Number(value.split('.')[1].slice(0, 2)) | ||
} | ||
|
||
const value = [...shifter].map(value => value ** 2).reduce((a, b) => { | ||
return Math.max(a + Math.sqrt(b) - 2, 1) | ||
}, 0) % 200 | ||
|
||
return [shifter, value] | ||
} | ||
|
||
const terraceBucket = (data, shifter, value) => { | ||
// undo bucket_terrace | ||
|
||
for (let i = 0; i < shifter.length; i++) { | ||
data[i] ^= shifter[i] ^ value | ||
} | ||
} | ||
|
||
const computeOilKey = () => { | ||
// just like in program.js, get the oil key | ||
|
||
// of course the flag will start with "bcactf" | ||
const oilKey = scriptTheory.bringOil('b'.charCodeAt(0)) | ||
|
||
for (let i = 0; i < oilKey.length; i++) { | ||
oilKey[i] = Math.abs(oilKey[i] - i) | ||
} | ||
|
||
return oilKey | ||
} | ||
|
||
const accurateDiplomat = (data, oilKey) => { | ||
// reverse diplomat_accurate | ||
|
||
const iv = Buffer.alloc(16) | ||
|
||
// skip the first 4 bytes for the counter | ||
for (let i = 4; i < iv.length; i++) { | ||
iv[i] = 0x32 | ||
} | ||
|
||
const cipher = crypto.createDecipheriv('chacha20', oilKey, iv) | ||
|
||
for (let i = 0; i < data.length; i++) { | ||
// because the lib calls reverse_bits | ||
const bits = [...data[i].toString(2).padStart(8, '0')] | ||
data[i] = parseInt(bits.reverse().join(''), 2) | ||
} | ||
|
||
return cipher.update(data).toString('utf-8') | ||
} | ||
|
||
const solve = () => { | ||
const data = Buffer.from(ENCODED_FLAG, 'base64') | ||
|
||
const [shifter, value] = computeShifterAndValue(data.length) | ||
const oilKey = computeOilKey() | ||
|
||
terraceBucket(data, shifter, value) | ||
|
||
console.log(accurateDiplomat(data, oilKey)) | ||
} | ||
|
||
solve() |