├── BUILD.md ├── LICENSE ├── Makefile ├── README.md ├── THS Mission Scripting.pdf ├── destiny.mis ├── engine.cpp ├── engine.h ├── hackingteam.mis ├── md5.cpp ├── md5.h ├── tinycon.cpp ├── tinycon.h └── vm.cpp /BUILD.md: -------------------------------------------------------------------------------- 1 | # "The Hacker's Sandbox" Build Documentation 2 | 3 | THS has three external dependencies, which you will need before you can compile. 4 | 5 | * Lua (tested with 5.2, though others should work) 6 | * PCRE 7 | * Boost (Thread and System modules) 8 | 9 | On a Debian-based system, you can install these using the following: 10 | 11 | ``` 12 | $ sudo apt-get install liblua5.2-dev libpcre3-dev libboost-thread-dev 13 | ``` 14 | 15 | ## Building 16 | 17 | Once the libraries are in-place, you can run `make` to build your binaries. This will create a `sandbox` binary that you can run. 18 | 19 | ``` 20 | $ make 21 | ``` 22 | 23 | By default, it uses the name `lua` for the linker. On some systems, however, this name may be different. If you have used `apt-get install liblua5.2-dev` to install Lua on Debian, for example, you will need to specify the Lua version to `make` in order to build properly. 24 | 25 | ``` 26 | $ make LUA=5.2 27 | ``` 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2016, Unix-Ninja 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=g++ 2 | CCFLAGS=-std=c++11 3 | LDIR=/usr/local/lib 4 | IDIR=/usr/local/include 5 | EXECS=sandbox 6 | OUTFILE=sandbox 7 | DEBUG= 8 | 9 | # Use system libraries - check /usr/local first, then fall back to /opt/homebrew 10 | INCLUA=-I /usr/local/include/lua -I /opt/homebrew/include/lua 11 | INCPCRE=-I /usr/local/include -I /opt/homebrew/include 12 | INCBOOST=-I /usr/local/include -I /opt/homebrew/include 13 | 14 | # Use system library paths - check /usr/local first, then fall back to /opt/homebrew 15 | LIBLUA=-L /usr/local/lib -L /opt/homebrew/lib 16 | LIBPCRE=-L /usr/local/lib -L /opt/homebrew/lib 17 | LIBBOOST=-L /usr/local/lib -L /opt/homebrew/lib 18 | 19 | .PHONY: 32bit 20 | 21 | OS := $(shell uname) 22 | ifeq ($(OS), Darwin) 23 | MAC_MIN=-mmacosx-version-min=10.9 24 | CCFLAGS+=-stdlib=libc++ 25 | # Force static linking on macOS 26 | STATIC_LUA=-Wl,-force_load,/opt/homebrew/lib/liblua.a 27 | STATIC_PCRE=-Wl,-force_load,/opt/homebrew/lib/libpcre.a -Wl,-force_load,/opt/homebrew/lib/libpcrecpp.a 28 | STATIC_BOOST=-Wl,-force_load,/opt/homebrew/lib/libboost_thread.a -Wl,-force_load,/opt/homebrew/lib/libboost_system.a 29 | else 30 | STATIC_FLAGS=-static-libstdc++ -static-libgcc 31 | STATIC_LUA=-llua 32 | STATIC_PCRE=-lpcre -lpcrecpp 33 | STATIC_BOOST=-lboost_thread -lboost_system 34 | endif 35 | 36 | all: $(EXECS) 37 | 38 | 32bit: ARCH=-arch i386 -m32 39 | 32bit: ARCP:=/x86 40 | 32bit: OUTFILE=sandbox32 41 | 32bit: sandbox 42 | 43 | sandbox: engine.cpp tinycon.cpp vm.cpp md5.cpp 44 | @echo "Compiling Pluto (The Hacker's Sandbox)..." 45 | @echo "#########################################" 46 | $(CC) $(DEBUG) $(ARCH) $(MAC_MIN) -o $(OUTFILE) $(CCFLAGS) $(STATIC_FLAGS) $^ $(INCLUA) $(LIBLUA) $(INCPCRE) $(LIBPCRE) $(INCBOOST) $(LIBBOOST) $(STATIC_LUA) $(STATIC_PCRE) $(STATIC_BOOST) 47 | @echo "done." 48 | @echo 49 | 50 | clean: 51 | rm -rf *.o *.dSYM $(OUTFILE) 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Hacker's Sandbox 2 | 3 | Thank you for your interest in this software! The Hacker's Sandbox (THS) is a 4 | simulation engine of hacking on Unix-like systems. It allows you to play various 5 | mission packs created by the engine's author or the community. 6 | 7 | The default mission pack is a small game called "Destiny". In this game, don the 8 | role of a conscripted computer hacker, fighting your way through several 9 | machines to gain both root... and your freedom... 10 | 11 | 12 | ## Playing the game 13 | 14 | In order to play the default mission pack, all you have to do is run the sandbox 15 | binary for your system. On OSX and Linux, this is "sandbox". On Windows OSes 16 | this binary is called "sandbox.exe" 17 | 18 | On many systems, it is often easier to open a command line and run the binary 19 | from there, rather than double-clicking from the GUI. (This is especially true 20 | for OSX). 21 | 22 | For example, if you downloaded the game to your Downloads folder on a Mac, you 23 | can open the Terminal app and type the following: 24 | 25 | ~~~ 26 | $ unzip ~/Downloads/ths.osx.zip 27 | $ cd ~/Downloads/ths.osx/ 28 | $ ./sandbox 29 | ~~~ 30 | 31 | To play other mission packs, simply append the mission pack name to the end of 32 | your command. 33 | 34 | For version information and a list of changes, please read the CHANGELOG file 35 | that accompanies this software. 36 | 37 | 38 | ## Viewing the source 39 | 40 | The Hacker's Sandbox is now open source! You are free to peruse and modify the 41 | code. This isn't quite as elegant as it should be, and there are too many reasons 42 | for that to list here. A lot of it revolves around old discussions and legacy 43 | designs. Suffice to say, it should all work. 44 | 45 | It's worth pointing out, the original save file format is a bit odd. It uses a 46 | *slightly* modified version of base64 (named ab64) to pack data in newline 47 | separated rows. This was an intentional design decision stemming from some long 48 | conversations with a few friends. The intention was to be a sort of easy puzzle 49 | for novice reverse-engineers to solve. Now that this is open source it doesn't 50 | make sense anymore, so it has been replaced with a JSON-based format. However, 51 | the legacy code is kept for backwards compatibility with old saved-game files. 52 | 53 | -------------------------------------------------------------------------------- /THS Mission Scripting.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unix-ninja/hackersandbox/7a9f5011ac5216d25eb64d98585d8444dde07383/THS Mission Scripting.pdf -------------------------------------------------------------------------------- /destiny.mis: -------------------------------------------------------------------------------- 1 | -- Destiny mission pack 2 | -- Written by Unix-Ninja 3 | -- Based on the game 'Fate' by m101 4 | -- MPVERS 1.18 5 | 6 | -- globals 7 | trinity_logs = true 8 | zion_logs = true 9 | solara_logs = true 10 | morbid_logs = true 11 | honeypot_logs = true 12 | welcome_msg = true 13 | has_bruteforcer = false 14 | has_wwwlook = false 15 | 16 | -- load area6 VM 17 | newVM ("area6") 18 | setProperty ({ ip = "1.1.1.1" }) 19 | setProperty ({ on_root = "f_area6_root", hint = "Find the root password hash and a program on the local system to crack it." }) 20 | addFile ({ name = "/home/m101/welcome", owner = "m101", content="Greetings, hacker!\n\nI am glad you accepted my offer. Your first mission is to gain root on this\nmachine and access the files in the /root directory. Once you have done this,\nI will be sending you messages with your following objectives, so remember to\ncheck your 'mail' application.\n\nA list of basic commands is available with 'help'.\n\nGood luck!\n(Your destiny has been decided...)\n\n~ A friend\n\n" }) 21 | addFile ({ name = "/root/Area6", content="Congratulations on your hack. Before I give you a real mission, however, you\nwill have to complete a series of simple hacks on a few low security facilities.\nDon't worry, it should be a walk in the park for someone like you.\n\nYour next contact will be from an agent named Harper. He will provide you with\na few tools for your next hack. The target is located at 203.59.0.206. Gain root\non the next server, but DO NOT forget to clear the logs. More than your career\nis riding on this one.\n\n~A friend\n\n" }) 22 | addFile ({ name = "/etc/passwd", content = "root:fwYGBn8+Pj5.Kysrfyoq:0:0:root:/root:/bin/sh\nm101:f0BAQHdiYmJ3cXFxd3Jy:100:100:m101:/home/m101:/bin/sh\ndalton:fxcFBX9xYWF.b29vf2xs:200:200:Dalton:/home/dalton:/bin/sh\n" }) 23 | addFile ({ name = "/bin/nmap", content = garbage(415), exec="p_nmap" }) 24 | addFile ({ name = "/etc/passed-pawn" }) 25 | addFile ({ name = "/usr/hashcat", exec="p_hashcat", acl="777" }) 26 | addUser ( "m101", "area6" ) 27 | addUser ( "dalton", "lawnmower" ) 28 | addUser ( "root", "gravity98" ) 29 | addFile ({ name = "/bin/wget", exec="f_wget", acl="777" }) 30 | addFile ({ name = "/bin/wwwlook", content = garbage(787), exec="f_wwwlook", acl="777" }) 31 | mail ({ to="root@area6", from="Weasil", subject="power", body="Hey Harper, I setup that 2-GPU rig you were asking about.\nShould make hashcat nicer to use. You can use it on beefbox whenever you want.\nThe creds are the usual temp stuff.\n" }) 32 | 33 | -- load beefbox VM 34 | newVM("beefbox") 35 | setProperty ({ ip = "41.213.108.114" }) 36 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 37 | addService ({ port = "21", name = "ftpd", exec = "", start="true", poll="G6 FTP Server Ready" }) 38 | addUser ( "ftp", "gremlin117" ) 39 | addUser ( "temp", "tempP@ss" ) 40 | addGPU ( "Gremlin VGA Adapter", 5 ) 41 | addGPU ( "Gremlin VGA Adapter", 5 ) 42 | addFile ({ name = "/usr/hashcat", exec="p_hashcat", acl="777" }) 43 | 44 | -- load trinity VM 45 | newVM ("trinity") 46 | setProperty ({ ip = "203.59.0.206", on_root="f_get_brute", hint = "Did you remove the logs?" }) 47 | addService ({ port = "7", name = "echod", exec = "", start="true" }) 48 | addService ({ port = "9", name = "discardd", exec = "", start="true" }) 49 | addService ({ port = "13", name = "daytimed", exec = "", start="true" }) 50 | addService ({ port = "21", name = "ftpd", exec = "", start="true", poll="G6 FTP Server Ready" }) 51 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 52 | addUser ( "frank", "" ) 53 | addUser ( "ftp", "" ) 54 | addFile ({ name = "/bin/wget", exec="f_wget", acl="777" }) 55 | addFile ({ name = "/etc/passwd", content = "root:*:0:0:Charlie Root:/root:/bin/sh\nftp:*:100:100:ftp:/home/ftp:/bin/sh\nfrank:*:110:110:Frank Howard:/home/ftp:/bin/sh\n" }) 56 | addFile ({ name = "/var/log/ftpd.log", on_delete="f_trinity_rm_logs" }) 57 | 58 | mail ({ to="root", from="a friend", subject="Fate", body="Nice to see you're still with us, script kiddie. You haven't done anything\neven slightly impressive yet. In fact, we think you've already had too much\nhelp, so this next mission you are going to need to figure out root on your\nown.\n\nThis system will have low security, but as before, remember to erase the logs.\nThe target IP is 116.233.142.168. Break into it and gain root by any means\npossible. You might want to do your research a little before hacking in.\n\nGood Luck.\n\n~A friend\n" }) 59 | 60 | -- load zion VM 61 | newVM ("zion") 62 | setProperty ({ ip = "116.233.142.168" , on_root="f_check_zion_logs", hint = "Sometimes programs do funky things when unexpected situations occur. Can you break the welcome program?" }) 63 | addService ({ port = "13", name = "daytimed", exec = "", start="true" }) 64 | addService ({ port = "21", name = "dftpd", exec = "", start="true", poll="Digital Tech FTP Server Ready" }) 65 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 66 | addUser ( "ftp", "janitor" ) 67 | addUser ( "games", "" ) 68 | addFile ({ name = "/var/log/ftpd.log", on_delete="f_zion_rm_logs", acl="666" }) 69 | addFile ({ name = "/etc/passwd", content = "root:*:0:0:Charlie Root:/root:/bin/sh\nftp:*:100:100:ftp:/home/ftp:/bin/sh\ngames:*:100:100:ftp:/home/ftp:/bin/sh\n" }) 70 | addFile ({ name = "/etc/welcome", content = garbage(229).."\n", exec = "f_welcome", acl="777", suid="true" }) 71 | addFile ({ name = "/etc/welcome.msg", content = "Welcome to the Zion FTP and Game Server!\n\n\nAll attempts to gain unauthorized access are logged.\n\nThe Games:\n\n************\n*Battleship*\n************\nEach player places their ships on an 8x8 grid. Then,\nplayers take turns firing at the other player's ships. As the\nplayers can't see each other's screens, the screen is erased\nbetween turns and the player whose turn it is is notified on\nthe screen. The grid to the left allows players to see their\nopponent's progress.\n\nKeys:\nArrow Keys: move cursor\nEnter : Fire/Place ship\nX,T,0 : Rotate a ship (when placing)\n\n**********\n*Warefare*\n**********\nThis game requires the players to enter speed and angle of\na tank's shell, the flight of which is then simulated. The\nwinner is the player who first hits their opponent's tank.\n\n***********\n*Earthworm*\n***********\nThis is the classic 'Snake' game. The player controls an\nearthworm which must move around without hitting blocks,\nitself, or walls, and which has a limited time to live. The time\ndecreases every time the worm moves, and increases when the worm\neats a pixel.\n\nKeys:\nArrow Keys: steer worm\nX : exit the game\nS : toggle sound (initially off)\n\n*************\n*MineSweeper*\n*************\nThis is the same game, suitably modified, as on Windows Computers.\nThe player moves a cursor around, and incovers squares. If a mine\nis uncovered, the game ends. Otherwise, the square will contain the\nnumber of mines in the adjacent eight squares. This allows the\nplayer to deduce the positions of the mines. Once a mine is known,\nit may be marked to prevent it being accidentally uncovered. If there\nare no mines in the surrounding squares, a square will be blank and\nthe squares around it are automatically uncovered (as they could not\npossibly be mines.) This can take a while. The bottom-right corner\ndisplays the number of quares remaining that do not conceal mines.\n\n20 mines is easy, 30 is reasonable.\nThe maximum ever scored, to the author's knowledge, is 55.\n\nKeys:\nArrow Keys : move curosr\nShift + Arrow Keys: jump to the specified edge\nEnter : uncover square\nK,T,0 : unmark a square\n\n*************\n*Master Mind*\n*************\nIn this game, the player must deduce a five character code.\nThe calculator is held by pressing the soft keys corresponding to\ndifferent symbols. Ever guess is scored with two numbers, printed to\nthe right of the guess. For example, a score of 1-2 means that of the\nsymbols in the guess, one character of the guess is the right symbol, in\nthe right place, and two characters in the guess are the right symbols\nin the wrong positions.\n\nKeys:\nLeft/Right : move cursor\nSoft keys : put a symbol at the current position\nENTER : submit a guess\n\n********\n*Oracle*\n********\nThink of a question! Think your question loud and firmly!\nRun the Oracle, and your calculator knows the answer!\n(DO NOT TAKE THIS SERIOUSLY)\n", acl="777", on_delete="f_rm_welcome_msg" }) 72 | addFile ({ name = "/bin/wget", exec="f_wget", acl="777" }) 73 | 74 | mail ({ to="ftp", from="a friend", subject="Just a nudge", body="I am feeling benevolent. If you get stuck, see if there are any programs with\nsetuid you can exploit. If you are lucky, the developers won't have put in\nproper error handling when weird things happen.\n\n~A friend\n" }) 75 | mail ({ to="root", from="a friend", subject="Next hop", body="Are you ready for the next challenge? You'd better figure out how to make some\ntime to breathe, because we won't give it to you.\n\nThe next target belongs to a small consulting firm. The sysadmin thinks he's a\nbadass, but I'm willing to bet he isn't even using a secure password for his\naccount. Hell, I wouldn't be surprised if it was one of the top 10 most common\npasswords. Anyway, his username is \"police\". (funny, right?). You will find the\ntarget at 92.13.211.4. Have fun...\n\n~A friend\n" }) 76 | 77 | -- load sentinel VM 78 | newVM ("sentinel") 79 | setProperty ({ ip = "92.13.211.4", on_root = "f_get_brute", hint = "Maybe we can find some clues inside the files on the filesystem." }) 80 | addNetDomain("kali-net") 81 | addUser ( "police", "123456" ) 82 | addUser ( "ftp", "pencil" ) 83 | addUser ( "root", "T0ps3cr3t" ) 84 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 85 | addDir ({ name = "/proc/" }) 86 | addDir ({ name = "/proc/113/" }) 87 | addDir ({ name = "/tmp" }) 88 | addFile ({ name = "/tmp/check_status.sh", content = "#!/bin/sh\n\nspawn su -\nexpect \"Password:\" { send \"T0ps3cr3t\\n\" }\nexpect \"# \" { send \"cat /proc/113/status\\n\" }\nexit\n" }) 89 | addFile ({ name = "/proc/113/status", content = "Name: srvmon\nState: R (running)\nTgid: 5452\nPid: 5452\nPPid: 743\nTracerPid: 0 (2.4)\nUid: 501 501 501 501\nGid: 100 100 100 100\nFDSize: 256\nGroups: 100 14 16\nVmPeak: 5004 kB\nVmSize: 5004 kB\nVmLck: 0 kB\nVmHWM: 476 kB\nVmRSS: 476 kB\nVmData: 156 kB\nVmStk: 88 kB\nVmExe: 68 kB\nVmLib: 1412 kB\nVmPTE: 20 kb\nVmSwap: 0 kB\nThreads: 1\nSigQ: 0/28578\nSigPnd: 0000000000000000\nShdPnd: 0000000000000000\nSigBlk: 0000000000000000\nSigIgn: 0000000000000000\nSigCgt: 0000000000000000\nCapInh: 00000000fffffeff\nCapPrm: 0000000000000000\nCapEff: 0000000000000000\nCapBnd: ffffffffffffffff\nSeccomp: 0\nvoluntary_ctxt_switches: 0\nnonvoluntary_ctxt_switches: 1\n" }) 90 | addFile ({ name = "/etc/passwd", content = "root:*:0:0:Charlie Root:/root:/bin/sh\nftp:*:100:100:ftp:/home/ftp:/bin/sh\npolice:*:500:500:Gary Thomas:/home/police:/bin/sh\n" }) 91 | addFile ({ name = "/var/log/syslog", content = "srvmon: Critical system error! Please restart service.\nsrvmon: status code: 241H\nsrvmon: status code: 188H\nsrvmon: status code: 236B\nlogger: System rebooted for hard disk upgrade\n" }) 92 | addFile ({ name = "/bin/wget", exec="f_wget", acl="777" }) 93 | mail ({ to="root", from="a friend", subject="pwned!", body="Hah! Good one! That looser had it coming to him. Let's move to the next hack\nquickly. Your next target can be found at 118.101.16.199. I think good things\nare in your destiny.\n\n~A friend\n" }) 94 | 95 | -- load solara VM 96 | newVM ("solara") 97 | setProperty ({ ip = "118.101.16.199", on_root = "f_check_solara_logs", hint = "Find a program on the local filesystem to help steal passwords." }) 98 | addUser("ben", "") 99 | addUser ( "eliott", "dragon77" ) 100 | addUser ( "ftp", "cowboy" ) 101 | addUser ( "root", "cs6Xk-11b" ) 102 | addService ({ port = "21", name = "superftpd", exec = "", start="true", poll="Super FTP Server Ready" }) 103 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 104 | addFile ({ name = "/bin/ipsniff", exec="f_ipsniff", acl="755" }) 105 | addFile ({ name = "/bin/wget", exec="f_wget", acl="777" }) 106 | addFile ({ name = "/var/log/ftpd.log", on_delete="f_solara_rm_logs", acl="666" }) 107 | mail ({ to="root", from="a friend", subject="2f challenge", body="You might have some potential kid... maybe. There's still a lot more to go, so\ndon't get full of yourself just yet. Besides, not all of us are impressed.\n\nYou want to earn some real cred? There's a certain box that's been pissing off\nr0shi for a while. If you can pwn the box, it would look pretty damned good for\nyou. Fortunately for you, some of the heavy lifting has already been done. The\nbox is located at 22.13.107.145. The account 'brian' has already been\ncompromised. swing1999. Once you're in there, you are going to be on your own.\nThe root account is protected with two-factor auth. Let's see how you do...\n\n~A friend\n" }) 108 | 109 | -- load ironman VM 110 | newVM("ironman") 111 | setProperty ({ ip = "22.13.107.145", on_login = "f_2factor_auth", hint = "You may want to write a script to help you get past this mission. You will need a way to create tokens." }) 112 | addUser ( "root", "toor" ) 113 | addUser("brian", "swing1999") 114 | addUser("ftp", "") 115 | addUser("lee", "") 116 | addUser("tom", "") 117 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 118 | addDir ({ name = "/usr/share/" }) 119 | addDir ({ name = "/usr/share/src/" }) 120 | addFile ({ name = "/usr/share/src/token_gen.c", content="/* Token Generator */\n/* Since the admin doesnt want to change his password from 'toor', I made this\n to help secure the box. Now, root will need tokens to log in. */\n\n#include \n#include \n#include \n\nint main(void)\n{\n int seed = time(NULL);\n seed >>= 6;\n char[32] hash = hex(md5(seed));\n char[8] token = substr(hash,0,6);\n printf (\"%s\\n\", token);\n return 0;\n}\n" }) 121 | addFile ({ name = "/bin/wget", exec="f_wget", acl="777" }) 122 | addFile ({ name = "/etc/passwd", content = "root:*:0:0:Charlie Root:/root:/bin/sh\nftp:*:100:100:ftp:/home/ftp:/bin/sh\nbrian:*:500:500:Brian Wright:/home/brian:/bin/sh\ntom:*:501:501:Tom Higgin:/home/tom:/bin/sh\nlee:*:502:502:Lee Farone:/home/lee:/bin/sh\n" }) 123 | addFile ({ name = "/root/Target", content = "Congratulations on another hack. I hope you have learned little from that weak\nattempt. As Dead_Beat said, this is near the end, before the real missions\nstart. I hope you last that long...\n\nYou are going to be taking over for our last recruit. Let's just say, he\nhas some pressing engagements and couldn't finish the task. There is a\nprogram located in /usr/db. Although the programmers are still\ndeveloping it, it has suid for root. If you can overflow the buffer on\nthis program, you should be able to gain root access.\n\njummyj was kind enough to leave behind a unicode sender so you can send any\ncharacters you like to the program's input. Apparently, the source code for\nthe program has been left there, so you may want to make use of it.\nThe target's ip is 44.236.143.86\n\nGood Luck...\n\n~A friend\n" }) 124 | mail ({ to="root", from="Dead_Beat", subject="Near the End", body="I hear you have been asking around, trying to find out who we are. If I were\nyou, I wouldn't be concerned with that. It's not important who we are or what\nwe stand for. So get back to your work!\n\nYour next mission has been assigned. The target is a machine that was already\nhacked by one of our other memebrs, but so far we haven't gotten root.\nAll the neccesary files you will need are already on the machine.\nThis is almost your last challenge before anything real. Don't mess this up.\n" }) 125 | 126 | -- load morbid VM 127 | newVM ("morbid") 128 | setProperty ({ ip = "44.236.143.86", on_root = "f_get_wwwlook", uname = "VNX Kernel 0.1: Tue Dec 22 11:34 EST 2010; amd64", hint = "For a primer on buffer overflows: http://www.unix-ninja.com/p/A_Foundation_for_Buffer_Overflow_Attacks/" }) 129 | addUser ( "ftp", "monkey" ) 130 | addService ({ port = "7", name = "echod", exec = "", start="true" }) 131 | addService ({ port = "21", name = "superftpd", exec = "", start="true", poll="Super FTP Server Ready" }) 132 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 133 | addFile ({ name = "/etc/passwd", content = "root:*:0:0:Charlie Root:/root:/bin/sh\nftp:*:100:100:ftp:/home/ftp:/bin/sh\n" }) 134 | addFile ({ name = "/bin/wget", exec="f_wget", acl="777" }) 135 | addFile ({ name = "/var/log/ftpd.log", on_delete="f_morbid_rm_logs", acl="666" }) 136 | addDir ({ name = "/usr/db/" }) 137 | addFile ({ name = "/usr/db/data", content = garbage(2318).."\n", exec = "f_dbdata", acl="777" }) 138 | addFile ({ name = "/usr/db/unicode", exec = "f_unicode", acl="777" }) 139 | addDir ({ name = "/usr/db/src" }) 140 | addFile ({ name = "/usr/db/src/code.c", content = "/* database engine */\n\nint main(int argc, char **argv)\n{\n char buf[10];\n strcpy(buf,argv[1]);\n}\nvoid the_shell()\n{\n system('bin/bash');\n}\n" }) 141 | addFile ({ name = "/usr/db/src/dump", content = "assembly code for function main:\nDump of
:\n0x8048500
push %ebp\n0x8048501 mov %esp, %ebp\n0x8048503 sub $0x18, %esp\n0x8048506 cmpl $0x1, 0x8 (%ebp)\n0x804850a jg 0x804851c \n0x804850c add $0xfffffff4, %esp\n0x804850f push $0x0\n0x8048511 call 0x80483e4 \n0x8048516 add $0x10, %esp\n0x8048519 lea 0x0 (%esi), %esi\n0x804851c add $0xfffffff8, %esp\n0x804851f mov 0xc (%ebp), %eax\n0x8048522 add $0x4, %eax\n0x8048525 mov %eax, %edx\n0x8048527 push %edx\n0x8048528 lea $0xfffffff4 (%ebp), %eax\n0x804852b push %eax\n0x804852c call 0x80483b4 \n0x8048531 add $0x10, %esp\n0x8048534 leave \n0x8048535 ret\n0x8048536 mov %esi, %esi\nEnd of assembly dump.\n" }) 142 | addFile ({ name = "/usr/db/src/dump2", content = "assembly code for function the_shell:\nDump of :\n0x8048538 push %ebp\n0x8048539 mov %esp, %ebp\n0x804853b sub $0x8, %esp\n0x804853e add $0xfffffff4, %esp\n0x8048541 push $0x8048587\n0x8048546 call 0x80483c4 \n0x804854b add $0x10, %esp\n0x804854e leave\n0x804854f ret\nEnd of assembly dump.\n" }) 143 | 144 | mail ({ to="root", from="Dead_Beat", subject="Destiny...", body="Ok, cowboy. Final test. There's a website at http://neongate/page?login and we\nwant you to hack it. If you can find some sort of an LFI, you'll have it made.\nTick tock, destiny is waiting..." }) 145 | 146 | -- load neongate VM 147 | newVM("neongate") 148 | setProperty ({ ip = "68.45.10.123", on_root = "ending" }) 149 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 150 | addService ({ port = "80", name = "httpd", exec = "", start="true", poll="

It works!

" }) 151 | addUser ( "root", "baseball" ) 152 | 153 | -- load kali VM 154 | newVM("honeypot") 155 | setProperty ({ ip = "73.45.101.8", netd = "kali-net", on_logout = "f_check_honeypot_logs", uname = "Linux kali 3.12-kali1-686-pae" }) 156 | addService ({ port = "21", name = "superftpd", exec = "", start="true", poll="Super FTP Server Ready" }) 157 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 158 | addUser ( "root", "4hjWm-q6#v" ) 159 | addUser ( "ftp", "password" ) 160 | addFile ({ name = "/var/log/ftpd.log", on_delete="f_honeypot_rm_logs", acl="700", owner = "root", content = "WARNING! Intrusion detected: Source [92.13.211.4]" }) 161 | addFile ({ name = "/etc/passwd", content = "root:".. hash("4hjWm-q6#v") ..":0:0:Charlie Root:/root:/bin/sh\nftp:".. hash("password") ..":100:100:ftp:/home/ftp:/bin/sh\n" }) 162 | mail ({ to="root", from="a friend", subject="GET OUT!!", body="It's a trap! This box is a honeypot! They're probably monitoring it right now!\nCover your tracks and get the hell out of there!!!\n\n~A friend\n" }) 163 | 164 | 165 | -- functions 166 | function f_get_brute() 167 | has_bruteforcer = true 168 | end 169 | 170 | function f_get_wwwlook() 171 | if (morbid_logs == true) then 172 | print "" 173 | print "" 174 | print "--------------------------------------------------------------------------------" 175 | print "" 176 | print "" 177 | print "As it turns out, a zealous jr. administrator happened to discover your logins" 178 | print "in the ftp log files. Your remote session ends, and you suddenly hear a knock" 179 | print "at the door." 180 | print "" 181 | print "Better luck next time..." 182 | print "" 183 | pause() 184 | quit() 185 | end 186 | has_wwwlook = true 187 | end 188 | 189 | function f_wwwlook(arg) 190 | if (#arg < 2) then 191 | print "wget: missing URL" 192 | print "usage: wget [URL]" 193 | return 194 | end 195 | url = arg[2] 196 | print ("Fetching " .. url .. "...") 197 | if (string.sub(url,0,7) ~= "http://") then 198 | print ("Sorry, but this program can only work with http:// resources.") 199 | return 200 | end 201 | host, uri = string.match(url, "http://([%w-.]+)(.*)") 202 | if(host == "neongate" or host == "68.45.10.123") then 203 | if(uri == "" or uri == "/" or uri == "/index.htm") then 204 | print ("

It works!

") 205 | elseif(uri == "/page" or string.match(uri, "/page??.*")) then 206 | ifile = string.match(uri, "/page??(.*)") 207 | -- Let's work around Lua's lack of pattern matching groups 208 | tmp = string.gsub(ifile, "(%.%./)", "!") 209 | tmp = string.gsub(tmp, "!!+", "/") 210 | -- if the condensed verion of the path is /etc/passwd, just assign it to ifile 211 | if (tmp == "/etc/passwd") then 212 | ifile = tmp 213 | end 214 | -- now we can get back to comparing strings 215 | if (ifile == "/etc/passwd") then 216 | print ("

Welcome

root:" .. hash("baseball") .. ":0:0:root:/root:/bin/sh\n") 217 | elseif (ifile == "login") then 218 | print ("

Welcome

Please Sign in with basic auth to contiue.

") 219 | elseif (ifile == "" or ifile == "home") then 220 | print ("

Welcome

We're Sorry!

Our site is under renovation, but you can still visit http://neongate/page?login to access your account.

") 221 | else 222 | print ("

Welcome

") 223 | end 224 | else 225 | print ("

404

File not found!

") 226 | end 227 | return 228 | end 229 | print ("Unable to connect to host: " .. host) 230 | end 231 | 232 | function f_ipsniff() 233 | print "IPSniff - Network Packet Analyzer" 234 | print "Scanning network interfaces for plaintext passwords..." 235 | sleep(5) 236 | print "Password detected on the network" 237 | print " User: root" 238 | print " Password: cs6Xk-11b" 239 | end 240 | 241 | function f_wget(arg) 242 | if (#arg < 2) then 243 | print "wget: missing URL" 244 | print "usage: wget [URL]" 245 | return 246 | end 247 | host = arg[2] 248 | print ("Connecting to " .. host .. "... connected.") 249 | if (host == "http://area6.net/tools/" or host == "http://area6.net/tools") then 250 | path = cwd() 251 | print ("Saving files to " .. path .. "...") 252 | echo (" portscan: ") 253 | for i = 1,5 do 254 | echo (".") 255 | sleep(1) 256 | end 257 | echo ("\n") 258 | addFile ({ name = path.."portscan", content = garbage(1623).."\n", exec="p_portscan", acl="777" }) 259 | echo (" ftpexploit: ") 260 | for i = 1,7 do 261 | echo (".") 262 | sleep(1) 263 | end 264 | echo ("\n") 265 | addFile ({ name = path.."ftpexploit", content = garbage(1644).."\n", exec="f_ftpexploit", acl="777" }) 266 | if (has_bruteforcer) then 267 | echo (" bruteforcer: ") 268 | for i = 1,4 do 269 | echo (".") 270 | sleep(1) 271 | end 272 | echo ("\n") 273 | addFile ({ name = path.."bruteforcer", content = garbage(944).."\n", exec="f_bruteforcer", acl="777" }) 274 | end 275 | if (has_wwwlook) then 276 | echo (" wwwlook: ") 277 | for i = 1,3 do 278 | echo (".") 279 | sleep(1) 280 | end 281 | echo ("\n") 282 | addFile ({ name = path.."wwwlook", content = garbage(787), exec="f_wwwlook", acl="777" }) 283 | end 284 | print ("done.") 285 | return 286 | end 287 | print ("ERROR 404: Not Found.") 288 | end 289 | 290 | function f_area6_root() 291 | print "You have new mail." 292 | mail ({ to="root@area6", from="Harper", subject="Congrats n00b", body="A mutual friend wants me to give you some tools. He says you are going to need\nthem. Honestly, you're going to need a lot more than that to survive.\nGet your tools by running: wget http://area6.net/tools/\n\nGood luck. Destiny's a bitch.\n" }) 293 | end 294 | 295 | function f_2factor_auth(user) 296 | if (user ~= "root") then 297 | return 298 | end 299 | echo ("Token: ") 300 | token = input() 301 | tok = timestamp() 302 | for i=1,6 do tok = math.floor(tok / 2) end 303 | tok = md5(math.floor(tok/1)) 304 | tok = string.sub(tok,0,6) 305 | if (token ~= tok) then 306 | print "Invalid token!" 307 | logout() 308 | end 309 | end 310 | 311 | function f_trinity_rm_logs() 312 | trinity_logs = false 313 | end 314 | 315 | function f_zion_rm_logs() 316 | zion_logs = false 317 | end 318 | 319 | function f_solara_rm_logs() 320 | solara_logs = false 321 | end 322 | 323 | function f_morbid_rm_logs() 324 | morbid_logs = false 325 | end 326 | 327 | function f_honeypot_rm_logs() 328 | honeypot_logs = false 329 | end 330 | 331 | function f_ftpexploit(arg) 332 | if (#arg ~= 2) then 333 | print ("usage: ftpexploit [hostname|address]") 334 | return 335 | end 336 | print ("G6 FTPD Remote Exploit by DIGICRIME") 337 | print ("Sending Shellcode") 338 | print ("/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f") 339 | print ("/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f/.f") 340 | print ("/.f/.f/.f/.f/.f/.f/.f/.f/.f/bin/sh") 341 | if (serviceRunning(arg[2], "ftpd")) then 342 | print ("Shell Created") 343 | login ({ host = arg[2], user = "root" }) 344 | print ("You are now logged in to "..arg[2]) 345 | else 346 | print ("Host is not vulnerable") 347 | end 348 | end 349 | 350 | function f_rm_welcome_msg() 351 | welcome_msg = false; 352 | end 353 | 354 | function f_welcome() 355 | page = 20 356 | n = 0 357 | if (welcome_msg == true) then 358 | for i,line in ipairs(readfile("/etc/welcome.msg")) do 359 | n = n + 1 360 | if (n > page) then 361 | print "[more]" 362 | pause() 363 | n = 1 364 | end 365 | print(line) 366 | end 367 | else 368 | print "Error: Unable to find welcome.msg" 369 | print "Dropping back to user shell..." 370 | print "(segmentation fault: 11)" 371 | login ({ host = "zion", user = "root" }) 372 | end 373 | end 374 | 375 | function f_check_zion_logs() 376 | if (zion_logs == true) then 377 | print "" 378 | print "" 379 | print "--------------------------------------------------------------------------------" 380 | print "" 381 | print "" 382 | print "As it turns out, a zealous jr. administrator happened to discover your logins" 383 | print "in the ftp log files. Your remote session ends, and you suddenly hear a knock" 384 | print "at the door." 385 | print "" 386 | print "Better luck next time..." 387 | print "" 388 | pause() 389 | quit() 390 | end 391 | end 392 | 393 | function f_check_solara_logs() 394 | if (solara_logs == true) then 395 | print "" 396 | print "" 397 | print "--------------------------------------------------------------------------------" 398 | print "" 399 | print "" 400 | print "Sadly, you never remembered to remove the ftp log files. Now they have been used" 401 | print "to track you down. The authorities gave you little opportunity to prepare, and" 402 | print "now the game is over." 403 | print "" 404 | print "Better luck next time..." 405 | print "" 406 | pause() 407 | quit() 408 | end 409 | end 410 | 411 | function f_check_honeypot_logs(user) 412 | if (user == "root" and honeypot_logs == true) then 413 | print "" 414 | print "" 415 | print "--------------------------------------------------------------------------------" 416 | print "" 417 | print "" 418 | print "Unfortunately for you, the logs were collected on this honeypot, exposing your" 419 | print "operation. The authorities were swift in tracking you down and pulling the plug." 420 | print "I hope you like orange, because it looks like you'll be wearing it for a while." 421 | print "" 422 | print "Better luck next time..." 423 | print "" 424 | pause() 425 | quit() 426 | end 427 | end 428 | 429 | function f_dbdata() 430 | print "All data is entered through the command line..." 431 | end 432 | 433 | function f_unicode(arg) 434 | if (#arg < 2) then 435 | print "Unicode Data Sender by jimmyj" 436 | print "" 437 | print "Please enter the desired hex value into the command line" 438 | print "and it will be sent to /usr/db/data" 439 | print "" 440 | print "Example: unicode \\x90\\x50\\x43" 441 | print "" 442 | else 443 | print "Sending data..." 444 | if (arg[2]:match("\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x%d%d\\x38\\x85\\x04\\x08")) then 445 | login ({ host = "morbid", user = "root" }) 446 | print ("You have new mail.") 447 | end 448 | end 449 | end 450 | 451 | function f_bruteforcer(arg) 452 | if (#arg < 2) then 453 | print ("usage: bruteforcer [hostname|address]") 454 | return 455 | end 456 | host = arg[2] 457 | f_check_trinity_logs() 458 | print "Simple Bruteforce Login Cracker by Dead_Beat" 459 | print "" 460 | echo ("Username to bruteforce: ") 461 | user = input() 462 | print "Creating multiple connections." 463 | print "Attacking..." 464 | sleep(3) 465 | if (user == "ftp") then 466 | if (host == "zion" or host == "116.233.142.168") then 467 | print "Password Cracked" 468 | print "Password for user 'ftp' is 'janitor'" 469 | elseif (host == "morbid" or host == "44.236.143.86") then 470 | print "Password Cracked" 471 | print "Password for user 'ftp' is 'monkey'" 472 | elseif (host == "solara" or host == "118.101.16.199") then 473 | print "Password Cracked" 474 | print "Password for user 'ftp' is 'cowboy'" 475 | elseif (host == "honeypot" or host == "73.45.101.8") then 476 | print "Password Cracked" 477 | print "Password for user 'ftp' is 'password'" 478 | else 479 | print "No passwords found." 480 | end 481 | end 482 | end 483 | 484 | function f_check_trinity_logs() 485 | if (hostname() ~= "trinity") then 486 | return 487 | end 488 | if (trinity_logs == true) then 489 | print "" 490 | print "" 491 | print "--------------------------------------------------------------------------------" 492 | print "" 493 | print "" 494 | print "Unfortunately, the authorities were able to pick up your trail from the login" 495 | print "info in the logs on trinity. You have now been apprehended, and your career cut" 496 | print "violently short by a prison sentence." 497 | print "" 498 | print "Better luck next time..." 499 | print "" 500 | pause() 501 | quit() 502 | end 503 | end 504 | 505 | function intro() 506 | print "" 507 | print "" 508 | print "Message 1:" 509 | print "To: a hacker" 510 | print "From: a friend" 511 | print "Subject: a little job" 512 | print "" 513 | print "I've been watching you for some time. Nice work, I must say. Unfortunatley for" 514 | print "you, I have a pretty hefty file on your exploits that the authorities would" 515 | print "LOVE to get their hands on." 516 | print "" 517 | print "Here's my offer: You work for me, and they'll never have to see it." 518 | print "" 519 | print "If you accept my offer, log in to the machine at 103.12.49.111 with the username" 520 | print "'m101' and the password 'area6'. You have 24 hours to comply." 521 | print "" 522 | print "Your fate has been decided..." 523 | print "" 524 | pause() 525 | print "--------------------------------------------------------------------------------" 526 | print "" 527 | print "" 528 | print "VNX Kernel 0.1: Tue Dec 21 14:11 EST 2010" 529 | end 530 | 531 | function ending() 532 | print "" 533 | print "" 534 | print "--------------------------------------------------------------------------------" 535 | print "" 536 | print "" 537 | print "Message 5:" 538 | print "To: a hacker" 539 | print "From: Opticon" 540 | print "Subject: Welcome to the family" 541 | print "" 542 | print "Well done on your latest hack. Don't get full of yourself though; your next" 543 | print "challenges will be of much greater difficulty." 544 | print "" 545 | print "The boss decided to give you a new name: 'hi-jack'. Get used to this" 546 | print "handle (you might have it for a long time)." 547 | print "" 548 | print "Someone will contact you once it's time for the next mission." 549 | print "Get some rest. You're going to need it..." 550 | print "" 551 | pause() 552 | quit() 553 | end 554 | -------------------------------------------------------------------------------- /engine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | description: unix hacker simulator 3 | written by Unix-Ninja 4 | original code february, 2010 5 | */ 6 | 7 | #include "engine.h" 8 | #include "md5.h" 9 | #include "tinycon.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32) 15 | #include 16 | #endif 17 | 18 | bool debug_on; 19 | vector vPC; // available vMachines 20 | vector shell; // current shell chain 21 | vector vhashes; // list of users' password hashes 22 | int cEC = 0; // command exit code 23 | string mission_file; // filename for mission pack 24 | char last_key; // last hotkey pressed 25 | std::map dns_map; // global DNS records 26 | std::map netd_map; // map of Network Domain IDs/Names 27 | boost::thread *cmd_thread; // reference to running cmd thread 28 | 29 | lua_State *lua; // Lua state object 30 | 31 | int lua_vdump(vector args); 32 | int lua_restore(vector args); 33 | int lua_save(vector args); 34 | 35 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 36 | void sleep(int t) 37 | { 38 | Sleep(t*1000); 39 | } 40 | #endif 41 | 42 | // setup console 43 | class tcon : public tinyConsole 44 | { 45 | public: 46 | tcon (std::string s): tinyConsole(s) {;} 47 | 48 | int trigger (std::string s); 49 | 50 | int hotkeys(char c) 51 | { 52 | if (c == TAB) 53 | { 54 | // save buffer length 55 | int length; 56 | length = buffer.size(); 57 | 58 | // convert buffer to string 59 | string s; 60 | s.assign(buffer.begin(),buffer.end()); 61 | 62 | // explode string buffer 63 | vector cmd; 64 | explode(s, " ", cmd); 65 | if (!cmd.size()) 66 | { 67 | cmd.push_back(s); 68 | } 69 | 70 | // try tab complete on last segment of commandline 71 | vector matches; 72 | matches = shell.back()->tabComplete(cmd.back()); 73 | 74 | // return if no matches 75 | if (!matches.size()) 76 | { 77 | if (cmd.size() == 1) 78 | { 79 | matches = shell.back()->tabComplete("/bin/" + cmd.back()); 80 | if (!matches.size()) return 1; 81 | for (int i=0; i 1) 98 | { 99 | s = ""; // reset s before reconstruction 100 | for (int i=0; i 0) s += " "; 103 | s += cmd[i]; 104 | } 105 | s += " "; 106 | } else { 107 | s = ""; 108 | } 109 | 110 | // process matches 111 | string buf; 112 | 113 | if (matches.size() == 1) 114 | { 115 | // do we need to replace the ./ ? 116 | if (pcrecpp::RE("^\\./[^\\/]+").PartialMatch(cmd.back())) 117 | { 118 | buf = s + "./" + matches[0]; 119 | } 120 | else 121 | { 122 | buf = s + matches[0]; 123 | } 124 | if (buf.substr(buf.length()-1) != "/") buf += " "; 125 | 126 | // set new buffer 127 | setBuffer(buf); 128 | length = buffer.size(); 129 | 130 | // copy buffer to screen 131 | std::cout << buf; 132 | } else { 133 | // on multiple matches, find the common chars 134 | // we will loop through the set and match against 135 | // the first index 136 | length = 0; 137 | int l = 0; 138 | for (int i=1; i length ? length : l; 153 | } else { 154 | length = l; 155 | } 156 | } 157 | buf = s + matches[0].substr(0,length); 158 | setBuffer(buf); 159 | cout << buf; 160 | if (last_key == TAB) { 161 | cout << endl; 162 | for (int i=0; i< matches.size(); i++) 163 | { 164 | cout << " " << matches[i] << endl; 165 | } 166 | cout << _prompt << buf; 167 | } 168 | } 169 | last_key = TAB; 170 | return 1; 171 | } else if (c == CTRLC) { 172 | raise(SIGINT); 173 | return 1; 174 | } 175 | last_key = c; 176 | return E_OK; 177 | } 178 | }; 179 | 180 | tcon tc (std::string("$ ")); 181 | 182 | // explode the string into words, each in an index of a vector 183 | int explode(std::string line,std::string delimiter,std::vector &store) 184 | { 185 | store.clear(); 186 | 187 | // if line is empty, return fail 188 | if (line.empty()) return -1; 189 | 190 | //unsigned int start = 0; 191 | signed int start = -1; 192 | int len = 0; 193 | int i = 0; 194 | std::vector temp; 195 | 196 | len = delimiter.length(); 197 | 198 | // if no instance of delimiter exist, return a single index 199 | if ( line.find(delimiter) == std::string::npos ) 200 | { 201 | store.push_back(line); 202 | return 1; 203 | } 204 | 205 | while ((start = line.find(delimiter)) != std::string::npos) // move along finding delimiter, inc start 206 | { 207 | store.push_back( line.substr( 0, start) ); 208 | line.erase( 0, start+len ); 209 | i++; 210 | } 211 | if (!line.empty()) store.push_back(line); 212 | i++; 213 | return i; 214 | } 215 | 216 | int explode(std::string line, std::string delimiter, std::vector &store, int limit) 217 | { 218 | store.clear(); 219 | 220 | // if line is empty, return fail 221 | if (line.empty()) return -1; 222 | 223 | //unsigned int start = 0; 224 | signed int start = -1; 225 | int len = 0; 226 | int i = 0; 227 | std::vector temp; 228 | 229 | len = delimiter.length(); 230 | 231 | // if no instance of delimiter exist, return a single index 232 | if ( line.find(delimiter) == std::string::npos ) 233 | { 234 | store.push_back(line); 235 | return 1; 236 | } 237 | 238 | while ((start = line.find(delimiter)) != std::string::npos) // move along finding delimiter, inc start 239 | { 240 | store.push_back( line.substr( 0, start) ); 241 | line.erase( 0, start+len ); 242 | i++; 243 | if (i == limit) break; 244 | } 245 | if (!line.empty()) store.push_back(line); 246 | i++; 247 | return i; 248 | } 249 | 250 | /* 251 | void replace_all(std::string& str, const std::string& from, const std::string& to) 252 | { 253 | if (from.empty()) return; 254 | size_t pos = 0; 255 | while ((pos = str.find(from, pos)) != std::string::npos) 256 | { 257 | str.replace(pos, from.length(), to); 258 | pos += to.length(); 259 | } 260 | } 261 | */ 262 | 263 | string realpath(string path) 264 | { 265 | if (path == "/") return path; 266 | if (path.substr(0,1) != "/") 267 | { 268 | // if relative path, append cwd 269 | path = shell.back()->getCwd() + path; 270 | } 271 | 272 | // sanitize path 273 | vector store, realp; 274 | explode(path, "/", store); 275 | 276 | for (int i=1; ipFile(path); 301 | 302 | // if no file or directory found, return nothing 303 | if (!fp) return ""; 304 | 305 | if (fp->getType() == T_FOLDER) 306 | { 307 | // remember to add trialing slash 308 | if (path.length()>1 && path.substr(path.length()-1) != "/") 309 | path += "/"; 310 | } 311 | return path; 312 | } 313 | 314 | void addDNS(string name, string record) 315 | { 316 | dns_map.insert(pair (name, record)); 317 | } 318 | 319 | string getDNS(string name) 320 | { 321 | if (name.empty()) return ""; 322 | // if we are given an IP, just return it 323 | if (pcrecpp::RE("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}").FullMatch(name)) return name; 324 | // return the record from the DNS map 325 | return dns_map[name]; 326 | } 327 | 328 | int registerNetDomain(int domain_id) 329 | { 330 | std::map::iterator it; 331 | 332 | if ((it=netd_map.find(domain_id)) == netd_map.end()) 333 | { 334 | netd_map[domain_id] = ""; 335 | } 336 | return domain_id; 337 | } 338 | 339 | int registerNetDomain(string domain_name) 340 | { 341 | int domain_id = 0; 342 | std::map::iterator it; 343 | 344 | // do we need to set the domain? 345 | domain_id = 1; 346 | for (it=netd_map.begin(); it!=netd_map.end(); it++) 347 | { 348 | if (it->second == domain_name) break; else domain_id++; 349 | } 350 | if (it==netd_map.end()) netd_map[domain_id] = domain_name; 351 | return domain_id; 352 | } 353 | 354 | int getNetDomainId(string domain_name) 355 | { 356 | int domain_id = 1; 357 | std::map::iterator it; 358 | for (it=netd_map.begin(); it!=netd_map.end(); it++) 359 | { 360 | if (it->second == domain_name) return domain_id; else domain_id++; 361 | } 362 | return E_OK; 363 | } 364 | 365 | string execFile(string f) 366 | { 367 | File *fp = shell.back()->pFile(f); 368 | if (fp) 369 | { 370 | if (fp->isExecutable()) 371 | { 372 | return fp->getExec(); 373 | } else { 374 | return "!"; 375 | } 376 | } 377 | return ""; 378 | } 379 | 380 | bool chainVM(string remote, int port, string user = "") 381 | { 382 | string svc_name; 383 | string password; 384 | string host = getDNS(remote); 385 | 386 | if (remote == "0.0.0.0") 387 | { 388 | cout << "no route to host!" << endl; 389 | return false; 390 | } 391 | 392 | for (int i=0; i < vPC.size(); i++) 393 | { 394 | if (vPC[i].getIp() == host && vPC[i].getIp() != "0.0.0.0" && shell.back()->getNetRoute(host)) 395 | { 396 | vector svc = vPC[i].getDaemons(); 397 | for (int ii=0; iiname; 400 | if ( svc_name == "telnet" || svc_name == "telnetd" || svc_name == "ssh" || svc_name == "sshd") 401 | { 402 | if (port == svc[ii]->port) 403 | { 404 | // get usrname 405 | if (user.empty()) 406 | { 407 | cout << "Login:"; 408 | user = tc.getLine(); 409 | } 410 | // get password 411 | cout << "Password:"; 412 | password = tc.getLine(M_PASSWORD); 413 | // try login 414 | shell.push_back(&(vPC[i])); 415 | if (vPC[i].login(user, password)) 416 | { 417 | // add VM to chain 418 | 419 | // make broken user 420 | shell.back()->startBrokenCounter(); 421 | cout << "connected." << endl; 422 | return true; 423 | } else { 424 | shell.pop_back(); 425 | cout << "invalid username or password." << endl; 426 | return false; 427 | } 428 | } else { 429 | sleep(3); 430 | cout << "connection timed out." << endl; 431 | return false; 432 | } 433 | } 434 | } 435 | } 436 | } 437 | cout << remote << ": nodename nor servname provided, or not known." << endl; 438 | return false; 439 | } 440 | 441 | VM* getVM(string hostname) 442 | { 443 | for (int i=0; i < vPC.size(); i++) 444 | { 445 | if (vPC[i].getHostname() == hostname) return &vPC[i]; 446 | } 447 | return NULL; 448 | } 449 | 450 | std::string ab64_encode(char const* bytes_to_encode, unsigned int in_len) 451 | { 452 | // slight base64 varient 453 | static const std::string base64_chars = 454 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 455 | "abcdefghijklmnopqrstuvwxyz" 456 | "0123456789+."; 457 | std::string ret; 458 | int i = 0; 459 | int j = 0; 460 | unsigned char char_array_3[3]; 461 | unsigned char char_array_4[4]; 462 | 463 | while (in_len--) { 464 | char_array_3[i++] = *(bytes_to_encode++); 465 | if (i == 3) { 466 | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; 467 | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); 468 | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); 469 | char_array_4[3] = char_array_3[2] & 0x3f; 470 | 471 | for (i = 0; (i <4) ; i++) 472 | ret += base64_chars[char_array_4[i]]; 473 | i = 0; 474 | } 475 | } 476 | 477 | if (i) 478 | { 479 | for (j = i; j < 3; j++) 480 | char_array_3[j] = '\0'; 481 | 482 | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; 483 | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); 484 | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); 485 | char_array_4[3] = char_array_3[2] & 0x3f; 486 | 487 | for (j = 0; (j < i + 1); j++) 488 | ret += base64_chars[char_array_4[j]]; 489 | 490 | while ((i++ < 3)) 491 | ret += '='; 492 | 493 | } 494 | return ret; 495 | } 496 | 497 | static inline bool is_ab64(unsigned char c) { 498 | return (isalnum(c) || (c == '+') || (c == '.')); 499 | } 500 | 501 | std::string ab64_decode(std::string const& encoded_string) 502 | { 503 | static const std::string base64_chars = 504 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 505 | "abcdefghijklmnopqrstuvwxyz" 506 | "0123456789+."; 507 | int in_len = encoded_string.size(); 508 | int i = 0; 509 | int j = 0; 510 | int in_ = 0; 511 | unsigned char char_array_4[4], char_array_3[3]; 512 | std::string ret; 513 | 514 | while (in_len-- && ( encoded_string[in_] != '=') && is_ab64(encoded_string[in_])) 515 | { 516 | char_array_4[i++] = encoded_string[in_]; in_++; 517 | if (i ==4) 518 | { 519 | for (i = 0; i <4; i++) 520 | char_array_4[i] = base64_chars.find(char_array_4[i]); 521 | char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); 522 | char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); 523 | char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; 524 | for (i = 0; (i < 3); i++) 525 | ret += char_array_3[i]; 526 | i = 0; 527 | } 528 | } 529 | 530 | if (i) 531 | { 532 | for (j = i; j <4; j++) 533 | char_array_4[j] = 0; 534 | 535 | for (j = 0; j <4; j++) 536 | char_array_4[j] = base64_chars.find(char_array_4[j]); 537 | 538 | char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); 539 | char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); 540 | char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; 541 | 542 | for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; 543 | } 544 | return ret; 545 | } 546 | 547 | string vhash(string input) 548 | { 549 | string hash; 550 | char t[] = { 'x', 'a', 'r', 'b', 'p', 'w', 'm', 'l', 'f', 'j', 'v', 'd', 'q', 'k', 'z', 'h' }; 551 | int len = 15; 552 | 553 | for (int i=0; i1) && (i%2 == 0)) 562 | { 563 | t[n] = t[n] & t[n-1]; 564 | } else { 565 | t[n] = t[n] ^ input.at(i); 566 | } 567 | } 568 | } 569 | for (int n=0; n store; 578 | explode(s, "/", store); 579 | string path = "/"; 580 | File *fp; 581 | 582 | for (int i=0; ipFile(path); 588 | if (!fp) 589 | { 590 | // file doesn't exist! 591 | return E_NO_FILE; 592 | } 593 | if (!fp->isReadable()) 594 | { 595 | // no permission to access 596 | return E_DENIED; 597 | } 598 | if (fp->getType() == T_FOLDER) 599 | { 600 | path += "/"; 601 | } 602 | } 603 | return E_OK; 604 | } 605 | 606 | // *********** built-in commands ************** // 607 | 608 | int cmd_cat(vector args) 609 | { 610 | string f; 611 | int ret =0; 612 | File *fp; 613 | for (int i=1; ipFile(f); 618 | if (!fp) { 619 | cout << "cat: " << args[i] << ": No such file or directory." << endl; 620 | ret = 1; 621 | } else { 622 | if (can_access(f) == E_OK) 623 | { 624 | cout << fp->getContent(); 625 | } else { 626 | cout << "-sh: cat: " << args[i] << ": Permission denied." << endl; 627 | ret = 1; 628 | } 629 | } 630 | } 631 | return ret; 632 | } 633 | 634 | int cmd_cd(vector args) 635 | { 636 | string path; 637 | 638 | if (args.size() < 2) 639 | { 640 | // if no args, set to home 641 | path = "/home/"; 642 | return 1; 643 | } else { 644 | path = args[1]; 645 | path = realpath(path); 646 | } 647 | 648 | // try to change dir 649 | int status = shell.back()->setCwd(path); 650 | switch (status) 651 | { 652 | case E_NO_FILE: 653 | cout << "-sh: cd: " << args[1] << ": No such directory." << endl; 654 | return 1; 655 | break; 656 | case E_DENIED: 657 | cout << "-sh: cd: " << args[1] << ": Permission denied." << endl; 658 | return 1; 659 | break; 660 | } 661 | // dir changed 662 | return E_OK; 663 | } 664 | 665 | int cmd_clear() 666 | { 667 | // we're going to cheat here. this should probably be re-made properly at some point 668 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 669 | system("cls"); 670 | #else 671 | system("clear"); 672 | #endif 673 | return E_OK; 674 | } 675 | 676 | int cmd_date(vector &args) 677 | { 678 | // current date/time based on current system 679 | time_t now = time(0); 680 | if (args.size() > 1 && args[1] == "+%s") 681 | { 682 | cout << now << endl; 683 | } else { 684 | // convert now to string form 685 | char* dt = ctime(&now); 686 | cout << dt; 687 | } 688 | return E_OK; 689 | } 690 | 691 | int cmd_echo(vector &args) 692 | { 693 | args.erase(args.begin()); 694 | if (args.size() == 0) 695 | { 696 | cout << endl; 697 | return E_OK; 698 | } 699 | for (int i=0; ilogout() < 1 ) 730 | { 731 | // leave VM 732 | if (shell.size() > 1) 733 | { 734 | shell.pop_back(); 735 | cout << "connection closed." << endl; 736 | } else { 737 | // if no VMs in shell chain, ask for init login again 738 | for (;;) 739 | { 740 | string user; 741 | string password; 742 | 743 | cout << endl; 744 | if (shell.back()->getUserCount()>0) break; 745 | cout << "Login: "; 746 | user = tc.getLine(); 747 | cout << "Password: "; 748 | password = tc.getLine(M_PASSWORD); 749 | if (shell.back()->login(user, password)) 750 | { 751 | break; 752 | } 753 | } 754 | } 755 | } else { 756 | cout << "logout." << endl; 757 | } 758 | return E_OK; 759 | } 760 | 761 | int cmd_quit() 762 | { 763 | cout << "Are you sure you want to quit the game? (y/N) "; 764 | string quit_game = tc.getLine(); 765 | if (quit_game == "y" || quit_game == "Y") 766 | { 767 | cout << "[Thanks for playing! Come back soon!]"; 768 | tc.quit(); 769 | } 770 | return E_OK; 771 | } 772 | 773 | int cmd_help() 774 | { 775 | cout << "Currently supported built-in commands:\n cat\n cd\n clear\n date\n echo\n exit\n help\n hint\n hostname\n id\n ifconfig\n load\n ls\n lspci\n mail\n ping\n pwd\n quit\n rm\n save\n su\n telnet\n uname\n whoami" << endl; 776 | return E_OK; 777 | } 778 | 779 | int cmd_hint() 780 | { 781 | if (!shell.back()->getHint().empty()) 782 | { 783 | cout << shell.back()->getHint() << endl; 784 | } else { 785 | cout << "Sorry, no hints are available for this VM." << endl; 786 | } 787 | return E_OK; 788 | } 789 | 790 | int cmd_hashcat(vector args) 791 | { 792 | // interruptable threads set error exits at the head 793 | cEC = 1; 794 | 795 | string plain; 796 | cout << "Initializing hashcat-micro (for virtual PCs)..." << endl; 797 | if (args.size() != 2 || args[1] == "-h") 798 | { 799 | cout << "usage: " << args[0] << " hash" << endl; 800 | cout << " Please note: hashcat-micro does not support hashfiles at this time." << endl; 801 | return cEC; 802 | } 803 | cout << "Added 1 hash" << endl << "Activating quick-digest mode for single-hash" << endl; 804 | cout << endl << "Running." << flush; 805 | // find plain in rainbow table 806 | for (int i=0; igetCPower()); 824 | } else { 825 | cracktime = 32; 826 | } 827 | 828 | for (int i=0; igetHostname() << endl; 851 | return E_OK; 852 | } 853 | 854 | int cmd_id(vector args) 855 | { 856 | string username; 857 | if (args.size() < 2) 858 | { 859 | username = shell.back()->getUsername(); 860 | } else { 861 | username = args[1]; 862 | } 863 | 864 | int cEC = E_OK; 865 | User* usr; 866 | usr = shell.back()->getUser(username); 867 | if (!usr) 868 | { 869 | cout << "id: " << username <<": no such user" << endl; 870 | return 1; 871 | } else { 872 | cout << "uid=" << username << endl; 873 | } 874 | return cEC; 875 | } 876 | 877 | int cmd_ifconfig() 878 | { 879 | if (shell.back()->getIp() == "0.0.0.0") return 1; 880 | cout << "en0 UP BROADCAST SMART SIMPLEX MULTICAST MTU 1500 Metric 0" << endl; 881 | cout << " inet addr " << shell.back()->getIp() << endl; 882 | cout << " media autoselect" << endl; 883 | return E_OK; 884 | } 885 | 886 | int cmd_ls(vector args) 887 | { 888 | string cmd; 889 | string n (shell.back()->getCwd()); // set name to cwd 890 | string op; 891 | string owners; 892 | bool longlist = false; 893 | File *fp, *fp2; 894 | 895 | // parse arguments. first non option is target 896 | for (int i=1; i store; 919 | explode(n, "/", store); 920 | string path = "/"; 921 | 922 | for (int i=0; ipFile(path + store[i]); 926 | if (!fp) 927 | { 928 | cout << "ls: " << cmd << ": No such file or directory." << endl; 929 | return 1; 930 | } 931 | if (fp->getType() == T_FOLDER) 932 | { 933 | path += store[i] + "/"; 934 | } 935 | 936 | fp2 = shell.back()->pFile(path); 937 | if (!fp->isReadable() || !fp2->isReadable()) 938 | { 939 | cout << "ls: " << cmd << ": permission denied." << endl; 940 | return 1; 941 | } 942 | } 943 | 944 | // get pointer to target 945 | fp = shell.back()->pFile(n); 946 | // get list of files 947 | vector files = shell.back()->getFiles(n); 948 | 949 | // sort files 950 | sort(files.begin(), files.end()); 951 | // loop through files 952 | for (int i=0; i < files.size(); i++) 953 | { 954 | if (longlist) 955 | { 956 | fp = shell.back()->pFile(path + files[i]); 957 | if (fp->getType() == T_FOLDER) 958 | { 959 | files[i] = files[i].substr(0, files[i].length()-1); 960 | } 961 | owners = " " + fp->getOwner() + " " + fp->getOwner(); 962 | cout << fp->drawAcl() << left << setw(20) << owners << files[i] << endl; 963 | } else { 964 | cout << files[i] << endl; 965 | } 966 | } 967 | 968 | return E_OK; 969 | } 970 | 971 | int cmd_lspci() 972 | { 973 | cout << "00:00.0 Host bridge: 82443BX/ZX" << endl; 974 | cout << "00:0f.0 VGA compatible controller (rev 01)" << endl; 975 | cout << "00:10.0 Storage controller: AB Logic / Fusion-X UltraStorage (rev 01)" << endl; 976 | cout << "00:20.0 Ethernet controller: FastNet Gigabit Ethernet Controller (rev 01)" << endl; 977 | vector gpus = shell.back()->getGPUs(); 978 | for (int i=0; igetUser(shell.back()->getUsername()); 989 | if ( up->inboxSize() ) 990 | { 991 | cout << "Mail version 3.2 6/6/91. Type h for help." << endl; 992 | string cmd = "f"; 993 | string buffer; 994 | vector args; 995 | Mail *m; 996 | while (cmd != "q" && cmd != "quit") 997 | { 998 | if (cmd == "f") { 999 | for (int i=0; iinboxSize(); i++) 1000 | { 1001 | m = up->getMail(i+1); 1002 | cout << " N " << setw(3) << i+1 << " " << m->from() << " " << m->subject() << endl; 1003 | } 1004 | } 1005 | else if (cmd == "h" || cmd == "help") 1006 | { 1007 | cout << " Mail Commands\nh help\nt type messages\nf give head lines of messages\nq quit\n\nA consists of integers, separated by spaces. If omitted, Mail uses the last message typed." << endl; 1008 | } 1009 | else if (cmd == "t") 1010 | { 1011 | if (args.size()>1) 1012 | { 1013 | for (int i=1; i< args.size(); i++) 1014 | { 1015 | m = up->getMail(atoi(args[i].c_str())); 1016 | if (m) 1017 | { 1018 | cout << "Message " << args[i] << ":" << endl; 1019 | cout << "From: " << m->from() << endl; 1020 | cout << "To: " << m->to() << endl; 1021 | cout << "Subject: " << m->subject() << endl; 1022 | cout << endl << m->body() << endl; 1023 | } 1024 | } 1025 | } 1026 | } 1027 | cout << "? "; 1028 | buffer = tc.getLine(); 1029 | explode(buffer, " ", args); 1030 | cmd = !args.empty() ? args[0] : buffer; 1031 | if (args.empty() && pcrecpp::RE("[0-9]*").FullMatch(cmd)) 1032 | { 1033 | args.push_back("t"); 1034 | args.push_back(cmd); 1035 | cmd = "t"; 1036 | } 1037 | } 1038 | } else { 1039 | cout << "No mail for " << up->getName() << "." << endl; 1040 | } 1041 | return E_OK; 1042 | } 1043 | 1044 | /* 1045 | int cmd_nmap(vector args) 1046 | { 1047 | time_t now = time(0); 1048 | // convert now to string form 1049 | char* dt = ctime(&now); 1050 | // banner 1051 | cout << "Starting Nmap-micro 1.01 ( for virtual PCs ) at " << dt << endl; 1052 | return E_OK; 1053 | } 1054 | */ 1055 | 1056 | int cmd_ping(vector args) 1057 | { 1058 | // interruptable threads set error exits at the head 1059 | cEC = 1; 1060 | 1061 | if (args.size() < 2) 1062 | { 1063 | cout << "usage: " << args[0] << " hostname" << endl; 1064 | return cEC; 1065 | } 1066 | string host = args[1]; 1067 | 1068 | // start info line 1069 | cout << "Sending 5, 100-byte ICMP Echos to " << host; 1070 | 1071 | // loop through vPCs 1072 | for (int i=0; igetNetRoute(host)) 1080 | { 1081 | // close info line 1082 | cout << ":" << endl; 1083 | cout << "!!!!!" << endl << "Success rate is 100 percent (5/5)" << endl; 1084 | cEC = E_OK; 1085 | return E_OK; 1086 | } 1087 | } 1088 | 1089 | // close info line 1090 | cout << ":" << endl; 1091 | 1092 | // timeout output 1093 | for (int i=0; i<5; i++) 1094 | { 1095 | cout << "." << flush; 1096 | boost::this_thread::sleep(boost::posix_time::seconds(1)); 1097 | } 1098 | cout << endl << "Success rate is 0 percent (0/5)" << endl; 1099 | return cEC; 1100 | } 1101 | 1102 | int cmd_portscan(vector args) 1103 | { 1104 | if ((args.size() != 2 && args.size() != 3) || args[1] == "-h") 1105 | { 1106 | cout << "usage: " << args[0] << " [options] hostname" << endl; 1107 | cout << " -h Display Help info" << endl; 1108 | cout << " -N Perform scan of network to find all live hosts" << endl; 1109 | return 1; 1110 | } 1111 | cout << "Stealth Port Scanner by o3u" << endl; 1112 | 1113 | if (args[1] == "-N") 1114 | { 1115 | cout << "Scanning network for live hosts..." << endl; 1116 | cout << "--------------------" << endl; 1117 | for (int i=0; igetNetRoute(vPC[i].getIp())) 1120 | { 1121 | sleep(2); 1122 | cout << "HOST ALIVE: " << vPC[i].getIp() << endl; 1123 | } 1124 | } 1125 | return E_OK; 1126 | } else { 1127 | string host = getDNS(args[1]); 1128 | // loop through vPCs 1129 | for (int i=0; igetNetRoute(host)) 1132 | { 1133 | cout << "Scanning " << host << "..." << endl; 1134 | sleep(3); 1135 | cout << "--------------------" << endl; 1136 | vector ports = vPC[i].getDaemons(); 1137 | for (int n=0; nport << ": CONNECT" <query.empty()) 1141 | { 1142 | cout << ports[n]->query << endl; 1143 | } 1144 | cout << "END PORT INFO" << endl << endl; 1145 | } 1146 | return E_OK; 1147 | } 1148 | } 1149 | sleep(3); 1150 | cout << "Unable to connect to remote host: Attempt to connect timed-out without" << endl << 1151 | "establishing a connection." << endl; 1152 | return 1; 1153 | } 1154 | } 1155 | 1156 | int cmd_pwd(vector args) 1157 | { 1158 | cout << shell.back()->getCwd() << endl; 1159 | return 1; 1160 | } 1161 | 1162 | int cmd_rm(vector args) 1163 | { 1164 | vector target; 1165 | File *fp; 1166 | string path; 1167 | 1168 | for (int i=1; ipFile(path); 1188 | if (!fp) 1189 | { 1190 | cout << "rm: " << target[i] << ": No such file." << endl; 1191 | return 1; 1192 | } 1193 | if (fp->getType() == T_FOLDER) 1194 | { 1195 | cout << "rm: " << target[i] << ": Unable to remove folders." << endl; 1196 | return 1; 1197 | } 1198 | if (!fp->isWritable()) 1199 | { 1200 | cout << "rm: " << target[i] << ": Permission denied." << endl; 1201 | return 1; 1202 | } 1203 | shell.back()->deleteFile(path); 1204 | }; 1205 | } 1206 | return E_OK; 1207 | } 1208 | 1209 | int cmd_su(vector args) 1210 | { 1211 | string user = "root"; 1212 | if (args.size()>1) { 1213 | user = args.back(); 1214 | } 1215 | if (shell.back()->getUsername() == "root") 1216 | { 1217 | if (shell.back()->login(user)) 1218 | { 1219 | return E_OK; 1220 | } else { 1221 | cout << "su: Sorry." << endl; 1222 | return 1; 1223 | } 1224 | } 1225 | cout << "Password:"; 1226 | string password = tc.getLine(M_PASSWORD); 1227 | if (shell.back()->login(user, password)) 1228 | { 1229 | return E_OK; 1230 | } else { 1231 | cout << endl << "su: Sorry." << endl; 1232 | return 1; 1233 | } 1234 | } 1235 | 1236 | int cmd_telnet(vector args) 1237 | { 1238 | if (args.size()<2 || args.size()>3) 1239 | { 1240 | cout << "usage: telnet host-name [port]" << endl; 1241 | return 1; 1242 | } 1243 | string remote = args[1]; 1244 | int port = 23; 1245 | if (args.size() == 3) 1246 | { 1247 | port = atoi(args[2].c_str()); 1248 | } 1249 | 1250 | if (chainVM (remote, port)) return E_OK; 1251 | return 1; 1252 | } 1253 | 1254 | int cmd_uname() 1255 | { 1256 | cout << shell.back()->getUname() << endl; 1257 | return E_OK; 1258 | } 1259 | 1260 | int cmd_whoami() 1261 | { 1262 | cout << shell.back()->getUsername() << endl; 1263 | return E_OK; 1264 | } 1265 | 1266 | // debug commands 1267 | void debug_globals() 1268 | { 1269 | string key; 1270 | int type; 1271 | 1272 | cout << "[DBG] Lua Globals:" << endl; 1273 | // let's get our globals 1274 | lua_pushglobaltable(lua); 1275 | lua_pushnil(lua); 1276 | while (lua_next(lua, -2) != 0) 1277 | { 1278 | key = lua_tostring(lua, -2); 1279 | type = lua_type(lua, -1); 1280 | 1281 | // skip reserved keys 1282 | if (!key.empty() && key.substr(0,1)=="_") 1283 | { 1284 | lua_pop(lua,1); 1285 | continue; 1286 | } 1287 | 1288 | if (type == LUA_TBOOLEAN) 1289 | { 1290 | bool b = lua_toboolean(lua, -1); 1291 | cout << key << " = "; 1292 | //_lua_data.append(key).append(" = "); 1293 | if (b) 1294 | { 1295 | cout << "true"; 1296 | //_lua_data.append("true"); 1297 | } else { 1298 | cout << "false"; 1299 | //_lua_data.append("false"); 1300 | } 1301 | cout << endl; 1302 | //_lua_data.append("\n"); 1303 | } 1304 | else if (type == LUA_TNUMBER) 1305 | { 1306 | ostringstream num; 1307 | num << lua_tonumber(lua, -1); 1308 | //_lua_data.append(key).append(" = ").append(num.str()); 1309 | //_lua_data.append(lua_tonumber(lua, -1)); 1310 | cout << key << " = "; 1311 | cout << lua_tonumber(lua, -1) << endl; 1312 | //_lua_data.append("\n"); 1313 | } 1314 | else if (type == LUA_TSTRING) 1315 | { 1316 | string s = lua_tostring(lua, -1); 1317 | // let's sanitize s! 1318 | pcrecpp::RE("\"").GlobalReplace("\\\\\"", &s); 1319 | //_lua_data.append(key).append(" = \"").append(s).append("\"");; 1320 | //_lua_data.append("\n"); 1321 | cout << key << "= \"" << s << "\"" << endl; 1322 | } 1323 | lua_pop(lua, 1); 1324 | } 1325 | lua_pop(lua,1); 1326 | } 1327 | 1328 | // more funcs 1329 | void lua_runp() 1330 | { 1331 | // call function 1332 | lua_pcall(lua, 1, 0, 0); 1333 | // TODO add threading here 1334 | } 1335 | 1336 | // trigger for tinyConcole 1337 | int tcon::trigger(string cmd) 1338 | { 1339 | bool run_debug = false; 1340 | // initialize vector for command parsing 1341 | vector args; 1342 | 1343 | // clean multi-whitespace 1344 | pcrecpp::RE("\\s{2,}").GlobalReplace(" ", &cmd); 1345 | 1346 | // parse args 1347 | if (explode(cmd.c_str()," ",args) != string::npos) 1348 | { 1349 | // if multiple args, assign first to cmd 1350 | cmd = args[0]; 1351 | } else { 1352 | args.push_back(cmd); 1353 | } 1354 | 1355 | // clean empty arg 1356 | if (args.size() == 2 && args[1].empty()) 1357 | { 1358 | args.pop_back(); 1359 | } 1360 | 1361 | if (cmd == "") 1362 | { 1363 | return E_OK; 1364 | } 1365 | 1366 | if (debug_on) 1367 | { 1368 | // loop through debug commands first 1369 | if (cmd == "globals") 1370 | { 1371 | debug_globals(); 1372 | run_debug = true; 1373 | } 1374 | } 1375 | 1376 | if (!run_debug) 1377 | { 1378 | // loop through commands 1379 | if (cmd == "exit") 1380 | { 1381 | cEC = cmd_exit(); 1382 | } 1383 | else if (cmd == "cat") 1384 | { 1385 | cEC = cmd_cat(args); 1386 | } 1387 | else if (cmd == "cd") 1388 | { 1389 | cEC = cmd_cd(args); 1390 | } 1391 | else if (cmd == "clear") 1392 | { 1393 | cEC = cmd_clear(); 1394 | } 1395 | else if (cmd == "date") 1396 | { 1397 | cEC = cmd_date(args); 1398 | } 1399 | else if (cmd == "dump") 1400 | { 1401 | lua_vdump(args); 1402 | cEC = E_OK; 1403 | } 1404 | else if (cmd == "echo") 1405 | { 1406 | cEC = cmd_echo(args); 1407 | } 1408 | else if (cmd == "help") 1409 | { 1410 | cEC = cmd_help(); 1411 | } 1412 | else if (cmd == "hint") 1413 | { 1414 | cEC = cmd_hint(); 1415 | } 1416 | else if (cmd == "hostname") 1417 | { 1418 | cEC = cmd_hostname(); 1419 | } 1420 | else if (cmd == "id") 1421 | { 1422 | cEC = cmd_id(args); 1423 | } 1424 | else if (cmd == "ifconfig") 1425 | { 1426 | cEC = cmd_ifconfig(); 1427 | } 1428 | else if (cmd == "load") 1429 | { 1430 | lua_restore(args); 1431 | cEC = E_OK; 1432 | } 1433 | else if (cmd == "ll") 1434 | { 1435 | args[0] = "ls"; 1436 | args.insert(args.begin()+1, "-l"); 1437 | cEC = cmd_ls(args); 1438 | } 1439 | else if (cmd == "ls") 1440 | { 1441 | cEC = cmd_ls(args); 1442 | } 1443 | else if (cmd == "lspci") 1444 | { 1445 | cEC = cmd_lspci(); 1446 | } 1447 | else if (cmd == "mail") 1448 | { 1449 | cEC = cmd_mail(); 1450 | } 1451 | else if (cmd == "ping") 1452 | { 1453 | //cEC = cmd_ping(args); 1454 | // let's run the ping command in a thread 1455 | boost::thread t(cmd_ping, args); 1456 | cmd_thread =& t; 1457 | t.join(); 1458 | } 1459 | else if (cmd == "pwd") 1460 | { 1461 | cEC = cmd_pwd(args); 1462 | } 1463 | else if (cmd == "quit") 1464 | { 1465 | cEC = cmd_quit(); 1466 | } 1467 | else if (cmd == "rm") 1468 | { 1469 | cEC = cmd_rm(args); 1470 | } 1471 | else if (cmd == "save") 1472 | { 1473 | lua_save(args); 1474 | cEC = E_OK; 1475 | } 1476 | else if (cmd == "su") 1477 | { 1478 | cEC = cmd_su(args); 1479 | } 1480 | else if (cmd == "telnet") 1481 | { 1482 | cEC = cmd_telnet(args); 1483 | } 1484 | else if (cmd == "uname") 1485 | { 1486 | cEC = cmd_uname(); 1487 | } 1488 | else if (cmd == "whoami") 1489 | { 1490 | cEC = cmd_whoami(); 1491 | } 1492 | else 1493 | { 1494 | string bin = execFile(realpath(cmd)); 1495 | if (bin.empty() && cmd.find("/") == -1) 1496 | { 1497 | bin = execFile(realpath("/bin/"+cmd)); 1498 | } 1499 | if (!bin.empty()) 1500 | { 1501 | if (bin == "!") 1502 | { 1503 | cout << "-sh: " << cmd << ": not executable." << endl; 1504 | } else { 1505 | if (bin == "p_hashcat") 1506 | { 1507 | boost::thread t(cmd_hashcat, args); 1508 | cmd_thread =& t; 1509 | t.join(); 1510 | } 1511 | /* 1512 | else if (bin == "p_nmap") 1513 | { 1514 | cEC = cmd_nmap(args); 1515 | } 1516 | */ 1517 | else if (bin == "p_portscan") 1518 | { 1519 | cEC = cmd_portscan(args); 1520 | } 1521 | else if (bin == "p_pwd") 1522 | { 1523 | cEC = cmd_pwd(args); 1524 | } else { 1525 | // push function to stack 1526 | lua_getglobal(lua, bin.c_str()); 1527 | // create arg table 1528 | lua_newtable(lua); 1529 | // push cmd name 1530 | lua_pushnumber(lua, 1); 1531 | lua_pushstring(lua, realpath(args[0]).c_str()); 1532 | lua_settable(lua, -3); 1533 | // push args 1534 | for (int i=1; iaddFile(f)) 1590 | { 1591 | cout << "Unable to add '" << name << "'" << endl; 1592 | return (ERR_BAD_SET); 1593 | } 1594 | return E_OK; 1595 | } 1596 | 1597 | int addDir(lua_State *lua) 1598 | { 1599 | string acl; 1600 | string name; 1601 | string key; 1602 | string value; 1603 | 1604 | // number of input arguments 1605 | int argc = lua_gettop(lua); 1606 | 1607 | // make sure argument passed is a table 1608 | int idx = lua_gettop(lua); 1609 | if (!lua_istable(lua, idx)) 1610 | { 1611 | cout << "Error! Invalid call to addDir." << endl; 1612 | exit (ERR_BAD_SET); 1613 | } 1614 | lua_pushnil(lua); // first key 1615 | while (lua_next(lua, -2) != 0 ) 1616 | { 1617 | key = lua_tostring(lua, -2); 1618 | value = lua_tostring(lua, -1); 1619 | 1620 | // check keys 1621 | if (key == "acl") 1622 | { 1623 | acl = value; 1624 | } 1625 | else if (key == "name") 1626 | { 1627 | name = value; 1628 | } 1629 | lua_pop(lua, 1); 1630 | } 1631 | 1632 | // make sure there is a name set 1633 | if (name.empty()) 1634 | { 1635 | cout << "Error! No filename specified to addDir." << endl; 1636 | exit (ERR_BAD_SET); 1637 | } 1638 | 1639 | // create the file 1640 | File f (File(name, T_FOLDER, "", "")); 1641 | 1642 | // set ACLs, if given 1643 | if (!acl.empty()) 1644 | { 1645 | f.setAcl(acl); 1646 | } 1647 | 1648 | // push file to chain 1649 | vPC.back().addFile(f); 1650 | 1651 | //cout << "[Lua] Add directory: " << name << endl; 1652 | return E_OK; 1653 | } 1654 | 1655 | int addFile(string name) 1656 | { 1657 | // make sure there is a name set 1658 | if (name.empty()) 1659 | { 1660 | cout << "Error! No filename specified to addFile." << endl; 1661 | exit (ERR_BAD_SET); 1662 | } 1663 | // create the file 1664 | File f (File(name, T_FILE, "", "")); 1665 | vPC.back().addFile(f); 1666 | 1667 | return E_OK; 1668 | } 1669 | 1670 | int addFile(lua_State *lua) 1671 | { 1672 | string acl; 1673 | string key; 1674 | string value; 1675 | string name; 1676 | string content; 1677 | string exec; 1678 | string on_delete; 1679 | string owner; 1680 | string host; 1681 | bool suid (false); 1682 | 1683 | // number of input arguments 1684 | int argc = lua_gettop(lua); 1685 | 1686 | // make sure argument passed is a table 1687 | if (!lua_istable(lua, argc)) 1688 | { 1689 | cout << "Error! Invalid call to addFile." << endl; 1690 | exit (ERR_BAD_SET); 1691 | } 1692 | lua_pushnil(lua); // first key 1693 | while (lua_next(lua, -2) != 0 ) 1694 | { 1695 | key = lua_tostring(lua, -2); 1696 | value = lua_tostring(lua, -1); 1697 | 1698 | // check keys 1699 | if (key == "acl") 1700 | { 1701 | acl = value; 1702 | } 1703 | else if (key == "name") 1704 | { 1705 | name = value; 1706 | } 1707 | else if (key == "content") 1708 | { 1709 | content = value; 1710 | } 1711 | else if (key == "exec") 1712 | { 1713 | exec = value; 1714 | } 1715 | else if (key == "on_delete") 1716 | { 1717 | on_delete = value; 1718 | } 1719 | else if (key == "owner") 1720 | { 1721 | owner = value; 1722 | } 1723 | else if (key == "host") 1724 | { 1725 | host = value; 1726 | } 1727 | else if (key == "suid") 1728 | { 1729 | if ( value == "true" ) 1730 | { 1731 | suid = true; 1732 | } 1733 | } 1734 | 1735 | lua_pop(lua, 1); 1736 | } 1737 | 1738 | // make sure there is a name set 1739 | if (name.empty()) 1740 | { 1741 | cout << "Error! No filename specified to addFile." << endl; 1742 | exit (ERR_BAD_SET); 1743 | } 1744 | 1745 | // create the file 1746 | File f (File(name, T_FILE, content, exec)); 1747 | 1748 | // set ACLs, if given 1749 | if (!acl.empty()) 1750 | { 1751 | f.setAcl(acl); 1752 | } 1753 | 1754 | // set owner if given 1755 | if (!owner.empty()) 1756 | { 1757 | f.setOwner(owner); 1758 | } 1759 | 1760 | // set on_delete if given 1761 | if (!on_delete.empty()) 1762 | { 1763 | f.setOnDelete(on_delete); 1764 | } 1765 | 1766 | // set suid if given 1767 | if ( suid ) 1768 | { 1769 | f.setSUID(true); 1770 | } 1771 | 1772 | // find VM to add file to 1773 | VM *vm; 1774 | if (!host.empty()) 1775 | { 1776 | for (int i=0; iFSgetFree()) 1799 | { 1800 | cout << "Error! Filesystem is full! Unable to add file: " << f.getName() << endl; 1801 | exit (ERR_BAD_SET); 1802 | } 1803 | if (!vm->addFile(f)) 1804 | { 1805 | cout << "Error! Illegal filename: " << f.getName() << endl; 1806 | exit (ERR_BAD_SET); 1807 | } 1808 | return E_OK; 1809 | } 1810 | 1811 | int addGPU(lua_State *lua) 1812 | { 1813 | string desc; 1814 | int power; 1815 | 1816 | power = lua_tonumber(lua, lua_gettop(lua)); 1817 | lua_pop(lua, 1); 1818 | desc = lua_tostring(lua, lua_gettop(lua)); 1819 | lua_pop(lua, 1); 1820 | 1821 | if (power < 1) power = 1; 1822 | vPC.back().addGPU(desc, power); 1823 | return E_OK; 1824 | } 1825 | 1826 | int addUser(lua_State *lua) 1827 | { 1828 | string user; 1829 | string password; 1830 | 1831 | // number of input arguments 1832 | int argc = lua_gettop(lua); 1833 | if (argc < 1 || 2 < argc) 1834 | { 1835 | cout << "Error! Invalid call to addUser." << endl; 1836 | exit (ERR_BAD_SET); 1837 | } 1838 | 1839 | VM* avm; // active VM 1840 | avm = NULL; 1841 | 1842 | if (argc == 1) 1843 | { 1844 | int idx = lua_gettop(lua); 1845 | if (!lua_istable(lua, idx)) 1846 | { 1847 | cout << "Error! Invalid call to addUser." << endl; 1848 | exit (ERR_BAD_SET); 1849 | } 1850 | 1851 | lua_pushnil(lua); // first key 1852 | while (lua_next(lua, -2) != 0 ) 1853 | { 1854 | string key = lua_tostring(lua, -2); 1855 | string value = lua_tostring(lua, -1); 1856 | 1857 | if (key == "host") 1858 | { 1859 | avm = getVM(value); 1860 | } 1861 | if (key == "user") 1862 | { 1863 | user = value; 1864 | } 1865 | if (key == "password") 1866 | { 1867 | password = value; 1868 | } 1869 | 1870 | lua_pop(lua, 1); 1871 | } 1872 | } else { 1873 | password = lua_tostring(lua, lua_gettop(lua)); 1874 | lua_pop(lua, 1); 1875 | user = lua_tostring(lua, lua_gettop(lua)); 1876 | lua_pop(lua, 1); 1877 | } 1878 | 1879 | if (user.empty()) 1880 | { 1881 | cout << "Error! Invalid call to addUser." << endl; 1882 | exit (ERR_BAD_SET); 1883 | } 1884 | 1885 | if (!avm) 1886 | { 1887 | avm = &(vPC.back()); 1888 | } 1889 | 1890 | if (!avm->addUser(User(user, password))) 1891 | { 1892 | cout << "Fatal error adding user." << endl; 1893 | exit (ERR_BAD_SET); 1894 | } 1895 | if (user != "root") 1896 | { 1897 | addDir("/home/"+user+"/", "770", user, avm->getHostname()); 1898 | } 1899 | return E_OK; 1900 | } 1901 | 1902 | int readfile (lua_State *lua) 1903 | { 1904 | string filename; 1905 | // number of input arguments 1906 | int argc = lua_gettop(lua); 1907 | 1908 | if (argc > 1) 1909 | { 1910 | cout << "Error! Invalid call to readfile." << endl; 1911 | exit (ERR_BAD_SET); 1912 | } 1913 | filename = lua_tostring (lua, lua_gettop(lua)); 1914 | lua_pop (lua, 1); 1915 | File *fp = shell.back()->pFile(filename); 1916 | if (!fp) 1917 | { 1918 | lua_pushnil(lua); 1919 | } else { 1920 | vector content; 1921 | explode(fp->getContent(),"\n", content); 1922 | 1923 | // create arg table 1924 | lua_newtable(lua); 1925 | // push cmd name 1926 | for (int i=0; igetUser(t); 2041 | if (!up) return false; 2042 | up->addMail(Mail(t, s, f, b)); 2043 | return true; 2044 | } 2045 | 2046 | int sendMail(lua_State *lua) 2047 | { 2048 | string key; 2049 | string value; 2050 | string t, f, s, b; 2051 | string host; 2052 | // number of input arguments 2053 | int argc = lua_gettop(lua); 2054 | 2055 | // make sure argument passed is a table 2056 | int idx = lua_gettop(lua); 2057 | if (!lua_istable(lua, idx)) 2058 | { 2059 | cout << "Error! Invalid call to sendMail." << endl; 2060 | exit (ERR_BAD_SET); 2061 | } 2062 | lua_pushnil(lua); // first key 2063 | while (lua_next(lua, -2) != 0 ) 2064 | { 2065 | key = lua_tostring(lua, -2); 2066 | value = lua_tostring(lua, -1); 2067 | 2068 | // check keys 2069 | if (key == "to") 2070 | { 2071 | int at = value.find("@"); 2072 | if (at != string::npos) 2073 | { 2074 | t = value.substr(0,at); 2075 | host = value.substr(at+1); 2076 | } else { 2077 | t = value; 2078 | } 2079 | } 2080 | else if (key == "from") 2081 | { 2082 | f = value; 2083 | } 2084 | else if (key == "subject") 2085 | { 2086 | s = value; 2087 | } 2088 | else if (key == "body") 2089 | { 2090 | b = value; 2091 | } 2092 | 2093 | lua_pop(lua, 1); 2094 | } 2095 | 2096 | if (t.empty() || f.empty() || s.empty() || b.empty()) 2097 | { 2098 | cout << "Error! Invalid call to sendMail." << endl; 2099 | exit (ERR_BAD_SET); 2100 | } 2101 | 2102 | User *up; 2103 | if (!host.empty()) 2104 | { 2105 | for (int i=0; igetUser(t); 2116 | } else { 2117 | up = vPC.back().getUser(t); 2118 | } 2119 | } 2120 | if (!up) 2121 | { 2122 | cout << "No such user" << endl; 2123 | return 1; 2124 | } 2125 | up->addMail(Mail(t, s, f, b)); 2126 | return E_OK; 2127 | } 2128 | 2129 | int lua_addDNS(lua_State *lua) 2130 | { 2131 | string name = lua_tostring(lua, lua_gettop(lua)); 2132 | lua_pop(lua, 1); 2133 | string record = lua_tostring(lua, lua_gettop(lua)); 2134 | lua_pop(lua, 1); 2135 | addDNS(name, record); 2136 | return E_OK; 2137 | } 2138 | 2139 | int lua_getDNS(lua_State *lua) 2140 | { 2141 | string name = lua_tostring(lua, lua_gettop(lua)); 2142 | lua_pop(lua, 1); 2143 | string record = getDNS(name); 2144 | lua_pushstring(lua, record.c_str()); 2145 | return E_OK; 2146 | } 2147 | 2148 | int lua_hashString(lua_State *lua) 2149 | { 2150 | string plain = lua_tostring(lua, lua_gettop(lua)); 2151 | lua_pop(lua, 1); 2152 | string hash = vhash(plain); 2153 | registerPassword(plain); 2154 | lua_pushstring(lua, hash.c_str()); 2155 | return 1; 2156 | } 2157 | 2158 | int isDir(lua_State *lua) 2159 | { 2160 | // number of input arguments 2161 | int argc = lua_gettop(lua); 2162 | 2163 | string filename = lua_tostring(lua, -1); // get filename from Lua 2164 | lua_pop(lua, 1); 2165 | 2166 | File *fp; 2167 | 2168 | // did we give a filename? 2169 | if (filename.empty()) 2170 | { 2171 | lua_pushboolean(lua, false); 2172 | return 1; 2173 | } 2174 | 2175 | // does the path exist? 2176 | fp = shell.back()->pFile(filename); 2177 | if (!fp) 2178 | { 2179 | lua_pushboolean(lua, false); 2180 | return 1; 2181 | } 2182 | 2183 | // is this a file? 2184 | if (fp->getType() != T_FOLDER) 2185 | { 2186 | lua_pushboolean(lua, false); 2187 | return 1; 2188 | } 2189 | 2190 | // all tests passed! 2191 | lua_pushboolean(lua, true); 2192 | return 1; 2193 | } 2194 | 2195 | int isFile(lua_State *lua) 2196 | { 2197 | // number of input arguments 2198 | int argc = lua_gettop(lua); 2199 | 2200 | string filename = lua_tostring(lua, -1); // get filename from Lua 2201 | lua_pop(lua, 1); 2202 | 2203 | File *fp; 2204 | 2205 | // did we give a filename? 2206 | if (filename.empty()) 2207 | { 2208 | lua_pushboolean(lua, false); 2209 | return 1; 2210 | } 2211 | 2212 | // does the path exist? 2213 | fp = shell.back()->pFile(filename); 2214 | if (!fp) 2215 | { 2216 | lua_pushboolean(lua, false); 2217 | return 1; 2218 | } 2219 | 2220 | // is this a file? 2221 | if (fp->getType() != T_FILE) 2222 | { 2223 | lua_pushboolean(lua, false); 2224 | return 1; 2225 | } 2226 | 2227 | // all tests passed! 2228 | lua_pushboolean(lua, true); 2229 | return 1; 2230 | } 2231 | 2232 | int lua_md5(lua_State *lua) 2233 | { 2234 | string plain = lua_tostring(lua, lua_gettop(lua)); 2235 | lua_pop(lua, 1); 2236 | string hash = md5(plain); 2237 | lua_pushstring(lua, hash.c_str()); 2238 | return 1; 2239 | } 2240 | 2241 | int lua_addService(lua_State *lua) 2242 | { 2243 | string key; 2244 | string value; 2245 | int port; 2246 | string name; 2247 | string exec; 2248 | string query; 2249 | bool start = false; 2250 | 2251 | // number of input arguments 2252 | int argc = lua_gettop(lua); 2253 | 2254 | // make sure argument passed is a table 2255 | int idx = lua_gettop(lua); 2256 | if (!lua_istable(lua, idx)) 2257 | { 2258 | cout << "Error! Invalid call to addService." << endl; 2259 | exit (ERR_BAD_SET); 2260 | } 2261 | lua_pushnil(lua); // first key 2262 | while (lua_next(lua, -2) != 0 ) 2263 | { 2264 | key = lua_tostring(lua, -2); 2265 | 2266 | // check keys 2267 | if (key == "port") 2268 | { 2269 | port = lua_tonumber(lua, -1); 2270 | } 2271 | else if (key == "name") 2272 | { 2273 | name = lua_tostring(lua, -1); 2274 | } 2275 | else if (key == "exec") 2276 | { 2277 | exec = lua_tostring(lua, -1); 2278 | } 2279 | else if (key == "poll") 2280 | { 2281 | query = lua_tostring(lua, -1); 2282 | } 2283 | else if (key == "start") 2284 | { 2285 | string s = lua_tostring(lua, -1); 2286 | if (s == "true") 2287 | { 2288 | start = true; 2289 | } 2290 | } 2291 | lua_pop(lua, 1); 2292 | } 2293 | if (!vPC.back().addDaemon(Daemon(port,name,exec,query))) 2294 | { 2295 | cout << "Error! Unable to add service" << endl; 2296 | } 2297 | if (start) 2298 | { 2299 | vPC.back().startDaemon(name); 2300 | } 2301 | return E_OK; 2302 | } 2303 | 2304 | int lua_addNetDomain(lua_State *lua) 2305 | { 2306 | int domain_id; 2307 | string domain_name; 2308 | std::map::iterator it; 2309 | 2310 | // make sure domains are registered 2311 | if (lua_isnumber(lua, -1)) 2312 | { 2313 | domain_id = lua_tonumber(lua,-1); 2314 | registerNetDomain(domain_id); 2315 | } else { 2316 | domain_name = lua_tostring(lua,-1); 2317 | if (pcrecpp::RE("[^0-9a-zA-Z+_-]").PartialMatch(domain_name)) 2318 | { 2319 | cout << domain_name.length() << endl; 2320 | cout << "Error! Invalid network domain name: " << domain_name << endl; 2321 | lua_pop(lua, 1); 2322 | exit (1); 2323 | } 2324 | domain_id = registerNetDomain(domain_name); 2325 | } 2326 | lua_pop(lua, 1); 2327 | 2328 | // add domain membership 2329 | vPC.back().addNetDomain(domain_id); 2330 | return E_OK; 2331 | } 2332 | 2333 | int lua_listNetDomains(lua_State *lua) 2334 | { 2335 | // number of input arguments 2336 | int argc = lua_gettop(lua); 2337 | 2338 | if (argc != 1) 2339 | { 2340 | cout << "Error! Invalid call to listNetDomains." << endl; 2341 | exit (ERR_BAD_SET); 2342 | } 2343 | 2344 | string host = lua_tostring(lua, 1); 2345 | lua_pop(lua, 1); 2346 | 2347 | for (int i=0; igetCPower(); 2402 | score = lua_tonumber(lua,-1); 2403 | lua_pop(lua, 1); 2404 | seconds = score / (int) sqrt((double) power); 2405 | lua_pushnumber(lua, seconds); 2406 | return 1; 2407 | } 2408 | 2409 | int lua_fsMax(lua_State *lua) 2410 | { 2411 | // number of input arguments 2412 | int argc = lua_gettop(lua); 2413 | 2414 | if (argc > 1) 2415 | { 2416 | cout << "Error! Invalid call to fsMax." << endl; 2417 | exit (ERR_BAD_SET); 2418 | } 2419 | int fs_size = lua_tointeger(lua, -1); 2420 | lua_pop(lua, 1); 2421 | 2422 | vPC.back().FSsetMax(fs_size); 2423 | 2424 | return E_OK; 2425 | } 2426 | 2427 | int startService(lua_State *lua) 2428 | { 2429 | // number of input arguments 2430 | int argc = lua_gettop(lua); 2431 | 2432 | if (argc > 1) 2433 | { 2434 | cout << "Error! Invalid call to startService." << endl; 2435 | exit (ERR_BAD_SET); 2436 | } 2437 | 2438 | string name = lua_tostring(lua, -1); 2439 | lua_pop(lua, 1); 2440 | 2441 | shell.back()->startDaemon(name); 2442 | return E_OK; 2443 | } 2444 | 2445 | int stopService(lua_State *lua) 2446 | { 2447 | // number of input arguments 2448 | int argc = lua_gettop(lua); 2449 | 2450 | if (argc > 1) 2451 | { 2452 | cout << "Error! Invalid call to stopService." << endl; 2453 | exit (ERR_BAD_SET); 2454 | } 2455 | 2456 | string name = lua_tostring(lua, -1); 2457 | lua_pop(lua, 1); 2458 | 2459 | shell.back()->stopDaemon(name); 2460 | return E_OK; 2461 | } 2462 | 2463 | int serviceRunning(lua_State *lua) 2464 | { 2465 | // number of input arguments 2466 | int argc = lua_gettop(lua); 2467 | 2468 | if (argc != 2) 2469 | { 2470 | cout << "Error! Invalid call to serviceRunning." << endl; 2471 | exit (ERR_BAD_SET); 2472 | } 2473 | 2474 | string srvc = lua_tostring(lua, -1); 2475 | lua_pop(lua, 1); 2476 | string host = lua_tostring(lua, -1); 2477 | lua_pop(lua, 1); 2478 | 2479 | for (int i=0; i inetd = vPC[i].getDaemons(); 2485 | for (int n = 0; nname == srvc) 2488 | { 2489 | // return true 2490 | lua_pushboolean(lua, true); 2491 | return 1; 2492 | } 2493 | } 2494 | } 2495 | } 2496 | // return false 2497 | lua_pushboolean(lua, false); 2498 | return 1; 2499 | } 2500 | 2501 | int lua_login(lua_State *lua) 2502 | { 2503 | string key; 2504 | string value; 2505 | string host; 2506 | string user; 2507 | string password; 2508 | bool skip_p = true; 2509 | VM *vm; 2510 | 2511 | // number of input arguments 2512 | int argc = lua_gettop(lua); 2513 | 2514 | // make sure argument passed is a table 2515 | int idx = lua_gettop(lua); 2516 | if (!lua_istable(lua, idx)) 2517 | { 2518 | cout << "Error! Invalid call to login." << endl; 2519 | exit (ERR_BAD_SET); 2520 | } 2521 | lua_pushnil(lua); // first key 2522 | while (lua_next(lua, -2) != 0 ) 2523 | { 2524 | key = lua_tostring(lua, -2); 2525 | value = lua_tostring(lua, -1); 2526 | 2527 | // check keys 2528 | if (key == "host") 2529 | { 2530 | host = value; 2531 | } 2532 | else if (key == "user") 2533 | { 2534 | user = value; 2535 | } 2536 | else if (key == "password") 2537 | { 2538 | password = value; 2539 | skip_p = false; 2540 | } 2541 | lua_pop(lua, 1); 2542 | } 2543 | if (host.empty() || user.empty()) 2544 | { 2545 | cout << "Error! Invalid call to login." << endl; 2546 | exit (ERR_BAD_SET); 2547 | } 2548 | 2549 | if (shell.back()->getIp() == getDNS(host)) 2550 | { 2551 | vm = shell.back(); 2552 | } else { 2553 | for (int i=0; ilogin(user)) // seg faults here 2573 | { 2574 | lua_pushboolean(lua, false); 2575 | return 1; 2576 | } 2577 | } else { 2578 | vm->login(user, password); 2579 | } 2580 | if (shell.back() != vm) shell.push_back(vm); 2581 | lua_pushboolean(lua, true); 2582 | return 1; 2583 | } 2584 | 2585 | int lua_logout(lua_State *lua) 2586 | { 2587 | cmd_exit(); 2588 | return E_OK; 2589 | } 2590 | 2591 | int lua_cwd(lua_State *lua) 2592 | { 2593 | lua_pushstring(lua, shell.back()->getCwd().c_str()); 2594 | return 1; 2595 | } 2596 | 2597 | int lua_hostname(lua_State *lua) 2598 | { 2599 | lua_pushstring(lua, shell.back()->getHostname().c_str()); 2600 | return 1; 2601 | } 2602 | 2603 | int lua_echo(lua_State *lua) 2604 | { 2605 | // number of input arguments 2606 | int argc = lua_gettop(lua); 2607 | 2608 | for (int i=0; i(lua_tonumber(lua, -1)))); 2640 | lua_pop(lua, 1); 2641 | return E_OK; 2642 | } 2643 | 2644 | int lua_timestamp(lua_State *lua) 2645 | { 2646 | // current date/time based on current system 2647 | time_t now = time(0); 2648 | lua_pushnumber(lua, now); 2649 | return 1; 2650 | } 2651 | 2652 | int lua_garbage(lua_State *lua) 2653 | { 2654 | // get time 2655 | time_t rawtime; 2656 | time (&rawtime); 2657 | struct tm *ltime; 2658 | ltime = localtime(&rawtime); 2659 | 2660 | // seed random with current second 2661 | srand(ltime->tm_sec); 2662 | 2663 | // set vars 2664 | int limit = 600; 2665 | char c; 2666 | string s; 2667 | 2668 | // number of input arguments 2669 | int argc = lua_gettop(lua); 2670 | 2671 | if (argc) 2672 | { 2673 | for (int i=1; i 40) 2695 | { 2696 | c = 32; 2697 | } 2698 | } 2699 | s += c; 2700 | } 2701 | lua_pushstring(lua, s.c_str()); 2702 | return 1; 2703 | } 2704 | 2705 | int lua_vdump(vector args) 2706 | { 2707 | if (!debug_on) 2708 | { 2709 | cout << "Debug off" << endl; 2710 | return E_OK; 2711 | } 2712 | if (args.size() != 2) 2713 | { 2714 | cout << "Invalid number of arguments to: 'dump'" << endl; 2715 | return E_OK; 2716 | } 2717 | 2718 | string key; 2719 | int type; 2720 | 2721 | // let's get our globals 2722 | lua_pushglobaltable(lua); 2723 | lua_pushnil(lua); 2724 | while (lua_next(lua, -2) != 0) 2725 | { 2726 | key = lua_tostring(lua, -2); 2727 | type = lua_type(lua, -1); 2728 | 2729 | // skip reserved keys 2730 | if (!key.empty() && key.substr(0,1)=="_") 2731 | { 2732 | lua_pop(lua,1); 2733 | continue; 2734 | } 2735 | 2736 | if (key == args[1] || args[1] == "@") 2737 | { 2738 | cout << "[DBG] var: " << key << " = "; 2739 | if (type == LUA_TBOOLEAN) 2740 | { 2741 | cout << " (b) " << lua_toboolean(lua, -1); 2742 | } 2743 | else if (type == LUA_TNUMBER) 2744 | { 2745 | cout << " (i) " << lua_tonumber(lua, -1); 2746 | } 2747 | else if (type == LUA_TSTRING) 2748 | { 2749 | cout << " (s) " << lua_tostring(lua, -1); 2750 | } 2751 | cout << endl; 2752 | } 2753 | lua_pop(lua, 1); 2754 | } 2755 | return E_OK; 2756 | } 2757 | 2758 | int old_restore(string filename) 2759 | { 2760 | ifstream savfile(filename.c_str()); 2761 | if (!savfile.is_open()) 2762 | { 2763 | cout << "Error! Unable to open save file." << endl; 2764 | return E_BAD; 2765 | } 2766 | 2767 | string data; 2768 | 2769 | while (std::getline(savfile, data)) 2770 | { 2771 | data = ab64_decode(data); 2772 | // let's process the saved data 2773 | if (data.substr(0,3)=="vm:") 2774 | { 2775 | VM* avm; // active VM 2776 | std::istringstream vm(data); 2777 | while (std::getline(vm, data)) 2778 | { 2779 | vector store; 2780 | if (data.substr(0,3)=="vm:") 2781 | { 2782 | string hostname = data.substr(3); 2783 | if (debug_on) cout << "[DBG] Loading vm: " << hostname << endl; 2784 | avm = getVM(hostname); 2785 | if (!avm) 2786 | { 2787 | cout << "Error! Corrupt save file." << endl; 2788 | exit(1); 2789 | } 2790 | // reset the machine so we can re-add state data 2791 | avm->reset(); 2792 | // add root of filesystem 2793 | File f (File("/", T_FOLDER, "", "")); 2794 | avm->addFile(f); 2795 | } 2796 | else if (data.substr(0,5)=="file:") 2797 | { 2798 | string f_parent; 2799 | string f_name; 2800 | string f_acl; 2801 | string f_owner; 2802 | string f_exec; 2803 | string f_content; 2804 | string f_on_delete; 2805 | int f_type; 2806 | int dbg = 1; 2807 | 2808 | data = data.substr(5); 2809 | explode(data,",",store); 2810 | for (int i=0;i kv; 2813 | if (store[i] == "f") f_type = T_FILE; 2814 | if (store[i] == "d") f_type = T_FOLDER; 2815 | explode(store[i],"=",kv,1); 2816 | if (kv.size()==1) kv.push_back(""); 2817 | if (kv.size()) 2818 | { 2819 | if (kv[0] == "parent") 2820 | { 2821 | f_parent = kv[1]; 2822 | } 2823 | else if (kv[0] == "name") 2824 | { 2825 | f_name = kv[1]; 2826 | } 2827 | else if (kv[0] == "acl") 2828 | { 2829 | f_acl = kv[1]; 2830 | } 2831 | else if (kv[0] == "owner") 2832 | { 2833 | f_owner = kv[1]; 2834 | } 2835 | else if (kv[0] == "exec") 2836 | { 2837 | if (kv.size()==2) 2838 | f_exec = kv[1]; 2839 | } 2840 | else if (kv[0] == "content") 2841 | { 2842 | if (debug_on) cout << "[DBG] (" << kv.size() << ") Loading content for " << f_name << endl; 2843 | if (kv.size()==2) 2844 | f_content = ab64_decode(kv[1]); 2845 | } 2846 | else if (kv[0] == "on_delete") 2847 | { 2848 | if (kv.size()==2) 2849 | f_on_delete = kv[1]; 2850 | } 2851 | } 2852 | } 2853 | if (!f_parent.empty() && !f_name.empty()) 2854 | { 2855 | if (debug_on) cout << "[DBG] Loading file: " << f_parent+f_name << endl; 2856 | if (debug_on) cout << "[DBG] exec: " << f_exec << endl; 2857 | if (debug_on) cout << "[DBG] on_delete: " << f_on_delete << endl; 2858 | if (debug_on) cout << "[DBG] content: " << f_content << endl; 2859 | // make file here 2860 | File f (File(f_parent+f_name, f_type, f_content, f_exec)); 2861 | f.setAcl(f_acl); 2862 | f.setOwner(f_owner); 2863 | if (!f_on_delete.empty()) 2864 | { 2865 | f.setOnDelete(f_on_delete); 2866 | } 2867 | if (!avm->addFile(f)) 2868 | { 2869 | cout << "Error! Unable to create file: " << f_name << endl; 2870 | exit(ERR_BAD_SET); 2871 | } 2872 | } 2873 | } 2874 | else if (data.substr(0,2)=="p:") 2875 | { 2876 | data = data.substr(2); 2877 | vector kv; 2878 | explode(data,"=",kv); 2879 | if (kv[0] == "cwd") 2880 | { 2881 | avm->setCwd(kv[1]); 2882 | } 2883 | else if (kv[0] == "bc") 2884 | { 2885 | avm->setBrokenCounter(std::atoi(kv[1].c_str())); 2886 | } 2887 | else if (kv[0] == "has_root") 2888 | { 2889 | if (kv[1] == "true") avm->setRoot(true); 2890 | else avm->setRoot(false); 2891 | } 2892 | } 2893 | else if (data.substr(0,6)=="chain:") 2894 | { 2895 | data = data.substr(6); 2896 | explode(data,",",store); 2897 | // loop through and log the users in to resetup the chain 2898 | for (int i=0;ilogin(store[i])) 2901 | cout << "Unable to chain " << store[i] << endl; 2902 | } 2903 | } 2904 | else if (data.substr(0,5)=="netd:") 2905 | { 2906 | data = data.substr(5); 2907 | explode(data,",",store); 2908 | for (int i=0;iaddNetDomain(std::atoi(store[i].c_str())); 2911 | } 2912 | } 2913 | } 2914 | } 2915 | else if (data.substr(0,5)=="netd:") 2916 | { 2917 | if (debug_on) cout << "[DBG] Loading net data" << endl; 2918 | data = data.substr(5); 2919 | vector store; 2920 | explode(data,",",store); 2921 | netd_map.clear(); 2922 | for (int i=0;i kv; 2925 | explode(store[i],"=",kv); 2926 | if (kv.size()==1) kv.push_back(""); 2927 | netd_map[std::atoi(kv[0].c_str())] = kv[1]; 2928 | } 2929 | } 2930 | else if (data.substr(0,6)=="shell:") 2931 | { 2932 | if (debug_on) cout << "[DBG] Building shell chain" << endl; 2933 | vector store; 2934 | data = data.substr(6); 2935 | explode(data,",",store); 2936 | 2937 | // clean up the shell chain 2938 | shell.clear(); 2939 | 2940 | // setup new chain 2941 | for (int i=0;ifirst=="vm") 2982 | { 2983 | VM* avm; // active VM 2984 | pt::ptree vm = it->second; 2985 | for (pt::ptree::iterator vm_it = vm.begin(); vm_it != vm.end(); vm_it++) 2986 | { 2987 | vector store; 2988 | if (vm_it->first=="hostname") 2989 | { 2990 | string hostname = vm_it->second.get_value(); 2991 | if (debug_on) cout << "[DBG] Loading vm: " << hostname << endl; 2992 | avm = getVM(hostname); 2993 | if (!avm) 2994 | { 2995 | cout << "Error! Corrupt save file." << endl; 2996 | exit(1); 2997 | } 2998 | // reset the machine so we can re-add state data 2999 | avm->reset(); 3000 | // add root of filesystem 3001 | File f (File("/", T_FOLDER, "", "")); 3002 | avm->addFile(f); 3003 | } 3004 | else if (vm_it->first=="file") 3005 | { 3006 | string f_parent; 3007 | string f_name; 3008 | string f_acl; 3009 | string f_owner; 3010 | string f_exec; 3011 | string f_content; 3012 | string f_on_delete; 3013 | int f_type; 3014 | int dbg = 1; 3015 | 3016 | pt::ptree file = vm_it->second; 3017 | for (pt::ptree::iterator f_it = file.begin(); f_it != file.end(); f_it++) 3018 | { 3019 | vector kv; 3020 | if (f_it->second.get_value() == "f") f_type = T_FILE; 3021 | if (f_it->second.get_value() == "d") f_type = T_FOLDER; 3022 | if (f_it->first == "parent") 3023 | { 3024 | f_parent = f_it->second.get_value(); 3025 | } 3026 | else if (f_it->first == "name") 3027 | { 3028 | f_name = f_it->second.get_value(); 3029 | } 3030 | else if (f_it->first == "acl") 3031 | { 3032 | f_acl = f_it->second.get_value(); 3033 | } 3034 | else if (f_it->first == "owner") 3035 | { 3036 | f_owner = f_it->second.get_value(); 3037 | } 3038 | else if (f_it->first == "exec") 3039 | { 3040 | f_exec = f_it->second.get_value(); 3041 | } 3042 | else if (f_it->first == "content") 3043 | { 3044 | if (debug_on) cout << "[DBG] Loading content for " << f_name << endl; 3045 | f_content = f_it->second.get_value(); 3046 | } 3047 | else if (f_it->first == "on_delete") 3048 | { 3049 | f_on_delete = f_it->second.get_value(); 3050 | } 3051 | } 3052 | if (!f_parent.empty() && !f_name.empty()) 3053 | { 3054 | if (debug_on) cout << "[DBG] Loading file: " << f_parent+f_name << endl; 3055 | if (debug_on) cout << "[DBG] exec: " << f_exec << endl; 3056 | if (debug_on) cout << "[DBG] on_delete: " << f_on_delete << endl; 3057 | if (debug_on) cout << "[DBG] content: " << f_content << endl; 3058 | // create file here 3059 | File f (File(f_parent+f_name, f_type, f_content, f_exec)); 3060 | f.setAcl(f_acl); 3061 | f.setOwner(f_owner); 3062 | if (!f_on_delete.empty()) 3063 | { 3064 | f.setOnDelete(f_on_delete); 3065 | } 3066 | if (!avm->addFile(f)) 3067 | { 3068 | cout << "Error! Unable to create file: " << f_name << endl; 3069 | exit(ERR_BAD_SET); 3070 | } 3071 | } 3072 | } 3073 | else if (vm_it->first=="cwd") 3074 | { 3075 | avm->setCwd(vm_it->second.get_value()); 3076 | } 3077 | else if (vm_it->first=="bc") 3078 | { 3079 | avm->setBrokenCounter(vm_it->second.get_value()); 3080 | } 3081 | else if (vm_it->first=="has_root") 3082 | { 3083 | avm->setRoot(vm_it->second.get_value()); 3084 | } 3085 | else if (vm_it->first=="chain") 3086 | { 3087 | data = vm_it->second.get_value(); 3088 | explode(data,",",store); 3089 | // loop through and log the users in to resetup the chain 3090 | for (int i=0;ilogin(store[i])) 3093 | cout << "Unable to chain " << store[i] << endl; 3094 | } 3095 | } 3096 | else if (vm_it->first=="netd") 3097 | { 3098 | data = vm_it->second.get_value(); 3099 | explode(data,",",store); 3100 | for (int i=0;iaddNetDomain(std::atoi(store[i].c_str())); 3103 | } 3104 | } 3105 | } 3106 | } 3107 | else if (it->first=="netd") 3108 | { 3109 | if (debug_on) cout << "[DBG] Loading net data" << endl; 3110 | data = it->second.get_value(); 3111 | vector store; 3112 | explode(data,",",store); 3113 | netd_map.clear(); 3114 | for (int i=0;i kv; 3117 | explode(store[i],"=",kv); 3118 | if (kv.size()==1) kv.push_back(""); 3119 | netd_map[std::atoi(kv[0].c_str())] = kv[1]; 3120 | } 3121 | } 3122 | else if (it->first=="shells") 3123 | { 3124 | if (debug_on) cout << "[DBG] Building shell chain" << endl; 3125 | vector store; 3126 | data = it->second.get_value(); 3127 | explode(data,",",store); 3128 | 3129 | // clean up the shell chain 3130 | shell.clear(); 3131 | 3132 | // setup new chain 3133 | for (int i=0;ifirst=="globals") 3145 | { 3146 | if (debug_on) cout << "[DBG] Loading Lua globals" << endl; 3147 | data = it->second.get_value(); 3148 | luaL_dostring(lua, data.c_str()); 3149 | } 3150 | } 3151 | //savfile.close(); 3152 | cout << "Restored!" << endl; 3153 | 3154 | return E_OK; 3155 | } 3156 | 3157 | int lua_restore(vector args) 3158 | { 3159 | if (args.size() != 2) 3160 | { 3161 | cout << "Invalid number of arguments to: 'load'" << endl; 3162 | return E_BAD; 3163 | } 3164 | 3165 | FILE *fp; 3166 | string filename = args[1]; 3167 | char c; 3168 | 3169 | // if they typed in .sav, remove it for analysis 3170 | if (filename.length() > 4 && filename.substr(strlen(filename.c_str())-4,4)==".sav") 3171 | { 3172 | filename = filename.substr(0,strlen(filename.c_str())-4); 3173 | } 3174 | 3175 | if (pcrecpp::RE("[^0-9a-zA-Z+_-]").PartialMatch(filename)) 3176 | { 3177 | cout << "Invalid save game name. Only the following characters are allowed:" << endl; 3178 | cout << "0-9 a-z A-Z '+' '_' '-'" << endl; 3179 | return E_BAD; 3180 | } 3181 | // add .sav to the filename 3182 | filename += ".sav"; 3183 | 3184 | // determine the save format 3185 | fp = fopen(filename.c_str(), "r"); 3186 | if (!fp) 3187 | { 3188 | cout << "Error! Unable to open file!" << endl; 3189 | return E_BAD; 3190 | } 3191 | c = fgetc(fp); 3192 | fclose(fp); 3193 | 3194 | // restore from file 3195 | if (c == '{') 3196 | { 3197 | return new_restore(filename); 3198 | } else { 3199 | return old_restore(filename); 3200 | } 3201 | } 3202 | 3203 | int lua_save(vector args) 3204 | { 3205 | if (args.size() != 2) 3206 | { 3207 | cout << "Invalid number of arguments to: 'save'" << endl; 3208 | return E_BAD; 3209 | } 3210 | 3211 | FILE *fp; 3212 | string filename = args[1]; 3213 | 3214 | if (pcrecpp::RE("[^0-9a-zA-Z+_-]").PartialMatch(filename)) 3215 | { 3216 | cout << "Invalid save game name. Only the following characters are allowed:" << endl; 3217 | cout << "0-9 a-z A-Z '+' '_' '-'" << endl; 3218 | return E_BAD; 3219 | } 3220 | filename += ".sav"; 3221 | 3222 | pt::ptree json; 3223 | string key; 3224 | int type; 3225 | string _lua_data = ""; 3226 | 3227 | // state save format version 3228 | json.put("version", 2); 3229 | 3230 | // let's get our globals 3231 | lua_pushglobaltable(lua); 3232 | lua_pushnil(lua); 3233 | while (lua_next(lua, -2) != 0) 3234 | { 3235 | key = lua_tostring(lua, -2); 3236 | type = lua_type(lua, -1); 3237 | 3238 | // skip reserved keys 3239 | if (!key.empty() && key.substr(0,1)=="_") 3240 | { 3241 | lua_pop(lua,1); 3242 | continue; 3243 | } 3244 | 3245 | if (type == LUA_TBOOLEAN) 3246 | { 3247 | bool b = lua_toboolean(lua, -1); 3248 | _lua_data.append(key).append(" = "); 3249 | if (b) 3250 | { 3251 | _lua_data.append("true"); 3252 | } else { 3253 | _lua_data.append("false"); 3254 | } 3255 | _lua_data.append("\n"); 3256 | } 3257 | else if (type == LUA_TNUMBER) 3258 | { 3259 | ostringstream num; 3260 | num << lua_tonumber(lua, -1); 3261 | _lua_data.append(key).append(" = ").append(num.str()); 3262 | _lua_data.append("\n"); 3263 | } 3264 | else if (type == LUA_TSTRING) 3265 | { 3266 | string s = lua_tostring(lua, -1); 3267 | // let's sanitize s! 3268 | pcrecpp::RE("\"").GlobalReplace("\\\\\"", &s); 3269 | _lua_data.append(key).append(" = \"").append(s) 3270 | .append("\"");; 3271 | _lua_data.append("\n"); 3272 | } 3273 | lua_pop(lua, 1); 3274 | } 3275 | lua_pop(lua,1); 3276 | // pack globals 3277 | json.put("globals", _lua_data); 3278 | _lua_data = "lua:" + ab64_encode(_lua_data.c_str(), _lua_data.length()); 3279 | // pack statement 3280 | _lua_data = ab64_encode(_lua_data.c_str(), _lua_data.length()); 3281 | // save data 3282 | //fputs(_lua_data.c_str(), fp); 3283 | //fputs("\n", fp); 3284 | 3285 | // save all net_domains 3286 | { 3287 | //string data = "netd:"; 3288 | string data; 3289 | std::map::iterator it; 3290 | 3291 | for (it=netd_map.begin(); it!=netd_map.end(); it++) 3292 | { 3293 | ostringstream num; 3294 | num << it->first; 3295 | if (it!=netd_map.begin()) data.append(","); 3296 | data.append(num.str()).append("=").append(it->second); 3297 | } 3298 | json.put("netd", data); 3299 | //data = ab64_encode(data.c_str(), data.length()); 3300 | //fputs(data.c_str(), fp); 3301 | //fputs("\n", fp); 3302 | } 3303 | 3304 | // save all VMs 3305 | { 3306 | vector::iterator it; 3307 | for (it=vPC.begin(); it!=vPC.end(); it++) 3308 | { 3309 | //string vms = it->serialize();; 3310 | pt::ptree vms = it->serialize();; 3311 | json.push_back(std::make_pair("vm", vms)); 3312 | //fputs(vms.c_str(), fp); 3313 | //fputs("\n", fp); 3314 | } 3315 | } 3316 | 3317 | // save shell chain 3318 | { 3319 | vector::iterator it; 3320 | string data; 3321 | for (it=shell.begin(); it!=shell.end(); it++) 3322 | { 3323 | string hostname = (*it)->getHostname(); 3324 | if (it!=shell.begin()) data.append(","); 3325 | data.append(hostname); 3326 | } 3327 | json.put("shells", data); 3328 | //data = ab64_encode(data.c_str(), data.length()); 3329 | //fputs(data.c_str(), fp); 3330 | //fputs("\n", fp); 3331 | } 3332 | //pt::write_json(std::cout, json); 3333 | pt::write_json(filename, json); 3334 | 3335 | // close save file 3336 | //fclose(fp); 3337 | cout << "Saved!" << endl; 3338 | 3339 | return E_OK; 3340 | } 3341 | 3342 | //int version (lua_State *lua) 3343 | //{ 3344 | // lua_pushnumber(lua, ENGINE_VERSION); 3345 | // return 1; 3346 | //} 3347 | 3348 | int lua_quit (lua_State *lua) 3349 | { 3350 | // maybe some cleanup should go here? 3351 | exit (0); 3352 | } 3353 | 3354 | // load game environment 3355 | int loadEnv() 3356 | { 3357 | // create Lua state 3358 | lua = luaL_newstate(); 3359 | 3360 | // load Lua libraries 3361 | static const luaL_Reg lualibs[] = 3362 | { 3363 | { "base", luaopen_base }, 3364 | { "string", luaopen_string }, 3365 | { "math", luaopen_math }, 3366 | { NULL, NULL} 3367 | }; 3368 | 3369 | const luaL_Reg *lib = lualibs; 3370 | for (; lib->func != NULL; lib++) 3371 | { 3372 | // use luaL_requiref to set lib globals 3373 | luaL_requiref(lua, lib->name, lib->func, 1); 3374 | lib->func(lua); 3375 | lua_settop(lua, 0); 3376 | } 3377 | 3378 | // register functions to be called in lua 3379 | lua_register(lua, "readfile", readfile); 3380 | lua_register(lua, "newVM", newVM); 3381 | lua_register(lua, "setProperty", setProperty); 3382 | lua_register(lua, "addDir", addDir); 3383 | lua_register(lua, "addFile", addFile); 3384 | lua_register(lua, "addGPU", addGPU); 3385 | lua_register(lua, "addService", lua_addService); 3386 | lua_register(lua, "addNetDomain", lua_addNetDomain); 3387 | lua_register(lua, "addUser", addUser); 3388 | lua_register(lua, "getCWait", lua_getCWait); 3389 | lua_register(lua, "fsMax", lua_fsMax); 3390 | lua_register(lua, "inNetDomain", lua_inNetDomain); 3391 | lua_register(lua, "listNetDomains", lua_listNetDomains); 3392 | lua_register(lua, "isDir", isDir); 3393 | lua_register(lua, "isFile", isFile); 3394 | lua_register(lua, "startService", startService); 3395 | lua_register(lua, "stopService", stopService); 3396 | lua_register(lua, "serviceRunning", serviceRunning); 3397 | lua_register(lua, "login", lua_login); 3398 | lua_register(lua, "logout", lua_logout); 3399 | lua_register(lua, "mail", sendMail); 3400 | lua_register(lua, "md5", lua_md5); 3401 | lua_register(lua, "addDNS", lua_addDNS); 3402 | lua_register(lua, "getDNS", lua_getDNS); 3403 | lua_register(lua, "hash", lua_hashString); 3404 | lua_register(lua, "echo", lua_echo); 3405 | lua_register(lua, "input", lua_input); 3406 | lua_register(lua, "hostname", lua_hostname); 3407 | lua_register(lua, "cwd", lua_cwd); 3408 | lua_register(lua, "pause", lua_pause); 3409 | lua_register(lua, "sleep", lua_sleep); 3410 | lua_register(lua, "timestamp", lua_timestamp); 3411 | lua_register(lua, "garbage", lua_garbage); 3412 | lua_register(lua, "quit", lua_quit); 3413 | 3414 | // setup the default Network Domain 3415 | netd_map[1] = "default"; 3416 | 3417 | // init pointer for current VM 3418 | VM *pVM; 3419 | 3420 | #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32) 3421 | char * mfn = (char *) malloc(mission_file.length()+1); 3422 | strcpy(mfn, mission_file.c_str()); 3423 | cout << "Loading mission pack (" << basename(mfn) << ")..." << endl; 3424 | free(mfn); 3425 | #else 3426 | char drive[255]; 3427 | char path[255]; 3428 | char fname[255]; 3429 | char fext[255]; 3430 | _splitpath_s(mission_file.c_str(), drive, path, fname, fext); 3431 | cout << "Loading mission pack (" << fname << "." << fext << ")..." << endl; 3432 | #endif 3433 | 3434 | // run the Lua script 3435 | if (luaL_dofile(lua, mission_file.c_str())==1) 3436 | { 3437 | cout << "Error! This mission pack seems to contain errors." << endl; 3438 | cout << lua_tostring(lua, -1) << endl; 3439 | exit (ERR_BAD_MIS_PACK); 3440 | } 3441 | 3442 | if (vPC.size()==0) 3443 | { 3444 | cout << "Error! No virtual machines have been loaded. Game can not continue." << endl; 3445 | exit (ERR_NO_VM); 3446 | } 3447 | 3448 | // init shell to first VM 3449 | shell.push_back(&(vPC[0])); 3450 | 3451 | // set engine version as a global 3452 | lua_pushnumber(lua, ENGINE_VERSION); 3453 | lua_setglobal(lua, "VERSION"); 3454 | 3455 | // launch intro func and begin game 3456 | luaL_dostring(lua, "intro()"); 3457 | return E_OK; 3458 | } 3459 | 3460 | void signalHandler(int signum) 3461 | { 3462 | if (cmd_thread) 3463 | { 3464 | cmd_thread->interrupt(); 3465 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 3466 | // Let's fake the Unix-type output you'd expect 3467 | cout << "^C"; 3468 | #endif 3469 | cout << endl; 3470 | } else { 3471 | if (!tc.getBuffer().empty()) 3472 | { 3473 | tc.setBuffer(""); 3474 | cout << endl << "$ " << flush; 3475 | } 3476 | } 3477 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 3478 | // on Win32, handle gets reset after call, so we call it again 3479 | signal(SIGINT, signalHandler); 3480 | #endif 3481 | } 3482 | 3483 | // entry point 3484 | int main(int argc, char** argv) 3485 | { 3486 | string opt; 3487 | string user; 3488 | string password; 3489 | mission_file = "destiny.mis"; 3490 | debug_on = false; 3491 | 3492 | // parse options 3493 | for ( int i=1; igetUserCount()>0) break; 3546 | cout << "Login: "; 3547 | user = tc.getLine(); 3548 | cout << "Password: "; 3549 | password = tc.getLine(M_PASSWORD); 3550 | if (shell.back()->login(user, password)) 3551 | { 3552 | break; 3553 | } 3554 | cout << endl; 3555 | } 3556 | // load terminal input 3557 | tc.run(); 3558 | // quit from terminal. cleanup now. 3559 | lua_close(lua); // clean Lua state 3560 | cout << endl; 3561 | return E_OK; 3562 | } 3563 | -------------------------------------------------------------------------------- /engine.h: -------------------------------------------------------------------------------- 1 | #include 2 | #define PCRE_STATIC 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 18 | #include 19 | extern void sleep(int t); 20 | #endif 21 | 22 | #define ENGINE_NAME "The Hacker's Sandbox" 23 | #define ENGINE_VERSION 1.21 24 | 25 | #define debug cout 26 | #define T_FOLDER 0 27 | #define T_FILE 1 28 | 29 | #define E_NO_FILE 1 30 | #define E_DENIED 2 31 | #define E_BAD 3 32 | #define E_OK 0 33 | #define E_BREAK -1 34 | 35 | #define ERR_NO_VM 1 36 | #define ERR_BAD_SET 2 37 | #define ERR_BAD_MIS_PACK 3 38 | 39 | using namespace std; 40 | namespace pt = boost::property_tree; 41 | 42 | struct RT 43 | { 44 | string hash; 45 | string plain; 46 | RT(string h, string p):hash(h),plain(p){}; 47 | }; 48 | 49 | class File 50 | { 51 | int filetype; 52 | string parent; 53 | string filename; 54 | string exec; 55 | string content; 56 | string owner; 57 | string acl; 58 | string on_delete; 59 | vector > getBitset(); 60 | bool setuid; 61 | 62 | public: 63 | File (); 64 | File (string n, int t, string c, string e); 65 | string getAcl (); 66 | string getContent(); 67 | string getExec (); 68 | int getType (); 69 | string getName (); 70 | string getOwner(); 71 | string getParent (); 72 | string getOnDelete(); 73 | 74 | bool setAcl(string acl); 75 | bool setOwner(string s); 76 | bool setOnDelete(string s); 77 | bool isReadable(); 78 | bool isWritable(); 79 | bool isExecutable(); 80 | void setSUID(bool); 81 | 82 | string drawAcl(); 83 | }; 84 | 85 | class Mail 86 | { 87 | string header_to; 88 | string header_subject; 89 | string header_from; 90 | string msg_body; 91 | public: 92 | Mail(string t, string s, string f, string b); 93 | string to(); 94 | string subject(); 95 | string from(); 96 | string body(); 97 | }; 98 | 99 | bool registerPassword(string s); 100 | 101 | class User 102 | { 103 | string name; 104 | string password; 105 | bool broken; 106 | vector inbox; 107 | public: 108 | User (string username, string password); 109 | string getName(); 110 | bool isPassword(string s); 111 | bool setPassword(string s); 112 | bool addMail(Mail); 113 | bool deleteMail(int index); 114 | Mail* getMail(int index); 115 | vector listInbox(); 116 | int inboxSize(); 117 | }; 118 | 119 | struct Daemon 120 | { 121 | public: 122 | int port; 123 | string name; 124 | string exec; 125 | string query; 126 | bool started; 127 | Daemon(int port, string name, string exec, string query); 128 | }; 129 | 130 | class VM 131 | { 132 | int broken_counter; 133 | string cpu; 134 | vector gpus; 135 | int compute_power; 136 | string cwd; 137 | int fs_maxSize; 138 | bool has_root; 139 | string hostname; 140 | string ip; 141 | string uname; 142 | string hint; 143 | vector users; 144 | vector user_chain; 145 | vector filesystem; 146 | string on_root; 147 | string on_login; 148 | string on_logout; 149 | vector services; 150 | vector net_domains; 151 | 152 | public: 153 | 154 | VM (string hn); 155 | //string serialize(); 156 | pt::ptree serialize(); 157 | string getCpu (); 158 | string getCwd (); 159 | const vector getFiles (string s); 160 | File *pFile (string s); 161 | string getHint(); 162 | string getHostname (); 163 | string getIp (); 164 | string getUname (); 165 | string getUsername (); 166 | User *getUser(string username); 167 | int getUserCount(); 168 | int setCwd (string s); 169 | void setHint(string s); 170 | void setIp (string s); 171 | void setUname (string s); 172 | bool addFile (File f); 173 | bool deleteFile (string filename); 174 | bool addUser (User u); 175 | bool login(string username, string password); 176 | bool login(string username); 177 | int logout(); 178 | bool startBrokenCounter(); 179 | void setBrokenCounter(int); 180 | bool hasRoot(); 181 | void setRoot(bool); 182 | void onRoot(string s); 183 | void onLogin(string s); 184 | void onLogout(string s); 185 | bool startDaemon(string daemon); 186 | bool stopDaemon(string daemon); 187 | bool addDaemon(Daemon d); 188 | vector getDaemons(); 189 | vector tabComplete(string); 190 | void addGPU(string, int); 191 | int getCPower(); 192 | vector getGPUs(); 193 | void setDefaultNetDomain(); 194 | void addNetDomain(int); 195 | void listNetDomains(); 196 | bool inNetDomain(int); 197 | bool getNetRoute(string ip); 198 | string printUserChain(); 199 | void reset(); 200 | int FSgetFree(); 201 | void FSsetMax(int); 202 | }; 203 | 204 | std::string ab64_encode(char const* bytes_to_encode, unsigned int in_len); 205 | std::string ab64_decode(std::string const& encoded_string); 206 | int explode(std::string line,std::string delimiter,std::vector &store); 207 | string vhash(string s); 208 | string realpath(string path); 209 | 210 | extern bool debug_on; 211 | extern vector vPC; 212 | extern vector shell; 213 | extern vector vhashes; 214 | extern std::map netd_map; 215 | 216 | extern lua_State *lua; // Lua state object 217 | -------------------------------------------------------------------------------- /hackingteam.mis: -------------------------------------------------------------------------------- 1 | -- Hacking Team mission pack 2 | -- Written by Unix-Ninja 3 | -- This is just a parody; Don't take it seriously!! 4 | -- MPVERS 1.0 5 | 6 | -- globals 7 | trophies = { poz_home = 0, fsv_hackteam = 0, fsv_clienti = 0, fsv_software = 0, git_opt = 0, wik_confluence = 0 } 8 | 9 | -- VMs 10 | local i 11 | 12 | -- 13 | newVM ("pozzmaster") 14 | setProperty ({ ip = "192.168.1.100" }) 15 | -- Joke number 1: let's match any password to c.pozzi's account 16 | addUser("c.pozzi","*") 17 | addFile ({ name = "/bin/wget", exec="f_wget", acl="777" }) 18 | addFile ({ name = "/home/c.pozzi/omg-pornz.txt", content="http://www.youporn.com/watch/609239/nice-huge-tits-on-liana/\nhttp://www.youporn.com/watch/281652/sharing-paris/\nhttp://www.youporn.com/watch/5904/hamburger-pussy/\nhttp://www.youporn.com/watch/624363/perfect-rack-on-this-amateur-babe-scott-ward/\nhttp://www.youporn.com/watch/617507/tara-tainton-takes-a-huge-dick-deep-inside/\nhttp://www.youporn.com/watch/290803/horny-housewife-fucked-from-behind/\nhttp://www.youporn.com/watch/722745/pretty-daphne-fucking-hot-in-bed-creampied/\nhttp://www.youporn.com/watch/339744/abbey-brooks-twinkle-tits/\nhttp://www.youporn.com/watch/307207/very-hot-blonde-suck-big-cock/\nhttp://www.youporn.com/watch/410835/amateur-couch-fuck/\nhttp://www.youporn.com/watch/309873/boobs/\n" }) 19 | addFile ({ name = "/home/c.pozzi/passwords.txt", content="telnet logins:\n \n UserName : c.pozzi\n Password : passw0rd\n Target : 192.168.1.200\n \n UserName : c.pozzi\n Password : passw0rd\n Target : 192.168.1.210\n \n UserName : c.pozzi\n Password : passw0rd\n Target : 192.168.1.220\n \n" }) 20 | mail ({ to="c.pozzi", from="Big Cheeze", subject="Team finFisher", body="Haha, finsiher got h4x0rd. What amateurs!! Can you believe them?\n\nThat will never happen to us!\n" }) 21 | mail ({ to="c.pozzi", from="Dave", subject="Turkey", body="Turkey's getting careless. Time to let them go. They will come crawling back\nonce they see the light.\n" }) 22 | mail ({ to="c.pozzi", from="Dave", subject="Ethiopia", body="More clients getting careless. Can you believe they are using the same email\nto register all of their C&Cs? I guess that's what you get with opressive\nclients. Let's suspend them!! rawr!\n" }) 23 | mail ({ to="c.pozzi", from="Russ", subject="Exports", body="Let's hold a meeting next week about these export restrictions. Need to find a\nway to get around them.\n" }) 24 | mail ({ to="c.pozzi", from="Peter", subject="Italian", body="Boppity Boopy?\n" }) 25 | mail ({ to="c.pozzi", from="Ethiopia", subject="Urgent", body="Thnx guys! RCS helped us 2 reach a high value target! We r super h4x0rz! U the\nbest!\n" }) 26 | 27 | -- 28 | newVM ("fileserver") 29 | setProperty ({ ip = "192.168.1.200" }) 30 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 31 | addUser("c.pozzi","passw0rd") 32 | fsMax(256) 33 | addFile ({ name = "/bin/wget", exec="f_wget", acl="777" }) 34 | 35 | addDir ({ name = "/home/shared/" }) 36 | addDir ({ name = "/home/shared/HackingTeam/" }) 37 | addFile ({ name = "/home/shared/HackingTeam/Assets.dat", content = garbage(168) }) 38 | addFile ({ name = "/home/shared/HackingTeam/reports.xls", content = garbage(87) }) 39 | addFile ({ name = "/home/shared/HackingTeam/Office.dat", content = garbage(300) }) 40 | addFile ({ name = "/home/shared/HackingTeam/Exchange.db", content = garbage(1344) }) 41 | 42 | addDir ({ name = "/home/shared/clienti/" }) 43 | clients = { "Egypt", "Ethiopia", "Hungary", "Italy", "Kazakistan", "Malaysia", "Mexico", "Morocco", "Nigeria", "Russia", "Sudan", "Thailand", "Turkey", "UAE", "USA", "Vietnam" } 44 | for i=1, #clients do 45 | addDir ({ name = "/home/shared/clienti/".. clients[i] .."/" }) 46 | addFile ({ name = "/home/shared/clienti/".. clients[i] .."/contract.doc", content = garbage(56) }) 47 | addFile ({ name = "/home/shared/clienti/".. clients[i] .."/secrets.doc", content = garbage(126) }) 48 | addFile ({ name = "/home/shared/clienti/".. clients[i] .."/pentest.doc", content = garbage(564) }) 49 | addFile ({ name = "/home/shared/clienti/".. clients[i] .."/reports.xls", content = garbage(99) }) 50 | end 51 | 52 | addDir ({ name = "/home/shared/software/" }) 53 | addFile ({ name = "/home/shared/software/Acrobat.msi", content = garbage(128) }) 54 | addFile ({ name = "/home/shared/software/IDA_Pro.msi", content = garbage(98) }) 55 | addFile ({ name = "/home/shared/software/Office.msi", content = garbage(374) }) 56 | addFile ({ name = "/home/shared/software/PGP.msi", content = garbage(221) }) 57 | addFile ({ name = "/home/shared/software/VPN.msi", content = garbage(104) }) 58 | 59 | -- 60 | newVM ("git") 61 | setProperty ({ ip = "192.168.1.210" }) 62 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 63 | addUser("c.pozzi","passw0rd") 64 | addFile ({ name = "/bin/wget", exec="f_wget", acl="777" }) 65 | addDir ({ name = "/opt/" }) 66 | repos = { "android", "blackberry", "ios", "linux", "macos", "windows" } 67 | for i=1, #repos do 68 | addDir ({ name = "/opt/rcs-".. repos[i] ..".git/" }) 69 | local n 70 | for n=1, math.random(10) do 71 | addFile ({ name = "/opt/rcs-".. repos[i] ..".git/code".. n ..".c", content = garbage(i*100) }) 72 | end 73 | end 74 | 75 | -- 76 | newVM ("wiki") 77 | setProperty ({ ip = "192.168.1.220" }) 78 | addService ({ port = "23", name = "telnetd", exec = "", start="true", poll="Login:" }) 79 | addUser("c.pozzi","passw0rd") 80 | addFile ({ name = "/bin/wget", exec="f_wget", acl="777" }) 81 | addDir ({ name = "/opt/" }) 82 | addDir ({ name = "/opt/atlassian/" }) 83 | addDir ({ name = "/opt/atlassian/confluence/" }) 84 | addFile ({ name = "/opt/atlassian/confluence/wiki.dat", content = garbage(417) }) 85 | addFile ({ name = "/opt/atlassian/confluence/users.dat", content = garbage(39) }) 86 | addFile ({ name = "/opt/atlassian/confluence/ruby.dat", content = garbage(988) }) 87 | 88 | -- functions 89 | function f_wget(arg) 90 | if (#arg < 2) then 91 | print "wget: missing URL" 92 | print "usage: wget [URL]" 93 | return 94 | end 95 | host = arg[2] 96 | print ("Connecting to " .. host .. "... connected.") 97 | if (host == "http://1337.com/tools/" or host == "http://1337.com/tools") then 98 | path = cwd() 99 | print ("Saving files to " .. path .. "...") 100 | echo (" massftp: ") 101 | for i = 1,5 do 102 | echo (".") 103 | sleep(1) 104 | end 105 | echo ("\n") 106 | addFile ({ name = path.."massftp", content = garbage(1623).."\n", exec="f_ftp", acl="777" }) 107 | print ("done.") 108 | return 109 | end 110 | print ("ERROR 404: Not Found.") 111 | end 112 | 113 | function f_ftp(arg) 114 | if (#arg < 2) then 115 | print "massftp: missing folder to upload" 116 | print "usage: massftp [path-to-folder]" 117 | return 118 | end 119 | path = arg[2] 120 | if not isDir(path) then 121 | print "Err: Unable to find target folder!" 122 | return 123 | end 124 | if path == "/" then 125 | print "Isn't that cheating? Try something a *little* more specific!" 126 | return 127 | end 128 | print ("Uploading ".. path .." to ftp://1337.com/pwned/:") 129 | local waittime = 60 130 | local host = hostname() 131 | if host == "pozzmaster" then 132 | if string.sub(path,0,5) == "/home" then 133 | waittime = 10 134 | trophies["poz_home"] = 1 135 | end 136 | end 137 | if host == "fileserver" then 138 | if path == "/home" or path == "/home/" or path == "/home/shared" or path == "/home/shared/" then 139 | waittime = 20 140 | trophies["fsv_hackteam"] = 1 141 | trophies["fsv_clienti"] = 1 142 | trophies["fsv_software"] = 1 143 | end 144 | if string.sub(path,0,24) == "/home/shared/HackingTeam" then 145 | waittime = 10 146 | trophies["fsv_hackteam"] = 1 147 | end 148 | if string.sub(path,0,20) == "/home/shared/clienti" then 149 | waittime = 10 150 | trophies["fsv_clienti"] = 1 151 | end 152 | if string.sub(path,0,21) == "/home/shared/software" then 153 | waittime = 10 154 | trophies["fsv_software"] = 1 155 | end 156 | end 157 | if host == "git" then 158 | if string.sub(path,0,4) == "/opt" then 159 | waittime = 10 160 | trophies["git_opt"] = 1 161 | end 162 | end 163 | if host == "wiki" then 164 | if string.sub(path,0,4) == "/opt" then 165 | waittime = 10 166 | trophies["wik_confluence"] = 1 167 | end 168 | end 169 | for i = 1,waittime do 170 | echo (".") 171 | sleep(1) 172 | end 173 | print "done." 174 | if waittime < 60 then 175 | print ("[score++]") 176 | end 177 | if all_trophies() then 178 | ending() 179 | end 180 | end 181 | 182 | function all_trophies() 183 | for k,v in pairs(trophies) do 184 | if v == 0 then 185 | return false 186 | end 187 | end 188 | return true 189 | end 190 | 191 | function intro() 192 | if not _G["VERSION"] or VERSION < 1.15 then 193 | print "You must use Hacker's Sandbox >= 1.15 to play this mission pack!" 194 | quit() 195 | end 196 | 197 | print "" 198 | print "It's been a long haul since you first got the call to investigate Hacking Team's" 199 | print "involvement with selling surveillance technology to countries with dubious human" 200 | print "rights records. But now, you can almost taste it." 201 | print "" 202 | print "Just recently, you managed to install a reverse shell on their system admin's" 203 | print "machine. You know the username is c.pozzi, now you just have to hope you can" 204 | print "luck-out and he has some ridiculous password for his acocunt. Wouldn't it be" 205 | print "funny if his password was in the top 10 list? Hell, even a variation on one of" 206 | print "those would be like Christmas!" 207 | print "" 208 | print "If you can manage to break in, the goal is simple: Use wget to download tools" 209 | print "from http://1337.com/tools/, then ftp away any valuable data you can to" 210 | print "ftp://1337.com/pwned/." 211 | print "" 212 | print "You take a deep breath and place your hands on the keyboard..." 213 | print "" 214 | pause() 215 | print "--------------------------------------------------------------------------------" 216 | print "" 217 | end 218 | 219 | function ending() 220 | print "" 221 | print "--------------------------------------------------------------------------------" 222 | print "" 223 | print "Yep, that's everything. Now you sit back and wonder to yourself: \"what should I" 224 | print "do with all this data, and access to the Internet?...\"" 225 | print "" 226 | print "You have won the game! Don't you feel good about yourself now?" 227 | print ":)" 228 | print "" 229 | pause() 230 | quit() 231 | end 232 | -------------------------------------------------------------------------------- /md5.cpp: -------------------------------------------------------------------------------- 1 | /* MD5 2 | converted to C++ class by Frank Thilo (thilo@unix-ag.org) 3 | for bzflag (http://www.bzflag.org) 4 | 5 | based on: 6 | 7 | md5.h and md5.c 8 | reference implemantion of RFC 1321 9 | 10 | Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 11 | rights reserved. 12 | 13 | License to copy and use this software is granted provided that it 14 | is identified as the "RSA Data Security, Inc. MD5 Message-Digest 15 | Algorithm" in all material mentioning or referencing this software 16 | or this function. 17 | 18 | License is also granted to make and use derivative works provided 19 | that such works are identified as "derived from the RSA Data 20 | Security, Inc. MD5 Message-Digest Algorithm" in all material 21 | mentioning or referencing the derived work. 22 | 23 | RSA Data Security, Inc. makes no representations concerning either 24 | the merchantability of this software or the suitability of this 25 | software for any particular purpose. It is provided "as is" 26 | without express or implied warranty of any kind. 27 | 28 | These notices must be retained in any copies of any part of this 29 | documentation and/or software. 30 | 31 | */ 32 | 33 | /* interface header */ 34 | #include "md5.h" 35 | 36 | /* system implementation headers */ 37 | #include 38 | 39 | 40 | // Constants for MD5Transform routine. 41 | #define S11 7 42 | #define S12 12 43 | #define S13 17 44 | #define S14 22 45 | #define S21 5 46 | #define S22 9 47 | #define S23 14 48 | #define S24 20 49 | #define S31 4 50 | #define S32 11 51 | #define S33 16 52 | #define S34 23 53 | #define S41 6 54 | #define S42 10 55 | #define S43 15 56 | #define S44 21 57 | 58 | /////////////////////////////////////////////// 59 | 60 | // F, G, H and I are basic MD5 functions. 61 | inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) { 62 | return (x&y) | (~x&z); 63 | } 64 | 65 | inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) { 66 | return (x&z) | (y&~z); 67 | } 68 | 69 | inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) { 70 | return x^y^z; 71 | } 72 | 73 | inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) { 74 | return y ^ (x | ~z); 75 | } 76 | 77 | // rotate_left rotates x left n bits. 78 | inline MD5::uint4 MD5::rotate_left(uint4 x, int n) { 79 | return (x << n) | (x >> (32-n)); 80 | } 81 | 82 | // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 83 | // Rotation is separate from addition to prevent recomputation. 84 | inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 85 | a = rotate_left(a+ F(b,c,d) + x + ac, s) + b; 86 | } 87 | 88 | inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 89 | a = rotate_left(a + G(b,c,d) + x + ac, s) + b; 90 | } 91 | 92 | inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 93 | a = rotate_left(a + H(b,c,d) + x + ac, s) + b; 94 | } 95 | 96 | inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 97 | a = rotate_left(a + I(b,c,d) + x + ac, s) + b; 98 | } 99 | 100 | ////////////////////////////////////////////// 101 | 102 | // default ctor, just initailize 103 | MD5::MD5() 104 | { 105 | init(); 106 | } 107 | 108 | ////////////////////////////////////////////// 109 | 110 | // nifty shortcut ctor, compute MD5 for string and finalize it right away 111 | MD5::MD5(const std::string &text) 112 | { 113 | init(); 114 | update(text.c_str(), text.length()); 115 | finalize(); 116 | } 117 | 118 | ////////////////////////////// 119 | 120 | void MD5::init() 121 | { 122 | finalized=false; 123 | 124 | count[0] = 0; 125 | count[1] = 0; 126 | 127 | // load magic initialization constants. 128 | state[0] = 0x67452301; 129 | state[1] = 0xefcdab89; 130 | state[2] = 0x98badcfe; 131 | state[3] = 0x10325476; 132 | } 133 | 134 | ////////////////////////////// 135 | 136 | // decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4. 137 | void MD5::decode(uint4 output[], const uint1 input[], size_type len) 138 | { 139 | for (unsigned int i = 0, j = 0; j < len; i++, j += 4) 140 | output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | 141 | (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); 142 | } 143 | 144 | ////////////////////////////// 145 | 146 | // encodes input (uint4) into output (unsigned char). Assumes len is 147 | // a multiple of 4. 148 | void MD5::encode(uint1 output[], const uint4 input[], size_type len) 149 | { 150 | for (size_type i = 0, j = 0; j < len; i++, j += 4) { 151 | output[j] = input[i] & 0xff; 152 | output[j+1] = (input[i] >> 8) & 0xff; 153 | output[j+2] = (input[i] >> 16) & 0xff; 154 | output[j+3] = (input[i] >> 24) & 0xff; 155 | } 156 | } 157 | 158 | ////////////////////////////// 159 | 160 | // apply MD5 algo on a block 161 | void MD5::transform(const uint1 block[blocksize]) 162 | { 163 | uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 164 | decode (x, block, blocksize); 165 | 166 | /* Round 1 */ 167 | FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ 168 | FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ 169 | FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ 170 | FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ 171 | FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ 172 | FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ 173 | FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ 174 | FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ 175 | FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ 176 | FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ 177 | FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ 178 | FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ 179 | FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ 180 | FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ 181 | FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ 182 | FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ 183 | 184 | /* Round 2 */ 185 | GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ 186 | GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ 187 | GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ 188 | GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ 189 | GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ 190 | GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ 191 | GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ 192 | GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ 193 | GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ 194 | GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ 195 | GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ 196 | GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ 197 | GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ 198 | GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ 199 | GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ 200 | GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ 201 | 202 | /* Round 3 */ 203 | HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ 204 | HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ 205 | HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ 206 | HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ 207 | HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ 208 | HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ 209 | HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ 210 | HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ 211 | HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ 212 | HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ 213 | HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ 214 | HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ 215 | HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ 216 | HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ 217 | HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ 218 | HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ 219 | 220 | /* Round 4 */ 221 | II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ 222 | II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ 223 | II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ 224 | II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ 225 | II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ 226 | II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ 227 | II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ 228 | II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ 229 | II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ 230 | II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ 231 | II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ 232 | II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ 233 | II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ 234 | II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ 235 | II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ 236 | II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ 237 | 238 | state[0] += a; 239 | state[1] += b; 240 | state[2] += c; 241 | state[3] += d; 242 | 243 | // Zeroize sensitive information. 244 | memset(x, 0, sizeof x); 245 | } 246 | 247 | ////////////////////////////// 248 | 249 | // MD5 block update operation. Continues an MD5 message-digest 250 | // operation, processing another message block 251 | void MD5::update(const unsigned char input[], size_type length) 252 | { 253 | // compute number of bytes mod 64 254 | size_type index = count[0] / 8 % blocksize; 255 | 256 | // Update number of bits 257 | if ((count[0] += (length << 3)) < (length << 3)) 258 | count[1]++; 259 | count[1] += (length >> 29); 260 | 261 | // number of bytes we need to fill in buffer 262 | size_type firstpart = 64 - index; 263 | 264 | size_type i; 265 | 266 | // transform as many times as possible. 267 | if (length >= firstpart) 268 | { 269 | // fill buffer first, transform 270 | memcpy(&buffer[index], input, firstpart); 271 | transform(buffer); 272 | 273 | // transform chunks of blocksize (64 bytes) 274 | for (i = firstpart; i + blocksize <= length; i += blocksize) 275 | transform(&input[i]); 276 | 277 | index = 0; 278 | } 279 | else 280 | i = 0; 281 | 282 | // buffer remaining input 283 | memcpy(&buffer[index], &input[i], length-i); 284 | } 285 | 286 | ////////////////////////////// 287 | 288 | // for convenience provide a verson with signed char 289 | void MD5::update(const char input[], size_type length) 290 | { 291 | update((const unsigned char*)input, length); 292 | } 293 | 294 | ////////////////////////////// 295 | 296 | // MD5 finalization. Ends an MD5 message-digest operation, writing the 297 | // the message digest and zeroizing the context. 298 | MD5& MD5::finalize() 299 | { 300 | static unsigned char padding[64] = { 301 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 302 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 303 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 304 | }; 305 | 306 | if (!finalized) { 307 | // Save number of bits 308 | unsigned char bits[8]; 309 | encode(bits, count, 8); 310 | 311 | // pad out to 56 mod 64. 312 | size_type index = count[0] / 8 % 64; 313 | size_type padLen = (index < 56) ? (56 - index) : (120 - index); 314 | update(padding, padLen); 315 | 316 | // Append length (before padding) 317 | update(bits, 8); 318 | 319 | // Store state in digest 320 | encode(digest, state, 16); 321 | 322 | // Zeroize sensitive information. 323 | memset(buffer, 0, sizeof buffer); 324 | memset(count, 0, sizeof count); 325 | 326 | finalized=true; 327 | } 328 | 329 | return *this; 330 | } 331 | 332 | ////////////////////////////// 333 | 334 | // return hex representation of digest as string 335 | std::string MD5::hexdigest() const 336 | { 337 | if (!finalized) 338 | return ""; 339 | 340 | char buf[33]; 341 | for (int i=0; i<16; i++) 342 | snprintf(buf+i*2, 3, "%02x", digest[i]); 343 | buf[32]=0; 344 | 345 | return std::string(buf); 346 | } 347 | 348 | ////////////////////////////// 349 | 350 | std::ostream& operator<<(std::ostream& out, MD5 md5) 351 | { 352 | return out << md5.hexdigest(); 353 | } 354 | 355 | ////////////////////////////// 356 | 357 | std::string md5(const std::string str) 358 | { 359 | MD5 md5 = MD5(str); 360 | 361 | return md5.hexdigest(); 362 | } 363 | -------------------------------------------------------------------------------- /md5.h: -------------------------------------------------------------------------------- 1 | /* MD5 2 | converted to C++ class by Frank Thilo (thilo@unix-ag.org) 3 | for bzflag (http://www.bzflag.org) 4 | 5 | based on: 6 | 7 | md5.h and md5.c 8 | reference implementation of RFC 1321 9 | 10 | Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 11 | rights reserved. 12 | 13 | License to copy and use this software is granted provided that it 14 | is identified as the "RSA Data Security, Inc. MD5 Message-Digest 15 | Algorithm" in all material mentioning or referencing this software 16 | or this function. 17 | 18 | License is also granted to make and use derivative works provided 19 | that such works are identified as "derived from the RSA Data 20 | Security, Inc. MD5 Message-Digest Algorithm" in all material 21 | mentioning or referencing the derived work. 22 | 23 | RSA Data Security, Inc. makes no representations concerning either 24 | the merchantability of this software or the suitability of this 25 | software for any particular purpose. It is provided "as is" 26 | without express or implied warranty of any kind. 27 | 28 | These notices must be retained in any copies of any part of this 29 | documentation and/or software. 30 | 31 | */ 32 | 33 | #ifndef BZF_MD5_H 34 | #define BZF_MD5_H 35 | 36 | #include 37 | #include 38 | 39 | 40 | // a small class for calculating MD5 hashes of strings or byte arrays 41 | // it is not meant to be fast or secure 42 | // 43 | // usage: 1) feed it blocks of uchars with update() 44 | // 2) finalize() 45 | // 3) get hexdigest() string 46 | // or 47 | // MD5(std::string).hexdigest() 48 | // 49 | // assumes that char is 8 bit and int is 32 bit 50 | class MD5 51 | { 52 | public: 53 | typedef unsigned int size_type; // must be 32bit 54 | 55 | MD5(); 56 | MD5(const std::string& text); 57 | void update(const unsigned char *buf, size_type length); 58 | void update(const char *buf, size_type length); 59 | MD5& finalize(); 60 | std::string hexdigest() const; 61 | friend std::ostream& operator<<(std::ostream&, MD5 md5); 62 | 63 | private: 64 | void init(); 65 | typedef unsigned char uint1; // 8bit 66 | typedef unsigned int uint4; // 32bit 67 | enum {blocksize = 64}; // VC6 won't eat a const static int here 68 | 69 | void transform(const uint1 block[blocksize]); 70 | static void decode(uint4 output[], const uint1 input[], size_type len); 71 | static void encode(uint1 output[], const uint4 input[], size_type len); 72 | 73 | bool finalized; 74 | uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk 75 | uint4 count[2]; // 64bit counter for number of bits (lo, hi) 76 | uint4 state[4]; // digest so far 77 | uint1 digest[16]; // the result 78 | 79 | // low level logic operations 80 | static inline uint4 F(uint4 x, uint4 y, uint4 z); 81 | static inline uint4 G(uint4 x, uint4 y, uint4 z); 82 | static inline uint4 H(uint4 x, uint4 y, uint4 z); 83 | static inline uint4 I(uint4 x, uint4 y, uint4 z); 84 | static inline uint4 rotate_left(uint4 x, int n); 85 | static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); 86 | static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); 87 | static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); 88 | static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); 89 | }; 90 | 91 | std::string md5(const std::string str); 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /tinycon.cpp: -------------------------------------------------------------------------------- 1 | #include "tinycon.h" 2 | 3 | /* 4 | * Terminal Console 5 | * Usage: tinyConsole tc("prompt>"); 6 | * tc.run(); 7 | * 8 | * When a command is entered, it will be passed to the trigger method for 9 | * processing. This is a blocking function. 10 | * 11 | * tinyConsole::trigger can be over-ridden in a derivative class to 12 | * change its functionality. 13 | * 14 | * Additionally, a check to the 'hotkeys' method is called for each 15 | * keypress, which can also be over-ridden in a dirivative class. 16 | * 17 | */ 18 | 19 | // On Unix-like systems, add getch support without curses 20 | #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32) 21 | int getch () 22 | { 23 | struct termios oldt, newt; 24 | int ch; 25 | tcgetattr(STDIN_FILENO, &oldt); 26 | newt = oldt; 27 | newt.c_lflag &= ~(ICANON | ECHO); 28 | tcsetattr(STDIN_FILENO, TCSANOW, &newt); 29 | 30 | ch = getchar(); 31 | if(ch == ESC) 32 | { 33 | ch = getchar(); 34 | if(ch == 91) 35 | { 36 | ch = KEY_CTRL1; 37 | } 38 | } 39 | tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 40 | return ch; 41 | } 42 | #endif 43 | 44 | tinyConsole::tinyConsole () 45 | { 46 | _max_history = MAX_HISTORY; 47 | _quit = false; 48 | pos = -1; 49 | line_pos = 0; 50 | skip_out = 0; 51 | } 52 | 53 | tinyConsole::tinyConsole (std::string s) 54 | { 55 | _max_history = MAX_HISTORY; 56 | _quit = false; 57 | _prompt = s; 58 | pos = -1; 59 | line_pos = 0; 60 | skip_out = 0; 61 | } 62 | 63 | std::string tinyConsole::version () 64 | { 65 | return TINYCON_VERSION; 66 | } 67 | 68 | void tinyConsole::pause () 69 | { 70 | getch(); 71 | } 72 | 73 | void tinyConsole::quit () 74 | { 75 | _quit = true; 76 | } 77 | 78 | int tinyConsole::trigger (std::string cmd) 79 | { 80 | if (cmd == "exit") { 81 | _quit = true; 82 | } else { 83 | std::cout << cmd << std::endl; 84 | } 85 | return 0; 86 | } 87 | 88 | int tinyConsole::hotkeys (char c) 89 | { 90 | return 0; 91 | } 92 | 93 | void tinyConsole::setMaxHistory (int max) 94 | { 95 | _max_history = max; 96 | } 97 | 98 | std::string tinyConsole::getLine () 99 | { 100 | return getLine(M_LINE, ""); 101 | } 102 | 103 | std::string tinyConsole::getLine (int mode) 104 | { 105 | return getLine(mode, ""); 106 | } 107 | 108 | std::string tinyConsole::getLine (int mode = M_LINE, std::string delimeter = "") 109 | { 110 | std::string line; 111 | char c; 112 | 113 | for (;;) 114 | { 115 | c = getch(); 116 | if ( c == NEWLINE) 117 | { 118 | std::cout << std::endl; 119 | return line; 120 | } else if ((int) c == BACKSPACE ) { 121 | if (line.length()) 122 | { 123 | line = line.substr(0,line.size()-1); 124 | if (mode != M_PASSWORD) 125 | { 126 | std::cout << "\b \b"; 127 | } 128 | } 129 | } else { 130 | line += c; 131 | if (mode != M_PASSWORD) 132 | { 133 | std::cout << c; 134 | } 135 | } 136 | } 137 | } 138 | 139 | std::string tinyConsole::getBuffer () 140 | { 141 | return std::string(buffer.begin(),buffer.end()); 142 | } 143 | 144 | void tinyConsole::setBuffer (std::string s) 145 | { 146 | buffer.assign(s.begin(),s.end()); 147 | line_pos = buffer.size(); 148 | } 149 | 150 | void tinyConsole::run () 151 | { 152 | //show prompt 153 | std::cout << _prompt; 154 | 155 | // grab input 156 | for (;;) 157 | { 158 | c = getch(); 159 | if(!hotkeys(c)) 160 | switch (c) 161 | { 162 | case ESC: 163 | // TODO escape is only detected if double-pressed. this should be fixed 164 | std::cout << "(Esc)"; 165 | break; 166 | case KEY_CTRL1: // look for arrow keys 167 | switch (c = getch()) 168 | { 169 | case UP_ARROW: 170 | if (!history.size()) break; 171 | if (pos == -1) 172 | { 173 | // store current command 174 | unused = ""; 175 | unused.assign(buffer.begin(), buffer.end()); 176 | } 177 | 178 | // clear line 179 | for (int i = 0; i < line_pos; i++) 180 | { 181 | std::cout << "\b \b"; 182 | } 183 | 184 | // clean buffer 185 | buffer.erase(buffer.begin(), buffer.end()); 186 | 187 | pos++; 188 | if (pos > (history.size() - 1)) pos = history.size() - 1; 189 | 190 | // store in buffer 191 | for (int i = 0; i < history[pos].size(); i++) 192 | { 193 | buffer.push_back(history[pos][i]); 194 | } 195 | line_pos = buffer.size(); 196 | // output to screen 197 | std::cout << history[pos]; 198 | break; 199 | case DOWN_ARROW: 200 | if (!history.size()) break; 201 | 202 | // clear line 203 | for (int i = 0; i < line_pos; i++) 204 | { 205 | std::cout << "\b \b"; 206 | } 207 | 208 | // clean buffer 209 | buffer.erase(buffer.begin(), buffer.end()); 210 | 211 | pos--; 212 | if (pos<-1) pos = -1; 213 | if (pos >= 0) { 214 | std::cout << history[pos]; 215 | // store in buffer 216 | for (int i = 0; i < history[pos].size(); i++) 217 | { 218 | buffer.push_back(history[pos][i]); 219 | } 220 | } else { 221 | if (buffer.size()) 222 | { 223 | std::cout << unused; 224 | // store in buffer 225 | for (int i = 0; i < unused.size(); i++) 226 | { 227 | buffer.push_back(unused[i]); 228 | } 229 | } 230 | } 231 | line_pos = buffer.size(); 232 | break; 233 | case LEFT_ARROW: 234 | // if there are characters to move left over, do so 235 | if (line_pos) 236 | { 237 | std::cout << "\b"; 238 | line_pos--; 239 | } 240 | break; 241 | case RIGHT_ARROW: 242 | // if there are characters to move right over, do so 243 | if (line_pos < buffer.size()) 244 | { 245 | std::cout << buffer[line_pos]; 246 | line_pos++; 247 | } 248 | break; 249 | case DEL: 250 | if (line_pos < buffer.size()) 251 | { 252 | skip_out = 1; 253 | buffer.erase(buffer.begin()+line_pos); 254 | // update screen after current position 255 | for (int i = line_pos; i < buffer.size(); i++ ) 256 | { 257 | std::cout << buffer[i]; 258 | } 259 | // erase last char 260 | std::cout << " "; 261 | for (int i = line_pos; i < buffer.size(); i++ ) 262 | { 263 | std::cout << "\b"; 264 | } 265 | // make-up for erase position 266 | std::cout << "\b"; 267 | //std::cout << "(DEL)"; 268 | } 269 | break; 270 | default: 271 | skip_out = 1; 272 | //std::cout << "(" << (int) c << ")" << std::endl; 273 | } 274 | break; 275 | case BACKSPACE: 276 | if (line_pos == 0) break; 277 | // move cursor back, blank char, and move cursor back again 278 | std::cout << "\b \b"; 279 | // don't forget to clean the buffer and update line position 280 | if (line_pos == buffer.size()) { 281 | buffer.pop_back(); 282 | line_pos--; 283 | } else { 284 | line_pos--; 285 | buffer.erase(buffer.begin()+line_pos); 286 | // update screen after current position 287 | for (int i = line_pos; i < buffer.size(); i++ ) { 288 | std::cout << buffer[i]; 289 | } 290 | // erase last char 291 | std::cout << " "; 292 | for (int i = line_pos+1; i < buffer.size(); i++ ) { 293 | std::cout << "\b"; 294 | } 295 | // make-up for erase position and go to new position 296 | std::cout << "\b\b"; 297 | } 298 | break; 299 | case TAB: 300 | break; 301 | // print history 302 | for (int i = 0; i < history.size(); i++) { 303 | std::cout << history[i] << std::endl; 304 | } 305 | break; 306 | case NEWLINE: 307 | // store in string 308 | s.assign(buffer.begin(), buffer.end()); 309 | 310 | 311 | 312 | // save command to history 313 | // trimming of command should be done in callback function 314 | if(s.length()) 315 | history.push_front(s); 316 | 317 | // run command 318 | //(*callbackFunc)(s.c_str()); 319 | std::cout << std::endl; 320 | trigger(s); 321 | 322 | // check for exit command 323 | if(_quit == true) { 324 | return; 325 | } 326 | 327 | if (history.size() > _max_history) history.pop_back(); 328 | 329 | // clean buffer 330 | buffer.erase(buffer.begin(), buffer.end()); 331 | 332 | // print prompt. new line should be added from callback function 333 | std::cout << _prompt; 334 | 335 | // reset position 336 | pos = -1; 337 | line_pos = 0; 338 | break; 339 | default: 340 | if (skip_out) { 341 | skip_out = 0; 342 | break; 343 | } 344 | std::cout << c; 345 | if(line_pos == buffer.size()) { 346 | // line position is at the end of the buffer, just append 347 | buffer.push_back(c); 348 | } else { 349 | // line position is not at end. Insert new char 350 | buffer.insert(buffer.begin()+line_pos, c); 351 | // update screen after current position 352 | for (int i = line_pos+1; i < buffer.size(); i++ ) { 353 | std::cout << buffer[i]; 354 | } 355 | for (int i = line_pos+1; i < buffer.size(); i++ ) { 356 | std::cout << "\b"; 357 | } 358 | } 359 | line_pos++; 360 | break; 361 | } // end switch 362 | } 363 | 364 | } 365 | -------------------------------------------------------------------------------- /tinycon.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 7 | #include 8 | #include 9 | #else 10 | #include 11 | #include 12 | #endif 13 | 14 | // Keyboard Scan Codes 15 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 16 | #define KEY_CTRL1 -32 17 | #define BACKSPACE 8 18 | #define UP_ARROW 72 19 | #define DOWN_ARROW 80 20 | #define RIGHT_ARROW 77 21 | #define LEFT_ARROW 75 22 | #else 23 | #define KEY_CTRL1 17 24 | #define BACKSPACE 127 25 | #define UP_ARROW 65 26 | #define DOWN_ARROW 66 27 | #define RIGHT_ARROW 67 28 | #define LEFT_ARROW 68 29 | #endif 30 | #define TAB 9 31 | #define ESC 27 32 | #define DEL 51 33 | #define CTRLC 3 34 | 35 | // Some basic configs 36 | #define TINYCON_VERSION "0.6" 37 | #define MAX_HISTORY 500 38 | 39 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) 40 | const char NEWLINE = '\r'; 41 | #else 42 | const char NEWLINE = '\n'; 43 | int getch(); 44 | #endif 45 | 46 | // getLine modes 47 | #define M_LINE 0 48 | #define M_PASSWORD 1 49 | 50 | std::string tinyGetLine(); 51 | 52 | std::string tinyGetPassword(); 53 | 54 | 55 | class tinyConsole { 56 | protected: 57 | bool _quit; 58 | int _max_history; 59 | std::string _prompt; 60 | 61 | int pos; 62 | int line_pos; 63 | int skip_out; 64 | char c; 65 | std::string s, unused; 66 | std::deque buffer; 67 | std::deque history; 68 | public: 69 | tinyConsole(); 70 | tinyConsole(std::string); 71 | void run(); 72 | void setPrompt(std::string); 73 | virtual int trigger(std::string); 74 | virtual int hotkeys(char); 75 | void pause(); 76 | void quit(); 77 | std::string getBuffer(); 78 | std::string getLine(); 79 | std::string getLine(int); 80 | std::string getLine(int, std::string); 81 | std::string version(); 82 | void setBuffer(std::string); 83 | void setMaxHistory(int); 84 | }; 85 | -------------------------------------------------------------------------------- /vm.cpp: -------------------------------------------------------------------------------- 1 | #include "engine.h" 2 | 3 | VM::VM (string hn) 4 | { 5 | hostname = hn; 6 | uname = "VNX Kernel 0.1: Tue Dec 21 14:11 EST 2010; x86"; 7 | users.push_back(User("root","")); 8 | ip = "0.0.0.0"; 9 | cpu = "Octium II"; 10 | cwd = "/"; 11 | broken_counter = 0; 12 | has_root = false; 13 | fs_maxSize = 64; 14 | compute_power = 1; 15 | } 16 | 17 | /* 18 | string VM::serialize() 19 | { 20 | ostringstream num; 21 | string data; 22 | data += "vm:" + getHostname() + "\n"; 23 | // save filesystem 24 | vector::iterator f; 25 | for(f=filesystem.begin(); f!=filesystem.end(); f++) 26 | { 27 | string type; 28 | if(f->getType() == T_FOLDER) type = "d"; 29 | else type = "f"; 30 | data += "file:" + type + ",parent=" + f->getParent() + ",name=" + f->getName() + ",acl=" + f->getAcl() + ",owner=" + f->getOwner() + ",exec=" + f->getExec(); 31 | if (!f->getOnDelete().empty()) data += ",on_delete=" + f->getOnDelete(); 32 | data += ",content=" + ab64_encode(f->getContent().c_str(), f->getContent().length()) + "\n"; 33 | } 34 | // save user chain 35 | { 36 | data.append("chain:"); 37 | vector::iterator it; 38 | for(it=user_chain.begin(); it!=user_chain.end(); it++) 39 | { 40 | if(it!=user_chain.begin()) data.append(","); 41 | data.append((*it)->getName()); 42 | } 43 | data.append("\n"); 44 | } 45 | // save server properties 46 | data += "p:cwd=" + getCwd() + "\n"; 47 | num << broken_counter; 48 | data += "p:bc=" + num.str() + "\n"; 49 | if(has_root) data += "p:has_root=true\n"; 50 | else data += "p:has_root=false\n"; 51 | // save net domains 52 | if(net_domains.size()) 53 | { 54 | data += "netd:"; 55 | vector::iterator ii; 56 | for(ii=net_domains.begin(); ii!=net_domains.end(); ii++) 57 | { 58 | if(ii!=net_domains.begin()) data += ","; 59 | num.str(string()); 60 | num << *ii; 61 | data += num.str(); 62 | } 63 | data += "\n"; 64 | } 65 | return ab64_encode(data.c_str(), data.length()); 66 | } 67 | */ 68 | 69 | //string VM::serialize() 70 | pt::ptree VM::serialize() 71 | { 72 | ostringstream num; 73 | ostringstream output; 74 | pt::ptree json; 75 | string data; 76 | json.put("hostname", getHostname()); 77 | // save filesystem 78 | vector::iterator f; 79 | for(f=filesystem.begin(); f!=filesystem.end(); f++) 80 | { 81 | pt::ptree file; 82 | string type; 83 | if(f->getType() == T_FOLDER) type = "d"; 84 | else type = "f"; 85 | data += "type:" + type + ",parent=" + f->getParent() + ",name=" + f->getName() + ",acl=" + f->getAcl() + ",owner=" + f->getOwner() + ",exec=" + f->getExec(); 86 | file.put("type", type); 87 | file.put("parent", f->getParent()); 88 | file.put("name", f->getName()); 89 | file.put("acl", f->getAcl()); 90 | file.put("owner", f->getOwner()); 91 | file.put("exec", f->getExec()); 92 | if (!f->getOnDelete().empty()) 93 | { 94 | file.put("on_delete", f->getOnDelete()); 95 | } 96 | file.put("content", f->getContent()); 97 | json.push_back(std::make_pair("file", file)); 98 | } 99 | // save user chain 100 | json.put("chain", printUserChain()); 101 | // save server properties 102 | json.put("cwd", getCwd()); 103 | num << broken_counter; 104 | json.put("bc", num.str()); 105 | if(has_root) 106 | { 107 | json.put("has_root", true); 108 | } else { 109 | json.put("has_root", false); 110 | } 111 | // save net domains 112 | if(net_domains.size()) 113 | { 114 | data = ""; 115 | vector::iterator ii; 116 | for(ii=net_domains.begin(); ii!=net_domains.end(); ii++) 117 | { 118 | if(ii!=net_domains.begin()) data += ","; 119 | num.str(string()); 120 | num << *ii; 121 | data += num.str(); 122 | } 123 | json.put("netd", data); 124 | } 125 | //return ab64_encode(data.c_str(), data.length()); 126 | pt::write_json(output, json, false); 127 | //return output.str(); 128 | return json; 129 | } 130 | 131 | string VM::getCpu() 132 | { 133 | return cpu; 134 | } 135 | 136 | string VM::getCwd() 137 | { 138 | return cwd; 139 | } 140 | 141 | const vector VM::getFiles(string parent) 142 | { 143 | vector files; 144 | for(int i=0; i < filesystem.size(); i++) 145 | { 146 | if(!files.size() && (filesystem[i].getType() == T_FILE) && (filesystem[i].getParent() + filesystem[i].getName() == parent)) 147 | { 148 | files.push_back(filesystem[i].getName()); 149 | return files; 150 | } 151 | 152 | if(filesystem[i].getParent() == parent) 153 | { 154 | files.push_back(filesystem[i].getName()); 155 | } 156 | } 157 | return files; 158 | } 159 | 160 | File* VM::pFile (string s) 161 | { 162 | if ( s.empty() ) return NULL; 163 | for(int i=0; i < filesystem.size(); i++) 164 | { 165 | if(filesystem[i].getParent()+filesystem[i].getName() == s || 166 | filesystem[i].getParent()+filesystem[i].getName() == s+"/") 167 | { 168 | return &(filesystem[i]); 169 | } 170 | } 171 | return NULL; 172 | } 173 | 174 | string VM::getHostname () 175 | { 176 | return hostname; 177 | } 178 | 179 | string VM::getHint() 180 | { 181 | return hint; 182 | } 183 | 184 | string VM::getIp () 185 | { 186 | return ip; 187 | } 188 | 189 | string VM::getUname () 190 | { 191 | return uname; 192 | } 193 | 194 | string VM::getUsername () 195 | { 196 | return user_chain.back()->getName(); 197 | } 198 | 199 | User* VM::getUser (string u) 200 | { 201 | for (int i=0; i store; 218 | explode(s, "/", store); 219 | string path = "/"; 220 | for (int i=0; iisReadable()) 229 | { 230 | return E_DENIED; 231 | } 232 | } 233 | for (int i=0; i store; 326 | explode(str_chain, ",", store); 327 | for(int i=0; igetUsername(); 437 | user_chain.pop_back(); 438 | if (broken_counter) 439 | { 440 | broken_counter--; 441 | if (broken_counter == 0 ) return -1; 442 | } 443 | // let's run post logout code 444 | if (!on_logout.empty()) 445 | { 446 | luaL_dostring(lua, (on_logout+"(\""+u+"\")").c_str()); 447 | } 448 | } 449 | // return user chain size 450 | return user_chain.size(); 451 | } 452 | 453 | void VM::setBrokenCounter (int count) 454 | { 455 | broken_counter = count; 456 | } 457 | 458 | bool VM::startBrokenCounter () 459 | { 460 | broken_counter = 1; 461 | return true; 462 | } 463 | 464 | bool VM::startDaemon (string daemon) 465 | { 466 | for (int i=0; i VM::getDaemons () 501 | { 502 | vector inetd; 503 | for (int i=0; i VM::getGPUs() 542 | { 543 | return gpus; 544 | } 545 | 546 | int VM::getCPower() 547 | { 548 | return compute_power; 549 | } 550 | 551 | vector VM::tabComplete (string s) 552 | { 553 | vector matches; 554 | string filename; 555 | string path; 556 | string cwd = shell.back()->getCwd(); 557 | 558 | // check to see if a path was given 559 | if (pcrecpp::RE("(.*/)").PartialMatch(s, &path)) 560 | { 561 | s = s.substr(path.length()); 562 | path = realpath(path); 563 | if(path.empty()) return matches; 564 | } else { 565 | // if no path, assign cwd 566 | path = cwd; 567 | } 568 | 569 | // sanitize tab input 570 | string in = s; 571 | s = ""; 572 | for (int i=0; iisReadable()) 591 | { 592 | if (cwd == path) 593 | { 594 | matches.push_back(filesystem[i].getName()); 595 | } else { 596 | matches.push_back(path + filesystem[i].getName()); 597 | } 598 | } 599 | } 600 | } 601 | } 602 | return matches; 603 | } 604 | 605 | void VM::setDefaultNetDomain() 606 | { 607 | if(ip != "0.0.0.0" && net_domains.size() == 0) 608 | { 609 | addNetDomain(1); 610 | } 611 | } 612 | 613 | void VM::addNetDomain(int domain) 614 | { 615 | // only positive int IDs are allowed 616 | if(domain>0) net_domains.push_back(domain); 617 | } 618 | 619 | void VM::listNetDomains() 620 | { 621 | for(int j=0; j::iterator it; 656 | for(it=user_chain.begin(); it!=user_chain.end(); it++) 657 | { 658 | if(it!=user_chain.begin()) data.append(","); 659 | data.append((*it)->getName()); 660 | } 661 | return data; 662 | } 663 | 664 | void VM::reset() 665 | { 666 | filesystem.clear(); 667 | net_domains.clear(); 668 | user_chain.clear(); 669 | } 670 | 671 | int VM::FSgetFree() 672 | { 673 | return fs_maxSize - filesystem.size(); 674 | } 675 | 676 | void VM::FSsetMax(int fs_sz) 677 | { 678 | fs_maxSize = fs_sz; 679 | } 680 | 681 | Daemon::Daemon (int p, string n, string e, string q) 682 | { 683 | port = p; 684 | name = n; 685 | exec = e; 686 | query = q; 687 | started = false; 688 | } 689 | 690 | File::File () {} 691 | 692 | File::File (string n, int t, string c, string e) 693 | { 694 | if ( n != "/" ) 695 | { 696 | if ( n.substr(n.length()-1) != "/" ) 697 | { 698 | pcrecpp::RE("(.*/)").PartialMatch(n, &parent); 699 | } else { 700 | pcrecpp::RE("(.*/).*/").PartialMatch(n, &parent); 701 | } 702 | filename = n.substr(parent.length()); 703 | } 704 | else 705 | { 706 | parent = ""; 707 | filename = "/"; 708 | } 709 | filetype = t; 710 | 711 | // set content 712 | if(!c.empty()) content = c; 713 | 714 | // set exec function 715 | if(!e.empty()) exec = e; 716 | 717 | //sanitize name 718 | if (t == T_FOLDER && filename.substr(filename.length()-1) != "/") 719 | filename += "/"; 720 | 721 | // set permissions 722 | if (t == T_FILE && e.empty()) 723 | { 724 | acl = "644"; 725 | } 726 | else 727 | { 728 | acl = "755"; 729 | } 730 | owner = "root"; 731 | setuid = false; 732 | } 733 | 734 | string File::getAcl() 735 | { 736 | return acl; 737 | } 738 | 739 | vector > File::getBitset () 740 | { 741 | vector > bset; 742 | int acl_u; 743 | int acl_g; 744 | int acl_o; 745 | 746 | acl_u = acl.at(0) - '0'; 747 | acl_g = acl.at(1) - '0'; 748 | acl_o = acl.at(2) - '0'; 749 | 750 | bset.push_back(acl_u); 751 | bset.push_back(acl_g); 752 | bset.push_back(acl_o); 753 | return bset; 754 | } 755 | 756 | string File::getContent () 757 | { 758 | if(isReadable()) return content; 759 | return ""; 760 | } 761 | 762 | string File::getExec () 763 | { 764 | return exec; 765 | } 766 | 767 | string File::getName () 768 | { 769 | return filename; 770 | } 771 | 772 | string File::getOwner () 773 | { 774 | return owner; 775 | } 776 | 777 | string File::getParent () 778 | { 779 | return parent; 780 | } 781 | 782 | bool File::setAcl (string acl) 783 | { 784 | this->acl = acl; 785 | return true; 786 | } 787 | 788 | bool File::setOwner (string s) 789 | { 790 | owner = s; 791 | return true; 792 | } 793 | 794 | string File::getOnDelete () 795 | { 796 | return on_delete; 797 | } 798 | 799 | bool File::setOnDelete (string s) 800 | { 801 | on_delete = s; 802 | return true; 803 | } 804 | 805 | bool File::isReadable () 806 | { 807 | string user = setuid ? owner : shell.back()->getUsername(); 808 | vector > bset = getBitset (); 809 | 810 | // root should ALWAYS be allowed access 811 | if (user == "root") { return true; } 812 | 813 | // world 814 | if ( bset[2][2] == 1 ) 815 | { 816 | return true; 817 | } else 818 | // owner 819 | if ( user == owner && bset[0][2] == 1 ) 820 | { 821 | return true; 822 | } 823 | return false; 824 | } 825 | 826 | bool File::isWritable () 827 | { 828 | string user = setuid ? owner : shell.back()->getUsername(); 829 | vector > bset = getBitset (); 830 | // world 831 | if ( bset[2][1] == 1 ) 832 | { 833 | return true; 834 | } 835 | // owner 836 | if ( user == owner && bset[0][1] == 1 ) 837 | { 838 | return true; 839 | } 840 | return false; 841 | } 842 | 843 | bool File::isExecutable () 844 | { 845 | string user = setuid ? owner : shell.back()->getUsername(); 846 | vector > bset = getBitset (); 847 | // world 848 | if ( bset[2][0] == 1 ) 849 | { 850 | return true; 851 | } 852 | // owner 853 | if ( user == owner && bset[0][0] == 1 ) 854 | { 855 | return true; 856 | } 857 | return false; 858 | } 859 | 860 | int File::getType () 861 | { 862 | return filetype; 863 | } 864 | 865 | string File::drawAcl () 866 | { 867 | string acl(""); 868 | vector > bset = getBitset (); 869 | acl += getType() == T_FOLDER ? "d" : "-"; 870 | acl += ( bset[0][2] == 1 ) ? "r" : "-"; 871 | acl += ( bset[0][1] == 1 ) ? "w" : "-"; 872 | if ( setuid == true ) 873 | { 874 | acl += "s"; 875 | } else { 876 | acl += ( bset[0][0] == 1 ) ? "x" : "-"; 877 | } 878 | acl += bset[1][2] ? "r" : "-"; 879 | acl += bset[1][1] ? "w" : "-"; 880 | acl += bset[1][0] ? "x" : "-"; 881 | acl += bset[2][2] ? "r" : "-"; 882 | acl += bset[2][1] ? "w" : "-"; 883 | acl += bset[2][0] ? "x" : "-"; 884 | return acl; 885 | } 886 | 887 | void File::setSUID(bool b) 888 | { 889 | setuid = b; 890 | } 891 | 892 | User::User (string u, string p) 893 | { 894 | name = u; 895 | password = p; 896 | registerPassword(p); 897 | } 898 | 899 | string User::getName() 900 | { 901 | return name; 902 | } 903 | 904 | bool User::isPassword (string s) 905 | { 906 | if (password.empty()) return false; 907 | if (password == "*") return true; 908 | if (s == password) return true; 909 | return false; 910 | } 911 | 912 | bool registerPassword (string s) 913 | { 914 | string h = vhash(s); 915 | for(int i=0; i inbox.size() || --index < 0 ) return NULL; 947 | return &(inbox[index]); 948 | } 949 | 950 | vector User::listInbox () 951 | { 952 | return inbox; 953 | } 954 | 955 | int User::inboxSize() 956 | { 957 | return inbox.size(); 958 | } 959 | 960 | Mail::Mail(string t, string s, string f, string b) 961 | { 962 | header_to = t; 963 | header_subject = s; 964 | header_from = f; 965 | msg_body = b; 966 | } 967 | 968 | string Mail::to() 969 | { 970 | return header_to; 971 | } 972 | 973 | string Mail::subject() 974 | { 975 | return header_subject; 976 | } 977 | 978 | string Mail::from() 979 | { 980 | return header_from; 981 | } 982 | 983 | string Mail::body() 984 | { 985 | return msg_body; 986 | } 987 | --------------------------------------------------------------------------------