Help for D-Link DIR-635 under Linux (no UPNP)
Moderator Edit: The script in the Wiki did not work for this user.
-----------------------------------------------------------------
I scripted one on my own (This was quite tricky, since I had to transfer lots of java-script-functions the router uses to compute the login hash...).
What I did was, I wrote a bash-script (sorry Windows-guys, Unix-only...) to do basic connecting/ disconnecting/ reconnecting with the router.
Only problem: The login-hash.
To compute this I wrote a java-program that computes the hash from the random number the router sends and the password.
bash-script:
Java-code:
Spoiler:
Code:
// Written by Entropy
class prepare_login {
static private int[] b64_char_to_6;
static private String pwd;
prepare_login() {
}
//Build a 256 entry array that convert a base-64 character to its corresponding 6-bit number. Invalid characters will be translated to 0.
static private void build_b64_char_to_6() {
b64_char_to_6 = new int[256];
for (int i=0; i<256; ++i) b64_char_to_6[i] = 0;
for (int i=0; i<26; ++i) b64_char_to_6[i+65] = i+1;
for (int i=0; i<26; ++i) b64_char_to_6[i+97] = i+27;
for (int i=0; i<10; ++i) b64_char_to_6[i+48] = i+53;
b64_char_to_6[95] = 63;
}
static private void from_base64(String buf, int[] dst) {
byte j = 0;
for (int i = 0; i < buf.length(); i += 4) {
int cc_1 = (b64_char_to_6[(int)buf.charAt(i)] << 18);
int cc_2 = (b64_char_to_6[(int)buf.charAt(i+1)] << 12);
int cc_3 = (b64_char_to_6[(int)buf.charAt(i+2)] << 6);
int cc_4 = (b64_char_to_6[(int)buf.charAt(i+3)]);
int cc = cc_1 | cc_2 | cc_3 | cc_4;
dst[j] = (cc >> 16) & 0xff;
dst[j+1] = (cc >> 8) & 0xff;
dst[j+2] = (cc) & 0xff;
j += 3;
}
}
static private String maketwochar(String s) {
if (s.length()<2) s="0"+s;
return s;
}
static private String fillstr(String s, byte l) {
while (s.length()<l) {
s = s + (char)1;
}
return s;
}
static private String to_HexString(int[] dst) {
String s = "";
for (byte i=0; i<4; ++i) {
s = s + maketwochar(Integer.toHexString(dst[i]));
}
return s.toUpperCase();
}
// Convert a string to an array of little-endian words
static private void str2binl(String s, int[] bin) {
byte mask = (byte)((1 << 8) - 1);
for(int i=0; i<s.length()*8; i+=8) {
bin[i>>5] |= ((byte)s.charAt(i/8) & mask) << (i%32);
}
}
// Bitwise rotate a 32-bit number to the left.
static private int bit_rol(int num, int cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
// Some obscure adding algorithm the router uses
static private int safe_add(int x, int y) {
int lsw = (x & 0xFFFF) + (y & 0xFFFF);
int msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
// Begin basic md5 algorithms
static private int md5_cmn(int q, int a, int b, int x, int s, int t) {
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
static private int md5_ff(int a, int b, int c, int d, int x, int s, int t) {
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
static private int md5_gg(int a, int b, int c, int d, int x, int s, int t) {
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
static private int md5_hh(int a, int b, int c, int d, int x, int s, int t) {
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
static private int md5_ii(int a, int b, int c, int d, int x, int s, int t) {
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
// End basic md5 algorithms
// Core md5algorithm
static public void core_md5(int[] x, int len, int[] md5_arr) {
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
int a = 1732584193;
int b = -271733879;
int c = -1732584194;
int d = 271733878;
for (int i = 0; i < x.length; i+=16) {
int olda = a;
int oldb = b;
int oldc = c;
int oldd = d;
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
md5_arr[0] = a;
md5_arr[1] = b;
md5_arr[2] = c;
md5_arr[3] = d;
}
static private String binl2hex(int[] binarray) {
String hex_tab = "0123456789abcdef";
String str = "";
for (int i = 0; i < binarray.length*4; ++i) {
str = str + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8)) & 0xF);
}
return str;
}
static private String hex_md5(String s) {
int[] bin;
bin = new int[32];
int[] md5_arr;
md5_arr = new int[4];
str2binl(s, bin);
core_md5(bin, s.length()*8, md5_arr);
return binl2hex(md5_arr);
}
// Convert a hex string of 'len' bytes into a byte array of 'len2' bytes. Ignore leading and trailing whitespace. If there are any conversion errors or the string is the wrong length or the string is empty or all whitespace, return an array of all zeros.
// Since here input is guaranteed to be a pure hex string, we ignore all the case-checking the router-script does...
static private void convertHexString(String s, int len, int len2, short[] a) {
int i;
for (i=0; i < len; ++i) {
a[i] = (short)Integer.parseInt(s.substring(i*2,i*2+2),16);
}
for (; i < len2; ++i) {
a[i] = (short)0;
}
}
static private String convertToBase64(short[] arr) {
// Make array with k*4 entries
short[] a;
int templen = arr.length;
while ( (templen%3) != 0 ) {
++templen;
}
a = new short[templen];
int i;
for (i = 0; i < arr.length; ++i) {
a[i] = arr[i];
}
for (; i < templen; ++i) {
a[i] = (short)0;
}
String b64 = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
String str = "";
for (i=0; i < a.length; i += 3) {
int x = (a[i] << 16) | (a[i+1] << 8) | a[i+2];
str = str + b64.charAt((x >> 18) & 0x3f) + b64.charAt((x >> 12) & 0x3f) + b64.charAt((x >> 6) & 0x3f) + b64.charAt(x & 0x3f);
}
return str;
}
static public void main(String[] args){
String buf;
int[] dst;
String str;
String shex;
String hash;
String saltHash;
short[] bytearr;
buf = args[0];
pwd = args[1];
while ( (buf.length()%4) != 0 ) { // Make buf.length() divisible by 4
buf = buf + ".";
}
dst = new int[buf.length()];
build_b64_char_to_6();
from_base64(buf, dst);
shex = to_HexString(dst);
pwd = fillstr(pwd, (byte)16);
str = shex + pwd;
str = fillstr(str, (byte)64);
hash = hex_md5(str);
saltHash = shex+hash;
bytearr = new short[20];
convertHexString(saltHash, 20, 20, bytearr);
System.out.println(convertToBase64(bytearr));
}
}
The script awaits the first parameter to be "reconnect" (which is what you want it to do for jDownloader) and the second one to be your password. (First line in the jDownloader-option-tab for the script is "reconnect", second one your password)
Additionally, the it expects the java program to be named prepare_login.class and to be at ${HOME}/java/; the path can be changed by the parameter "-j <dir>" (one line in jDownloader-option-tab for the script is "-j", the next one the directory where you stored the class).
(To compile the java-file simply safe it as prepare_login.java and enter "java prepare_login" to your console)
I hope I am able to help all those who experienced the same annoyance with this router as I did
Feel free to use and spread these as long as you don't remove the "Written by"s
Last edited by drbits; 17.10.2010 at 09:09.
|