aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>2023-07-17 17:14:23 +0200
committerDenis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>2023-09-03 22:26:41 +0200
commit4c975c844c989384b9e979dc599d72488e9a55bc (patch)
tree7158507294ce6e95f6f5f27adf1c0f193d9a3805
parentfde17775c9ef146b23ffcf9fdfdeb9a8b7e88f31 (diff)
downloadhardware_replicant_libsamsung-ipc-4c975c844c989384b9e979dc599d72488e9a55bc.tar.gz
hardware_replicant_libsamsung-ipc-4c975c844c989384b9e979dc599d72488e9a55bc.tar.bz2
hardware_replicant_libsamsung-ipc-4c975c844c989384b9e979dc599d72488e9a55bc.zip
tools: add tool to bruteforce sim unlock codes
This was made for the Galaxy SII (GT-I9100), and while the bruteforce was verified against articles online, it doesn't work on Replicant yet, probably because there is still things missing in libsamsung-ipc to do the proper unlock. TODO: - make hashcat work on Guix: test: hashcat -I => works on Parabola where it finds opencl-icd-loader - Handle errors - Test on a real device, probably after implementing the missing support in Replicant. Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
-rw-r--r--.gitignore2
-rw-r--r--configure.ac3
-rw-r--r--scripts/PKGBUILD1
-rw-r--r--scripts/guix.scm3
-rw-r--r--scripts/manifest.scm4
-rw-r--r--tools/Makefile.am6
-rw-r--r--tools/nv_data-sim-unlock.c174
-rwxr-xr-xtools/tests/nv_data-sim-unlock.py206
8 files changed, 398 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 9bfa7dc..b72ba40 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,8 @@
/tools/tests/nv_data-imei.trs
/tools/tests/nv_data-md5.log
/tools/tests/nv_data-md5.trs
+/tools/tests/nv_data-sim-unlock.log
+/tools/tests/nv_data-sim-unlock.trs
/tools/test-suite.log
valgrind.*.log
diff --git a/configure.ac b/configure.ac
index f164c53..908e157 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,6 +54,9 @@ AC_SUBST(LIBCURL_CFLAGS)
AC_SUBST(LIBCURL_LIBS)
#------------------------------------------------------------------------------
+AC_CHECK_PROG([HASHCAT], [hashcat], [hashcat])
+
+#------------------------------------------------------------------------------
# check for debugging
AC_ARG_ENABLE(debug,
[AS_HELP_STRING([--enable-debug], [Enable debug build (default=disabled)])],
diff --git a/scripts/PKGBUILD b/scripts/PKGBUILD
index 155a765..43b2cac 100644
--- a/scripts/PKGBUILD
+++ b/scripts/PKGBUILD
@@ -16,6 +16,7 @@ makedepends=('autoconf'
'ddrescue'
'gawk'
'grep'
+ 'hashcat'
'libtool'
'pkg-config'
'python'
diff --git a/scripts/guix.scm b/scripts/guix.scm
index bc2f7c3..57a2469 100644
--- a/scripts/guix.scm
+++ b/scripts/guix.scm
@@ -170,6 +170,7 @@
automake
ddrescue
`(,(canonical-package glibc) "debug")
+ hashcat
libtool
pkg-config
python
@@ -214,6 +215,7 @@ found in many Samsung smartphones and tablets.")
automake
binutils
ddrescue
+ hashcat
libtool
pkg-config
python
@@ -289,6 +291,7 @@ found in many Samsung smartphones and tablets.")
(native-inputs (list autoconf
automake
ddrescue
+ hashcat
libtool
pkg-config
python
diff --git a/scripts/manifest.scm b/scripts/manifest.scm
index dfc82c7..51e0f61 100644
--- a/scripts/manifest.scm
+++ b/scripts/manifest.scm
@@ -29,6 +29,8 @@
(gnu packages curl)
(gnu packages disk)
(gnu packages gawk)
+ (gnu packages opencl)
+ (gnu packages password-utils)
(gnu packages pkg-config)
(gnu packages python)
(gnu packages python-xyz)
@@ -47,11 +49,13 @@
gzip
gcc-toolchain
grep
+ hashcat
lcov
libtool
gnu-make
openssl
pkg-config
+ pocl
python
python-sh
sed
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 4f86fc3..d318a7b 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -17,6 +17,7 @@ bin_PROGRAMS = \
ipc-test \
nv_data-imei \
nv_data-md5 \
+ nv_data-sim-unlock \
$(NULL)
# TODO: Find a way to make test more modular and represent each run of the
@@ -28,7 +29,8 @@ PY_LOG_COMPILER = $(PYTHON3)
TEST_EXTENSIONS = .py
TESTS = \
tests/nv_data-imei.py \
- tests/nv_data-md5.py
+ tests/nv_data-md5.py \
+ tests/nv_data-sim-unlock.py
EXTRA_DIST += $(TESTS)
https_send_sms_SOURCES = https-send-sms.c
@@ -42,3 +44,5 @@ nv_data_imei_LDADD = $(top_builddir)/samsung-ipc/libsamsung-ipc.la
nv_data_md5_SOURCES = nv_data-md5.c
nv_data_md5_LDADD = $(top_builddir)/samsung-ipc/libsamsung-ipc.la
+
+nv_data_sim_unlock_SOURCES = nv_data-sim-unlock.c
diff --git a/tools/nv_data-sim-unlock.c b/tools/nv_data-sim-unlock.c
new file mode 100644
index 0000000..360789d
--- /dev/null
+++ b/tools/nv_data-sim-unlock.c
@@ -0,0 +1,174 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2023 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+void usage(char *progname)
+{
+ printf("Usage:\n");
+ printf("\t%s FILE command <index> # %s\n",
+ basename(progname),
+ "Get bruteforce command.");
+ printf("\t%s list-supported # %s\n",
+ basename(progname),
+ "List supported devices/EFS.");
+ printf("\t%s --help # %s\n",
+ basename(progname),
+ "Print this help.");
+}
+
+int print_byte(int fd, off_t base, uint8_t offset)
+{
+ off_t file_offset;
+ ssize_t rd;
+ char buf[1];
+ int rc;
+
+ bzero(&buf, sizeof(buf));
+
+ file_offset = lseek(fd, base + offset, SEEK_SET);
+ if (file_offset == -1) {
+ int err = errno;
+ printf("%s: lseek: %s\n", __func__, strerror(err));
+ return EX_OSERR;
+ }
+
+ do {
+ rd = read(fd, &buf, 1);
+ if (rd == -1) {
+ int err = errno;
+ printf("%s: read: %s\n", __func__, strerror(err));
+ return EX_OSERR;
+ }
+ } while (rd != 1);
+
+ rc = printf("%02x", buf[0] & 0xff);
+ if (rc < 0) {
+ int err = errno;
+ printf("%s: printf: %s\n", __func__, strerror(err));
+ return EX_OSERR;
+ }
+
+ return 0;
+}
+
+off_t field_offset(unsigned field_nr)
+{
+ if (field_nr == 0)
+ return 0x18146e;
+ else if (field_nr == 1)
+ return 0x18148e;
+ else if (field_nr == 2)
+ return 0x1814ce;
+ else if (field_nr == 3)
+ return 0x1814fe;
+ else
+ return 0;
+}
+
+int cmd_list_supported(void)
+{
+
+ printf("Supported devices:\n\t%s\n",
+ "Galaxy S II (GT-I9100)");
+
+ return 0;
+}
+
+
+int cmd_command(char* nv_data_path, int field_nr)
+{
+ int fd;
+ int rc;
+ int i;
+ off_t base;
+
+ base = field_offset(field_nr);
+ if (base == 0) {
+ printf("%s: invalid field_offset: 0\n", __func__);
+ return EX_SOFTWARE;
+ }
+
+ fd = open(nv_data_path, O_RDONLY);
+ if (fd == -1) {
+ printf("%s: open: %s\n", __func__, strerror(errno));
+ return EX_NOINPUT;
+ }
+
+ printf("hashcat -m 110 --hex-salt -a 3 ");
+ for (i=0; i<20 ; i++) {
+ rc = print_byte(fd, base, i);
+ if (rc)
+ return rc;
+ }
+
+ rc = printf(":0000000000000000 ?d?d?d?d?d?d?d?d --show"
+ " | "
+ "cut -d : -f 3\n");
+ if (rc == -1) {
+ printf("%s: printf: %s\n", __func__, strerror(errno));
+ return EX_OSERR;
+ }
+
+ rc = close (fd);
+ if (fd == -1) {
+ printf("%s: close: %s\n", __func__, strerror(errno));
+ return EX_OSERR;
+ }
+
+ return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+ if (argc == 4 && !strcmp(argv[2], "command")) {
+ char *endptr;
+ int field_nr = 0;
+
+ field_nr = strtol(argv[3], &endptr, 10);
+ if (errno != 0) {
+ usage(argv[0]);
+ return EX_USAGE;
+ }
+
+ if (!(argv[3][0] != '\0' && *endptr == '\0')) {
+ usage(argv[0]);
+ return EX_USAGE;
+ }
+
+ return cmd_command(argv[1], field_nr);
+ } else if (argc == 2 && !strcmp(argv[1], "list-supported")) {
+ return cmd_list_supported();
+ } else if (argc == 2 && !strcmp(argv[1], "--help")) {
+ usage(argv[0]);
+ return 0;
+ } else {
+ usage(argv[0]);
+ return EX_USAGE;
+ }
+
+}
diff --git a/tools/tests/nv_data-sim-unlock.py b/tools/tests/nv_data-sim-unlock.py
new file mode 100755
index 0000000..6c83677
--- /dev/null
+++ b/tools/tests/nv_data-sim-unlock.py
@@ -0,0 +1,206 @@
+#!/usr/bin/env python3
+#
+# This file is part of libsamsung-ipc.
+#
+# Copyright (C) 2020 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
+#
+# libsamsung-ipc is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# libsamsung-ipc is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import re
+import sys
+import sh
+import traceback
+
+def usage(progname):
+ print('{} [test]'.format(progname))
+ sys.exit(1)
+
+def get_output(data):
+ return str(data).replace(os.linesep, '')
+
+class NvDataSimUnlock(object):
+ def __init__(self):
+ srcdir = os.environ.get('srcdir', None)
+
+ command_path = ''
+ if srcdir:
+ command_path = '.' + os.sep + 'nv_data-sim-unlock'
+ # Enable to run tests without automake
+ else:
+ command_path = os.path.dirname(sys.argv[0]) \
+ + os.sep \
+ + '..' \
+ + os.sep \
+ + 'nv_data-sim-unlock'
+
+ if 'VALGRIND' in os.environ:
+ self.nv_data_sim_unlock = sh.Command(os.environ['VALGRIND'])
+ self.nv_data_sim_unlock = self.nv_data_sim_unlock.bake(
+ '-v',
+ '--log-file=valgrind.%p.log',
+ '--leak-check=full',
+ command_path)
+ else:
+ self.nv_data_sim_unlock = sh.Command(command_path)
+ def test_help(self):
+ try:
+ self.nv_data_sim_unlock()
+ except sh.ErrorReturnCode_64:
+ pass
+ else:
+ raise Exception()
+
+ def field_offset(self, field_nr):
+ if field_nr == 0:
+ return 0x18146e;
+ elif field_nr == 1:
+ return 0x18148e;
+ elif field_nr == 2:
+ return 0x1814ce;
+ elif field_nr == 3:
+ return 0x1814fe;
+ else:
+ raise Exception()
+
+ # nv_data_bin is the path of the file.
+ # config is an array of size 4 with either None or the data to
+ # write at each offset. Offset 0 => data written at 0x18146e,
+ # offset 1 => data written at 0x18148e, etc. The data is expected
+ # to be in bytes.
+ # example: [bytes([0xef, 0x63, 0xbF, 0x26, 0xe2, 0x38, 0x29, 0x17,
+ # 0xd9, 0x68, 0x50, 0xCC, 0xf9, 0x63, 0x24, 0x58,
+ # 0xee, 0x6e, 0x6c, 0x77]),
+ # None,
+ # None,
+ # None]
+ def create_file(self, nv_data_bin, config):
+ if len(config) != 4:
+ raise Exception()
+
+ # Create nv_data.bin
+ NV_DATA_SIZE = 0x200000
+ sh.ddrescue('/dev/zero', nv_data_bin, '-s', str(NV_DATA_SIZE))
+
+ # Add hash inside if requested
+ index = 0
+ for offset_config in config:
+ if offset_config == None:
+ pass
+ else:
+ assert (len(offset_config) == 20)
+ f = open(nv_data_bin, 'rb+')
+ assert (f.seekable)
+ f.seek(self.field_offset(index), 0)
+ f.write(offset_config);
+ f.close()
+
+ index += 1
+
+ def test_commands_with_empty_file(self):
+ expected_output = " ".join([
+ "hashcat",
+ "-m", "110", "--hex-salt",
+ "-a", "3",
+ "0000000000000000000000000000000000000000:0000000000000000",
+ "?d?d?d?d?d?d?d?d",
+ "--show",
+ "|", "cut", "-d", ":", "-f", "3"])
+
+ nv_data_bin = get_output(sh.mktemp())
+ self.create_file(nv_data_bin, [None, None, None, None])
+
+ for index in range(0,4):
+ output = get_output(self.nv_data_sim_unlock(nv_data_bin,
+ "command", str(index)))
+ if output != expected_output:
+ raise Exception()
+
+ # Try invalid offset
+ try:
+ self.nv_data_sim_unlock(nv_data_bin, "command", "4")
+ except sh.ErrorReturnCode_70:
+ pass
+ else:
+ raise Exception()
+
+ os.unlink(nv_data_bin)
+
+ def test_commands_with_example_file(self):
+ expected_output = " ".join([
+ "hashcat",
+ "-m", "110", "--hex-salt",
+ "-a", "3",
+ "ef63bf26e2382917d96850ccf9632458ee6e6c77:0000000000000000",
+ "?d?d?d?d?d?d?d?d",
+ "--show",
+ "|", "cut", "-d", ":", "-f", "3"])
+
+ nv_data_bin = get_output(sh.mktemp())
+ # 7D 3E 17 CF CD 81 6C AC D4 E0 25 FA A6 50 04 FD D1 7D 51 F8 # skip
+ # EF 63 BF 26 E2 38 29 17 D9 68 50 CC F9 63 24 58 EE 6E 6C 77 # example
+ # `+-> 50681318
+ self.create_file(nv_data_bin,
+ [bytes([0xef, 0x63, 0xbF, 0x26,
+ 0xe2, 0x38, 0x29, 0x17,
+ 0xd9, 0x68, 0x50, 0xCC,
+ 0xf9, 0x63, 0x24, 0x58,
+ 0xee, 0x6e, 0x6c, 0x77]),
+ None,
+ None,
+ None])
+
+ output = get_output(self.nv_data_sim_unlock(nv_data_bin,
+ "command", "0"))
+ assert(output == expected_output)
+
+ os.unlink(nv_data_bin)
+
+ def test_hashcat(self):
+ command = sh.hashcat(
+ ["-m", "110",
+ "--hex-salt",
+ "-a", "3",
+ "ef63bf26e2382917d96850ccf9632458ee6e6c77:0000000000000000",
+ "?d?d?d?d?d?d?d?d",
+ "--show"])
+ print ("hashcat " + " ".join(["-m", "110",
+ "--hex-salt",
+ "-a", "3",
+ "ef63bf26e2382917d96850ccf9632458ee6e6c77:0000000000000000",
+ "?d?d?d?d?d?d?d?d",
+ "--show"]))
+ code = get_output(command).split(":")[2]
+ assert(code == "50681318")
+
+def run_test(test):
+ try:
+ test()
+ except Exception as e:
+ print("[ !! ] nv_data_sim_unlock.py: {} failed:".format(test.__name__))
+ traceback.print_exc()
+ else:
+ print("[ OK ] nv_data_sim_unlock.py: {}".format(test.__name__))
+
+def main():
+ nv_data_sim_unlock = NvDataSimUnlock()
+
+ run_test(nv_data_sim_unlock.test_help)
+ run_test(nv_data_sim_unlock.test_commands_with_empty_file)
+ run_test(nv_data_sim_unlock.test_commands_with_example_file)
+ run_test(nv_data_sim_unlock.test_hashcat)
+
+if __name__ == '__main__':
+ rc = main()
+ sys.exit(rc)