downloadbrowsetomkol's Bomb 2

Download bomb2_eng.zip, 14 kb (password: crackmes.de)
Browse contents of bomb2_eng.zip

Serial with tricks, not for newbies

Difficulty: 4 - Needs special knowledge
Platform: Unspecified/other
Language: Unspecified/other

Published: 22. Jul, 2002
Downloads: 1034

Rating

Waiting for at least 3 votes
(we have only 2).

Rate this crackme:

Send a message to tomkol »

View profile of tomkol »

Solutions

Solution by redoC, published 09. sep, 2014; download (61 kb), password: crackmes.de or browse.

redoC has not rated this crackme yet.

Submit your solution »

Discussion and comments

redoC
24. Aug 2010
Can anyone reverse this algo? I can provide assembler code.


void Algo()
{
#define FILE_LEN 16 // must be at least 16, change arbitrary if needed
char szSerial[17] = "################"; // 16 bytes serial, bytes values can be non-asci, any from 0-255
DWORD *dwPtr = (DWORD*)szSerial;
DWORD dwSum = 0;
DWORD dwEAX, dwEBX, dwECX, dwEDX, dwEDI;
ULONG64 uLong;

for (DWORD i=0; i<16; i++)
dwSum += szSerial[i]; // dwSum should == 0x3E4

dwEDX = *dwPtr; dwPtr++;
dwECX = *dwPtr; dwPtr++;
dwEBX = *dwPtr; dwPtr++;
dwEAX = *dwPtr;
// byte reversing
dwEDX = (dwEDX>>24) | (dwEDX<<24) | ((dwEDX & 0x00FF0000)>>8) | ((dwEDX & 0x0000FF00)<<8);
dwECX = (dwECX>>24) | (dwECX<<24) | ((dwECX & 0x00FF0000)>>8) | ((dwECX & 0x0000FF00)<<8);
dwEBX = (dwEBX>>24) | (dwEBX<<24) | ((dwEBX & 0x00FF0000)>>8) | ((dwEBX & 0x0000FF00)<<8);
dwEAX = (dwEAX>>24) | (dwEAX<<24) | ((dwEAX & 0x00FF0000)>>8) | ((dwEAX & 0x0000FF00)<<8);

dwEAX *= FILE_LEN; dwEBX *= FILE_LEN; dwECX *= FILE_LEN;

dwEBX ^= dwECX;
dwEAX ^= dwECX;
dwEAX ^= dwEBX;

dwEAX *= dwECX;

// dwEDX:dwEAX = dwEAX * dwEAX;
uLong = (ULONG64)dwEAX * (ULONG64)dwEAX;
dwEAX = uLong & 0xFFFFFFFF;
dwEDX = uLong >> 32;

dwEDI = dwEAX % dwEBX;

// dwEDX:dwEAX = dwEAX * dwEDX;
uLong = (ULONG64)dwEAX * (ULONG64)dwEDX; // here is the biggest problem
dwEAX = uLong & 0xFFFFFFFF;
dwEDX = uLong >> 32;

dwECX ^= dwEDX;
dwEAX += dwEBX;
dwEBX -= dwECX;
dwEDX ^= dwEAX;
dwECX += dwEDI;
dwEBX ^= dwEDI;
dwEAX -= dwEDI;
dwEDX ^= dwEDI;

// byte reversing
dwEAX = (dwEAX>>24) | (dwEAX<<24) | ((dwEAX & 0x00FF0000)>>8) | ((dwEAX & 0x0000FF00)<<8);
dwEBX = (dwEBX>>24) | (dwEBX<<24) | ((dwEBX & 0x00FF0000)>>8) | ((dwEBX & 0x0000FF00)<<8);
dwECX = (dwECX>>24) | (dwECX<<24) | ((dwECX & 0x00FF0000)>>8) | ((dwECX & 0x0000FF00)<<8);
dwEDX = (dwEDX>>24) | (dwEDX<<24) | ((dwEDX & 0x00FF0000)>>8) | ((dwEDX & 0x0000FF00)<<8);

dwEAX -= dwEDI;
dwEBX -= dwEDI;
dwECX -= dwEDI;
dwEDX -= dwEDI;

dwEAX ^= dwEDI;
dwEBX ^= dwEDI;
dwECX ^= dwEDI;
dwEDX ^= dwEDI;

dwEAX += dwEDI;
dwEBX += dwEDI;
dwECX += dwEDI;
dwEDX += dwEDI;

// final values:
// dwEAX == 0x7E1618D8
// dwEBX == 0x18CCE9FD
// dwECX == 0xCC533F7B
// dwEDX == 0xFCE8CE16
// dwSum == 0x3E4
}
tomkol
Author
25. Aug 2010
It's rather not reversible. Don't have src any more to check. But as far as i remember all chars in keyfile are in range that crackme uses to check pass. So you only have 24 possibilities for each of 16 bytes.
redoC
25. Aug 2010
... and according to algo first 4 bytes are ignored, still very high number of combinations.

For future reversers these chars are

~!@#$%^*()-_=+[]{},.<>/?
andrewl.us
Moderator
25. Aug 2010
no more clues, let's keep it a challenge :)
redoC
30. Apr 2011
tomkol, have this crackme solution? Algo can't be reversed and if we go through bruteforcing... we should construct all 16-character combinations of chars ~!@#$%^*()-_=+[]{},.<>/? where sum of all chars is 996.... that is about 100.000.000 combinations. That's not very high number. But we must test all 12-character permutation consisted of characters from each combination. That's the high number! I don't have supercomputer at home.
tomkol
Author
01. May 2011
Yes. Solution exists. This will be big clue "any character can occurs only once". Hope this will help you in solving this crackme.
redoC
23. Jun 2014
Yes, it's reversible. One of sequence.dat code: ?]*##<=>+-]?[+)~

But disarm check is more harder.
tomkol
Author
24. Jun 2014
Congrats on solving this part. Disarm is only bit harder and can be quickly solved by good brute-force.
redoC
27. Jun 2014
Here is second check in C. Input is 16-byte serial from 24-charset ~!@#$%^*()-_=+[]{},.<>/?
Sum of all 16 chars should be 0x400. Output checksum is also 16-byte long. Required final values are below.
This algo looks harder than previous. I can't find any place which allows reversing/optimizing (at least partially).
Can someone advice something?


// Disarm button, address: 00401101
void SequenceTest (BYTE szSerial[16])
{
DWORD *dwPtr = (DWORD*)szSerial;
DWORD dwSum = 0;
DWORD dwEAX, dwEBX, dwECX, dwEDX, dwEDI, dwESI;
ULONG64 uLong;

_00401112:
for (DWORD i=0; i<16; i++)
dwSum += szSerial[i]; // dwSum should be 0x400

dwEDX = *dwPtr++;
dwECX = *dwPtr++;
dwEBX = *dwPtr++;
dwEAX = *dwPtr;

__asm { // byte swap
mov eax, dword ptr [dwEAX]
bswap eax
mov dword ptr [dwEAX], eax
mov eax, dword ptr [dwEBX]
bswap eax
mov dword ptr [dwEBX], eax
mov eax, dword ptr [dwECX]
bswap eax
mov dword ptr [dwECX], eax
mov eax, dword ptr [dwEDX]
bswap eax
mov dword ptr [dwEDX], eax
}

_00401139:
dwEAX += dwEBX + dwECX + dwEDX;
dwEBX ^= dwEAX ^ dwECX ^ dwEDX;

dwECX -= dwEAX;
_00401149:
// dwEDX:dwEAX = dwEAX * dwECX;
uLong = (ULONG64)dwEAX * (ULONG64)dwECX; // MUL
dwEAX = uLong & 0xFFFFFFFF;
dwEDX = uLong >> 32;

dwEAX ^= dwEDX;
dwEDX += dwECX;
_00401153:
dwESI = dwEAX % dwEBX; // DIV
dwEDI = dwESI * 3;
dwEAX += dwESI;
dwEBX -= dwESI;
dwECX ^= dwEDX;
dwEDX ^= dwESI;
_00401164:
// dwEDX:dwEAX = dwEAX * dwEDX;
uLong = (ULONG64)dwEAX * (ULONG64)dwEDX; // MUL
dwEAX = uLong & 0xFFFFFFFF;
dwEDX = uLong >> 32;

dwEDX += dwEAX;
dwECX ^= dwEDI;
dwECX += dwESI;
_00401170:
//dwEDI = dwEAX % dwECX; // IDIV
__asm {
mov eax, dword ptr[dwEAX]
mov ecx, dword ptr[dwECX]
xor edx, edx
idiv ecx
mov dword ptr[dwEDI], edx
}

dwEAX ^= dwEBX;
dwECX ^= dwEDX;
dwEBX += dwEDX;
dwEAX += dwECX;
dwEDX -= dwEAX;
dwECX -= dwEBX;
_00401186:
dwESI = dwEDI * 0xC; // IMUL
dwEAX ^= dwEBX ^ dwEDX;
dwECX += dwEDX - dwEAX;
_0040119B:
dwEDI = dwEAX % dwECX; // DIV
dwEAX = dwEDI * 0x11; // IMUL
dwEBX = dwEDI * 0xA; // IMUL
dwECX = dwESI * 0x13; // IMUL

_004011AD:
// dwEDX:dwEAX = dwEAX * dwECX;
uLong = (ULONG64)dwEAX * (ULONG64)dwECX; // MUL
dwEAX = uLong & 0xFFFFFFFF;
dwEDX = uLong >> 32;

dwEDX ^= dwEBX;
dwEAX -= dwECX;

// expected final values:
// dwEAX == 0x906F7F8C
// dwEBX == 0x772127E8
// dwECX == 0xAD249F04
// dwEDX == 0x563717AA
// dwSum == 0x400
}
redoC
27. Jun 2014
...and probably "any serial character can occurs only once"
tomkol
Author
28. Jun 2014
It's very easy to optimize. Just look at the code. There is one place that can save you a lot of time for bf. And yes as far as I remember in correct code characters occurs only once.
redoC
24. Sep 2014
Half of solution posted... waited for solving second part.
redoC
17. Jul 2015
Crackme is not solved for 13 years so I request moderators to not delete this post. For future reversers:

In 16-byte sequence, chars at this indexes can be swapped without change to overal checksum: 0-8 1-9 2-10 3-11

For example this two sequences has identical checksum:
0123456789abcdef
892b456701a3cdef
...here 09af chars is used for better illustration

This can shrink bruteforce zone by factor of 16.

Now main problem is how to create effective 16-chars permutation algorithm that includes above mentioned properties. Someone has any ideas?

You may leave your comment, thoughts and discuss this crackme with other reversers here.
Acting childish will not be tolerated.
HTML and such will be left as-is, so don't try.