Valhalla Legends Forums Archive | C/C++ Programming | [C++] Gigantic Loops

AuthorMessageTime
JoeTheOdd
Basically, I'm trying to loop from 0 to 9999999999999. This is too long for a long, and clearly for an int. I fixed the problem, but its a really, really discusting way. I can't think of a better way to do it though. Anyone know how to make this code a bit better?

[code]void genKeys() {
  int a, b, c, d, e, f, g, h, i, j, k, l, m;
  string key = "0000000000000";
  a = 0; b = 0; c = 0; e = 0; f = 0; g = 0; h = 0; i = 0; j = 0; k = 0; l = 0; m = 0;
  for(a = 0; a < 10; a++) {
    for(b = 0; b < 10; b++) {
      for(c = 0; c < 10; c++) {
        for(d = 0; e < 10; f++) {
          for(e = 0; e < 10; e++) {
            for(f = 0; f < 10; f++) {
              for(g = 0; g < 10; g++) {
                for(h = 0; h < 10; h++) {
                  for(i = 0; i < 10; i++) {
                    for(j = 0; j < 10; j++) {
                      for(k = 0; k < 10; k++) {
                        for(l = 0; l < 10; l++) {
                          for(m = 0; m < 10; m++) {
                            //cout << a << b << c << d << e << f << g << h << i << j << k << l << m << endl;
                            key[0]  = a + 0x30;
                            key[1]  = b + 0x30;
                            key[2]  = c + 0x30;
                            key[3]  = d + 0x30;
                            key[4]  = e + 0x30;
                            key[5]  = f + 0x30;
                            key[6]  = g + 0x30;
                            key[7]  = h + 0x30;
                            key[8]  = i + 0x30;
                            key[9]  = j + 0x30;
                            key[10] = k + 0x30;
                            key[11] = l + 0x30;
                            key[12] = m + 0x30;
                            if(verifyKey(key) == true) {
                              cout << "Valid key: " << key << endl;
                            //} else {
                            //  cout << "Invalid key: " << key << endl;
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}[/code]
October 16, 2005, 6:11 AM
Myndfyr
OK so you're running a loop with 10 trillion iterations.  Increment/comparison is 2 instructions per iteration.

You have 13 addition operations there.

You also have 13 assignment operations there.

Since you're using an array you'll have to go to memory; you can't use registers to store what's being assigned.  There are also too many variables to use registers to do the temporary additions.

That's 28 operations per iteration, or 280 trillion operations.

If you manage to run this at one clock cycle per instruction without any other preemption or task switching, you'll be running it for ~116666.67 seconds, roughly 1945 minutes, or 32 hours.

There has GOT to be a better way to come up with a CD key.

I'm curious: are you trying to bruteforce all of Starcraft's possible CD keys?
October 16, 2005, 9:24 AM
rabbit
[code]while(true)
{
unsigned long long key = 0;
if(functionToCheckValidity(key) == true)
printf("%013d\n", key);

key++;

if(key == 9999999999999)
break;
}[/code]
-.-
Note that it's untested...and I don't really care either way, so what may come of this, I don't know.
October 16, 2005, 3:20 PM
Kp
You realize that's a rather silly way of approaching this, right? :)  First, you'll only identify keys which can be used to install Starcraft - most of the keys you identify won't work on battle.net, never have, and probably never will.  Second, since the last character is just a verifier, you could shave off the innermost loop by computing the verifier for each possible 12-digit sequence, then outputting the 12-digit sequence + verifier.  Finally, your d loop is wrong.
October 16, 2005, 3:26 PM
JoeTheOdd
[quote]I'm curious: are you trying to bruteforce all of Starcraft's possible CD keys?[/quote]
Exactly.

Thanks Rabbit, forgot all about the long long.
EDIT -
999,999,999,999 is too big for a long long.

[quote author=Kp link=topic=13042.msg131178#msg131178 date=1129476387]
You realize that's a rather silly way of approaching this, right? :) First, you'll only identify keys which can be used to install Starcraft - most of the keys you identify won't work on battle.net, never have, and probably never will. Second, since the last character is just a verifier, you could shave off the innermost loop by computing the verifier for each possible 12-digit sequence, then outputting the 12-digit sequence + verifier. Finally, your d loop is wrong.
[/quote]
*cough* DUHHH. I can't believe I forgot about that. I did it that way when I wrote this in VB, but of course, that took even longer. Also, I can't believe I screwed my d loop up so much. =p

EDIT -
Kp, if I weren't reasonably sure you're a male, I'd say I love you. It now generates arround 10,000 keys per second.

Time to work on decoding the CD-Key to see if its productID is correct!
October 16, 2005, 9:25 PM
Kp
If you're interested in coming up with keys for use on battle.net, there's a faster way.  Skip this generation/decode phase and go straight to generating keys in pre-decomposed form.  You know the productID which Starcraft must have, you know (or should know!) the range of values which are appropriate for the "secret" value, and you don't care about the value for the "magic" part.  So: try keys for productID = Starcraft, magic = counter++, secret in [secret_low, secret_high].  One in every secret_high-secret_low keys generated this way has the potential to be valid on battle.net.  Of course, not all "magic" values are legal (some were never sold, so they're prohibited on the server), and some will have been rendered useless by other people (jailed, banned, muted, etc.).
October 16, 2005, 10:07 PM
JoeTheOdd
Excuse my idioticy, but huh?
October 16, 2005, 10:10 PM
laurion
Kp, I didn't understand what you said either time.


Joe: can you send me the file when you are done, whatever you have generated? I will host it if you'd like
October 16, 2005, 10:29 PM
Mangix
@Tazo: here's Joe's code

http://www.javaop.com/uploads/guest/sckmg.tar.gz
October 16, 2005, 10:33 PM
Arta
What Kp wrote is not indecipherable. Give it some time and thought. Understanding how keys work will make it easier for you to generate them!
October 16, 2005, 10:37 PM
laurion
ty Mangix, do I need to fix the d error?
October 16, 2005, 10:40 PM
Yoni
[quote author=Kp link=topic=13042.msg131178#msg131178 date=1129476387]
Finally, your d loop is wrong.
[/quote]
:-*
October 16, 2005, 10:41 PM
rabbit
[quote author=Arta[vL] link=topic=13042.msg131240#msg131240 date=1129502255]
What Kp wrote is not indecipherable. Give it some time and thought. Understanding how keys work will make it easier for you to generate them!
[/quote]I understood it, I just don't know how to do it.

@Joe: Hence "unsigned".  I'm not exactly sure of the size, but that will increase the bound anyway.
October 17, 2005, 1:36 AM
laurion
I don't even understand how keys work, so its hard to understand what Kp is saying.. Point out the magic, secret, and low_high things for me in this?
[code]
verifyKey(string key) {
  int v, c, n, n2, i;
  v = 3;
  for (i = 0; i < 12; i++) {
    c = key[i];
    n = c - 0x30;
    n2 = v * 2;
    n ^= n2;
    v += n;
  }
  if (v % 10 == (key[12] - 0x30)) {
    return true;
  } else {
    return false;
  }
}
[/code]
October 17, 2005, 1:43 AM
Kp
[quote author=Tazo link=topic=13042.msg131259#msg131259 date=1129513386]Point out the magic, secret, and low_high things for me in this?[/quote]

No.
October 17, 2005, 1:47 AM
Arta
If you have some code for decoding cd keys, then you can figure it out. The constituent parts of the keys are what gets sent to Battle.net (in one form or another).
October 17, 2005, 9:18 AM
JoeTheOdd
Something I was trying to do was decode the CD Key and extract the productID and compare it to StarCraft's ID.

According to a post I saw, this is 0x01, and according to tmp's slackchat source code, this is 0x53544152. I guess I'll use tmp's, because I found it in a working bot.

A problem though, sckmg is in C++ which I'm still very inexperienced in, and slackchat is in C. As much as I hate leeching, can anyone point me to some code to extract the key's productID?

EDIT -
Almost forgot. I'm now using finishKey() on every ten keys, instead of verifyKey() on every one. Poke

EDIT -
I read Kp's post again. I guess by magic he means public value, and secret is private value, right? Basically what I was going to do was loop through the 999,999,999,999 keys (each one valid by installer), and check if its productID is correct. Is there any relationship between the magic and secret?
October 17, 2005, 11:50 PM
Myndfyr
Why don't you use BNCSUtil?  It's open-source, and you can do CD key verification via C functions as well as a C++ class (IIRC).  Just import the appropriate headers and link to the BNCSUtil library.
October 18, 2005, 12:27 AM
Kp
[quote author=Joe link=topic=13042.msg131384#msg131384 date=1129593022]I read Kp's post again. I guess by magic he means public value, and secret is private value, right? Basically what I was going to do was loop through the 999,999,999,999 keys (each one valid by installer), and check if its productID is correct. Is there any relationship between the magic and secret?[/quote]

It is widely believed that there is, but if anybody outside Blizzard knows how to compute secret from magic, they're not talking.  It stands to reason that there must be though, since otherwise the server would need to have a lookup table to map every issued magic to a secret.  Of course, the conversion function is probably some really nasty hash function with a nonlinear correlation of input to output.  Otherwise anybody with enough keys could figure it out just by looking for patterns.
October 18, 2005, 12:52 AM
Arta
Tip: CD key product codes are not the same as product IDs.
October 18, 2005, 8:58 AM
JoeTheOdd
@Arta, whats the CDKey product code for StarCraft? 0x01?

@MyndFyre, I looked at BNCSUtil for something (cant remember what), and the entire thing was over my head. I might look into it again, but the very idea of using it gives me a headache. I know next to no C++. I'm pretty amazed I've gotten this far.
October 23, 2005, 6:15 AM
Arta
I can't remember - decode an SC key and have a look! :)
October 24, 2005, 8:30 AM
mynameistmp
Joe, when I was writing slackchat I used the linux bash shell to help me out with sorting through some of bncsutil's source code. I made a script like so:

[code]
#!/bin/sh

for file in *
do
        grep -Hn $1 $file
done
exit 0
[/code]

Stick that in the source directory, throw the string you're looking for as an arg, and it'll tell you which file/line:

[quote]
sh-3.00$ ./locate calcHash
bsha1.cpp:52:MEXP(void) calcHashBuf(const char* input, unsigned int length, char* result) {
bsha1.h:34: * calcHashBuf
bsha1.h:43:MEXP(void) calcHashBuf(const char* data, unsigned int length, char* hash);
[/quote]

I know it's a little bit off topic but it may help you in searching for what you're looking for ;P
October 25, 2005, 7:18 AM
kamakazie
[quote author=mynameistmp link=topic=13042.msg131903#msg131903 date=1130224720]
Joe, when I was writing slackchat I used the linux bash shell to help me out with sorting through some of bncsutil's source code. I made a script like so:

[code]
#!/bin/sh

for file in *
do
        grep -Hn $1 $file
done
exit 0
[/code]

Stick that in the source directory, throw the string you're looking for as an arg, and it'll tell you which file/line:

[quote]
sh-3.00$ ./locate calcHash
bsha1.cpp:52:MEXP(void) calcHashBuf(const char* input, unsigned int length, char* result) {
bsha1.h:34: * calcHashBuf
bsha1.h:43:MEXP(void) calcHashBuf(const char* data, unsigned int length, char* hash);
[/quote]

I know it's a little bit off topic but it may help you in searching for what you're looking for ;P
[/quote]

why not just [tt]grep -Hn calcHash *[/tt]?

[pre]
[dxoigmn@tahoe:bncsutil]# grep -Hn calcHash *
bsha1.cpp:73:MEXP(void) calcHashBuf(const char* input, unsigned int length, char* result) {
bsha1.cpp:142:MEXP(void) calcHashBuf(const char* input, unsigned int length, char* result) {
bsha1.h:34: * calcHashBuf
bsha1.h:43:MEXP(void) calcHashBuf(const char* data, unsigned int length, char* hash);
cdkeydecoder.cpp:220:            calcHashBuf((char*) &kh, 24, keyHash);
oldauth.cpp:41:    calcHashBuf(password, std::strlen(password), intermediate + 8);
oldauth.cpp:45:    calcHashBuf(intermediate, 28, outBuffer);
oldauth.cpp:54:    calcHashBuf(password, std::strlen(password), outBuffer);
[/pre]
October 25, 2005, 7:43 AM
mynameistmp
It's just an example for him. That method is great for this particular example but it loses functionality as his requests become more complicated. I didn't particularly feel like typing grep -Hn everytime.
October 25, 2005, 8:49 AM
Kp
alias hgrep 'grep -H -n \!*'

# Bonus:
alias ehgrep 'grep -E -H -n \!*'
October 26, 2005, 1:27 AM
JoeTheOdd
Heh, Kp renamed his topic title. =).

From C++ looping to Shell Scripting 101, all in less than two full pages. =)
November 11, 2005, 6:25 AM

Search