├── LICENSE.md ├── README.md ├── compiler.js └── index.html /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Dylan Katz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This project is no longer mainained. Please see [The new repo](https://github.com/Dukweeno/Duckuino). 2 | 3 | Duckuino 4 | ======== 5 | 6 | An unofficial Duckyscript to Arduino converter This program was tested on an Arduino Micro, 7 | but should work just as well on the leonardo or other models that support the keyboard library. 8 | To run this program, simply download the repository and open "Duckuino.html" in your web browser. 9 | Paste the duckyscript into the left box, and press "Compile". Your Arduino code will appear in the box on the right. 10 | **Please note that I am not affiliated with Arduino or Hak5.** 11 | Enjoy! 12 | -------------------------------------------------------------------------------- /compiler.js: -------------------------------------------------------------------------------- 1 | var functions = ["ALT", "GUI", "CTRL", "CONTROL", "SHIFT", "WINDOWS", "COMMAND", "MENU", "ESC", "END", "SPACE", "TAB", "PRINTSCREEN", "ENTER", 2 | "UPARROW", "DOWNARROW", "LEFTARROW", "RIGHTARROW", "CAPSLOCK", "DELETE"]; 3 | var mappings = ["KEY_LEFT_ALT", "KEY_LEFT_GUI", "KEY_LEFT_CTRL", "KEY_LEFT_CTRL", "KEY_LEFT_SHIFT", "KEY_LEFT_GUI", "KEY_LEFT_GUI", "229", 4 | "KEY_LEFT_ESC", "KEY_END", "' '", "KEY_TAB", "206", "KEY_RETURN", "KEY_UP_ARROW", "KEY_DOWN_ARROW", "KEY_LEFT_ARROW", "KEY_RIGHT_ARROW", "KEY_CAPS_LOCK", "KEY_DELETE"]; 5 | //the 229 is due to 6 | //arduino's conversion method, it's the mapping 7 | //for key code 93 or the menu key. 8 | //The same concept applies to 206 and the printscreen key. 9 | function parseScript(){ 10 | var input = document.getElementById("duckyscript").value; 11 | var lines = input.toUpperCase().split('\n'); 12 | lines = cleanDuplicateFunctions(lines); 13 | var outputLines = []; 14 | for(var i = 0; i < lines.length; i++) { 15 | var line = lines[i].trim(); 16 | var firstWord = line.split(" ",1)[0]; 17 | 18 | switch(firstWord) { 19 | case "STRING": { 20 | line = printKeys(line.replace(" ", "").substr(6)); 21 | outputLines[i] = line; 22 | break; 23 | }; 24 | case "DELAY": { 25 | line = replaceFunctionWhereNeeded(line, "DELAY ", "delay"); 26 | outputLines[i] = line; 27 | break; 28 | }; 29 | case "REM": { 30 | line = line.replace("REM ", "//"); 31 | outputLines[i] = line; 32 | break; 33 | } 34 | } 35 | if(firstWord === "STRING" || firstWord === "DELAY" || firstWord === "REM") 36 | continue; 37 | line = line.replace(/ F([0-9]{1,2})([$\s])/g, "Keyboard.press(KEY_F$1);$2" ); 38 | var isModifier = functions.indexOf(firstWord) > -1; 39 | var keysToPress = JSON.parse(JSON.stringify(line)); 40 | for(var j = 0; j <= functions.length; j++) { 41 | keysToPress = keysToPress.replace(functions[j], ""); 42 | } 43 | if(isModifier) 44 | keysToPress = pressKeys(keysToPress); 45 | line = insertFunctions(line); 46 | 47 | if(isModifier) { 48 | line = line.split(" ")[0] + keysToPress + "\nKeyboard.releaseAll();"; 49 | } 50 | outputLines[i] = " " + line; 51 | } 52 | var output = outputLines.join("\n"); 53 | output = "\n/* Converted by Duckuino:" 54 | +"\n* https://forums.hak5.org/index.php?/topic/32719-payload-converter-duckuino-duckyscript-to-arduino/?p=244590" 55 | +"\n* Enjoy!" 56 | +"\n*/" 57 | + "\nvoid setup() {" 58 | + "\n Keyboard.begin();" 59 | + "\n" + output; 60 | output += "\nKeyboard.end();"+ 61 | "\n}"; 62 | output +="\nvoid type(int key, boolean release) {" 63 | + "\n Keyboard.press(key);" 64 | +"\n if(release)" 65 | + "\n Keyboard.release(key);" 66 | +"\n}"; 67 | output +="\nvoid print(const __FlashStringHelper *value) {" //This is used to reduce the amount of memory strings take. 68 | +"\n Keyboard.print(value);" 69 | +"\n}"; 70 | 71 | output +="\nvoid loop(){}" 72 | document.getElementById("arduinoout").textContent = output; 73 | } 74 | /* 75 | * Insert all proper functions on 'line' 76 | */ 77 | function insertFunctions(line) { 78 | var firstWord = line.split(" ",1)[0]; 79 | if(functions.indexOf(firstWord) == -1) { 80 | for(var i = 0; i < mappings.length; i++) { //not functions.length so we don't deal with delay here. 81 | line = replaceValWhereNeeded(line, functions[i], "\ntype(" + mappings[i] + ",false);"); 82 | } 83 | } else { 84 | for(var i = 0; i < mappings.length; i++) { //not functions.length so we don't deal with delay here. 85 | line = replaceValWhereNeeded(line, functions[i], "\ntype(" + mappings[i] + ",false);"); 86 | } 87 | 88 | } 89 | return line 90 | } 91 | //Press and release keys 92 | function typeKeys(keys) { 93 | var keyStr = ""; 94 | if(keys === '') { //Just to be sure. 95 | return ""; 96 | } 97 | for(var i = 0; i < keys.length; i++) { 98 | if(keys.charAt(i) == ' ') 99 | continue; 100 | keyStr += i != 0 ? "\n" : ""; 101 | keyStr += "\n type(" + keys.charCodeAt(i) + ",true);"; 102 | } 103 | return keyStr; 104 | } 105 | //Press and release keys to form a string 106 | function printKeys(keys) { 107 | var keyStr = ""; 108 | keys = keys.replace(/\\/g, "\\\\"); 109 | keys = keys.replace(/"/g, "\\\""); 110 | keyStr = "\nprint(F(\""+keys+"\"));" 111 | return keyStr; 112 | } 113 | //Press a key down, but don't release it just yet 114 | function pressKeys(keys) { 115 | if(keys === keys.trim()) { //Just to be sure. 116 | return ""; 117 | } 118 | var keyStr = ""; 119 | var hasFoundSpecial = false; 120 | for(var i = 0; i < functions.length; i++) { 121 | if(keys.indexOf(functions[i]) != -1) { 122 | keys = keys.replace(functions[i], ""); 123 | hasFoundSpecial = true; 124 | console.log("Found special!"); 125 | keyStr += "\n" + functions[i]; 126 | } 127 | } 128 | keys = keys.replace(/\\/g, "\\\\"); 129 | keys = keys.replace(/"/g, "\\\""); 130 | if(keys.charAt(1) == '') 131 | return keyStr; 132 | if(!hasFoundSpecial) { 133 | keyStr += "\ntype('" + keys.charAt(1) + "',false);"; 134 | } 135 | return keyStr; 136 | } 137 | //Check if value exists in line, if so, replace it 138 | function replaceValWhereNeeded(line, orig, replacement) { 139 | if(line.indexOf(orig) == -1) 140 | return line; 141 | return line.replace(orig, replacement); 142 | } 143 | //A similar function to replaceValWhereNeeded, but surrounding arguments with parentheses and adding ';\n' 144 | function replaceFunctionWhereNeeded(line, orig, funcname) { 145 | if(line.indexOf(orig) == -1) 146 | return line; 147 | var outputVal = line.replace(orig, funcname + "("); 148 | outputVal += ");"; 149 | return outputVal; 150 | } 151 | function cleanDuplicateFunctions(lines) { 152 | var tmpLines = lines; 153 | var blocks = generateFunctionBlocks(tmpLines); 154 | for(var i = 0; i < blocks.length; i++) { 155 | tmpLines.splice(blocks[i].index, blocks[i].length, "for(int i = 0; i < "+blocks[i].length + "; i++) { ", blocks[i].func, "}"); 156 | } 157 | return tmpLines; 158 | } 159 | function generateFunctionBlocks(lines) { 160 | var tmpLines = lines; 161 | var blocks = []; 162 | for(var i = 0; i < tmpLines.length-1; i++) { 163 | if(tmpLines[i+1] === tmpLines[i]) { 164 | var block = blockFactoryGo(); 165 | block.index = i; 166 | var blockLen = 1; 167 | while(tmpLines[i+blockLen] === tmpLines[i]) { 168 | blockLen++; 169 | } 170 | block.func = tmpLines[i]; 171 | block.length = blockLen; 172 | blocks.push(block); 173 | i+=blockLen; 174 | } 175 | } 176 | return blocks; 177 | } 178 | function blockFactoryGo() { 179 | var block = { 180 | func: "", 181 | index: 0, 182 | length: 0 183 | } 184 | return block 185 | } 186 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 |