
tomkol'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 | RatingWaiting for at least 3 votes 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.
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.