├── .gitignore ├── LICENSE ├── META-INF └── MANIFEST.MF ├── README.md ├── build.sh └── src └── me └── timschneeberger └── servicemode └── otp ├── Main.java └── OTPSecurity.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Project exclude paths 2 | /out/ 3 | *.class 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Tim Schneeberger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: me.timschneeberger.servicemode.otp.Main 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SamsungServiceModeOTP 2 | Generate OTP tokens for Samsung Service Mode to activate hidden debug/dumping features 3 | 4 | 1. Download .jar file: https://github.com/ThePBone/SamsungServiceModeOTP/releases/ 5 | 2. Access SysDump service mode menu using secret code: `*#9900#` 6 | 3. Select any option that requires OTP authentication (i.e. `TCP DUMP START`) 7 | 4. Use this program to generate an activation key using the nonce provided by the app (`java -jar SamsungServiceModeOTP.jar `) 8 | 5. Insert the generated key into the app and activate the locked features 9 | 10 | Note: The generated OTPs expire after a while and are calculated using time and date. Make sure the clock on your computer and phone are accurate and in the same timezone. 11 | 12 | Example: 13 | ```bash 14 | java -jar SamsungServiceModeOTP.jar yuh0h 15 | ``` 16 | ``` 17 | Decrypted one-time password: 2142664100 18 | => Key verified. OTP expires in 13 minutes. 19 | ``` 20 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | javac src/me/timschneeberger/servicemode/otp/Main.java src/me/timschneeberger/servicemode/otp/OTPSecurity.java 4 | jar cvfe SamsungServiceModeOTP.jar me.timschneeberger.servicemode.otp.Main -C src/ . 5 | -------------------------------------------------------------------------------- /src/me/timschneeberger/servicemode/otp/Main.java: -------------------------------------------------------------------------------- 1 | package me.timschneeberger.servicemode.otp; 2 | 3 | public class Main { 4 | 5 | public static void main(String[] args) { 6 | if(args.length != 1) 7 | { 8 | System.out.println("Usage: SamsungServiceModeOTP "); 9 | return; 10 | } 11 | 12 | String otp = OTPSecurity.getOTP(args[0]); 13 | System.out.println("Decrypted one-time password: " + otp); 14 | 15 | if(OTPSecurity.checkOTP(otp, args[0])) 16 | { 17 | System.out.println("=> Key verified. OTP expires in " + OTPSecurity.getExpireDate() + "."); 18 | } 19 | else 20 | { 21 | System.out.println("=> Key not verified. Something is wrong"); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/me/timschneeberger/servicemode/otp/OTPSecurity.java: -------------------------------------------------------------------------------- 1 | package me.timschneeberger.servicemode.otp; 2 | 3 | import java.text.DecimalFormat; 4 | import java.time.temporal.ChronoUnit; 5 | import java.time.Duration; 6 | import java.time.LocalDateTime; 7 | import java.time.ZoneOffset; 8 | import java.util.Calendar; 9 | import java.util.TimeZone; 10 | 11 | 12 | public class OTPSecurity { 13 | public static boolean checkOTP(String str, String str2) { 14 | int i = 5; 15 | while (true) { 16 | if (i <= -1) 17 | return false; 18 | 19 | i -= 1; 20 | if (str.equalsIgnoreCase(Integer.toString(makeHashCode(str2 + getDateString(i))))) 21 | return true; 22 | } 23 | } 24 | 25 | public static String getOTP(String basekey) 26 | { 27 | return Integer.toString(makeHashCode(basekey + getDateString(4))); 28 | } 29 | 30 | public static String getExpireDate() { 31 | LocalDateTime start = LocalDateTime.now(ZoneOffset.UTC).minusMinutes(4); 32 | LocalDateTime end = start.plusHours(1).truncatedTo(ChronoUnit.HOURS); 33 | return Duration.between(start, end).toMinutes() + " minutes"; 34 | } 35 | 36 | private static String getDateString(int i) { 37 | Calendar instance = Calendar.getInstance(TimeZone.getTimeZone("GMT")); 38 | instance.add(Calendar.MINUTE, i * -1); 39 | return new DecimalFormat("00").format(instance.get(Calendar.YEAR) - 2000) + 40 | new DecimalFormat("00").format(instance.get(Calendar.MONTH) + 1) + 41 | new DecimalFormat("00").format(instance.get(Calendar.MINUTE)) + 42 | new DecimalFormat("00").format(instance.get(Calendar.DATE)) + 43 | new DecimalFormat("00").format(instance.get(Calendar.HOUR_OF_DAY)); 44 | } 45 | 46 | private static int makeHashCode(String str) { 47 | int i = 0; 48 | for (int i2 = 0; i2 < str.length(); i2++) { 49 | i = str.charAt(i2) + (i << 5) + i; 50 | } 51 | return i < 0 ? i * -1 : i; 52 | } 53 | } 54 | --------------------------------------------------------------------------------