Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions nips/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
FROM ubuntu:20.04

# Avoid prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive

# Install required packages
RUN apt-get update && apt-get install -y \
build-essential \
gcc-10-mipsel-linux-gnu \
qemu-user-static \
python3 \
upx \
&& rm -rf /var/lib/apt/lists/*

# Set up working directory
WORKDIR /challenge

# Copy files into the container
COPY nips.c generate_flag.py ./

# Build the challenge
RUN python3 generate_flag.py > flag_constants.h && \
mipsel-linux-gnu-gcc-10 -o nips nips.c -static -fno-stack-protector -z execstack -O0 && \
mipsel-linux-gnu-strip nips && upx -9 nips -o nipsz

# Test the binary compiles and runs (expect failure with wrong flag)
RUN echo "Testing binary compilation:" && \
ls -la nips && \
echo "Binary compiled successfully" || true

# Output directory for the built binary
VOLUME /output
18 changes: 18 additions & 0 deletions nips/challenge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: nips
author: Colin
category: rev
description: nips nips nips mips mips mips
attribution: Written by Colin
value: 200
type: standard
version: '0.1'
image: null
protocol: null
host: null
flags:
- bcactf{S3lf_M0d1fy1ng_MIPS}
hints:
- learn mips rn
files:
- output/nips
state: visible
16 changes: 16 additions & 0 deletions nips/flag_constants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef FLAG_CONSTANTS_H
#define FLAG_CONSTANTS_H

// Encrypted flag data generated by generate_flag.py
// Original flag: bcactf{S3lf_M0d1fy1ng_MIPS}
// Flag length: 27

unsigned char encrypted_flag[] = {
0x45, 0xa8, 0xd6, 0x7f, 0x79, 0xb2, 0xe7, 0x28, 0xe8, 0xc5, 0x1b, 0x24, 0x4f, 0xc5, 0xd7, 0xf7,
0x54, 0x9b, 0xa9, 0x08, 0x90, 0x9f, 0x81, 0xec, 0x0f, 0x84, 0x1f, 0xc3, 0x97, 0x15, 0xf9, 0x55
};

#define ENCRYPTED_FLAG_SIZE 32
#define ORIGINAL_FLAG_SIZE 27

#endif // FLAG_CONSTANTS_H
105 changes: 105 additions & 0 deletions nips/generate_flag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/usr/bin/env python3
import struct
import sys


def tea_encrypt(v, k):
"""TEA encryption function - encrypts 8 bytes using 16-byte key"""
v0, v1 = v[0], v[1]
sum_val = 0
delta = 0x9E3779B9

for i in range(32):
sum_val = (sum_val + delta) & 0xFFFFFFFF
v0 = (v0 + (((v1 << 4) + k[0]) ^ (v1 + sum_val) ^ ((v1 >> 5) + k[1]))) & 0xFFFFFFFF
v1 = (v1 + (((v0 << 4) + k[2]) ^ (v0 + sum_val) ^ ((v0 >> 5) + k[3]))) & 0xFFFFFFFF

return [v0, v1]


def tea_decrypt(v, k):
"""TEA decryption function - decrypts 8 bytes using 16-byte key"""
v0, v1 = v[0], v[1]
sum_val = 0xC6EF3720 # delta * 32
delta = 0x9E3779B9

for i in range(32):
v1 = (v1 - (((v0 << 4) + k[2]) ^ (v0 + sum_val) ^ ((v0 >> 5) + k[3]))) & 0xFFFFFFFF
v0 = (v0 - (((v1 << 4) + k[0]) ^ (v1 + sum_val) ^ ((v1 >> 5) + k[1]))) & 0xFFFFFFFF
sum_val = (sum_val - delta) & 0xFFFFFFFF

return [v0, v1]


def encrypt_flag(flag, key_schedule):
"""Encrypt flag using TEA in blocks"""
# Pad flag to multiple of 8 bytes
flag_bytes = flag.encode('ascii')
while len(flag_bytes) % 8 != 0:
flag_bytes += b'\x00'

encrypted = bytearray()

# Process flag in 8-byte blocks
for i in range(0, len(flag_bytes), 8):
block = flag_bytes[i:i+8]
v = list(struct.unpack("<II", block)) # Little endian 32-bit words
encrypted_v = tea_encrypt(v, key_schedule)
encrypted.extend(struct.pack("<II", *encrypted_v))

return encrypted


def main():
# The flag for this challenge
flag = "bcactf{S3lf_M0d1fy1ng_MIPS}"

# Key schedule (same as in nips.c)
key_schedule = [0xDEADBEEF, 0xCAFEBABE, 0xFEEDFACE, 0xC0DEFEED]

# Encrypt the flag
encrypted_flag = encrypt_flag(flag, key_schedule)

# Verify decryption works
decrypted_blocks = []
for i in range(0, len(encrypted_flag), 8):
block = encrypted_flag[i:i+8]
v = list(struct.unpack("<II", block))
decrypted_v = tea_decrypt(v, key_schedule)
decrypted_blocks.extend(struct.pack("<II", *decrypted_v))

decrypted_flag = bytes(decrypted_blocks).rstrip(b'\x00').decode('ascii')

# Verify it matches
if decrypted_flag != flag:
print(f"ERROR: Decryption failed! Got: {decrypted_flag}", file=sys.stderr)
sys.exit(1)

# Generate flag_constants.h
print("#ifndef FLAG_CONSTANTS_H")
print("#define FLAG_CONSTANTS_H")
print()
print("// Encrypted flag data generated by generate_flag.py")
print(f"// Original flag: {flag}")
print(f"// Flag length: {len(flag)}")
print()

# Output as C array
print("unsigned char encrypted_flag[] = {")
for i in range(0, len(encrypted_flag), 16):
line_bytes = encrypted_flag[i:i+16]
hex_bytes = [f"0x{b:02x}" for b in line_bytes]
if i + 16 < len(encrypted_flag):
print(f" {', '.join(hex_bytes)},")
else:
print(f" {', '.join(hex_bytes)}")
print("};")
print()
print(f"#define ENCRYPTED_FLAG_SIZE {len(encrypted_flag)}")
print(f"#define ORIGINAL_FLAG_SIZE {len(flag)}")
print()
print("#endif // FLAG_CONSTANTS_H")


if __name__ == "__main__":
main()
Loading