Initial commit

This commit is contained in:
Rayhan Hanaputra
2025-10-10 22:18:06 +07:00
committed by GitHub
commit ea02892f14
1246 changed files with 289342 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
FROM public.ecr.aws/docker/library/python:slim
ARG PASSWORD
WORKDIR /opt
RUN apt-get update && \
apt-get install -y nano openssh-server \
gcc curl
# Create ctfuser and set password
RUN useradd -m -d /opt ctfuser && echo ctfuser:${PASSWORD} | chpasswd
COPY src/ .
# Generate a random flag and write it to /opt/flag
RUN python3 -c "import random; import string; flag = ''.join(random.choices(string.digits, k=8)); open('/opt/flag', 'w').write(flag)"
# Change ownership of /opt and its contents to ctfuser
RUN chown -R ctfuser:ctfuser /opt
# Set restrictive permissions for the /opt directory and its contents
RUN chmod 700 /opt && \
find /opt -type f -exec chmod 400 {} \;
# Allow write permissions only for /opt/server.py for ctfuser
RUN chmod 700 /opt/server.py
# Configure SSH for ctfuser
RUN echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config && \
echo "PermitRootLogin no" >> /etc/ssh/sshd_config && \
echo "AllowUsers ctfuser" >> /etc/ssh/sshd_config
# Start SSH service
RUN ssh-keygen -A
RUN mkdir -p /run/sshd && chmod 755 /run/sshd
RUN touch /flag.txt
RUN pip install -r requirements.txt
RUN chmod +x ./start.sh
RUN chmod +x ./niko
CMD service ssh start && ./start.sh
EXPOSE 8000
EXPOSE 22
+15
View File
@@ -0,0 +1,15 @@
version: "3"
services:
niko:
restart: always
container_name: niko
build:
context: ./
args:
- PASSWORD=PASSWORD_15000
ports:
- "15000:8000"
- "15022:22"
volumes:
- ./flag.txt:/flag.txt:ro
+1
View File
@@ -0,0 +1 @@
WRECKIT50{PLACEHOLDER}
Binary file not shown.
+153
View File
@@ -0,0 +1,153 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>NikoChat</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM"
crossorigin="anonymous"
/>
<style>
@import url('https://fonts.googleapis.com/css2?family=Kiwi+Maru:wght@700&display=swap');
:root {
--bs-body-bg: var(--bs-gray-100);
}
/* Hide the video container initially */
#video-container {
display: none;
position: fixed;
top: 50px;
right: 50px;
width: 400px;
height: 400px;
border-radius: 50%;
overflow: hidden;
z-index: 1000;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
#video-player {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Centering the main container */
.chat-container {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 100vh;
text-align: center;
font-family: 'Kiwi Maru', serif;
}
h1 {
font-size: 3rem;
color: #333;
}
textarea {
height: 200px;
resize: none;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="/">NikoChat</a>
</div>
</nav>
<!-- Video Container -->
<div id="video-container">
<video id="video-player" loop>
<source src="./static/konten-deepweb.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
</div>
<!-- Centered Content -->
<div class="chat-container">
<h1>こんにちは、NIKO!</h1>
<div class="container flex d-flex flex-column p-5">
<div class="p-3">
<label for="input" class="form-label">Send Message</label>
<textarea
class="form-control font-monospace"
id="input"
></textarea>
</div>
<div class="d-flex p-1 justify-content-end">
<button
type="button"
class="my-2 btn btn-primary m-3"
onclick="run()"
>
Send
</button>
</div>
<div class="p-3">
<label for="output" class="form-label">Reply</label>
<textarea
class="form-control font-monospace"
id="output"
disabled
></textarea>
</div>
</div>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz"
crossorigin="anonymous"
></script>
<script>
// Disable right-click
document.addEventListener("contextmenu", function (e) {
e.preventDefault();
});
// Function to start the video and show the container
function startVideo() {
var videoContainer = document.getElementById("video-container");
var videoPlayer = document.getElementById("video-player");
if (videoPlayer.paused) {
videoContainer.style.display = "block"; // Show the video container
videoPlayer.play();
}
}
// Event listener for typing in the input
document.querySelector("#input").addEventListener("input", startVideo);
// Function to send the message
function run() {
startVideo(); // Start the video when the send button is clicked
var inputEl = document.querySelector("#input");
var outputEl = document.querySelector("#output");
var msg = inputEl.value;
fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ msg }),
})
.then((r) => r.json())
.then((r) => (outputEl.value = r.output));
}
</script>
</body>
</html>
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
uvicorn==0.23.2
fastapi==0.103.1
+92
View File
@@ -0,0 +1,92 @@
import tempfile
import subprocess
import random
import base64
from subprocess import check_output
from fastapi import FastAPI, Query, Request
from fastapi.responses import FileResponse, PlainTextResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
import os
class Input(BaseModel):
msg: bytes
class Output(BaseModel):
output: str
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/")
def index():
return FileResponse("index.html")
@app.get("/api/chat")
def index():
return PlainTextResponse("/api/getFlag might be interesting")
@app.post("/api/chat", response_model=Output)
async def run(request: Request):
msg = await request.body()
error_messages = [
"あなたはどんなオタクですか",
"冗談じゃないよ!",
"tch なんだよ こいつ",
"どうしてそんなことが可能でしょうか…不可能です",
"本当のあなたは何ですか?",
"うわー、ごめんなさい",
"御心のままに、主よ",
"もういいよ、やめて!",
"時間です",
"悪くないよ。"
]
with tempfile.NamedTemporaryFile() as fp:
fp.write(msg)
fp.flush()
try:
with subprocess.Popen(["./niko"], stdin=open(fp.name, 'r'), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as proc:
try:
output, error = proc.communicate(timeout=5)
if proc.returncode != 0:
output = random.choice(error_messages)
except subprocess.TimeoutExpired:
proc.kill()
output = "ああ、くそ、君は私を捕まえた。༼☯﹏☯༽"
except Exception as e:
output = random.choice(error_messages)
return Output(output=output.strip())
# DO NOT CHANGE BELOW CODE (IT WILL BREAK YOUR SLA CHECK)
@app.get("/api/getFlag")
def get_flag(flag: str = Query(None)):
if flag is None:
html_content = f"""
<html>
<body>
<p>(´;︵;`) フラグを入力してください</p>
<img src="../static/thehek.jpeg" alt="No flag provided">
</body>
</html>
"""
return HTMLResponse(content=html_content)
try:
with open("/flag.txt", "r") as file:
flag_content = file.read().strip()
except FileNotFoundError:
return PlainTextResponse("╥﹏╥ フラグファイルが見つかりません")
try:
with open("flag", "r") as file:
key_content = file.read().strip()
except FileNotFoundError:
return PlainTextResponse("╥﹏╥ キーファイルが見つかりません")
if flag == key_content:
return PlainTextResponse(flag_content)
else:
return PlainTextResponse("(⋟﹏⋞) 私をバカにしようとしているのか (´ ͡༎ຶ ͜ʖ ͡༎ຶ `)︵‿︵")
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
/usr/sbin/sshd -D &
uvicorn server:app --host 0.0.0.0 --port 8000
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB