├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── README.md ├── String Obfuscator definition.postman_collection.json ├── mvnw ├── mvnw.cmd ├── pom.xml ├── src ├── main │ ├── java │ │ └── com │ │ │ └── satsana │ │ │ └── so │ │ │ ├── StringObfuscatorApplication.java │ │ │ ├── controllers │ │ │ └── ObfuscationServiceController.java │ │ │ ├── engine │ │ │ ├── model │ │ │ │ ├── Context.java │ │ │ │ ├── Engine.java │ │ │ │ ├── GenerationTarget.java │ │ │ │ ├── PolymorphicEngine.java │ │ │ │ └── TransformationChain.java │ │ │ ├── transforms │ │ │ │ ├── Add.java │ │ │ │ ├── MulMod.java │ │ │ │ ├── MulModInv.java │ │ │ │ ├── Not.java │ │ │ │ ├── Permutation.java │ │ │ │ ├── RotateLeft.java │ │ │ │ ├── RotateRight.java │ │ │ │ ├── Substract.java │ │ │ │ ├── Xor.java │ │ │ │ └── model │ │ │ │ │ ├── Modulus.java │ │ │ │ │ ├── Rotation.java │ │ │ │ │ └── Transformation.java │ │ │ └── visitors │ │ │ │ ├── BashVisitor.java │ │ │ │ ├── CSharpVisitor.java │ │ │ │ ├── CVisitor.java │ │ │ │ ├── JavaScriptVisitor.java │ │ │ │ ├── JavaVisitor.java │ │ │ │ ├── LanguageVisitor.java │ │ │ │ ├── Masm64Visitor.java │ │ │ │ ├── PowerShellVisitor.java │ │ │ │ ├── PythonVisitor.java │ │ │ │ └── Visitor.java │ │ │ └── services │ │ │ ├── ObfuscationService.java │ │ │ └── ObfuscationServiceImpl.java │ └── resources │ │ └── application.properties └── test │ └── java │ └── com │ └── satsana │ └── so │ ├── engines │ ├── BashEngineTest.java │ ├── CEngineTest.java │ ├── CSharpEngineTest.java │ ├── JavaEngineTest.java │ ├── JavaScriptEngineTest.java │ ├── Masm64EngineTest.java │ ├── PowerShellEngineTest.java │ ├── PythonEngineTest.java │ └── TestsUtil.java │ ├── suites │ └── EnginesTestSuite.java │ └── transformations │ └── TransformationsTest.java └── string-obfuscator-1.0.0.jar /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | 35 | # Compiled class file 36 | *.class 37 | 38 | # Log file 39 | *.log 40 | 41 | # BlueJ files 42 | *.ctxt 43 | 44 | # Mobile Tools for Java (J2ME) 45 | .mtj.tmp/ 46 | 47 | # Package Files # 48 | *.war 49 | *.nar 50 | *.ear 51 | *.zip 52 | *.tar.gz 53 | *.rar 54 | 55 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 56 | hs_err_pid* -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54754N4/String-Obfuscator/2ff721460e2b193386517c655259f9fd8576280e/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # String Obfuscator 2 | Obfuscates strings using a polymorphic engine. Creates a chain of transformations which are then reversed to generate the decryption routine. Each time its ran it generates a unique routine. 3 | 4 | ## Language Targets 5 | 6 | - [x] Java 7 | - [x] C# 8 | - [x] C & C++ 9 | - [x] Python 10 | - [x] JS 11 | - [x] PowerShell 12 | - [x] Bash 13 | - [x] MASM (64 bit) 14 | 15 | ## Java-based Generation 16 | The engine can be configured to generate a random number of transformation (in a specified range), as well in how many bits to encode the data: 17 | ```java 18 | int minOps = 5; // minimum number of transformations 19 | int maxOps = 10; // maximum number of transformations 20 | int maxBits = 16; // encodes UTF-16 data 21 | PolymorphicEngine engine = new PolymorphicEngine(minOps, maxOps, maxBits); 22 | ``` 23 | 24 | Then generate a transformation chain and encoded data by calling the `Engine#transform` method. To generate the decryption routine in a specific target language, just use the correct `Visitor` class: 25 | ```java 26 | String stringToObfuscate = "Hello World!"; 27 | Context ctx = engine.transform(stringToObfuscate); 28 | JavaVisitor visitor = new JavaVisitor(); // or any other target 29 | System.out.println(visitor.visit(ctx)); 30 | ``` 31 | 32 | ## API Endpoints Generation 33 | 34 | After running the spring boot application, each target can be accessed through the `/obfuscate/{target}` api url path, where `{target}` can be any of the following: c, cpp, csharp, java, javascript, python, masm64, bash, powershell. The Swagger UI can also be accessed using this URL `:1337/swagger-ui/index.html`. 35 | Each endpoint takes two optional parameters to specify the range `[minOps, maxOps]` that the polymorphic engine will use to generate transformations. 36 | 37 | ## C & C++ Target Example 38 | ```c 39 | wchar_t string[12] = {0xe7e5,0xef5f,0xee64,0xee64,0xeeac,0xe6d7,0xef9e,0xeeac,0xef24,0xee64,0xef57,0xe6df}; 40 | for (unsigned int qiTILYFPbT=0, OzYohOKxe, ZNtEkIj; qiTILYFPbT < 12; qiTILYFPbT++) { 41 | OzYohOKxe = string[qiTILYFPbT]; 42 | ZNtEkIj = ((OzYohOKxe >> 0x4) ^ (OzYohOKxe >> 0x2)) & ((1 << 0x2) - 1); 43 | OzYohOKxe ^= (ZNtEkIj << 0x4) | (ZNtEkIj << 0x2); 44 | OzYohOKxe -= 0x2c16; 45 | OzYohOKxe = (((OzYohOKxe & 0xffff) << 0x7) | (OzYohOKxe >> 0x9)) & 0xffff; 46 | OzYohOKxe = (((OzYohOKxe & 0xffff) >> 0x5) | (OzYohOKxe << 0xb)) & 0xffff; 47 | ZNtEkIj = ((OzYohOKxe >> 0xb) ^ (OzYohOKxe >> 0x2)) & ((1 << 0x2) - 1); 48 | OzYohOKxe ^= (ZNtEkIj << 0xb) | (ZNtEkIj << 0x2); 49 | OzYohOKxe = (((OzYohOKxe & 0xffff) >> 0x7) | (OzYohOKxe << 0x9)) & 0xffff; 50 | OzYohOKxe -= 0xdb6; 51 | string[qiTILYFPbT] = OzYohOKxe; 52 | } 53 | wprintf(string); 54 | ``` 55 | ## C# Target Example 56 | ```csharp 57 | var str = new System.Text.StringBuilder("\u69c5\u4f85\u79a5\u79a5\u65a5\u4b65\u45c5\u65a5\u41a5\u79a5\u5b85\u7d65"); 58 | for (int dSouLvBYK=0, ZFKLohnHzM, TnaNQlKjk; dSouLvBYK < str.Length; dSouLvBYK++) { 59 | ZFKLohnHzM = str[dSouLvBYK]; 60 | TnaNQlKjk = ((ZFKLohnHzM >> 0x5) ^ (ZFKLohnHzM >> 0xa)) & ((1 << 0x4) - 1); 61 | ZFKLohnHzM ^= (TnaNQlKjk << 0x5) | (TnaNQlKjk << 0xa); 62 | ZFKLohnHzM = (((ZFKLohnHzM & 0xffff) << 0xb) | (ZFKLohnHzM >> 0x5)) & 0xffff; 63 | ZFKLohnHzM += 0x2d3d; 64 | TnaNQlKjk = ((ZFKLohnHzM >> 0x3) ^ (ZFKLohnHzM >> 0x3)) & ((1 << 0x9) - 1); 65 | ZFKLohnHzM ^= (TnaNQlKjk << 0x3) | (TnaNQlKjk << 0x3); 66 | ZFKLohnHzM ^= 0xc60e; 67 | ZFKLohnHzM -= 0x118d; 68 | ZFKLohnHzM ^= 0x1bbb; 69 | ZFKLohnHzM ^= 0x6970; 70 | ZFKLohnHzM = ~ZFKLohnHzM & 0xffff; 71 | str[dSouLvBYK] = (char) ZFKLohnHzM; 72 | } 73 | Console.WriteLine(str); 74 | ``` 75 | ## Java Target Example 76 | ```java 77 | StringBuilder string = new StringBuilder("\u2be6\uabec\uebfe\uebfe\uabe0\uabf7\ue7f1\uabe0\u6bfa\uebfe\uabee\uabf5"); 78 | for (int LuLHaKFh=0, oY_FOvLH, eebCvtC; LuLHaKFh < string.length(); LuLHaKFh++) { 79 | oY_FOvLH = string.charAt(LuLHaKFh); 80 | oY_FOvLH = (((oY_FOvLH & 0xffff) << 0x6) | (oY_FOvLH >> 0xa)) & 0xffff; 81 | eebCvtC = ((oY_FOvLH >> 0x0) ^ (oY_FOvLH >> 0x7)) & ((1 << 0x4) - 1); 82 | oY_FOvLH ^= (eebCvtC << 0x0) | (eebCvtC << 0x7); 83 | oY_FOvLH ^= 0x600f; 84 | oY_FOvLH -= 0x2aa2; 85 | oY_FOvLH += 0x25b0; 86 | oY_FOvLH ^= 0x9852; 87 | string.setCharAt(LuLHaKFh, (char) oY_FOvLH); 88 | } 89 | System.out.println(string); 90 | ``` 91 | ## Python Target Example 92 | ```python 93 | string = [0xbaec,0x3b6a,0xbbee,0xbbee,0x3be9,0xbb08,0x3b6d,0x3be9,0xbbeb,0xbbee,0xbb6a,0x3b08] 94 | for ehNxDDeClr in range(len(string)): 95 | JvYJM = string[ehNxDDeClr] 96 | JvYJM = ~JvYJM & 0xffff 97 | rukl = ((JvYJM >> 0x7) ^ (JvYJM >> 0x3)) & ((1 << 0x2) - 1) 98 | JvYJM ^= (rukl << 0x7) | (rukl << 0x3) 99 | JvYJM = (((JvYJM & 0xffff) << 0x2) | (JvYJM >> 0xe)) & 0xffff 100 | JvYJM ^= 0x4f69 101 | JvYJM -= 0x179c 102 | rukl = ((JvYJM >> 0x6) ^ (JvYJM >> 0x6)) & ((1 << 0x3) - 1) 103 | JvYJM ^= (rukl << 0x6) | (rukl << 0x6) 104 | JvYJM = (((JvYJM & 0xffff) >> 0x1) | (JvYJM << 0xf)) & 0xffff 105 | JvYJM -= 0x217c 106 | string[ehNxDDeClr] = chr(JvYJM & 0xffff) 107 | del ehNxDDeClr, JvYJM, rukl 108 | string = ''.join(string) 109 | print(string) 110 | ``` 111 | ## JavaScript Target Example 112 | ```js 113 | var string = [0x346e,0x22ee,0x266e,0x266e,0x27ee,0x6e,0x3bee,0x27ee,0x296e,0x266e,0x226e,0xee]; 114 | for (var LeKvHT=0, bpbEN; LeKvHT < string.length; LeKvHT++) { 115 | bpbEN = string[LeKvHT]; 116 | bpbEN = (((bpbEN & 0xffff) << 0xb) | (bpbEN >> 0x5)) & 0xffff; 117 | bpbEN = ~bpbEN & 0xffff; 118 | bpbEN = (((bpbEN & 0xffff) << 0xf) | (bpbEN >> 0x1)) & 0xffff; 119 | bpbEN = ~bpbEN & 0xffff; 120 | bpbEN ^= 0xb841; 121 | bpbEN = (((bpbEN & 0xffff) >> 0x1) | (bpbEN << 0xf)) & 0xffff; 122 | string[LeKvHT] = bpbEN; 123 | } 124 | string = String.fromCodePoint(...string); 125 | console.log(string); 126 | ``` 127 | ## PowerShell Target Example 128 | ```powershell 129 | [uint64[]]$HZaRySkFpz = 0x67b1,0xf791,0xd7b1,0xd7b1,0xc7d1,0x7b1,0x27d1,0xc7d1,0xb7f1,0xd7b1,0xf7b1,0x791 130 | $string = [System.Text.StringBuilder]::new() 131 | for ($ONsGU = 0; $ONsGU -lt $HZaRySkFpz.Length; $ONsGU++) { 132 | $XKvkUzFdZ = $HZaRySkFpz[$ONsGU] 133 | $XKvkUzFdZ = ((($XKvkUzFdZ -band 0xffff) -shl 0x2) -bor ($XKvkUzFdZ -shr 0xe)) -band 0xffff 134 | $XKvkUzFdZ = ((($XKvkUzFdZ -band 0xffff) -shr 0xf) -bor ($XKvkUzFdZ -shl 0x1)) -band 0xffff 135 | $QCjLahqh = (($XKvkUzFdZ -shr 0x7) -bxor ($XKvkUzFdZ -shr 0xc)) -band ((1 -shl 0x3) - 1) 136 | $XKvkUzFdZ = $XKvkUzFdZ -bxor (($QCjLahqh -shl 0x7) -bor ($QCjLahqh -shl 0xc)) 137 | $XKvkUzFdZ = ((($XKvkUzFdZ -band 0xffff) -shr 0xc) -bor ($XKvkUzFdZ -shl 0x4)) -band 0xffff 138 | $XKvkUzFdZ = -bnot $XKvkUzFdZ -band 0xffff 139 | $XKvkUzFdZ = ((($XKvkUzFdZ -band 0xffff) -shl 0xf) -bor ($XKvkUzFdZ -shr 0x1)) -band 0xffff 140 | $XKvkUzFdZ += 0x2282 141 | $QCjLahqh = (($XKvkUzFdZ -shr 0xa) -bxor ($XKvkUzFdZ -shr 0xb)) -band ((1 -shl 0x4) - 1) 142 | $XKvkUzFdZ = $XKvkUzFdZ -bxor (($QCjLahqh -shl 0xa) -bor ($QCjLahqh -shl 0xb)) 143 | $XKvkUzFdZ = $XKvkUzFdZ -bxor 0x4a60 144 | [void]$string.Append([char]($XKvkUzFdZ -band 0xffff)) 145 | } 146 | $XKvkUzFdZ = [void]$XKvkUzFdZ 147 | $ONsGU = [void]$ONsGU 148 | $HZaRySkFpz = [void]$HZaRySkFpz 149 | $QCjLahqh = [void]$QCjLahqh 150 | $string = $string.ToString() 151 | Write-Host $string 152 | ``` 153 | ## Bash Target Example 154 | ```bash 155 | string=( 0x8cfa 0x873c 0x8b3a 0x8b3a 0x8a3c 0x89ba 0x861c 0x8a3c 0x885a 0x8b3a 0x873a 0x89bc ) 156 | for bEkkOsPjN in ${!string[@]}; do 157 | xC_adWJDY=${string[$bEkkOsPjN]} 158 | ((yLexvN = ((xC_adWJDY >> 0x3) ^ (xC_adWJDY >> 0x3)) & ((1 << 0xb)-1))) 159 | ((xC_adWJDY ^= (yLexvN << 0x3) | (yLexvN << 0x3))) 160 | ((xC_adWJDY = (((xC_adWJDY & 0xffff) << 0xc) | (xC_adWJDY >> 0x4)) & 0xffff)) 161 | ((xC_adWJDY = (((xC_adWJDY & 0xffff) << 0xa) | (xC_adWJDY >> 0x6)) & 0xffff)) 162 | ((xC_adWJDY += 0x243c)) 163 | ((xC_adWJDY = (((xC_adWJDY & 0xffff) << 0x9) | (xC_adWJDY >> 0x7)) & 0xffff)) 164 | ((xC_adWJDY -= 0x186d)) 165 | ((xC_adWJDY += 0x396b)) 166 | ((xC_adWJDY -= 0xc3b)) 167 | ((yLexvN = ((xC_adWJDY >> 0x1) ^ (xC_adWJDY >> 0x7)) & ((1 << 0x3)-1))) 168 | ((xC_adWJDY ^= (yLexvN << 0x1) | (yLexvN << 0x7))) 169 | ((xC_adWJDY ^= 0xd246)) 170 | string[$bEkkOsPjN]=$xC_adWJDY 171 | done 172 | unset bEkkOsPjN 173 | unset xC_adWJDY 174 | unset yLexvN 175 | string=$(printf %b "$(printf '\\U%x' "${string[@]}")") 176 | echo $string 177 | ``` 178 | ## MASM 64 bit Target Example 179 | ```asm 180 | extern GetStdHandle: proc 181 | extern WriteFile: proc 182 | extern GetFileType: proc 183 | extern WriteConsoleW: proc 184 | 185 | .data? 186 | stdout dq ? 187 | written dq ? 188 | .data 189 | string dw 0c5d7h,0afd8h,0b457h,0b457h,0add7h,065d8h,0edd6h,0add7h,0c756h,0b457h,0b458h,06f58h 190 | len equ $-string 191 | .code 192 | main proc 193 | push rbp 194 | mov rbp, rsp 195 | sub rsp, 32 196 | and rsp, -10h 197 | 198 | mov rbx, offset string 199 | xor rcx, rcx 200 | Qjlc: 201 | xor rax, rax 202 | xor rdx, rdx 203 | xor r8, r8 204 | xor r9, r9 205 | xor r10, r10 206 | mov dx, word ptr [rbx + rcx*2] 207 | mov r8w, dx 208 | shr r8w, 7 209 | mov r9w, dx 210 | shr r9w, 10 211 | xor r8w, r9w 212 | mov r9w, 1 213 | shl r9w, 2 214 | sub r9w, 1 215 | and r8w, r9w 216 | mov r9w, r8w 217 | shl r9w, 7 218 | mov r10w, r8w 219 | shl r10w, 10 220 | or r9w, r10w 221 | xor dx, r9w 222 | sub dx, 14630 223 | ror dx, 13 224 | ror dx, 14 225 | mov r8w, dx 226 | shr r8w, 5 227 | mov r9w, dx 228 | shr r9w, 0 229 | xor r8w, r9w 230 | mov r9w, 1 231 | shl r9w, 2 232 | sub r9w, 1 233 | and r8w, r9w 234 | mov r9w, r8w 235 | shl r9w, 5 236 | mov r10w, r8w 237 | shl r10w, 0 238 | or r9w, r10w 239 | xor dx, r9w 240 | sub dx, 293 241 | not dx 242 | rol dx, 3 243 | xor dx, 22228 244 | mov word ptr [rbx + rcx*2], dx 245 | inc cx 246 | cmp cx, 12 247 | jne Qjlc 248 | 249 | ; Printing code 250 | xor rax, rax 251 | xor rcx, rcx 252 | xor rdx, rdx 253 | xor r8, r8 254 | xor r9, r9 255 | mov rcx, -11 256 | call GetStdHandle 257 | mov [stdout], rax 258 | mov rcx, rax 259 | call GetFileType 260 | cmp rax, 1 261 | je fileWrite 262 | mov rcx, [stdout] 263 | mov rdx, rbx 264 | mov r8, len 265 | mov r9, written 266 | call WriteConsoleW 267 | jmp epilog 268 | fileWrite: 269 | mov rcx, [stdout] 270 | mov rdx, rbx 271 | mov r8, len 272 | mov r9, written 273 | call WriteFile 274 | epilog: 275 | add rsp, 32 276 | mov rsp, rbp 277 | pop rbp 278 | ret 279 | main endp 280 | end 281 | ``` 282 | -------------------------------------------------------------------------------- /String Obfuscator definition.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "fcb31d9e-08ec-4219-9f19-7bd11846fdb4", 4 | "name": "String Obfuscator definition", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 6 | "_exporter_id": "4110057" 7 | }, 8 | "item": [ 9 | { 10 | "name": "obfuscate", 11 | "item": [ 12 | { 13 | "name": "Obfuscates text in Python", 14 | "request": { 15 | "method": "GET", 16 | "header": [ 17 | { 18 | "key": "Accept", 19 | "value": "*/*" 20 | } 21 | ], 22 | "url": { 23 | "raw": "{{baseUrl}}/obfuscate/python?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 24 | "host": [ 25 | "{{baseUrl}}" 26 | ], 27 | "path": [ 28 | "obfuscate", 29 | "python" 30 | ], 31 | "query": [ 32 | { 33 | "key": "text", 34 | "value": "dolor adipisicing ex nisi", 35 | "description": "(Required) " 36 | }, 37 | { 38 | "key": "minOps", 39 | "value": "5" 40 | }, 41 | { 42 | "key": "maxOps", 43 | "value": "15" 44 | } 45 | ] 46 | } 47 | }, 48 | "response": [ 49 | { 50 | "name": "Example", 51 | "originalRequest": { 52 | "method": "GET", 53 | "header": [ 54 | { 55 | "key": "Accept", 56 | "value": "*/*" 57 | } 58 | ], 59 | "url": { 60 | "raw": "http://localhost:1337/obfuscate/python?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 61 | "protocol": "http", 62 | "host": [ 63 | "localhost" 64 | ], 65 | "port": "1337", 66 | "path": [ 67 | "obfuscate", 68 | "python" 69 | ], 70 | "query": [ 71 | { 72 | "key": "text", 73 | "value": "dolor adipisicing ex nisi", 74 | "description": "(Required) " 75 | }, 76 | { 77 | "key": "minOps", 78 | "value": "5" 79 | }, 80 | { 81 | "key": "maxOps", 82 | "value": "15" 83 | } 84 | ] 85 | } 86 | }, 87 | "status": "OK", 88 | "code": 200, 89 | "_postman_previewlanguage": "plain", 90 | "header": [ 91 | { 92 | "key": "Content-Type", 93 | "value": "text/plain;charset=UTF-8" 94 | }, 95 | { 96 | "key": "Content-Length", 97 | "value": "537" 98 | }, 99 | { 100 | "key": "Date", 101 | "value": "Sun, 10 Jul 2022 16:26:50 GMT" 102 | }, 103 | { 104 | "key": "Keep-Alive", 105 | "value": "timeout=60" 106 | }, 107 | { 108 | "key": "Connection", 109 | "value": "keep-alive" 110 | } 111 | ], 112 | "cookie": [], 113 | "body": "string = [0x72c7,0xb2c5,0x72c5,0xb2c5,0xf2c2,0x72d6,0x32c6,0x72c7,0x32c4,0x72c2,0x32c4,0xb2c2,0x32c4,0xb2c6,0x32c4,0xf2c5,0xb2c7,0x72d6,0x32c7,0x72c0,0x72d6,0xf2c5,0x32c4,0xb2c2,0x32c4]\nfor AeaNmAQ in range(len(string)):\n\tsClygEF = string[AeaNmAQ]\n\tsClygEF ^= 0xed6d\n\tsClygEF ^= 0x604c\n\tsClygEF = ~sClygEF & 0xffff\n\tsClygEF = (((sClygEF & 0xffff) << 0xb) | (sClygEF >> 0x5)) & 0xffff\n\tsClygEF = (((sClygEF & 0xffff) << 0x7) | (sClygEF >> 0x9)) & 0xffff\n\tstring[AeaNmAQ] = chr(sClygEF & 0xffff)\ndel AeaNmAQ, sClygEF\nprint(''.join(string))" 114 | } 115 | ] 116 | }, 117 | { 118 | "name": "Obfuscates text in PowerShell", 119 | "request": { 120 | "method": "GET", 121 | "header": [ 122 | { 123 | "key": "Accept", 124 | "value": "*/*" 125 | } 126 | ], 127 | "url": { 128 | "raw": "{{baseUrl}}/obfuscate/powershell?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 129 | "host": [ 130 | "{{baseUrl}}" 131 | ], 132 | "path": [ 133 | "obfuscate", 134 | "powershell" 135 | ], 136 | "query": [ 137 | { 138 | "key": "text", 139 | "value": "dolor adipisicing ex nisi", 140 | "description": "(Required) " 141 | }, 142 | { 143 | "key": "minOps", 144 | "value": "5" 145 | }, 146 | { 147 | "key": "maxOps", 148 | "value": "15" 149 | } 150 | ] 151 | } 152 | }, 153 | "response": [ 154 | { 155 | "name": "Example", 156 | "originalRequest": { 157 | "method": "GET", 158 | "header": [ 159 | { 160 | "key": "Accept", 161 | "value": "*/*" 162 | } 163 | ], 164 | "url": { 165 | "raw": "http://localhost:1337/obfuscate/powershell?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 166 | "protocol": "http", 167 | "host": [ 168 | "localhost" 169 | ], 170 | "port": "1337", 171 | "path": [ 172 | "obfuscate", 173 | "powershell" 174 | ], 175 | "query": [ 176 | { 177 | "key": "text", 178 | "value": "dolor adipisicing ex nisi", 179 | "description": "(Required) " 180 | }, 181 | { 182 | "key": "minOps", 183 | "value": "5" 184 | }, 185 | { 186 | "key": "maxOps", 187 | "value": "15" 188 | } 189 | ] 190 | } 191 | }, 192 | "status": "OK", 193 | "code": 200, 194 | "_postman_previewlanguage": "plain", 195 | "header": [ 196 | { 197 | "key": "Content-Type", 198 | "value": "text/plain;charset=UTF-8" 199 | }, 200 | { 201 | "key": "Content-Length", 202 | "value": "860" 203 | }, 204 | { 205 | "key": "Date", 206 | "value": "Sun, 10 Jul 2022 16:28:43 GMT" 207 | }, 208 | { 209 | "key": "Keep-Alive", 210 | "value": "timeout=60" 211 | }, 212 | { 213 | "key": "Connection", 214 | "value": "keep-alive" 215 | } 216 | ], 217 | "cookie": [], 218 | "body": "[uint64[]]$_nJnYiJW = 0x548f,0xa48e,0xd48e,0xa48e,0x748e,0x9493,0x848f,0x548f,0x48f,0x948e,0x48f,0x648e,0x48f,0x648f,0x48f,0xb48e,0x248f,0x9493,0x448f,0x148e,0x9493,0xb48e,0x48f,0x648e,0x48f\n$string = [System.Text.StringBuilder]::new()\nfor ($sPmCWnnqQ = 0; $sPmCWnnqQ -lt $_nJnYiJW.Length; $sPmCWnnqQ++) {\n\t$N_ApoKOK = $_nJnYiJW[$sPmCWnnqQ]\n\t$N_ApoKOK = ((($N_ApoKOK -band 0xffff) -shr 0x8) -bor ($N_ApoKOK -shl 0x8)) -band 0xffff\n\t$N_ApoKOK = -bnot $N_ApoKOK -band 0xffff\n\t$N_ApoKOK -= 0x1da9\n\t$N_ApoKOK = ((($N_ApoKOK -band 0xffff) -shl 0xc) -bor ($N_ApoKOK -shr 0x4)) -band 0xffff\n\t$N_ApoKOK -= 0x24cc\n\t$N_ApoKOK = -bnot $N_ApoKOK -band 0xffff\n\t$N_ApoKOK = -bnot $N_ApoKOK -band 0xffff\n\t[void]$string.Append([char]($N_ApoKOK -band 0xffff))\n}\n$N_ApoKOK = [void]$N_ApoKOK\n$sPmCWnnqQ = [void]$sPmCWnnqQ\n$_nJnYiJW = [void]$_nJnYiJW\nWrite-Host $string.ToString()" 219 | } 220 | ] 221 | }, 222 | { 223 | "name": "Obfuscates text in MASM 64 bit", 224 | "request": { 225 | "method": "GET", 226 | "header": [ 227 | { 228 | "key": "Accept", 229 | "value": "*/*" 230 | } 231 | ], 232 | "url": { 233 | "raw": "{{baseUrl}}/obfuscate/masm64?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 234 | "host": [ 235 | "{{baseUrl}}" 236 | ], 237 | "path": [ 238 | "obfuscate", 239 | "masm64" 240 | ], 241 | "query": [ 242 | { 243 | "key": "text", 244 | "value": "dolor adipisicing ex nisi", 245 | "description": "(Required) " 246 | }, 247 | { 248 | "key": "minOps", 249 | "value": "5" 250 | }, 251 | { 252 | "key": "maxOps", 253 | "value": "15" 254 | } 255 | ] 256 | } 257 | }, 258 | "response": [ 259 | { 260 | "name": "Example", 261 | "originalRequest": { 262 | "method": "GET", 263 | "header": [ 264 | { 265 | "key": "Accept", 266 | "value": "*/*" 267 | } 268 | ], 269 | "url": { 270 | "raw": "{{baseUrl}}/obfuscate/masm64?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 271 | "host": [ 272 | "{{baseUrl}}" 273 | ], 274 | "path": [ 275 | "obfuscate", 276 | "masm64" 277 | ], 278 | "query": [ 279 | { 280 | "key": "text", 281 | "value": "dolor adipisicing ex nisi", 282 | "description": "(Required) " 283 | }, 284 | { 285 | "key": "minOps", 286 | "value": "5" 287 | }, 288 | { 289 | "key": "maxOps", 290 | "value": "15" 291 | } 292 | ] 293 | } 294 | }, 295 | "status": "OK", 296 | "code": 200, 297 | "_postman_previewlanguage": "plain", 298 | "header": [ 299 | { 300 | "key": "Content-Type", 301 | "value": "text/plain;charset=UTF-8" 302 | }, 303 | { 304 | "key": "Content-Length", 305 | "value": "1160" 306 | }, 307 | { 308 | "key": "Date", 309 | "value": "Sun, 10 Jul 2022 16:28:51 GMT" 310 | }, 311 | { 312 | "key": "Keep-Alive", 313 | "value": "timeout=60" 314 | }, 315 | { 316 | "key": "Connection", 317 | "value": "keep-alive" 318 | } 319 | ], 320 | "cookie": [], 321 | "body": "extern GetStdHandle: proc\nextern WriteFile: proc\nextern GetFileType: proc\nextern WriteConsoleW: proc\n\n.data?\n\tstdout\tdq ?\n\twritten\tdq ?\n.data\n\tstring dw 0b5b0h,0b5dah,0b5c0h,0b5dah,0b5d4h,0b438h,0b5b6h,0b5b0h,0b5c6h,0b5d8h,0b5c6h,0b5d2h,0b5c6h,0b5b2h,0b5c6h,0b5dch,0b5cah,0b438h,0b5ceh,0b5e8h,0b438h,0b5dch,0b5c6h,0b5d2h,0b5c6h\n\tlen\tequ $-string\n.code\nmain proc\n\tpush\trbp\n\tmov\trbp, rsp\n\tsub\trsp, 32\n\tand\trsp, -10h\n\n\tmov\trbx, offset string\n\txor\trcx, rcx\nKTDW:\n\txor\trax, rax\n\txor\trdx, rdx\n\txor\tr8, r8\n\txor\tr9, r9\n\txor\tr10, r10\n\tmov\tdx, word ptr [rbx + rcx*2]\n\tror\tdx, 6\n\tror\tdx, 4\n\tror\tdx, 7\n\tnot\tdx\n\txor\tdx, 57784\n\tadd\tdx, 7106\n\tsub\tdx, 13866\n\tsub\tdx, 10707\n\tmov\tword ptr [rbx + rcx*2], dx\n\tinc\tcx\n\tcmp\tcx, 25\n\tjne\tKTDW\n\n\t; Printing code\n\txor\trax, rax\n\txor\trcx, rcx\n\txor\trdx, rdx\n\txor\tr8, r8\n\txor\tr9, r9\n\tmov\trcx, -11\n\tcall\tGetStdHandle\n\tmov\t[stdout], rax\n\tmov\trcx, rax\n\tcall\tGetFileType\n\tcmp\trax, 1\n\tje\tfileWrite\n\tmov\trcx, [stdout]\n\tmov\trdx, rbx\n\tmov\tr8, len\n\tmov\tr9, written\n\tcall\tWriteConsoleW\n\tjmp\tepilog\nfileWrite:\n\tmov\trcx, [stdout]\n\tmov\trdx, rbx\n\tmov\tr8, len\n\tmov\tr9, written\n\tcall\tWriteFile\nepilog:\n\tadd\trsp, 32\n\tmov\trsp, rbp\n\tpop\trbp\n\tret\nmain endp\nend" 322 | } 323 | ] 324 | }, 325 | { 326 | "name": "Obfuscates text in JS", 327 | "request": { 328 | "method": "GET", 329 | "header": [ 330 | { 331 | "key": "Accept", 332 | "value": "*/*" 333 | } 334 | ], 335 | "url": { 336 | "raw": "{{baseUrl}}/obfuscate/javascript?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 337 | "host": [ 338 | "{{baseUrl}}" 339 | ], 340 | "path": [ 341 | "obfuscate", 342 | "javascript" 343 | ], 344 | "query": [ 345 | { 346 | "key": "text", 347 | "value": "dolor adipisicing ex nisi", 348 | "description": "(Required) " 349 | }, 350 | { 351 | "key": "minOps", 352 | "value": "5" 353 | }, 354 | { 355 | "key": "maxOps", 356 | "value": "15" 357 | } 358 | ] 359 | } 360 | }, 361 | "response": [ 362 | { 363 | "name": "Example", 364 | "originalRequest": { 365 | "method": "GET", 366 | "header": [ 367 | { 368 | "key": "Accept", 369 | "value": "*/*" 370 | } 371 | ], 372 | "url": { 373 | "raw": "{{baseUrl}}/obfuscate/javascript?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 374 | "host": [ 375 | "{{baseUrl}}" 376 | ], 377 | "path": [ 378 | "obfuscate", 379 | "javascript" 380 | ], 381 | "query": [ 382 | { 383 | "key": "text", 384 | "value": "dolor adipisicing ex nisi", 385 | "description": "(Required) " 386 | }, 387 | { 388 | "key": "minOps", 389 | "value": "5" 390 | }, 391 | { 392 | "key": "maxOps", 393 | "value": "15" 394 | } 395 | ] 396 | } 397 | }, 398 | "status": "OK", 399 | "code": 200, 400 | "_postman_previewlanguage": "plain", 401 | "header": [ 402 | { 403 | "key": "Content-Type", 404 | "value": "text/plain;charset=UTF-8" 405 | }, 406 | { 407 | "key": "Content-Length", 408 | "value": "690" 409 | }, 410 | { 411 | "key": "Date", 412 | "value": "Sun, 10 Jul 2022 16:28:58 GMT" 413 | }, 414 | { 415 | "key": "Keep-Alive", 416 | "value": "timeout=60" 417 | }, 418 | { 419 | "key": "Connection", 420 | "value": "keep-alive" 421 | } 422 | ], 423 | "cookie": [], 424 | "body": "var string = [0x43ea,0x23e9,0x43e9,0x23e9,0x83e7,0xc3f1,0xe3e9,0x43ea,0xe3e8,0xc3e7,0xe3e8,0xa3e7,0xe3e8,0xa3e9,0xe3e8,0x3e9,0x23ea,0xc3f1,0x63ea,0xc3e6,0xc3f1,0x3e9,0xe3e8,0xa3e7,0xe3e8];\nfor (var iwoYTOei=0, G_vSBlQsEh; iwoYTOei < string.length; iwoYTOei++) {\n\tG_vSBlQsEh = string[iwoYTOei];\n\tG_vSBlQsEh = ~G_vSBlQsEh & 0xffff;\n\tG_vSBlQsEh = (((G_vSBlQsEh & 0xffff) >> 0x5) | (G_vSBlQsEh << 0xb)) & 0xffff;\n\tG_vSBlQsEh = (((G_vSBlQsEh & 0xffff) << 0x8) | (G_vSBlQsEh >> 0x8)) & 0xffff;\n\tG_vSBlQsEh -= 0x154c;\n\tG_vSBlQsEh ^= 0x9b07;\n\tG_vSBlQsEh = ~G_vSBlQsEh & 0xffff;\n\tG_vSBlQsEh ^= 0xaffd;\n\tstring[iwoYTOei] = G_vSBlQsEh;\n}\nstring = String.fromCodePoint(...string);\nconsole.log(string);\n" 425 | } 426 | ] 427 | }, 428 | { 429 | "name": "Obfuscates text in Java", 430 | "request": { 431 | "method": "GET", 432 | "header": [ 433 | { 434 | "key": "Accept", 435 | "value": "*/*" 436 | } 437 | ], 438 | "url": { 439 | "raw": "{{baseUrl}}/obfuscate/java?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 440 | "host": [ 441 | "{{baseUrl}}" 442 | ], 443 | "path": [ 444 | "obfuscate", 445 | "java" 446 | ], 447 | "query": [ 448 | { 449 | "key": "text", 450 | "value": "dolor adipisicing ex nisi", 451 | "description": "(Required) " 452 | }, 453 | { 454 | "key": "minOps", 455 | "value": "5" 456 | }, 457 | { 458 | "key": "maxOps", 459 | "value": "15" 460 | } 461 | ] 462 | } 463 | }, 464 | "response": [ 465 | { 466 | "name": "Example", 467 | "originalRequest": { 468 | "method": "GET", 469 | "header": [ 470 | { 471 | "key": "Accept", 472 | "value": "*/*" 473 | } 474 | ], 475 | "url": { 476 | "raw": "{{baseUrl}}/obfuscate/java?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 477 | "host": [ 478 | "{{baseUrl}}" 479 | ], 480 | "path": [ 481 | "obfuscate", 482 | "java" 483 | ], 484 | "query": [ 485 | { 486 | "key": "text", 487 | "value": "dolor adipisicing ex nisi", 488 | "description": "(Required) " 489 | }, 490 | { 491 | "key": "minOps", 492 | "value": "5" 493 | }, 494 | { 495 | "key": "maxOps", 496 | "value": "15" 497 | } 498 | ] 499 | } 500 | }, 501 | "status": "OK", 502 | "code": 200, 503 | "_postman_previewlanguage": "plain", 504 | "header": [ 505 | { 506 | "key": "Content-Type", 507 | "value": "text/plain;charset=UTF-8" 508 | }, 509 | { 510 | "key": "Content-Length", 511 | "value": "629" 512 | }, 513 | { 514 | "key": "Date", 515 | "value": "Sun, 10 Jul 2022 16:29:07 GMT" 516 | }, 517 | { 518 | "key": "Keep-Alive", 519 | "value": "timeout=60" 520 | }, 521 | { 522 | "key": "Connection", 523 | "value": "keep-alive" 524 | } 525 | ], 526 | "cookie": [], 527 | "body": "StringBuilder string = new StringBuilder(\"\\u69f8\\ue9f2\\u69f4\\ue9f2\\u69e9\\u6a12\\ue9f1\\u69f8\\ue9dd\\u69ea\\ue9dd\\ue9e8\\ue9dd\\ue9f0\\ue9dd\\u69f3\\ue9f6\\u6a12\\ue9f7\\u69f6\\u6a12\\u69f3\\ue9dd\\ue9e8\\ue9dd\");\nfor (int ELfijgJVD=0, hyjYlr_eE; ELfijgJVD < string.length(); ELfijgJVD++) {\n\thyjYlr_eE = string.charAt(ELfijgJVD);\n\thyjYlr_eE = ~hyjYlr_eE & 0xffff;\n\thyjYlr_eE += 0x30ee;\n\thyjYlr_eE = (((hyjYlr_eE & 0xffff) << 0x1) | (hyjYlr_eE >> 0xf)) & 0xffff;\n\thyjYlr_eE += 0x3825;\n\thyjYlr_eE -= 0x750;\n\thyjYlr_eE ^= 0x516;\n\thyjYlr_eE += 0x2a9c;\n\thyjYlr_eE ^= 0xe616;\n\tstring.setCharAt(ELfijgJVD, (char) hyjYlr_eE);\n}\nSystem.out.println(string);" 528 | } 529 | ] 530 | }, 531 | { 532 | "name": "Obfuscates text in C#", 533 | "request": { 534 | "method": "GET", 535 | "header": [ 536 | { 537 | "key": "Accept", 538 | "value": "*/*" 539 | } 540 | ], 541 | "url": { 542 | "raw": "{{baseUrl}}/obfuscate/csharp?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 543 | "host": [ 544 | "{{baseUrl}}" 545 | ], 546 | "path": [ 547 | "obfuscate", 548 | "csharp" 549 | ], 550 | "query": [ 551 | { 552 | "key": "text", 553 | "value": "dolor adipisicing ex nisi", 554 | "description": "(Required) " 555 | }, 556 | { 557 | "key": "minOps", 558 | "value": "5" 559 | }, 560 | { 561 | "key": "maxOps", 562 | "value": "15" 563 | } 564 | ] 565 | } 566 | }, 567 | "response": [ 568 | { 569 | "name": "Example", 570 | "originalRequest": { 571 | "method": "GET", 572 | "header": [ 573 | { 574 | "key": "Accept", 575 | "value": "*/*" 576 | } 577 | ], 578 | "url": { 579 | "raw": "{{baseUrl}}/obfuscate/csharp?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 580 | "host": [ 581 | "{{baseUrl}}" 582 | ], 583 | "path": [ 584 | "obfuscate", 585 | "csharp" 586 | ], 587 | "query": [ 588 | { 589 | "key": "text", 590 | "value": "dolor adipisicing ex nisi", 591 | "description": "(Required) " 592 | }, 593 | { 594 | "key": "minOps", 595 | "value": "5" 596 | }, 597 | { 598 | "key": "maxOps", 599 | "value": "15" 600 | } 601 | ] 602 | } 603 | }, 604 | "status": "OK", 605 | "code": 200, 606 | "_postman_previewlanguage": "plain", 607 | "header": [ 608 | { 609 | "key": "Content-Type", 610 | "value": "text/plain;charset=UTF-8" 611 | }, 612 | { 613 | "key": "Content-Length", 614 | "value": "577" 615 | }, 616 | { 617 | "key": "Date", 618 | "value": "Sun, 10 Jul 2022 16:29:14 GMT" 619 | }, 620 | { 621 | "key": "Keep-Alive", 622 | "value": "timeout=60" 623 | }, 624 | { 625 | "key": "Connection", 626 | "value": "keep-alive" 627 | } 628 | ], 629 | "cookie": [], 630 | "body": "var str = new System.Text.StringBuilder(\"\\u21be\\u21c9\\u21c6\\u21c9\\u21cc\\u217a\\u21bb\\u21be\\u21c3\\u21ca\\u21c3\\u21cd\\u21c3\\u21bd\\u21c3\\u21c8\\u21c1\\u217a\\u21bf\\u21d2\\u217a\\u21c8\\u21c3\\u21cd\\u21c3\");\nfor (int iWiBdYyo_=0, VTFPxA, nmuIaZG_kb; iWiBdYyo_ < str.Length; iWiBdYyo_++) {\n\tVTFPxA = str[iWiBdYyo_];\n\tVTFPxA = ~VTFPxA & 0xffff;\n\tVTFPxA = ~VTFPxA & 0xffff;\n\tVTFPxA += 0xdba;\n\tnmuIaZG_kb = ((VTFPxA >> 0x8) ^ (VTFPxA >> 0xa)) & ((1 << 0x2) - 1);\n\tVTFPxA ^= (nmuIaZG_kb << 0x8) | (nmuIaZG_kb << 0xa);\n\tVTFPxA -= 0x2f14;\n\tstr[iWiBdYyo_] = (char) VTFPxA;\n}\nConsole.WriteLine(str);" 631 | } 632 | ] 633 | }, 634 | { 635 | "name": "Obfuscates text in C++", 636 | "request": { 637 | "method": "GET", 638 | "header": [ 639 | { 640 | "key": "Accept", 641 | "value": "*/*" 642 | } 643 | ], 644 | "url": { 645 | "raw": "{{baseUrl}}/obfuscate/cpp?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 646 | "host": [ 647 | "{{baseUrl}}" 648 | ], 649 | "path": [ 650 | "obfuscate", 651 | "cpp" 652 | ], 653 | "query": [ 654 | { 655 | "key": "text", 656 | "value": "dolor adipisicing ex nisi", 657 | "description": "(Required) " 658 | }, 659 | { 660 | "key": "minOps", 661 | "value": "5" 662 | }, 663 | { 664 | "key": "maxOps", 665 | "value": "15" 666 | } 667 | ] 668 | } 669 | }, 670 | "response": [ 671 | { 672 | "name": "Example", 673 | "originalRequest": { 674 | "method": "GET", 675 | "header": [ 676 | { 677 | "key": "Accept", 678 | "value": "*/*" 679 | } 680 | ], 681 | "url": { 682 | "raw": "{{baseUrl}}/obfuscate/cpp?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 683 | "host": [ 684 | "{{baseUrl}}" 685 | ], 686 | "path": [ 687 | "obfuscate", 688 | "cpp" 689 | ], 690 | "query": [ 691 | { 692 | "key": "text", 693 | "value": "dolor adipisicing ex nisi", 694 | "description": "(Required) " 695 | }, 696 | { 697 | "key": "minOps", 698 | "value": "5" 699 | }, 700 | { 701 | "key": "maxOps", 702 | "value": "15" 703 | } 704 | ] 705 | } 706 | }, 707 | "status": "OK", 708 | "code": 200, 709 | "_postman_previewlanguage": "plain", 710 | "header": [ 711 | { 712 | "key": "Content-Type", 713 | "value": "text/plain;charset=UTF-8" 714 | }, 715 | { 716 | "key": "Content-Length", 717 | "value": "549" 718 | }, 719 | { 720 | "key": "Date", 721 | "value": "Sun, 10 Jul 2022 16:29:19 GMT" 722 | }, 723 | { 724 | "key": "Keep-Alive", 725 | "value": "timeout=60" 726 | }, 727 | { 728 | "key": "Connection", 729 | "value": "keep-alive" 730 | } 731 | ], 732 | "cookie": [], 733 | "body": "wchar_t string[25] = {0x4006,0xf006,0xc006,0xf006,0x2007,0x2,0x1006,0x4006,0x9006,0x7,0x9006,0x3007,0x9006,0x3006,0x9006,0xe006,0x7006,0x2,0x5006,0x8007,0x2,0xe006,0x9006,0x3007,0x9006};\nfor (unsigned int OPXi=0, waKxk; OPXi < 25; OPXi++) {\n\twaKxk = string[OPXi];\n\twaKxk = ~waKxk & 0xffff;\n\twaKxk = (((waKxk & 0xffff) << 0xb) | (waKxk >> 0x5)) & 0xffff;\n\twaKxk = ~waKxk & 0xffff;\n\twaKxk = (((waKxk & 0xffff) << 0x3) | (waKxk >> 0xd)) & 0xffff;\n\twaKxk = (((waKxk & 0xffff) << 0x6) | (waKxk >> 0xa)) & 0xffff;\n\tstring[OPXi] = waKxk;\n}\nwprintf(string);" 734 | } 735 | ] 736 | }, 737 | { 738 | "name": "Obfuscates text in C", 739 | "request": { 740 | "method": "GET", 741 | "header": [ 742 | { 743 | "key": "Accept", 744 | "value": "*/*" 745 | } 746 | ], 747 | "url": { 748 | "raw": "{{baseUrl}}/obfuscate/c?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 749 | "host": [ 750 | "{{baseUrl}}" 751 | ], 752 | "path": [ 753 | "obfuscate", 754 | "c" 755 | ], 756 | "query": [ 757 | { 758 | "key": "text", 759 | "value": "dolor adipisicing ex nisi", 760 | "description": "(Required) " 761 | }, 762 | { 763 | "key": "minOps", 764 | "value": "5" 765 | }, 766 | { 767 | "key": "maxOps", 768 | "value": "15" 769 | } 770 | ] 771 | } 772 | }, 773 | "response": [ 774 | { 775 | "name": "Example", 776 | "originalRequest": { 777 | "method": "GET", 778 | "header": [ 779 | { 780 | "key": "Accept", 781 | "value": "*/*" 782 | } 783 | ], 784 | "url": { 785 | "raw": "{{baseUrl}}/obfuscate/c?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 786 | "host": [ 787 | "{{baseUrl}}" 788 | ], 789 | "path": [ 790 | "obfuscate", 791 | "c" 792 | ], 793 | "query": [ 794 | { 795 | "key": "text", 796 | "value": "dolor adipisicing ex nisi", 797 | "description": "(Required) " 798 | }, 799 | { 800 | "key": "minOps", 801 | "value": "5" 802 | }, 803 | { 804 | "key": "maxOps", 805 | "value": "15" 806 | } 807 | ] 808 | } 809 | }, 810 | "status": "OK", 811 | "code": 200, 812 | "_postman_previewlanguage": "plain", 813 | "header": [ 814 | { 815 | "key": "Content-Type", 816 | "value": "text/plain;charset=UTF-8" 817 | }, 818 | { 819 | "key": "Content-Length", 820 | "value": "606" 821 | }, 822 | { 823 | "key": "Date", 824 | "value": "Sun, 10 Jul 2022 16:29:25 GMT" 825 | }, 826 | { 827 | "key": "Keep-Alive", 828 | "value": "timeout=60" 829 | }, 830 | { 831 | "key": "Connection", 832 | "value": "keep-alive" 833 | } 834 | ], 835 | "cookie": [], 836 | "body": "wchar_t string[25] = {0x6d12,0x7812,0x7512,0x7812,0x7b12,0x2912,0x6a12,0x6d12,0x7212,0x7912,0x7212,0x7c12,0x7212,0x6c12,0x7212,0x7712,0x7012,0x2912,0x6e12,0x8112,0x2912,0x7712,0x7212,0x7c12,0x7212};\nfor (unsigned int QnoW=0, yFfuwM; QnoW < 25; QnoW++) {\n\tyFfuwM = string[QnoW];\n\tyFfuwM = (((yFfuwM & 0xffff) << 0xb) | (yFfuwM >> 0x5)) & 0xffff;\n\tyFfuwM = (((yFfuwM & 0xffff) >> 0xb) | (yFfuwM << 0x5)) & 0xffff;\n\tyFfuwM -= 0x912;\n\tyFfuwM = (((yFfuwM & 0xffff) << 0x3) | (yFfuwM >> 0xd)) & 0xffff;\n\tyFfuwM = (((yFfuwM & 0xffff) >> 0xb) | (yFfuwM << 0x5)) & 0xffff;\n\tstring[QnoW] = yFfuwM;\n}\nwprintf(string);" 837 | } 838 | ] 839 | }, 840 | { 841 | "name": "Obfuscates text in Bash", 842 | "request": { 843 | "method": "GET", 844 | "header": [ 845 | { 846 | "key": "Accept", 847 | "value": "*/*" 848 | } 849 | ], 850 | "url": { 851 | "raw": "{{baseUrl}}/obfuscate/bash?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 852 | "host": [ 853 | "{{baseUrl}}" 854 | ], 855 | "path": [ 856 | "obfuscate", 857 | "bash" 858 | ], 859 | "query": [ 860 | { 861 | "key": "text", 862 | "value": "dolor adipisicing ex nisi", 863 | "description": "(Required) " 864 | }, 865 | { 866 | "key": "minOps", 867 | "value": "5" 868 | }, 869 | { 870 | "key": "maxOps", 871 | "value": "15" 872 | } 873 | ] 874 | } 875 | }, 876 | "response": [ 877 | { 878 | "name": "Example", 879 | "originalRequest": { 880 | "method": "GET", 881 | "header": [ 882 | { 883 | "key": "Accept", 884 | "value": "*/*" 885 | } 886 | ], 887 | "url": { 888 | "raw": "{{baseUrl}}/obfuscate/bash?text=dolor adipisicing ex nisi&minOps=5&maxOps=15", 889 | "host": [ 890 | "{{baseUrl}}" 891 | ], 892 | "path": [ 893 | "obfuscate", 894 | "bash" 895 | ], 896 | "query": [ 897 | { 898 | "key": "text", 899 | "value": "dolor adipisicing ex nisi", 900 | "description": "(Required) " 901 | }, 902 | { 903 | "key": "minOps", 904 | "value": "5" 905 | }, 906 | { 907 | "key": "maxOps", 908 | "value": "15" 909 | } 910 | ] 911 | } 912 | }, 913 | "status": "OK", 914 | "code": 200, 915 | "_postman_previewlanguage": "plain", 916 | "header": [ 917 | { 918 | "key": "Content-Type", 919 | "value": "text/plain;charset=UTF-8" 920 | }, 921 | { 922 | "key": "Content-Length", 923 | "value": "628" 924 | }, 925 | { 926 | "key": "Date", 927 | "value": "Sun, 10 Jul 2022 16:29:33 GMT" 928 | }, 929 | { 930 | "key": "Keep-Alive", 931 | "value": "timeout=60" 932 | }, 933 | { 934 | "key": "Connection", 935 | "value": "keep-alive" 936 | } 937 | ], 938 | "cookie": [], 939 | "body": "string=( 0x1c83 0x1c5f 0x1c63 0x1c5f 0x1ccb 0x1b93 0x1c97 0x1c83 0x1c77 0x1cd3 0x1c77 0x1ccf 0x1c77 0x1c8f 0x1c77 0x1c5b 0x1c7f 0x1b93 0x1c87 0x1cb3 0x1b93 0x1c5b 0x1c77 0x1ccf 0x1c77 )\nfor pRrKRtrMA in ${!string[@]}; do\n\tyaADtrcgl=${string[$pRrKRtrMA]}\n\t((yaADtrcgl = ~yaADtrcgl & 0xffff))\n\t((yaADtrcgl = ~yaADtrcgl & 0xffff))\n\t((yaADtrcgl = (((yaADtrcgl & 0xffff) << 0xe) | (yaADtrcgl >> 0x2)) & 0xffff))\n\t((yaADtrcgl += 0x35aa))\n\t((yaADtrcgl ^= 0x351))\n\t((yaADtrcgl = ~yaADtrcgl & 0xffff))\n\tstring[$pRrKRtrMA]=$yaADtrcgl\ndone\nunset pRrKRtrMA\nunset yaADtrcgl\nstring=$(printf %b \"$(printf '\\\\U%x' \"${string[@]}\")\")\necho $string" 940 | } 941 | ] 942 | } 943 | ] 944 | } 945 | ], 946 | "variable": [ 947 | { 948 | "key": "baseUrl", 949 | "value": "http://localhost:1337", 950 | "type": "string" 951 | } 952 | ] 953 | } -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /usr/local/etc/mavenrc ] ; then 40 | . /usr/local/etc/mavenrc 41 | fi 42 | 43 | if [ -f /etc/mavenrc ] ; then 44 | . /etc/mavenrc 45 | fi 46 | 47 | if [ -f "$HOME/.mavenrc" ] ; then 48 | . "$HOME/.mavenrc" 49 | fi 50 | 51 | fi 52 | 53 | # OS specific support. $var _must_ be set to either true or false. 54 | cygwin=false; 55 | darwin=false; 56 | mingw=false 57 | case "`uname`" in 58 | CYGWIN*) cygwin=true ;; 59 | MINGW*) mingw=true;; 60 | Darwin*) darwin=true 61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 63 | if [ -z "$JAVA_HOME" ]; then 64 | if [ -x "/usr/libexec/java_home" ]; then 65 | export JAVA_HOME="`/usr/libexec/java_home`" 66 | else 67 | export JAVA_HOME="/Library/Java/Home" 68 | fi 69 | fi 70 | ;; 71 | esac 72 | 73 | if [ -z "$JAVA_HOME" ] ; then 74 | if [ -r /etc/gentoo-release ] ; then 75 | JAVA_HOME=`java-config --jre-home` 76 | fi 77 | fi 78 | 79 | if [ -z "$M2_HOME" ] ; then 80 | ## resolve links - $0 may be a link to maven's home 81 | PRG="$0" 82 | 83 | # need this for relative symlinks 84 | while [ -h "$PRG" ] ; do 85 | ls=`ls -ld "$PRG"` 86 | link=`expr "$ls" : '.*-> \(.*\)$'` 87 | if expr "$link" : '/.*' > /dev/null; then 88 | PRG="$link" 89 | else 90 | PRG="`dirname "$PRG"`/$link" 91 | fi 92 | done 93 | 94 | saveddir=`pwd` 95 | 96 | M2_HOME=`dirname "$PRG"`/.. 97 | 98 | # make it fully qualified 99 | M2_HOME=`cd "$M2_HOME" && pwd` 100 | 101 | cd "$saveddir" 102 | # echo Using m2 at $M2_HOME 103 | fi 104 | 105 | # For Cygwin, ensure paths are in UNIX format before anything is touched 106 | if $cygwin ; then 107 | [ -n "$M2_HOME" ] && 108 | M2_HOME=`cygpath --unix "$M2_HOME"` 109 | [ -n "$JAVA_HOME" ] && 110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 111 | [ -n "$CLASSPATH" ] && 112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 113 | fi 114 | 115 | # For Mingw, ensure paths are in UNIX format before anything is touched 116 | if $mingw ; then 117 | [ -n "$M2_HOME" ] && 118 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 119 | [ -n "$JAVA_HOME" ] && 120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 121 | fi 122 | 123 | if [ -z "$JAVA_HOME" ]; then 124 | javaExecutable="`which javac`" 125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 126 | # readlink(1) is not available as standard on Solaris 10. 127 | readLink=`which readlink` 128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 129 | if $darwin ; then 130 | javaHome="`dirname \"$javaExecutable\"`" 131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 132 | else 133 | javaExecutable="`readlink -f \"$javaExecutable\"`" 134 | fi 135 | javaHome="`dirname \"$javaExecutable\"`" 136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 137 | JAVA_HOME="$javaHome" 138 | export JAVA_HOME 139 | fi 140 | fi 141 | fi 142 | 143 | if [ -z "$JAVACMD" ] ; then 144 | if [ -n "$JAVA_HOME" ] ; then 145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 146 | # IBM's JDK on AIX uses strange locations for the executables 147 | JAVACMD="$JAVA_HOME/jre/sh/java" 148 | else 149 | JAVACMD="$JAVA_HOME/bin/java" 150 | fi 151 | else 152 | JAVACMD="`\\unset -f command; \\command -v java`" 153 | fi 154 | fi 155 | 156 | if [ ! -x "$JAVACMD" ] ; then 157 | echo "Error: JAVA_HOME is not defined correctly." >&2 158 | echo " We cannot execute $JAVACMD" >&2 159 | exit 1 160 | fi 161 | 162 | if [ -z "$JAVA_HOME" ] ; then 163 | echo "Warning: JAVA_HOME environment variable is not set." 164 | fi 165 | 166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 167 | 168 | # traverses directory structure from process work directory to filesystem root 169 | # first directory with .mvn subdirectory is considered project base directory 170 | find_maven_basedir() { 171 | 172 | if [ -z "$1" ] 173 | then 174 | echo "Path not specified to find_maven_basedir" 175 | return 1 176 | fi 177 | 178 | basedir="$1" 179 | wdir="$1" 180 | while [ "$wdir" != '/' ] ; do 181 | if [ -d "$wdir"/.mvn ] ; then 182 | basedir=$wdir 183 | break 184 | fi 185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 186 | if [ -d "${wdir}" ]; then 187 | wdir=`cd "$wdir/.."; pwd` 188 | fi 189 | # end of workaround 190 | done 191 | echo "${basedir}" 192 | } 193 | 194 | # concatenates all lines of a file 195 | concat_lines() { 196 | if [ -f "$1" ]; then 197 | echo "$(tr -s '\n' ' ' < "$1")" 198 | fi 199 | } 200 | 201 | BASE_DIR=`find_maven_basedir "$(pwd)"` 202 | if [ -z "$BASE_DIR" ]; then 203 | exit 1; 204 | fi 205 | 206 | ########################################################################################## 207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 208 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 209 | ########################################################################################## 210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Found .mvn/wrapper/maven-wrapper.jar" 213 | fi 214 | else 215 | if [ "$MVNW_VERBOSE" = true ]; then 216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 217 | fi 218 | if [ -n "$MVNW_REPOURL" ]; then 219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 220 | else 221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 222 | fi 223 | while IFS="=" read key value; do 224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 225 | esac 226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 227 | if [ "$MVNW_VERBOSE" = true ]; then 228 | echo "Downloading from: $jarUrl" 229 | fi 230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 231 | if $cygwin; then 232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 233 | fi 234 | 235 | if command -v wget > /dev/null; then 236 | if [ "$MVNW_VERBOSE" = true ]; then 237 | echo "Found wget ... using wget" 238 | fi 239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 241 | else 242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 243 | fi 244 | elif command -v curl > /dev/null; then 245 | if [ "$MVNW_VERBOSE" = true ]; then 246 | echo "Found curl ... using curl" 247 | fi 248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 249 | curl -o "$wrapperJarPath" "$jarUrl" -f 250 | else 251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 252 | fi 253 | 254 | else 255 | if [ "$MVNW_VERBOSE" = true ]; then 256 | echo "Falling back to using Java to download" 257 | fi 258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 259 | # For Cygwin, switch paths to Windows format before running javac 260 | if $cygwin; then 261 | javaClass=`cygpath --path --windows "$javaClass"` 262 | fi 263 | if [ -e "$javaClass" ]; then 264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 265 | if [ "$MVNW_VERBOSE" = true ]; then 266 | echo " - Compiling MavenWrapperDownloader.java ..." 267 | fi 268 | # Compiling the Java class 269 | ("$JAVA_HOME/bin/javac" "$javaClass") 270 | fi 271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 272 | # Running the downloader 273 | if [ "$MVNW_VERBOSE" = true ]; then 274 | echo " - Running MavenWrapperDownloader.java ..." 275 | fi 276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 277 | fi 278 | fi 279 | fi 280 | fi 281 | ########################################################################################## 282 | # End of extension 283 | ########################################################################################## 284 | 285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 286 | if [ "$MVNW_VERBOSE" = true ]; then 287 | echo $MAVEN_PROJECTBASEDIR 288 | fi 289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 290 | 291 | # For Cygwin, switch paths to Windows format before running java 292 | if $cygwin; then 293 | [ -n "$M2_HOME" ] && 294 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 295 | [ -n "$JAVA_HOME" ] && 296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 297 | [ -n "$CLASSPATH" ] && 298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 299 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 301 | fi 302 | 303 | # Provide a "standardized" way to retrieve the CLI args that will 304 | # work with both Windows and non-Windows executions. 305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 306 | export MAVEN_CMD_LINE_ARGS 307 | 308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 309 | 310 | exec "$JAVACMD" \ 311 | $MAVEN_OPTS \ 312 | $MAVEN_DEBUG_OPTS \ 313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 314 | "-Dmaven.home=${M2_HOME}" \ 315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 317 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 124 | 125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% ^ 162 | %JVM_CONFIG_MAVEN_PROPS% ^ 163 | %MAVEN_OPTS% ^ 164 | %MAVEN_DEBUG_OPTS% ^ 165 | -classpath %WRAPPER_JAR% ^ 166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 168 | if ERRORLEVEL 1 goto error 169 | goto end 170 | 171 | :error 172 | set ERROR_CODE=1 173 | 174 | :end 175 | @endlocal & set ERROR_CODE=%ERROR_CODE% 176 | 177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 181 | :skipRcPost 182 | 183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 185 | 186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 187 | 188 | cmd /C exit /B %ERROR_CODE% 189 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.7.1 9 | 10 | 11 | 54754n4 12 | string-obfuscator 13 | 1.0.0 14 | String-Obfuscator 15 | String obfuscation service with different language generation targets 16 | 17 | 17 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-devtools 28 | runtime 29 | true 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-configuration-processor 34 | true 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-test 39 | test 40 | 41 | 42 | org.junit.platform 43 | junit-platform-suite-engine 44 | 45 | 46 | 47 | org.springdoc 48 | springdoc-openapi-ui 49 | 1.6.9 50 | 51 | 52 | 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-maven-plugin 58 | 59 | -Dspring.application.admin.enabled=true -Pintegration -Dspringdoc.writer-with-default-pretty-printer=true 60 | 61 | 62 | 63 | 64 | start 65 | stop 66 | 67 | 68 | 69 | 70 | 71 | org.springdoc 72 | springdoc-openapi-maven-plugin 73 | 1.4 74 | 75 | 76 | integration-test 77 | 78 | generate 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | spring-milestones 88 | Spring Milestones 89 | https://repo.spring.io/milestone 90 | 91 | false 92 | 93 | 94 | 95 | spring-snapshots 96 | Spring Snapshots 97 | https://repo.spring.io/snapshot 98 | 99 | false 100 | 101 | 102 | 103 | 104 | 105 | spring-milestones 106 | Spring Milestones 107 | https://repo.spring.io/milestone 108 | 109 | false 110 | 111 | 112 | 113 | spring-snapshots 114 | Spring Snapshots 115 | https://repo.spring.io/snapshot 116 | 117 | false 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/StringObfuscatorApplication.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class StringObfuscatorApplication { 8 | public static void main(String[] args) { 9 | SpringApplication.run(StringObfuscatorApplication.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/controllers/ObfuscationServiceController.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.controllers; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | import org.springframework.web.bind.annotation.ResponseStatus; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import com.satsana.so.engine.model.GenerationTarget; 12 | import com.satsana.so.services.ObfuscationService; 13 | 14 | import io.swagger.v3.oas.annotations.Operation; 15 | 16 | @RestController 17 | @RequestMapping("/obfuscate") 18 | public class ObfuscationServiceController { 19 | @Autowired 20 | private ObfuscationService service; 21 | 22 | @Operation(summary = "Obfuscates text in C") 23 | @GetMapping(value = "/c") 24 | @ResponseStatus(code = HttpStatus.OK) 25 | public String obfuscateC( 26 | @RequestParam(required = true, name = "text") String text, 27 | @RequestParam(required = false, name = "minOps", defaultValue = "5") int minOps, 28 | @RequestParam(required = false, name = "maxOps", defaultValue = "15") int maxOps) { 29 | return service.generate(text, minOps, maxOps, GenerationTarget.C); 30 | } 31 | 32 | @Operation(summary = "Obfuscates text in C++") 33 | @GetMapping(value = "/cpp") 34 | @ResponseStatus(code = HttpStatus.OK) 35 | public String obfuscateCPP( 36 | @RequestParam(required = true, name = "text") String text, 37 | @RequestParam(required = false, name = "minOps", defaultValue = "5") int minOps, 38 | @RequestParam(required = false, name = "maxOps", defaultValue = "15") int maxOps) { 39 | return service.generate(text, minOps, maxOps, GenerationTarget.C); 40 | } 41 | 42 | @Operation(summary = "Obfuscates text in C#") 43 | @GetMapping(value = "/csharp") 44 | @ResponseStatus(code = HttpStatus.OK) 45 | public String obfuscateCSharp( 46 | @RequestParam(required = true, name = "text") String text, 47 | @RequestParam(required = false, name = "minOps", defaultValue = "5") int minOps, 48 | @RequestParam(required = false, name = "maxOps", defaultValue = "15") int maxOps) { 49 | return service.generate(text, minOps, maxOps, GenerationTarget.C_SHARP); 50 | } 51 | 52 | @Operation(summary = "Obfuscates text in Java") 53 | @GetMapping(value = "/java") 54 | @ResponseStatus(code = HttpStatus.OK) 55 | public String obfuscateJava( 56 | @RequestParam(required = true, name = "text") String text, 57 | @RequestParam(required = false, name = "minOps", defaultValue = "5") int minOps, 58 | @RequestParam(required = false, name = "maxOps", defaultValue = "15") int maxOps) { 59 | return service.generate(text, minOps, maxOps, GenerationTarget.JAVA); 60 | } 61 | 62 | @Operation(summary = "Obfuscates text in JS") 63 | @GetMapping(value = "/javascript") 64 | @ResponseStatus(code = HttpStatus.OK) 65 | public String obfuscateJavaScript( 66 | @RequestParam(required = true, name = "text") String text, 67 | @RequestParam(required = false, name = "minOps", defaultValue = "5") int minOps, 68 | @RequestParam(required = false, name = "maxOps", defaultValue = "15") int maxOps) { 69 | return service.generate(text, minOps, maxOps, GenerationTarget.JS); 70 | } 71 | 72 | @Operation(summary = "Obfuscates text in Python") 73 | @GetMapping(value = "/python") 74 | @ResponseStatus(code = HttpStatus.OK) 75 | public String obfuscatePython( 76 | @RequestParam(required = true, name = "text") String text, 77 | @RequestParam(required = false, name = "minOps", defaultValue = "5") int minOps, 78 | @RequestParam(required = false, name = "maxOps", defaultValue = "15") int maxOps) { 79 | return service.generate(text, minOps, maxOps, GenerationTarget.PYTHON); 80 | } 81 | 82 | @Operation(summary = "Obfuscates text in MASM 64 bit") 83 | @GetMapping(value = "/masm64") 84 | @ResponseStatus(code = HttpStatus.OK) 85 | public String obfuscateMasm64( 86 | @RequestParam(required = true, name = "text") String text, 87 | @RequestParam(required = false, name = "minOps", defaultValue = "5") int minOps, 88 | @RequestParam(required = false, name = "maxOps", defaultValue = "15") int maxOps) { 89 | return service.generate(text, minOps, maxOps, GenerationTarget.MASM64); 90 | } 91 | 92 | @Operation(summary = "Obfuscates text in Bash") 93 | @GetMapping(value = "/bash") 94 | @ResponseStatus(code = HttpStatus.OK) 95 | public String obfuscateBash( 96 | @RequestParam(required = true, name = "text") String text, 97 | @RequestParam(required = false, name = "minOps", defaultValue = "5") int minOps, 98 | @RequestParam(required = false, name = "maxOps", defaultValue = "15") int maxOps) { 99 | return service.generate(text, minOps, maxOps, GenerationTarget.BASH); 100 | } 101 | 102 | @Operation(summary = "Obfuscates text in PowerShell") 103 | @GetMapping(value = "/powershell") 104 | @ResponseStatus(code = HttpStatus.OK) 105 | public String obfuscatePowerShell( 106 | @RequestParam(required = true, name = "text") String text, 107 | @RequestParam(required = false, name = "minOps", defaultValue = "5") int minOps, 108 | @RequestParam(required = false, name = "maxOps", defaultValue = "15") int maxOps) { 109 | return service.generate(text, minOps, maxOps, GenerationTarget.POWERSHELL); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/model/Context.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.model; 2 | 3 | public class Context { 4 | private final int maxBits; 5 | private final long[] bytes; 6 | private final long mask; 7 | private final TransformationChain forward, reverse; 8 | 9 | public Context(int maxBits, long[] bytes, long mask, TransformationChain forward, TransformationChain reverse) { 10 | this.maxBits = maxBits; 11 | this.bytes = bytes; 12 | this.mask = mask; 13 | this.forward = forward; 14 | this.reverse = reverse; 15 | } 16 | 17 | public int getMaxBits() { 18 | return maxBits; 19 | } 20 | 21 | public long getMask() { 22 | return mask; 23 | } 24 | 25 | public long[] getBytes() { 26 | return bytes; 27 | } 28 | 29 | public TransformationChain getForward() { 30 | return forward; 31 | } 32 | 33 | public TransformationChain getReverse() { 34 | return reverse; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/model/Engine.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.model; 2 | 3 | import java.io.File; 4 | import java.nio.file.Files; 5 | import java.nio.file.Path; 6 | 7 | public interface Engine { 8 | Context transform(String text) throws Exception; 9 | 10 | /* Convenience methods */ 11 | default Context transform(Path path) throws Exception { 12 | return transform(Files.readString(path)); 13 | } 14 | 15 | default Context transform(File file) throws Exception { 16 | return transform(file.toPath()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/model/GenerationTarget.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.model; 2 | 3 | public enum GenerationTarget { 4 | BASH, 5 | C_SHARP, 6 | C, 7 | CPP, 8 | JS, 9 | JAVA, 10 | MASM64, 11 | POWERSHELL, 12 | PYTHON; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/model/PolymorphicEngine.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.model; 2 | 3 | import java.util.concurrent.ThreadLocalRandom; 4 | 5 | import com.satsana.so.engine.transforms.Add; 6 | import com.satsana.so.engine.transforms.MulMod; 7 | import com.satsana.so.engine.transforms.MulModInv; 8 | import com.satsana.so.engine.transforms.Not; 9 | import com.satsana.so.engine.transforms.Permutation; 10 | import com.satsana.so.engine.transforms.RotateLeft; 11 | import com.satsana.so.engine.transforms.RotateRight; 12 | import com.satsana.so.engine.transforms.Substract; 13 | import com.satsana.so.engine.transforms.Xor; 14 | import com.satsana.so.engine.transforms.model.Transformation; 15 | 16 | public class PolymorphicEngine implements Engine { 17 | private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current(); 18 | private final int maxBits, minOps, maxOps; 19 | private final long MASK, MULTIPLICATIVE_LIMIT, ADDITIVE_LIMIT; 20 | 21 | public PolymorphicEngine(int minOps, int maxOps, int maxBits) { 22 | this.maxBits = maxBits; 23 | this.minOps = minOps; 24 | this.maxOps = maxOps; 25 | MASK = (1l << maxBits) - 1; 26 | MULTIPLICATIVE_LIMIT = 1l << (maxBits / 2); 27 | ADDITIVE_LIMIT = 1l << (maxBits - 2); 28 | } 29 | 30 | /* Returns long[] instead of int[] because some 32/64 bit 31 | * transformations might overflow and we want to be able to 32 | * detect them easily. It will be downcasted in the end anyways. 33 | * Note: Reads all in memory since array needs to be stored 34 | * before generating decryption routine either way. */ 35 | @Override 36 | public Context transform(String text) { 37 | long[] buffer = new long[text.length()]; 38 | TransformationChain forward, reverse; 39 | long check; 40 | retry: while (true) { 41 | forward = generateForward(); 42 | reverse = forward.reverse(); 43 | for (int pos = 0; pos < buffer.length; pos++) { 44 | try { 45 | long c = text.charAt(pos); 46 | buffer[pos] = forward.apply(c); 47 | // dynamic check in case of implicit overflows 48 | check = reverse.apply(buffer[pos]).longValue(); 49 | if ((char) check != (char) c) 50 | continue retry; 51 | } catch (ArithmeticException e) { // explicit overflow/underflow 52 | continue retry; 53 | } 54 | // valid range sanity check 55 | if (buffer[pos] < 0 || buffer[pos] >= max()) 56 | continue retry; 57 | } 58 | break; // passed all sanity checks 59 | } 60 | return new Context(maxBits, buffer, MASK, forward, reverse); 61 | } 62 | 63 | private final TransformationChain generateForward() { 64 | TransformationChain forward = new TransformationChain(); 65 | int total = RANDOM.nextInt(minOps, maxOps+1); 66 | for (int i=0; i= maxBits 101 | || (pos2 + bits) >= maxBits); 102 | return new Permutation(pos1, pos2, bits, maxBits); 103 | } 104 | 105 | private final Transformation mulMod() { 106 | MulMod mm; 107 | while (true) { 108 | mm = new MulMod(randomMax(), 1l << maxBits, maxBits); 109 | if (mm.getValue() == 1) 110 | continue; 111 | try { 112 | MulModInv mmi = (MulModInv) mm.reversed(); 113 | if (mmi.getValue() > MULTIPLICATIVE_LIMIT) 114 | continue; 115 | } catch (Exception e) { // no inverse mod 116 | continue; 117 | } 118 | break; 119 | } 120 | return mm; 121 | } 122 | 123 | private final Transformation mulModInv() { 124 | MulModInv mmi; 125 | while (true) { 126 | try { 127 | mmi = new MulModInv(randomMax(), 1l << maxBits, maxBits); 128 | if (mmi.getValue() == 1) 129 | continue; 130 | } catch (Exception e) { // no inverse mod 131 | continue; 132 | } 133 | MulMod mm = (MulMod) mmi.reversed(); 134 | if (mm.getValue() > MULTIPLICATIVE_LIMIT) 135 | continue; 136 | break; 137 | } 138 | return mmi; 139 | } 140 | 141 | /* Random generator */ 142 | 143 | public static long nextLong(long bound) { 144 | return RANDOM.nextLong(bound); 145 | } 146 | 147 | private long randomMax() { 148 | return nextLong(max()); 149 | } 150 | 151 | private long max() { 152 | return 1l << maxBits; 153 | } 154 | 155 | /* Accessors */ 156 | 157 | public int getMaxBits() { 158 | return maxBits; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/model/TransformationChain.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.function.Function; 5 | 6 | import com.satsana.so.engine.transforms.Permutation; 7 | import com.satsana.so.engine.transforms.model.Transformation; 8 | 9 | public class TransformationChain extends ArrayList implements Function { 10 | private static final long serialVersionUID = 6587027146192465729L; 11 | 12 | @Override 13 | public Long apply(Long t) { 14 | long c = t; 15 | for (int i=0; i= 0; --i) 23 | reverse.add(get(i).reversed()); 24 | return reverse; 25 | } 26 | 27 | public boolean contains(Class cls) { 28 | for (Transformation t : this) 29 | if (cls.isInstance(t)) 30 | return true; 31 | return false; 32 | } 33 | 34 | public boolean containsPermutation() { 35 | return contains(Permutation.class); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/Add.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms; 2 | 3 | import com.satsana.so.engine.transforms.model.Transformation; 4 | 5 | public class Add extends Transformation { 6 | private final long value; 7 | 8 | public Add(long value, int maxBits) { 9 | super(maxBits); 10 | this.value = value; 11 | } 12 | 13 | @Override 14 | public long transform(long i) { 15 | if (i > max() - value) 16 | throw new ArithmeticException("Additive overflow"); 17 | return i+value; 18 | } 19 | 20 | @Override 21 | public Transformation reversed() { 22 | return new Substract(value, maxBits()); 23 | } 24 | 25 | public long getValue() { 26 | return value; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/MulMod.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms; 2 | 3 | import com.satsana.so.engine.transforms.model.Modulus; 4 | import com.satsana.so.engine.transforms.model.Transformation; 5 | 6 | public class MulMod extends Modulus { 7 | public MulMod(long value, long modulo, int maxBits) { 8 | super(value, modulo, maxBits); 9 | } 10 | 11 | @Override 12 | public long transform(long i) { 13 | if (i != (i*getValue())/getValue() || i * getValue() >= max()) 14 | throw new ArithmeticException("Multiplicative overflow"); 15 | return (i*getValue()) % getModulo(); 16 | } 17 | 18 | @Override 19 | public Transformation reversed() { 20 | return new MulModInv(getValue(), getModulo(), maxBits()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/MulModInv.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms; 2 | 3 | import com.satsana.so.engine.transforms.model.Transformation; 4 | 5 | /* long c; 6 | forward = (a*c)%m; 7 | reverse = (inv*forward)%m == c 8 | */ 9 | public class MulModInv extends MulMod { 10 | private long initial; 11 | 12 | public MulModInv(long value, long modulo, int maxBits) { 13 | super(modInverse(value, modulo), modulo, maxBits); 14 | initial = value; 15 | } 16 | 17 | @Override 18 | public Transformation reversed() { 19 | return new MulMod(initial, getModulo(), maxBits()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/Not.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms; 2 | 3 | import com.satsana.so.engine.transforms.model.Transformation; 4 | 5 | public class Not extends Transformation { 6 | public Not(int maxBits) { 7 | super(maxBits); 8 | } 9 | 10 | @Override 11 | public long transform(long i) { 12 | return ~i & ((1l << maxBits()) - 1); 13 | } 14 | 15 | @Override 16 | public Transformation reversed() { 17 | return this; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/Permutation.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms; 2 | 3 | import com.satsana.so.engine.transforms.model.Transformation; 4 | 5 | public class Permutation extends Transformation { 6 | private final long pos1, pos2, bits; 7 | 8 | public Permutation(int pos1, int pos2, int bits, int maxBits) { 9 | super(maxBits); 10 | this.pos1 = pos1; 11 | this.pos2 = pos2; 12 | this.bits = bits; 13 | if (Math.max(pos1, pos2) + bits > maxBits) 14 | throw new ArithmeticException("Invalid ranges"); 15 | } 16 | 17 | @Override 18 | public long transform(long i) { 19 | long xor = ((i >> pos1) ^ (i >> pos2)) & ((1l << bits) - 1l); 20 | return i ^ ((xor << pos1) | (xor << pos2)); 21 | } 22 | 23 | @Override 24 | public Transformation reversed() { 25 | return this; 26 | } 27 | 28 | public long getPosition1() { 29 | return pos1; 30 | } 31 | 32 | public long getPosition2() { 33 | return pos2; 34 | } 35 | 36 | public long getBits() { 37 | return bits; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/RotateLeft.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms; 2 | 3 | import com.satsana.so.engine.transforms.model.Rotation; 4 | import com.satsana.so.engine.transforms.model.Transformation; 5 | 6 | public class RotateLeft extends Rotation { 7 | public RotateLeft(long value, int maxBits) { 8 | super(value, maxBits); 9 | } 10 | 11 | @Override 12 | public long transform(long i) { 13 | return (((i & getMask()) >> lhs()) | (i << rhs())) & getMask(); 14 | } 15 | 16 | @Override 17 | public Transformation reversed() { 18 | return new RotateRight(getValue(), maxBits()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/RotateRight.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms; 2 | 3 | import com.satsana.so.engine.transforms.model.Rotation; 4 | import com.satsana.so.engine.transforms.model.Transformation; 5 | 6 | public class RotateRight extends Rotation { 7 | public RotateRight(long value, int maxBits) { 8 | super(value, maxBits); 9 | } 10 | 11 | @Override 12 | public long transform(long i) { 13 | return (((i & getMask()) << lhs()) | (i >> rhs())) & getMask(); 14 | } 15 | 16 | @Override 17 | public Transformation reversed() { 18 | return new RotateLeft(getValue(), maxBits()); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/Substract.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms; 2 | 3 | import com.satsana.so.engine.transforms.model.Transformation; 4 | 5 | public class Substract extends Transformation { 6 | private final long value; 7 | 8 | public Substract(long value, int maxBits) { 9 | super(maxBits); 10 | this.value = value; 11 | } 12 | 13 | @Override 14 | public long transform(long i) { 15 | if (i < value) 16 | throw new ArithmeticException("Substraction underflow"); 17 | return i - value; 18 | } 19 | 20 | @Override 21 | public Transformation reversed() { 22 | return new Add(value, maxBits()); 23 | } 24 | 25 | public long getValue() { 26 | return value; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/Xor.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms; 2 | 3 | import com.satsana.so.engine.transforms.model.Transformation; 4 | 5 | public class Xor extends Transformation { 6 | private final long value; 7 | 8 | public Xor(long value, int maxBits) { 9 | super(maxBits); 10 | this.value = value; 11 | } 12 | 13 | @Override 14 | public long transform(long i) { 15 | return i ^ value; 16 | } 17 | 18 | @Override 19 | public Transformation reversed() { 20 | return this; 21 | } 22 | 23 | public long getValue() { 24 | return value; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/model/Modulus.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms.model; 2 | 3 | public abstract class Modulus extends Transformation { 4 | private final long value, modulo; 5 | 6 | public Modulus(long value, long modulo, int maxBits) { 7 | super(maxBits); 8 | this.value = value; 9 | this.modulo = modulo; 10 | } 11 | 12 | public long getValue() { 13 | return value; 14 | } 15 | 16 | public long getModulo() { 17 | return modulo; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/model/Rotation.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms.model; 2 | 3 | public abstract class Rotation extends Transformation { 4 | private final long value; 5 | 6 | public Rotation(long value, int maxBits) { 7 | super(maxBits); 8 | this.value = value; 9 | } 10 | 11 | public long getValue() { 12 | return value; 13 | } 14 | 15 | /* Both rotations use the same left/right hand sides */ 16 | 17 | public long lhs() { 18 | return ((long) maxBits()) - getValue(); 19 | } 20 | 21 | public long rhs() { 22 | return getValue(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/transforms/model/Transformation.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.transforms.model; 2 | 3 | public abstract class Transformation { 4 | private final int maxBits; 5 | private final long mask; 6 | 7 | public Transformation(int maxBits) { 8 | this.maxBits = maxBits; 9 | mask = (1l << maxBits) - 1l; // avoid sign extension to keep 64 bits 10 | } 11 | 12 | public long getMask() { 13 | return mask; 14 | } 15 | 16 | public int maxBits() { 17 | return maxBits; 18 | } 19 | 20 | public long max() { 21 | return 1l << maxBits; 22 | } 23 | 24 | public abstract long transform(long i); 25 | public abstract Transformation reversed(); 26 | 27 | /* Helper methods */ 28 | 29 | public static long gcd(long a, long b) { // steins algorithm 30 | if (a == 0) 31 | return b; 32 | if (b == 0) 33 | return a; 34 | int n; 35 | for (n = 0; ((a | b) & 1) == 0; n++) { 36 | a >>= 1; 37 | b >>= 1; 38 | } 39 | while ((a & 1) == 0) 40 | a >>= 1; 41 | do { 42 | while ((b & 1) == 0) 43 | b >>= 1; 44 | if (a > b) { 45 | long temp = a; 46 | a = b; 47 | b = temp; 48 | } 49 | b = (b - a); 50 | } while (b != 0); 51 | return a << n; 52 | } 53 | 54 | public static long modInverse(long a, long m) { 55 | if (a%m == 0) 56 | throw new ArithmeticException("Modular inverse can't be calculated when a/m"); 57 | if (gcd(a, m) != 1) 58 | throw new ArithmeticException("Modular inverse exists only if a and m are coprime"); 59 | long m0 = m; 60 | long y = 0, x = 1; 61 | if (m == 1) 62 | return 0; 63 | while (a > 1) { 64 | long q = a / m, 65 | t = m; 66 | m = a % m; 67 | a = t; 68 | t = y; 69 | y = x - q * y; 70 | x = t; 71 | } 72 | if (x < 0) 73 | x += m0; 74 | return x; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/visitors/BashVisitor.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.visitors; 2 | 3 | import com.satsana.so.engine.model.Context; 4 | import com.satsana.so.engine.transforms.Add; 5 | import com.satsana.so.engine.transforms.MulMod; 6 | import com.satsana.so.engine.transforms.MulModInv; 7 | import com.satsana.so.engine.transforms.Not; 8 | import com.satsana.so.engine.transforms.Permutation; 9 | import com.satsana.so.engine.transforms.RotateLeft; 10 | import com.satsana.so.engine.transforms.RotateRight; 11 | import com.satsana.so.engine.transforms.Substract; 12 | import com.satsana.so.engine.transforms.Xor; 13 | 14 | public class BashVisitor extends LanguageVisitor { 15 | private String variable, variableName, tempName, i, iName, result, resultName; 16 | private boolean hasPermutations; 17 | 18 | // Arithmetic expansion helper method 19 | private final String ae(String format, Object...args) { 20 | return String.format("(("+format+"))", args); 21 | } 22 | 23 | @Override 24 | public StringBuilder initialise(Context context) { 25 | // Generate variable names 26 | variableName = generateName(); 27 | variable = "$" + variableName; 28 | tempName = generateName(); 29 | iName = generateName(); 30 | i = "$"+iName; 31 | resultName = "string"; 32 | result = "$" + resultName; 33 | hasPermutations = context.getReverse().containsPermutation(); 34 | // Write bytes in string 35 | StringBuilder sb = new StringBuilder(); 36 | long[] bytes = context.getBytes(); 37 | sb.append(resultName+"=( "); 38 | for (long b : bytes) 39 | sb.append(hex(b)+" "); 40 | sb.append(")\n"); 41 | // Write for loop 42 | sb.append(String.format("for %s in ${!%s[@]}; do\n", iName, resultName)); 43 | sb.append("\t"+variableName+"=${"+resultName+"["+i+"]}\n"); 44 | return sb; 45 | } 46 | 47 | @Override 48 | public void finalise(StringBuilder in) { 49 | in.append(String.format("\t%s[%s]=%s\n", resultName, i, variable)) 50 | .append("done\n") 51 | .append(String.format("unset %s\n", iName)) 52 | .append(String.format("unset %s\n", variableName)); 53 | if (hasPermutations) 54 | in.append(String.format("unset %s\n", tempName)); 55 | in.append(resultName+"=$(printf %b \"$(printf '\\\\U%x' \"${"+resultName+"[@]}\")\")\n") 56 | .append("echo "+result); 57 | } 58 | 59 | @Override 60 | public void visit(Add a, StringBuilder in) { 61 | if (a.getValue() == 1) { 62 | in.append("\t").append(ae("%s++", variableName)) 63 | .append("\n"); 64 | return; 65 | } 66 | in.append("\t") 67 | .append(ae("%s += %s", variableName, hex(a.getValue()))) 68 | .append("\n"); 69 | } 70 | 71 | @Override 72 | public void visit(MulMod mm, StringBuilder in) { 73 | in.append("\t") 74 | .append(ae("%s = (%s * %s) %% %s", variableName, variableName, hex(mm.getValue()), hex(mm.getModulo()))) 75 | .append("\n"); 76 | } 77 | 78 | @Override 79 | public void visit(MulModInv mmi, StringBuilder in) { 80 | visit(MulMod.class.cast(mmi), in); 81 | } 82 | 83 | @Override 84 | public void visit(Not n, StringBuilder in) { 85 | in.append("\t") 86 | .append(ae("%s = ~%s & %s", variableName, variableName, hex(n.getMask()))) 87 | .append("\n"); 88 | } 89 | 90 | @Override 91 | public void visit(Permutation p, StringBuilder in) { 92 | in.append("\t") 93 | .append(ae("%s = ((%s >> %s) ^ (%s >> %s)) & ((1 << %s)-1)", tempName, variableName, hex(p.getPosition1()), variableName, hex(p.getPosition2()), hex(p.getBits()))) 94 | .append("\n"); 95 | in.append("\t") 96 | .append(ae("%s ^= (%s << %s) | (%s << %s)", variableName, tempName, hex(p.getPosition1()), tempName, hex(p.getPosition2()))) 97 | .append("\n"); 98 | } 99 | 100 | @Override 101 | public void visit(RotateLeft rl, StringBuilder in) { 102 | String mask = hex(rl.getMask()); 103 | in.append("\t") 104 | .append(ae("%s = (((%s & %s) >> %s) | (%s << %s)) & %s", variableName, variableName, mask, hex(rl.lhs()), variableName, hex(rl.rhs()), mask)) 105 | .append("\n"); 106 | } 107 | 108 | @Override 109 | public void visit(RotateRight rr, StringBuilder in) { 110 | String mask = hex(rr.getMask()); 111 | in.append("\t") 112 | .append(ae("%s = (((%s & %s) << %s) | (%s >> %s)) & %s", variableName, variableName, mask, hex(rr.lhs()), variableName, hex(rr.rhs()), mask)) 113 | .append("\n"); 114 | } 115 | 116 | @Override 117 | public void visit(Substract s, StringBuilder in) { 118 | if (s.getValue() == 1) { 119 | in.append("\t").append(ae("%s--", variableName)) 120 | .append("\n"); 121 | return; 122 | } 123 | in.append("\t") 124 | .append(ae("%s -= %s", variableName, hex(s.getValue()))) 125 | .append("\n"); 126 | } 127 | 128 | @Override 129 | public void visit(Xor x, StringBuilder in) { 130 | in.append("\t") 131 | .append(ae("%s ^= %s", variableName, hex(x.getValue()))) 132 | .append("\n"); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/visitors/CSharpVisitor.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.visitors; 2 | 3 | import com.satsana.so.engine.model.Context; 4 | import com.satsana.so.engine.transforms.Add; 5 | import com.satsana.so.engine.transforms.MulMod; 6 | import com.satsana.so.engine.transforms.MulModInv; 7 | import com.satsana.so.engine.transforms.Not; 8 | import com.satsana.so.engine.transforms.Permutation; 9 | import com.satsana.so.engine.transforms.RotateLeft; 10 | import com.satsana.so.engine.transforms.RotateRight; 11 | import com.satsana.so.engine.transforms.Substract; 12 | import com.satsana.so.engine.transforms.Xor; 13 | 14 | public class CSharpVisitor extends LanguageVisitor { 15 | private String variable, temp, i, result; 16 | 17 | @Override 18 | public StringBuilder initialise(Context context) { 19 | // Generate variable names 20 | variable = generateName(); 21 | temp = generateName(); 22 | i = generateName(); 23 | result = "str"; 24 | // Write bytes in string 25 | StringBuilder sb = new StringBuilder(); 26 | sb.append("var "+result+" = new System.Text.StringBuilder(\""); 27 | for (long b : context.getBytes()) 28 | sb.append("\\u"+String.format("%04x", b)); 29 | sb.append("\");\n"); 30 | // Write for loop 31 | String permutation = ""; 32 | if (context.getReverse().containsPermutation()) 33 | permutation = ", "+temp; 34 | sb.append(String.format("for (int %s=0, %s%s; %s < %s.Length; %s++) {\n", i, variable, permutation, i, result, i)); 35 | sb.append("\t"+variable+" = "+result+"["+i+"];\n"); 36 | return sb; 37 | } 38 | 39 | @Override 40 | public void finalise(StringBuilder in) { 41 | in.append(String.format("\t%s[%s] = (char) %s;\n", result, i, variable)) 42 | .append("}\n") 43 | .append("Console.WriteLine("+result+");"); 44 | } 45 | 46 | @Override 47 | public void visit(Add a, StringBuilder in) { 48 | if (a.getValue() == 1) { 49 | in.append("\t").append(variable) 50 | .append("++;\n"); 51 | return; 52 | } 53 | in.append("\t").append(variable) 54 | .append(" += ").append(hex(a.getValue())) 55 | .append(";\n"); 56 | } 57 | 58 | @Override 59 | public void visit(MulMod mm, StringBuilder in) { 60 | in.append("\t").append(variable) 61 | .append(" = ").append("("+variable).append(" * "+hex(mm.getValue())+") % "+hex(mm.getModulo())) 62 | .append(";\n"); 63 | } 64 | 65 | @Override 66 | public void visit(MulModInv mmi, StringBuilder in) { 67 | visit(MulMod.class.cast(mmi), in); 68 | } 69 | 70 | @Override 71 | public void visit(Not n, StringBuilder in) { 72 | in.append("\t").append(variable) 73 | .append(" = ").append("~"+variable+" & "+hex(n.getMask())) 74 | .append(";\n"); 75 | } 76 | 77 | @Override 78 | public void visit(Permutation p, StringBuilder in) { 79 | in.append("\t").append(temp) 80 | .append(" = ").append("(("+variable+" >> "+hex(p.getPosition1())+")") 81 | .append(" ^ ("+variable+" >> "+hex(p.getPosition2())+")) & ((1 << "+hex(p.getBits())+") - 1)") 82 | .append(";\n"); 83 | in.append("\t").append(variable) 84 | .append(" ^= ").append("("+temp+" << "+hex(p.getPosition1())+") | ("+temp+" << "+hex(p.getPosition2())+")") 85 | .append(";\n"); 86 | } 87 | 88 | @Override 89 | public void visit(RotateLeft rl, StringBuilder in) { 90 | String mask = hex(rl.getMask()); 91 | in.append("\t").append(variable) 92 | .append(" = ").append("((("+variable+" & "+mask+") >> "+hex(rl.lhs())+") | (") 93 | .append(variable+" << "+hex(rl.rhs())+")) & "+mask) 94 | .append(";\n"); 95 | } 96 | 97 | @Override 98 | public void visit(RotateRight rr, StringBuilder in) { 99 | String mask = hex(rr.getMask()); 100 | in.append("\t").append(variable) 101 | .append(" = ").append("((("+variable+" & "+mask+") << "+hex(rr.lhs())+") | (") 102 | .append(variable+" >> "+hex(rr.rhs())+")) & "+mask) 103 | .append(";\n"); 104 | } 105 | 106 | @Override 107 | public void visit(Substract s, StringBuilder in) { 108 | if (s.getValue() == 1) { 109 | in.append("\t").append(variable) 110 | .append("--;\n"); 111 | return; 112 | } 113 | in.append("\t").append(variable) 114 | .append(" -= ").append(hex(s.getValue())) 115 | .append(";\n"); 116 | } 117 | 118 | @Override 119 | public void visit(Xor x, StringBuilder in) { 120 | in.append("\t").append(variable) 121 | .append(" ^= ").append(hex(x.getValue())) 122 | .append(";\n"); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/visitors/CVisitor.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.visitors; 2 | 3 | import com.satsana.so.engine.model.Context; 4 | import com.satsana.so.engine.transforms.Add; 5 | import com.satsana.so.engine.transforms.MulMod; 6 | import com.satsana.so.engine.transforms.MulModInv; 7 | import com.satsana.so.engine.transforms.Not; 8 | import com.satsana.so.engine.transforms.Permutation; 9 | import com.satsana.so.engine.transforms.RotateLeft; 10 | import com.satsana.so.engine.transforms.RotateRight; 11 | import com.satsana.so.engine.transforms.Substract; 12 | import com.satsana.so.engine.transforms.Xor; 13 | 14 | public class CVisitor extends LanguageVisitor { 15 | private String variable, temp, i, result; 16 | 17 | @Override 18 | public StringBuilder initialise(Context context) { 19 | // Generate variable names 20 | variable = generateName(); 21 | temp = generateName(); 22 | i = generateName(); 23 | result = "string"; 24 | // Write bytes in string 25 | StringBuilder sb = new StringBuilder(); 26 | long[] bytes = context.getBytes(); 27 | sb.append("wchar_t "+result+"["+bytes.length+"] = {"); 28 | for (long b : bytes) 29 | sb.append(hex(b)+","); 30 | sb.deleteCharAt(sb.length()-1) // remove last comma 31 | .append("};\n"); 32 | // Write for loop 33 | String permutation = ""; 34 | if (context.getReverse().containsPermutation()) 35 | permutation = ", "+temp; 36 | sb.append(String.format("for (unsigned int %s=0, %s%s; %s < %d; %s++) {\n", i, variable, permutation, i, bytes.length, i)); 37 | sb.append("\t"+variable+" = "+result+"["+i+"];\n"); 38 | return sb; 39 | } 40 | 41 | @Override 42 | public void finalise(StringBuilder in) { 43 | in.append(String.format("\t%s[%s] = %s;\n", result, i, variable)) 44 | .append("}\n") 45 | .append("wprintf("+result+");"); 46 | } 47 | 48 | @Override 49 | public void visit(Add a, StringBuilder in) { 50 | if (a.getValue() == 1) { 51 | in.append("\t").append(variable) 52 | .append("++;\n"); 53 | return; 54 | } 55 | in.append("\t").append(variable) 56 | .append(" += ").append(hex(a.getValue())) 57 | .append(";\n"); 58 | } 59 | 60 | @Override 61 | public void visit(MulMod mm, StringBuilder in) { 62 | in.append("\t").append(variable) 63 | .append(" = ").append("("+variable).append(" * "+hex(mm.getValue())+") % "+hex(mm.getModulo())) 64 | .append(";\n"); 65 | } 66 | 67 | @Override 68 | public void visit(MulModInv mmi, StringBuilder in) { 69 | visit(MulMod.class.cast(mmi), in); 70 | } 71 | 72 | @Override 73 | public void visit(Not n, StringBuilder in) { 74 | in.append("\t").append(variable) 75 | .append(" = ").append("~"+variable+" & "+hex(n.getMask())) 76 | .append(";\n"); 77 | } 78 | 79 | @Override 80 | public void visit(Permutation p, StringBuilder in) { 81 | in.append("\t").append(temp) 82 | .append(" = ").append("(("+variable+" >> "+hex(p.getPosition1())+")") 83 | .append(" ^ ("+variable+" >> "+hex(p.getPosition2())+")) & ((1 << "+hex(p.getBits())+") - 1)") 84 | .append(";\n"); 85 | in.append("\t").append(variable) 86 | .append(" ^= ").append("("+temp+" << "+hex(p.getPosition1())+") | ("+temp+" << "+hex(p.getPosition2())+")") 87 | .append(";\n"); 88 | } 89 | 90 | @Override 91 | public void visit(RotateLeft rl, StringBuilder in) { 92 | String mask = hex(rl.getMask()); 93 | in.append("\t").append(variable) 94 | .append(" = ").append("((("+variable+" & "+mask+") >> "+hex(rl.lhs())+") | (") 95 | .append(variable+" << "+hex(rl.rhs())+")) & "+mask) 96 | .append(";\n"); 97 | } 98 | 99 | @Override 100 | public void visit(RotateRight rr, StringBuilder in) { 101 | String mask = hex(rr.getMask()); 102 | in.append("\t").append(variable) 103 | .append(" = ").append("((("+variable+" & "+mask+") << "+hex(rr.lhs())+") | (") 104 | .append(variable+" >> "+hex(rr.rhs())+")) & "+mask) 105 | .append(";\n"); 106 | } 107 | 108 | @Override 109 | public void visit(Substract s, StringBuilder in) { 110 | if (s.getValue() == 1) { 111 | in.append("\t").append(variable) 112 | .append("--;\n"); 113 | return; 114 | } 115 | in.append("\t").append(variable) 116 | .append(" -= ").append(hex(s.getValue())) 117 | .append(";\n"); 118 | } 119 | 120 | @Override 121 | public void visit(Xor x, StringBuilder in) { 122 | in.append("\t").append(variable) 123 | .append(" ^= ").append(hex(x.getValue())) 124 | .append(";\n"); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/visitors/JavaScriptVisitor.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.visitors; 2 | 3 | import com.satsana.so.engine.model.Context; 4 | import com.satsana.so.engine.transforms.Add; 5 | import com.satsana.so.engine.transforms.MulMod; 6 | import com.satsana.so.engine.transforms.MulModInv; 7 | import com.satsana.so.engine.transforms.Not; 8 | import com.satsana.so.engine.transforms.Permutation; 9 | import com.satsana.so.engine.transforms.RotateLeft; 10 | import com.satsana.so.engine.transforms.RotateRight; 11 | import com.satsana.so.engine.transforms.Substract; 12 | import com.satsana.so.engine.transforms.Xor; 13 | 14 | public class JavaScriptVisitor extends LanguageVisitor { 15 | private String variable, temp, i, result; 16 | 17 | @Override 18 | public StringBuilder initialise(Context context) { 19 | // Generate variables 20 | variable = generateName(); 21 | temp = generateName(); 22 | i = generateName(); 23 | result = "string"; 24 | // Write bytes in string 25 | StringBuilder sb = new StringBuilder(); 26 | sb.append("var "+result+" = ["); 27 | for (long b : context.getBytes()) 28 | sb.append(hex(b)+","); 29 | sb.deleteCharAt(sb.length()-1) // remove last comma 30 | .append("];\n"); 31 | // Write for loop 32 | String permutation = ""; 33 | if (context.getReverse().containsPermutation()) 34 | permutation = ", "+temp; 35 | sb.append(String.format("for (var %s=0, %s%s; %s < %s.length; %s++) {\n", i, variable, permutation, i, result, i)); 36 | sb.append("\t"+variable+" = "+result+"["+i+"];\n"); 37 | return sb; 38 | } 39 | 40 | @Override 41 | public void finalise(StringBuilder in) { 42 | in.append(String.format("\t%s[%s] = %s;\n", result, i, variable)) 43 | .append("}\n") 44 | .append(result + " = String.fromCodePoint(..."+result+");\n") 45 | .append("console.log("+result+");\n"); 46 | } 47 | 48 | @Override 49 | public void visit(Add a, StringBuilder in) { 50 | if (a.getValue() == 1) { 51 | in.append("\t").append(variable) 52 | .append("++;\n"); 53 | return; 54 | } 55 | in.append("\t").append(variable) 56 | .append(" += ").append(hex(a.getValue())) 57 | .append(";\n"); 58 | } 59 | 60 | @Override 61 | public void visit(MulMod mm, StringBuilder in) { 62 | in.append("\t").append(variable) 63 | .append(" = ").append("("+variable).append(" * "+hex(mm.getValue())+") % "+hex(mm.getModulo())) 64 | .append(";\n"); 65 | } 66 | 67 | @Override 68 | public void visit(MulModInv mmi, StringBuilder in) { 69 | visit(MulMod.class.cast(mmi), in); 70 | } 71 | 72 | @Override 73 | public void visit(Not n, StringBuilder in) { 74 | in.append("\t").append(variable) 75 | .append(" = ").append("~"+variable+" & "+hex(n.getMask())) 76 | .append(";\n"); 77 | } 78 | 79 | @Override 80 | public void visit(Permutation p, StringBuilder in) { 81 | in.append("\t").append(temp) 82 | .append(" = ").append("(("+variable+" >> "+hex(p.getPosition1())+")") 83 | .append(" ^ ("+variable+" >> "+hex(p.getPosition2())+")) & ((1 << "+hex(p.getBits())+") - 1)") 84 | .append(";\n"); 85 | in.append("\t").append(variable) 86 | .append(" ^= ").append("("+temp+" << "+hex(p.getPosition1())+") | ("+temp+" << "+hex(p.getPosition2())+")") 87 | .append(";\n"); 88 | } 89 | 90 | @Override 91 | public void visit(RotateLeft rl, StringBuilder in) { 92 | String mask = hex(rl.getMask()); 93 | in.append("\t").append(variable) 94 | .append(" = ").append("((("+variable+" & "+mask+") >> "+hex(rl.lhs())+") | (") 95 | .append(variable+" << "+hex(rl.rhs())+")) & "+mask) 96 | .append(";\n"); 97 | } 98 | 99 | @Override 100 | public void visit(RotateRight rr, StringBuilder in) { 101 | String mask = hex(rr.getMask()); 102 | in.append("\t").append(variable) 103 | .append(" = ").append("((("+variable+" & "+mask+") << "+hex(rr.lhs())+") | (") 104 | .append(variable+" >> "+hex(rr.rhs())+")) & "+mask) 105 | .append(";\n"); 106 | } 107 | 108 | @Override 109 | public void visit(Substract s, StringBuilder in) { 110 | if (s.getValue() == 1) { 111 | in.append("\t").append(variable) 112 | .append("--;\n"); 113 | return; 114 | } 115 | in.append("\t").append(variable) 116 | .append(" -= ").append(hex(s.getValue())) 117 | .append(";\n"); 118 | } 119 | 120 | @Override 121 | public void visit(Xor x, StringBuilder in) { 122 | in.append("\t").append(variable) 123 | .append(" ^= ").append(hex(x.getValue())) 124 | .append(";\n"); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/visitors/JavaVisitor.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.visitors; 2 | 3 | import com.satsana.so.engine.model.Context; 4 | import com.satsana.so.engine.transforms.Add; 5 | import com.satsana.so.engine.transforms.MulMod; 6 | import com.satsana.so.engine.transforms.MulModInv; 7 | import com.satsana.so.engine.transforms.Not; 8 | import com.satsana.so.engine.transforms.Permutation; 9 | import com.satsana.so.engine.transforms.RotateLeft; 10 | import com.satsana.so.engine.transforms.RotateRight; 11 | import com.satsana.so.engine.transforms.Substract; 12 | import com.satsana.so.engine.transforms.Xor; 13 | 14 | public class JavaVisitor extends LanguageVisitor { 15 | private String variable, temp, i, result; 16 | 17 | @Override 18 | public StringBuilder initialise(Context context) { 19 | // Generate variable names 20 | variable = generateName(); 21 | temp = generateName(); 22 | i = generateName(); 23 | result = "string"; 24 | // Write bytes in string 25 | StringBuilder sb = new StringBuilder(); 26 | sb.append("StringBuilder "+result+" = new StringBuilder(\""); 27 | for (long b : context.getBytes()) 28 | sb.append("\\u"+String.format("%04x", b)); 29 | sb.append("\");\n"); 30 | // Write for loop 31 | String permutation = ""; 32 | if (context.getReverse().containsPermutation()) 33 | permutation = ", "+temp; 34 | sb.append(String.format("for (int %s=0, %s%s; %s < %s.length(); %s++) {\n", i, variable, permutation, i, result, i)); 35 | sb.append("\t"+variable+" = "+result+".charAt("+i+");\n"); 36 | return sb; 37 | } 38 | 39 | @Override 40 | public void finalise(StringBuilder in) { 41 | in.append(String.format("\t%s.setCharAt(%s, (char) %s);\n", result, i, variable)) 42 | .append("}\n") 43 | .append("System.out.println("+result+");"); 44 | } 45 | 46 | @Override 47 | public void visit(Add a, StringBuilder in) { 48 | if (a.getValue() == 1) { 49 | in.append("\t").append(variable) 50 | .append("++;\n"); 51 | return; 52 | } 53 | in.append("\t").append(variable) 54 | .append(" += ").append(hex(a.getValue())) 55 | .append(";\n"); 56 | } 57 | 58 | @Override 59 | public void visit(MulMod mm, StringBuilder in) { 60 | in.append("\t").append(variable) 61 | .append(" = ").append("("+variable).append(" * "+hex(mm.getValue())+") % "+hex(mm.getModulo())) 62 | .append(";\n"); 63 | } 64 | 65 | @Override 66 | public void visit(MulModInv mmi, StringBuilder in) { 67 | visit(MulMod.class.cast(mmi), in); 68 | } 69 | 70 | @Override 71 | public void visit(Not n, StringBuilder in) { 72 | in.append("\t").append(variable) 73 | .append(" = ").append("~"+variable+" & "+hex(n.getMask())) 74 | .append(";\n"); 75 | } 76 | 77 | @Override 78 | public void visit(Permutation p, StringBuilder in) { 79 | in.append("\t").append(temp) 80 | .append(" = ").append("(("+variable+" >> "+hex(p.getPosition1())+")") 81 | .append(" ^ ("+variable+" >> "+hex(p.getPosition2())+")) & ((1 << "+hex(p.getBits())+") - 1)") 82 | .append(";\n"); 83 | in.append("\t").append(variable) 84 | .append(" ^= ").append("("+temp+" << "+hex(p.getPosition1())+") | ("+temp+" << "+hex(p.getPosition2())+")") 85 | .append(";\n"); 86 | } 87 | 88 | @Override 89 | public void visit(RotateLeft rl, StringBuilder in) { 90 | String mask = hex(rl.getMask()); 91 | in.append("\t").append(variable) 92 | .append(" = ").append("((("+variable+" & "+mask+") >> "+hex(rl.lhs())+") | (") 93 | .append(variable+" << "+hex(rl.rhs())+")) & "+mask) 94 | .append(";\n"); 95 | } 96 | 97 | @Override 98 | public void visit(RotateRight rr, StringBuilder in) { 99 | in.append("\t").append(variable) 100 | .append(" = ").append("((("+variable+" & "+hex(rr.getMask())+") << "+hex(rr.lhs())+") | (") 101 | .append(variable+" >> "+hex(rr.rhs())+")) & "+hex(rr.getMask())) 102 | .append(";\n"); 103 | } 104 | 105 | @Override 106 | public void visit(Substract s, StringBuilder in) { 107 | if (s.getValue() == 1) { 108 | in.append("\t").append(variable) 109 | .append("--;\n"); 110 | return; 111 | } 112 | in.append("\t").append(variable) 113 | .append(" -= ").append(hex(s.getValue())) 114 | .append(";\n"); 115 | } 116 | 117 | @Override 118 | public void visit(Xor x, StringBuilder in) { 119 | in.append("\t").append(variable) 120 | .append(" ^= ").append(hex(x.getValue())) 121 | .append(";\n"); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/visitors/LanguageVisitor.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.visitors; 2 | 3 | import java.util.concurrent.ThreadLocalRandom; 4 | 5 | public abstract class LanguageVisitor implements Visitor { 6 | private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current(); 7 | private static final int NAME_MIN = 4, NAME_MAX = 10; 8 | private static final String DEFAULT_ALPHABET; 9 | 10 | static { 11 | StringBuilder sb = new StringBuilder(); 12 | sb.append("_"); 13 | for (char c = 'a'; c <= 'z'; c++) 14 | sb.append(c).append((char) (c ^ 32)); // lowercase and uppercase 15 | DEFAULT_ALPHABET = sb.toString(); 16 | } 17 | 18 | public static String generateName(String alphabet) { 19 | int size = RANDOM.nextInt(NAME_MIN, NAME_MAX+1); 20 | StringBuilder sb = new StringBuilder(); 21 | for (int i=0; i> "+hex(p.getPosition1())+")") 82 | .append(" ^ ("+variable+" >> "+hex(p.getPosition2())+")) & ((1 << "+hex(p.getBits())+") - 1)") 83 | .append("\n"); 84 | in.append("\t").append(variable) 85 | .append(" ^= ").append("("+temp+" << "+hex(p.getPosition1())+") | ("+temp+" << "+hex(p.getPosition2())+")") 86 | .append("\n"); 87 | } 88 | 89 | @Override 90 | public void visit(RotateLeft rl, StringBuilder in) { 91 | String mask = hex(rl.getMask()); 92 | in.append("\t").append(variable) 93 | .append(" = ").append("((("+variable+" & "+mask+") >> "+hex(rl.lhs())+") | (") 94 | .append(variable+" << "+hex(rl.rhs())+")) & "+mask) 95 | .append("\n"); 96 | } 97 | 98 | @Override 99 | public void visit(RotateRight rr, StringBuilder in) { 100 | String mask = hex(rr.getMask()); 101 | in.append("\t").append(variable) 102 | .append(" = ").append("((("+variable+" & "+mask+") << "+hex(rr.lhs())+") | (") 103 | .append(variable+" >> "+hex(rr.rhs())+")) & "+mask) 104 | .append("\n"); 105 | } 106 | 107 | @Override 108 | public void visit(Substract s, StringBuilder in) { 109 | in.append("\t").append(variable) 110 | .append(" -= ") 111 | .append(hex(s.getValue())) 112 | .append("\n"); 113 | } 114 | 115 | @Override 116 | public void visit(Xor x, StringBuilder in) { 117 | in.append("\t").append(variable) 118 | .append(" ^= ").append(hex(x.getValue())) 119 | .append("\n"); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/engine/visitors/Visitor.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engine.visitors; 2 | 3 | import com.satsana.so.engine.model.Context; 4 | import com.satsana.so.engine.model.TransformationChain; 5 | import com.satsana.so.engine.transforms.Add; 6 | import com.satsana.so.engine.transforms.MulMod; 7 | import com.satsana.so.engine.transforms.MulModInv; 8 | import com.satsana.so.engine.transforms.Not; 9 | import com.satsana.so.engine.transforms.Permutation; 10 | import com.satsana.so.engine.transforms.RotateLeft; 11 | import com.satsana.so.engine.transforms.RotateRight; 12 | import com.satsana.so.engine.transforms.Substract; 13 | import com.satsana.so.engine.transforms.Xor; 14 | import com.satsana.so.engine.transforms.model.Transformation; 15 | 16 | public interface Visitor { 17 | T initialise(Context ctx); 18 | void finalise(T in); 19 | 20 | default T visit(Context ctx) { 21 | T t = initialise(ctx); 22 | visit(ctx.getReverse(), t); 23 | finalise(t); 24 | return t; 25 | } 26 | 27 | default void visit(TransformationChain chain, T in) { 28 | for (Transformation element : chain) 29 | visit(element, in); 30 | } 31 | 32 | /* Visit methods */ 33 | 34 | void visit(Add a, T in); 35 | void visit(MulMod mm, T in); 36 | void visit(MulModInv mmi, T in); 37 | void visit(Not n, T in); 38 | void visit(Permutation p, T in); 39 | void visit(RotateLeft rl, T in); 40 | void visit(RotateRight rr, T in); 41 | void visit(Substract s, T in); 42 | void visit(Xor x, T in); 43 | 44 | /* Double dispatch visitor methods */ 45 | 46 | default void visit(Transformation t, T in) { 47 | if (Add.class.isInstance(t)) { 48 | visit(Add.class.cast(t), in); 49 | return; 50 | } if (MulMod.class.isInstance(t)) { 51 | visit(MulMod.class.cast(t), in); 52 | return; 53 | } if (MulModInv.class.isInstance(t)) { 54 | visit(MulModInv.class.cast(t), in); 55 | return; 56 | } if (Not.class.isInstance(t)) { 57 | visit(Not.class.cast(t), in); 58 | return; 59 | } if (Permutation.class.isInstance(t)) { 60 | visit(Permutation.class.cast(t), in); 61 | return; 62 | } if (RotateLeft.class.isInstance(t)) { 63 | visit(RotateLeft.class.cast(t), in); 64 | return; 65 | } if (RotateRight.class.isInstance(t)) { 66 | visit(RotateRight.class.cast(t), in); 67 | return; 68 | } if (Substract.class.isInstance(t)) { 69 | visit(Substract.class.cast(t), in); 70 | return; 71 | } if (Xor.class.isInstance(t)) { 72 | visit(Xor.class.cast(t), in); 73 | return; 74 | } else 75 | throw new IllegalStateException("Unimplemented transformation double dispatch"); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/services/ObfuscationService.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.services; 2 | 3 | import com.satsana.so.engine.model.GenerationTarget; 4 | 5 | public interface ObfuscationService { 6 | String generate(String message, int minOps, int maxOps, GenerationTarget target); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/satsana/so/services/ObfuscationServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.services; 2 | 3 | import org.springframework.stereotype.Service; 4 | 5 | import com.satsana.so.engine.model.Context; 6 | import com.satsana.so.engine.model.GenerationTarget; 7 | import com.satsana.so.engine.model.PolymorphicEngine; 8 | import com.satsana.so.engine.visitors.BashVisitor; 9 | import com.satsana.so.engine.visitors.CSharpVisitor; 10 | import com.satsana.so.engine.visitors.CVisitor; 11 | import com.satsana.so.engine.visitors.JavaScriptVisitor; 12 | import com.satsana.so.engine.visitors.JavaVisitor; 13 | import com.satsana.so.engine.visitors.LanguageVisitor; 14 | import com.satsana.so.engine.visitors.Masm64Visitor; 15 | import com.satsana.so.engine.visitors.PowerShellVisitor; 16 | import com.satsana.so.engine.visitors.PythonVisitor; 17 | 18 | @Service 19 | public class ObfuscationServiceImpl implements ObfuscationService { 20 | 21 | @Override 22 | public String generate(String message, int minOps, int maxOps, GenerationTarget target) { 23 | PolymorphicEngine engine = new PolymorphicEngine(minOps, maxOps, 16); 24 | Context context = engine.transform(message); 25 | LanguageVisitor visitor = getVisitor(target); 26 | return visitor.visit(context).toString(); 27 | } 28 | 29 | private static LanguageVisitor getVisitor(GenerationTarget target) { 30 | switch (target) { 31 | case BASH: 32 | return new BashVisitor(); 33 | case C: 34 | case CPP: 35 | return new CVisitor(); 36 | case C_SHARP: 37 | return new CSharpVisitor(); 38 | case JAVA: 39 | return new JavaVisitor(); 40 | case JS: 41 | return new JavaScriptVisitor(); 42 | case MASM64: 43 | return new Masm64Visitor(); 44 | case POWERSHELL: 45 | return new PowerShellVisitor(); 46 | case PYTHON: 47 | return new PythonVisitor(); 48 | default: 49 | throw new RuntimeException("No visitor bound to this target"); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=1337 2 | # swagger-ui custom path 3 | springdoc.swagger-ui.path=/swagger-ui.html -------------------------------------------------------------------------------- /src/test/java/com/satsana/so/engines/BashEngineTest.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engines; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import java.io.IOException; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.nio.file.Paths; 10 | import java.util.concurrent.ExecutionException; 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | 14 | import org.junit.jupiter.api.AfterAll; 15 | import org.junit.jupiter.api.BeforeAll; 16 | import org.junit.jupiter.api.Test; 17 | import org.springframework.boot.test.context.SpringBootTest; 18 | 19 | import com.satsana.so.engine.model.Context; 20 | import com.satsana.so.engine.model.PolymorphicEngine; 21 | import com.satsana.so.engine.visitors.BashVisitor; 22 | import com.satsana.so.engines.TestsUtil.ProcessOutput; 23 | 24 | /* Requires WSL and a linux distro installed to run */ 25 | @SpringBootTest 26 | class BashEngineTest { 27 | private static String SHEBANG = "#!/bin/bash\n\n"; 28 | private static ExecutorService executor; 29 | 30 | @BeforeAll 31 | static void setUpBeforeClass() throws Exception { 32 | executor = Executors.newCachedThreadPool(); 33 | } 34 | 35 | @AfterAll 36 | static void tearDownAfterClass() throws Exception { 37 | executor.shutdownNow(); 38 | } 39 | 40 | @Test 41 | void testBash() throws IOException, InterruptedException, ExecutionException { 42 | // Check valid compiler location 43 | ProcessOutput po = TestsUtil.run(executor, "bash --help"); 44 | assertTrue(po.getOutput().toLowerCase().startsWith("gnu bash")); 45 | 46 | // Create polymorphic engine and bash target generator 47 | PolymorphicEngine engine = new PolymorphicEngine(5, 10, 16); 48 | BashVisitor visitor = new BashVisitor(); 49 | String message = "Hello World!"; 50 | 51 | // Test multiple decryption routines 52 | int decryptionRoutines = 100; 53 | for (int i=0; i;", sb.toString()); 63 | Path path = Paths.get(filename+".cpp"); 64 | try { 65 | Files.writeString(path, generated); 66 | TestsUtil.run(executor, "call \"%s\" && \"%s\\cl\" \"%s.cpp\"", ENV_BUILD_VARS, COMPILER_DIR, filename); 67 | po = TestsUtil.run(executor, ".\\%s.exe", filename); 68 | assertEquals(message, po.getOutput(), sb.toString()); 69 | } finally { 70 | Files.deleteIfExists(Paths.get(filename+".cpp")); 71 | Files.deleteIfExists(Paths.get(filename+".exe")); 72 | Files.deleteIfExists(Paths.get(filename+".obj")); 73 | } 74 | } 75 | } 76 | 77 | /* C & C++ compilation helper methods */ 78 | 79 | public static String createMainFile(String imports, String body) { 80 | return new StringBuilder() 81 | .append(imports).append("\n\n") 82 | .append("int main(int argc, char**argv) {\n\t") 83 | .append(body.replaceAll("\n", "\n\t")) 84 | .append("\n\treturn 0;\n}\n") 85 | .toString(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/test/java/com/satsana/so/engines/CSharpEngineTest.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engines; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.nio.file.Files; 9 | import java.nio.file.Path; 10 | import java.nio.file.Paths; 11 | import java.util.Comparator; 12 | import java.util.concurrent.ExecutionException; 13 | import java.util.concurrent.ExecutorService; 14 | import java.util.concurrent.Executors; 15 | 16 | import org.junit.jupiter.api.AfterAll; 17 | import org.junit.jupiter.api.BeforeAll; 18 | import org.junit.jupiter.api.Test; 19 | import org.springframework.boot.test.context.SpringBootTest; 20 | 21 | import com.satsana.so.engine.model.Context; 22 | import com.satsana.so.engine.model.PolymorphicEngine; 23 | import com.satsana.so.engine.visitors.CSharpVisitor; 24 | import com.satsana.so.engines.TestsUtil.ProcessOutput; 25 | 26 | /* Requires .NET and Visual Studio installed (code tested on .NET v6.0) */ 27 | @SpringBootTest 28 | class CSharpEngineTest { 29 | private static ExecutorService executor; 30 | 31 | @BeforeAll 32 | static void setUpBeforeClass() throws Exception { 33 | executor = Executors.newCachedThreadPool(); 34 | } 35 | 36 | @AfterAll 37 | static void tearDownAfterClass() throws Exception { 38 | executor.shutdownNow(); 39 | } 40 | 41 | /** 42 | * Add .\build folder as exception in Antivirus to avoid it delaying the test 43 | */ 44 | @Test 45 | void testCSharp() throws IOException, InterruptedException, ExecutionException { 46 | // Check C# in env path 47 | ProcessOutput po = TestsUtil.run(executor, "dotnet --info"); 48 | assertTrue(po.getOutput().toLowerCase().startsWith(".net")); 49 | 50 | // Create polymorphic engine and C# target generator 51 | PolymorphicEngine engine = new PolymorphicEngine(5, 10, 16); 52 | CSharpVisitor visitor = new CSharpVisitor(); 53 | String message = "Hello World!"; 54 | 55 | // Test multiple decryption routines 56 | int decryptionRoutines = 100; 57 | for (int i=0; i\r\n" 96 | + "\r\n" 97 | + " \r\n" 98 | + " Exe\r\n" 99 | + " net6.0\r\n" 100 | + " enable\r\n" 101 | + " enable\r\n" 102 | + " \r\n" 103 | + "\r\n" 104 | + "\r\n" 105 | + ""; 106 | } 107 | -------------------------------------------------------------------------------- /src/test/java/com/satsana/so/engines/JavaEngineTest.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engines; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import java.io.IOException; 7 | import java.nio.charset.StandardCharsets; 8 | import java.nio.file.Files; 9 | import java.nio.file.Path; 10 | import java.nio.file.Paths; 11 | import java.util.concurrent.ExecutionException; 12 | import java.util.concurrent.ExecutorService; 13 | import java.util.concurrent.Executors; 14 | 15 | import org.junit.jupiter.api.AfterAll; 16 | import org.junit.jupiter.api.BeforeAll; 17 | import org.junit.jupiter.api.Test; 18 | import org.springframework.boot.test.context.SpringBootTest; 19 | 20 | import com.satsana.so.engine.model.Context; 21 | import com.satsana.so.engine.model.PolymorphicEngine; 22 | import com.satsana.so.engine.visitors.JavaVisitor; 23 | import com.satsana.so.engines.TestsUtil.ProcessOutput; 24 | 25 | /* Requires Java to be installed and in PATH */ 26 | @SpringBootTest 27 | class JavaEngineTest { 28 | private static ExecutorService executor; 29 | 30 | @BeforeAll 31 | public static void setUpBeforeClass() { 32 | executor = Executors.newCachedThreadPool(); 33 | } 34 | 35 | @AfterAll 36 | public static void tearDownAfterClass() { 37 | executor.shutdownNow(); 38 | } 39 | 40 | @Test 41 | void testJava() throws IOException, InterruptedException, ExecutionException { 42 | // Check java in env path 43 | ProcessOutput po = TestsUtil.run(executor, "java -version"); 44 | assertTrue(po.getError().toLowerCase().startsWith("java")); // somehow java returns the version in stderr lol 45 | 46 | // Create polymorphic engine and java target generator 47 | PolymorphicEngine engine = new PolymorphicEngine(5, 10, 16); 48 | JavaVisitor visitor = new JavaVisitor(); 49 | String message = "Hello World!"; 50 | 51 | // Test multiple decryption routines 52 | int decryptionRoutines = 100; 53 | for (int i=0; i output.txt"); 73 | String output = Files.readString(Paths.get("output.txt"), StandardCharsets.UTF_16LE); 74 | assertEquals(message, output, sb.toString()); 75 | } finally { 76 | Files.deleteIfExists(Paths.get("build/main.asm")); 77 | Files.deleteIfExists(Paths.get("build/main.pdb")); 78 | Files.deleteIfExists(Paths.get("build/main.obj")); 79 | Files.deleteIfExists(Paths.get("build/main.ilk")); 80 | Files.deleteIfExists(Paths.get("build/main.exe.intermediate.manifest")); 81 | Files.deleteIfExists(Paths.get("build/main.exe")); 82 | Files.deleteIfExists(Paths.get("output.txt")); 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/com/satsana/so/engines/PowerShellEngineTest.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.engines; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import java.io.IOException; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.nio.file.Paths; 10 | import java.util.concurrent.ExecutionException; 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | 14 | import org.junit.jupiter.api.AfterAll; 15 | import org.junit.jupiter.api.BeforeAll; 16 | import org.junit.jupiter.api.Test; 17 | import org.springframework.boot.test.context.SpringBootTest; 18 | 19 | import com.satsana.so.engine.model.Context; 20 | import com.satsana.so.engine.model.PolymorphicEngine; 21 | import com.satsana.so.engine.visitors.PowerShellVisitor; 22 | import com.satsana.so.engines.TestsUtil.ProcessOutput; 23 | 24 | @SpringBootTest 25 | class PowerShellEngineTest { 26 | private static String CMD_FORMAT = "powershell -Command \"& '%s'\""; 27 | private static ExecutorService executor; 28 | 29 | @BeforeAll 30 | static void setUpBeforeClass() throws Exception { 31 | executor = Executors.newCachedThreadPool(); 32 | } 33 | 34 | @AfterAll 35 | static void tearDownAfterClass() throws Exception { 36 | executor.shutdownNow(); 37 | } 38 | 39 | @Test 40 | void testPowerShell() throws IOException, InterruptedException, ExecutionException { 41 | // Check valid interpreter 42 | assertTrue(TestsUtil.isWindows, "This test case cannot run on linux"); 43 | 44 | // Create polymorphic engine and PowerShell target generator 45 | PolymorphicEngine engine = new PolymorphicEngine(5, 10, 16); 46 | PowerShellVisitor visitor = new PowerShellVisitor(); 47 | String message = "Hello World!"; 48 | 49 | // Test multiple decryption routines 50 | int decryptionRoutines = 100; 51 | for (int i=0; i { 44 | private InputStream is; 45 | 46 | public StreamConsumer(InputStream is) { 47 | this.is = is; 48 | } 49 | 50 | @Override 51 | public String call() throws IOException { 52 | StringBuilder sb = new StringBuilder(); 53 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) { 54 | reader.lines().forEachOrdered(line -> sb.append(line).append(System.lineSeparator())); 55 | } 56 | return sb.toString().trim(); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/com/satsana/so/suites/EnginesTestSuite.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.suites; 2 | 3 | import org.junit.platform.suite.api.SelectPackages; 4 | import org.junit.platform.suite.api.Suite; 5 | import org.junit.platform.suite.api.SuiteDisplayName; 6 | 7 | @SelectPackages(value = { "com.satsana.so.engines" }) 8 | @Suite 9 | @SuiteDisplayName("Language generation targets Test Suite") 10 | public class EnginesTestSuite { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/com/satsana/so/transformations/TransformationsTest.java: -------------------------------------------------------------------------------- 1 | package com.satsana.so.transformations; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | import static org.junit.jupiter.api.Assertions.assertTrue; 6 | 7 | import java.util.function.BiFunction; 8 | 9 | import org.apache.logging.log4j.util.TriConsumer; 10 | import org.junit.jupiter.api.Test; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import com.satsana.so.engine.transforms.MulMod; 15 | import com.satsana.so.engine.transforms.Not; 16 | import com.satsana.so.engine.transforms.Permutation; 17 | import com.satsana.so.engine.transforms.RotateLeft; 18 | import com.satsana.so.engine.transforms.model.Rotation; 19 | import com.satsana.so.engine.transforms.model.Transformation; 20 | 21 | class TransformationsTest { 22 | private Logger logger = LoggerFactory.getLogger(TransformationsTest.class); 23 | 24 | @Test 25 | void testPermutation() { 26 | Transformation perm = new Permutation(0, 3, 2, 16), 27 | reverse = perm.reversed(); 28 | for (long x=30; x<100; x++) { 29 | long temp = perm.transform(x); 30 | temp = reverse.transform(temp); 31 | assertEquals(x, temp, x + " & "+temp + "are not equal"); 32 | } 33 | } 34 | 35 | @Test 36 | void testNeg() { 37 | Transformation not = new Not(32), 38 | rev = not.reversed(); 39 | for (long x=0; x<1000; x++) { 40 | long temp = not.transform(x); 41 | temp = rev.transform(temp); 42 | assertEquals(x, temp, x + " & "+temp + "are not equal"); 43 | } 44 | } 45 | 46 | @Test 47 | void testMulMod() { 48 | MulMod mm = new MulMod(3, 11, 16); 49 | Transformation mmi = mm.reversed(); 50 | long c = 5, 51 | temp = mm.transform(c); 52 | temp = mmi.transform(temp); 53 | assertEquals(c, temp, c + " & "+temp + "are not equal"); 54 | } 55 | 56 | @Test 57 | void testRotations() { 58 | Rotation r = new RotateLeft(1, 16); 59 | long v = 10, 60 | temp = r.transform(v); 61 | Rotation rr = (Rotation) r.reversed(); 62 | temp = r.reversed().transform(temp); 63 | assertEquals(r.lhs(), rr.lhs()); 64 | assertEquals(r.rhs(), rr.rhs()); 65 | assertEquals(v, temp); 66 | } 67 | 68 | @Test 69 | void testCoprimeGeneration() { 70 | /* All pair of positive coprime numbers (m,n) (with m > n) can be arranged 71 | * in two disjoint complete ternary trees starting from (2,1) and (3,1). 72 | * The three branches are as follow : (2m-n, m), (2m+n, m), (m+2n, n) 73 | * Ref: https://en.wikipedia.org/wiki/Coprime_integers 74 | */ 75 | final long limit = 1000; 76 | BiFunction gcd = Transformation::gcd, 77 | modInv = Transformation::modInverse; 78 | TriConsumer tester = (s, m, n) -> { 79 | long inv = modInv.apply(n, m); 80 | assertTrue(m > n, m +" is not bigger than "+n); 81 | assertTrue(gcd.apply(m, n) == 1); 82 | assertDoesNotThrow(() -> inv); 83 | logger.debug("{} ({}, {}) mod inv of {} [{}] = {}", s, m, n, n, m, inv); 84 | }; 85 | TriConsumer seededTest = (s, m, n) -> { 86 | long im = m, in = n, 87 | pm, pn; 88 | // Branch 1 89 | while (m < limit) { 90 | pm = m; pn = n; 91 | tester.accept(s+"Branch 1",m, n); 92 | m = (pm << 1) - pn; // 2m-n 93 | n = pm; // m 94 | } 95 | m = im; n = in; 96 | // Branch 2 97 | while (m < limit) { 98 | pm = m; pn = n; 99 | tester.accept(s+"Branch 2",m, n); 100 | m = (pm << 1) + pn; // 2m+n 101 | n = pm; // m 102 | } 103 | m = im; n = in; 104 | // Branch 3 105 | while (m < limit) { 106 | pm = m; pn = n; 107 | tester.accept(s+"Branch 3",m, n); 108 | m = pm + (pn << 1); // m+2n 109 | n = pn; // n 110 | } 111 | }; 112 | // Even-odd/ood-even pairs starting with (2,1) 113 | seededTest.accept("Even-odds ", 2l,1l); 114 | // Odd-odd pairs starting with (3,1) 115 | seededTest.accept("Odd-odds ", 3l,1l); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /string-obfuscator-1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54754N4/String-Obfuscator/2ff721460e2b193386517c655259f9fd8576280e/string-obfuscator-1.0.0.jar --------------------------------------------------------------------------------