Valhalla Legends Forums Archive | Assembly Language (any cpu) | Try Out Your Reversing Skills

AuthorMessageTime
iago
Here's a little assembly, can you get the original C or C++ code back?
Note that this is a __fastcall function with a single char* parameter passed in ecx.
BOOL __fastcall func(char *param);
It's a 13-character null-terminated String with every character in the range [0-9].
(Note: none of the registers are preserved, I just skipped over preservation)

[code]----------------------------------------
   mov eax, 3
   mov esi, ecx
   mov ebp, edx
   xor ecx, ecx
Top:
   movsx edx, byte ptr [ecx+esi]
   sub edx, 30h
   lea edi, [eax+eax]
   xor edx, edi
   add eax, edx
   inc ecx
   cmp ecx, 0Ch
   jl short Top
   xor edx, edx
   mov ecx, 0Ah
   div ecx
   
   movsx eax, byte ptr [esi+0Ch]
   movsx edx, dl
   add edx, 30h
   cmp eax, edx
   jnz bottom
   mov eax, 1
   retn 8
bottom:
   xor eax, eax
   retn 8
----------------------------------------[/code]

Solution (in C++):
[quote][color=black]bool verifyStarcraftCDKey(char *cdkey)
{
   int accum = 3;
   for(int i = 0; i < 13; i++)
      accum += ((cdkey[i] - '0') ^ (accum * 2));

   return ((accum % 10) == (cdkey[13] - '0'));
}[/color][/quote]
March 15, 2004, 12:23 AM
Maddox
Exact C code? Or just the same functionality?

Anyways, I suggest not posting the answer in this thread. Maybe people should PM you the answer.

Edit: Ok, done reversing. :) PM'd iago.
March 15, 2004, 3:39 AM
Maddox
I don't understand the point of rewriting these kind of functions in C when they will probably be slower, and especially when you can use inline assembly.

If I were really going to use this, I probably would leave it like this.
[code]
BOOL __declspec(naked) __fastcall func_asm(char *param)
{
   __asm
   {
      pushad
      mov eax, 3
      mov esi, ecx
      xor ecx, ecx
Top:
      movsx edx, byte ptr [ecx+esi]
      sub edx, 30h
      lea edi, [eax+eax]
      xor edx, edi
      add eax, edx
      inc ecx
      cmp ecx, 0Ch
      jl Top
      xor edx, edx
      mov ecx, 0Ah
      div ecx

      movsx eax, byte ptr [esi+0Ch]
      movsx edx, dl
      add edx, 30h
      cmp eax, edx
      jnz bottom
      popad
      mov eax, 1
      ret
bottom:
      popad
      xor eax, eax
      ret
   }
}
[/code]
March 15, 2004, 4:51 AM
iago
Assembly != portability. I use Linux 30% of the time. And, I'm going to convert this to Java.

Incidentally, stop spamming me with IM's. 3! :P

Anyway, I found that it's easiest to first do it like in his example, then convert them exactly to C, then to cut down the code until there's no redundant statements.
March 15, 2004, 2:23 PM
Kp
[quote author=iago link=board=7;threadid=5778;start=0#msg49492 date=1079360597]Assembly != portability. I use Linux 30% of the time. And, I'm going to convert this to Java.[/quote]

Assembly is quite portable within an ISA. :) If you're using an x86 based Linux, you can take the assembly with you very easily. For reasons of personal prejudice, I recommend against doing emulations in Java if it can be avoided. Some of the things that are needed just don't work right/well (for instance, try doing an efficient CheckRevision in Java :)).
March 15, 2004, 2:58 PM
iago
[quote author=Kp link=board=7;threadid=5778;start=0#msg49496 date=1079362736]
(for instance, try doing an efficient CheckRevision in Java :)).
[/quote]

With a little help from Skywing, I got CheckRevision to run on Starcraft in ~100ms in Java.
[code]For 100 runs:
Total time: 9682ms
Average time: 96ms
Min time: 76ms
Max time: 547ms[/code]
March 15, 2004, 3:46 PM
Kp
[quote author=iago link=board=7;threadid=5778;start=0#msg49502 date=1079365571]With a little help from Skywing, I got CheckRevision to run on Starcraft in ~100ms in Java.[/quote]

I'm honestly impressed. I expected performance much more similar to VB, which just does absolutely horribly with it iirc. How long was your code that implements it? I'd consider it a bit cheating if you got this speed just by unrolling all possible combinations of the version check. :)
March 15, 2004, 4:32 PM
iago
[quote author=Kp link=board=7;threadid=5778;start=0#msg49509 date=1079368358]
[quote author=iago link=board=7;threadid=5778;start=0#msg49502 date=1079365571]With a little help from Skywing, I got CheckRevision to run on Starcraft in ~100ms in Java.[/quote]

I'm honestly impressed. I expected performance much more similar to VB, which just does absolutely horribly with it iirc. How long was your code that implements it? I'd consider it a bit cheating if you got this speed just by unrolling all possible combinations of the version check. :)
[/quote]

Haha, me and skywing talked about that :)

The code is very similar to Yobgul's public one, except I changed the initial parsing a little. The actual running is pretty much the same as his.

When I actually get this bot working, I'll make it open source, just to prove that bots can be done in Java :)

[edit] I posted it on the Java forum.
March 15, 2004, 5:45 PM
UserLoser.
[quote author=iago link=board=7;threadid=5778;start=0#msg49502 date=1079365571]
[quote author=Kp link=board=7;threadid=5778;start=0#msg49496 date=1079362736]
(for instance, try doing an efficient CheckRevision in Java :)).
[/quote]

With a little help from Skywing, I got CheckRevision to run on Starcraft in ~100ms in Java.
[code]For 100 runs:
Total time: 9682ms
Average time: 96ms
Min time: 76ms
Max time: 547ms[/code]
[/quote]

What's the fastest way to perform CheckRevision? I'm assuming calling CheckRevision from the ver DLLs would be the fastest -- am I wrong? (If so, explain :P)
March 16, 2004, 1:10 AM
Maddox
[quote author=UserLoser. link=board=7;threadid=5778;start=0#msg49632 date=1079399446]
[quote author=iago link=board=7;threadid=5778;start=0#msg49502 date=1079365571]
[quote author=Kp link=board=7;threadid=5778;start=0#msg49496 date=1079362736]
(for instance, try doing an efficient CheckRevision in Java :)).
[/quote]

With a little help from Skywing, I got CheckRevision to run on Starcraft in ~100ms in Java.
[code]For 100 runs:
Total time: 9682ms
Average time: 96ms
Min time: 76ms
Max time: 547ms[/code]
[/quote]

What's the fastest way to perform CheckRevision? I'm assuming calling CheckRevision from the ver DLLs would be the fastest -- am I wrong? (If so, explain :P)
[/quote]

Like Kp said, "...unrolling all possible combinations of the version check."
March 16, 2004, 1:36 AM
iago
Or compiling the check revision code into assembly and running it. I believe that's the way the vercheck dlls, although I heard somewhere that those leak memory.
March 16, 2004, 1:45 AM
Kp
There are several ways to do it, each with their own bonuses and drawbacks.

1) YobGuls' code -- very portable, but not very efficient.
2) BNLS -- very portable, but you suffer network latency and require a BNLS authentication
3) Calling IX86Ver?.dll -- Win32 specific and requires either memory patching the DLL or enduring memory leaks.
4) Performing the revision using a method Skywing designed (which, with my modifications, is used in BNLS afaik)
5) Unrolling all possible combinations of the version check. This is theoretically slightly faster even than the method that we use internally, but requires a tremendous amount of space to account for all possible combinations.

In all cases, you can gain a slight performance boost (if you reconnect frequently anyway) by keeping the files memory mapped for the duration of execution, rather than loading them on-demand (and thereby incurring all mapping overhead every time).
March 16, 2004, 1:51 AM
Maddox
[quote author=Kp link=board=7;threadid=5778;start=0#msg49649 date=1079401898]
4) Performing the revision using a method Skywing designed (which, with my modifications, is used in BNLS afaik)
[/quote]

Very descriptive.
March 16, 2004, 2:01 AM
Kp
[quote author=Maddox link=board=7;threadid=5778;start=0#msg49653 date=1079402476]Very descriptive.[/quote]

His design, his call whether to explain how it works.
March 16, 2004, 2:14 AM
Arta
TestBNCS compiles the version check formula and then runs it. This is the fastest way of doing it, and is the method used by the vercheck DLLs. Mine runs in about 11-15ms, depending on the other things my machine is doing. That doesn't include the time taken to map the hash files into memory. That also doesn't include cache optimisations which I think might improve the speed by a few ms - something I've been meaning to test but never got round to.
March 16, 2004, 2:21 AM
Maddox
(on topic)
The solution for this is

[code]
BOOL __fastcall funcc(char *param)
{
int i = 0, eax = 3, edx;

while(i < 0x0c)
eax += (param[i++] - 0x30) ^ (eax + eax);

edx = (eax % 0x0a) + 0x30;

if(edx == param[0x0c])
return 1;

return 0;
}
[/code]
March 16, 2004, 4:13 AM
iago
[quote author=Maddox link=board=7;threadid=5778;start=15#msg49678 date=1079410425]
(on topic)
The solution for this is

[code]
BOOL __fastcall funcc(char *param)
{
int i = 0, eax = 3, edx;

while(i < 0x0c)
eax += (param[i++] - 0x30) ^ (eax + eax);

edx = (eax % 0x0a) + 0x30;

if(edx == param[0x0c])
return 1;

return 0;
}
[/code]
[/quote]

You do realize that I posted the solution in my initial post in a black quote box? :P

<edit> and, I like my solution better. for > while :P
March 16, 2004, 2:34 PM
Maddox
Hah, I never noticed that. :o
March 17, 2004, 2:18 AM
Mephisto
[quote]
The code is very similar to Yobgul's public one, except I changed the initial parsing a little. The actual running is pretty much the same as his.
[/quote]

Who is YobGuls? I've never heard of him before until I started coding for Battle.net which has no only been two weeks when I tested out his hashing algorithm and check revision.
March 17, 2004, 2:57 AM
iago
[quote author=Mephisto link=board=7;threadid=5778;start=15#msg49973 date=1079492245]
[quote]
The code is very similar to Yobgul's public one, except I changed the initial parsing a little. The actual running is pretty much the same as his.
[/quote]

Who is YobGuls? I've never heard of him before until I started coding for Battle.net which has no only been two weeks when I tested out his hashing algorithm and check revision.
[/quote]

He's some ancient and powerful person in battle.net's history.
March 17, 2004, 3:17 AM
Maddox
The only program I ever saw from YobGuls was a stand-alone d2 gamebot that didn't get very far.
March 17, 2004, 3:22 AM
Mephisto
Is he still around?
March 17, 2004, 4:26 AM
iago
Probably. I wouldn't be surprised if he's a member of vL under a different name. *looks around suspiciously*
March 17, 2004, 2:07 PM
Mephisto
^^
March 17, 2004, 8:15 PM
Adron
[quote author=iago link=board=7;threadid=5778;start=15#msg50027 date=1079532469]
Probably. I wouldn't be surprised if he's a member of vL under a different name. *looks around suspiciously*
[/quote]

I don't know, but I don't think so. He was clever and good at reversing, but he wrote simple code. He didn't refine it as much as we did. He renewed bot making by being the first person to widely publicly post the results of his reversing. As far as I know, he dove into it for a limited time and then got bored. I think he was more skilled as a hacker/reverser than as a programmer.
March 17, 2004, 9:12 PM
Death_Ryder
By the way, I noticed a little problem with your original asm code:

[quote author=iago link=board=7;threadid=5778;start=0#msg49414 date=1079310187]
[code]
--snip--
   mov eax, 1
   retn 8
bottom:
   xor eax, eax
   retn 8
[/code]
[/quote]

Isn't it a tad unusual for a __fastcall function with only 1 param to be returning 8 bytes to the stack?

~Death_Ryder
March 27, 2004, 12:41 AM
iago
I think there was a second parameter, but it was irrelevant for that.
March 27, 2004, 3:02 AM
TheMinistered
I thought fastcall didn't even use the stack. I thought it used registers for passing arguements to functions. I could be wrong and correct me if I am.
March 27, 2004, 4:52 PM
iago
The first 2 parameters are ecx/edx, after that they are done like stdcall.
March 27, 2004, 5:00 PM
Maddox
[quote author=iago link=board=7;threadid=5778;start=15#msg52062 date=1080406855]
The first 2 parameters are ecx/edx, after that they are done like stdcall.
[/quote]

In your previous post you meant to say "third."
March 27, 2004, 8:21 PM
iago
Fine!! "I think there was a second stack parameter" is what I meant.

Go away :P
March 27, 2004, 8:25 PM
Maddox
What was the first stack parameter then? :P
March 27, 2004, 10:30 PM
iago
Irrelevant!

int __fastcall DecodeStarcraftKey(char *CDKeyCopy,int *product,int *CDKeyVal2,int *CDKeyVal1)
March 27, 2004, 11:45 PM

Search