
tomkol's BiT WalkeR ChAlLeNgE
Download bit_walker.zip, 49 kb (password: crackmes.de) Browse contents of bit_walker.zip Welcome to this small keygenme. Your task is to made my keygenme say it's registered by you. You can do whatever you want while reversing. Your final solution can't patch or bruteforce my code. Everything is fully reverseable. Should be interesting and unusual.
Difficulty: 3 - Getting harder | Send a message to tomkol » View profile of tomkol » |
Solutions
Solution by tamaroth, published 03. sep, 2013; download (199 kb), password: crackmes.de or browse.
tamaroth has rated this crackme as awesome.
Discussion and comments
tamaroth Moderator 16. Aug 2013 | Hey, I think I have found out why your keygenme is not working under windows 7. It's all in your parsing of EAT of certain system API's. For instance: API you want -> API you get CloseHandle -> CloseHandle CreateMutexA -> CreateMutexExA CreateThread -> CreateThreadpoolCleanupGroup FreeLibrary -> FreeResource GetProcessHeap -> GetProcessIoCounters As a result nothing's working and your code just crashes (thank you for SEH, at least no shitty windows). Now, the reason for this is in ordinals. Again, an example (same order as functions above): 0054 -> 0054 009E -> 009D 00B9 -> 00B7 0167 -> 0164 024E -> 024A It's because of this instruction, I believe: 004012CF . 43 INC EBX Notice how the difference between your ordinal and the correct one increases by one with every API. Below you will find the code that works both in w7 and xp (haven't tested with vista/8 but I reckon it should fare just fine). typedef HANDLE (WINAPI *CrThread)(LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD); CrThread findCreateThread() { LPVOID lpFile = (LPVOID)GetModuleHandle("kernel32.dll"); IMAGE_DOS_HEADER *dosh = (IMAGE_DOS_HEADER *)lpFile; IMAGE_NT_HEADERS *nth = (IMAGE_NT_HEADERS *)((PBYTE)lpFile + dosh->e_lfanew); IMAGE_EXPORT_DIRECTORY *exp = (IMAGE_EXPORT_DIRECTORY *)((PBYTE)lpFile + nth->OptionalHeader.DataDirectory->VirtualAddress); DWORD *pNames = (DWORD *)((PBYTE)lpFile + exp->AddressOfNames); WORD *pOrds = (WORD *)((PBYTE)lpFile + exp->AddressOfNameOrdinals); DWORD *pEAT = (DWORD *)((PBYTE)lpFile + exp->AddressOfFunctions); BYTE *name; WORD ordinal; CrThread cr; for (DWORD i = 0; i < exp->NumberOfNames; i++) { name = (PBYTE)lpFile + pNames[i]; if (strcmp((const char *)name, "GetProcessHeap") == 0) { ordinal = pOrds[i]; cr = (CrThread)((PBYTE)lpFile + pEAT[ordinal]); break; } } return cr; } Best regards, tamaroth |
---|---|
tomkol Author 17. Aug 2013 | From my tests i've found out that win7 simply ignores entry point from PE header and starts in middle of the code. But theres always a VM. Maybe next time when i'll switch to win7 as main system. |
tamaroth Moderator 18. Aug 2013 | When I tested on Win7 x64 it worked good until the import part. Maybe you had some old version of windows? Anyhow, there's absolutely no reason why one would stick to xp still. It's ancient now. Follow new technologies and opportunities ;-) |
tomkol Author 19. Aug 2013 | You're right. It was problem with my VM. Give me a day and i'll fix it. On older copy it starts but crashes. I'm working on making it run on win7. |
andrewl.us Moderator 19. Aug 2013 | thanks tomkol and tamaroth for the win7 effort! |
redoC 19. Aug 2013 | timer always creates 5 new tooltip windows |
tomkol Author 20. Aug 2013 | @tamaroth i hope it now works correctly for you @andrewl.us thanks @redoc tooltips got sometimes lost, don't know why. thats why they recreated with timer. this shouldn't be a problem while reversing algo |
tamaroth Moderator 20. Aug 2013 | Yep, it's working great now! Time for some reversing ;-) |
tomkol Author 20. Aug 2013 | Shouldn't be hard. It's only coded in different way. Good luck and I'm waiting for solution now. |
redoC 20. Aug 2013 | Checking code is somewhere in animation procedure? |
redoC 20. Aug 2013 | ehm ... WM_USER+1 |
tomkol Author 21. Aug 2013 | Your close redoC. It's a bit different than what you used to. And you can treat animation as a messagebox. It simply displays text and looks better than messagebox. |
tamaroth Moderator 21. Aug 2013 | redoC - don't want to spoil everything (well ATM I'm working on the functions in the array) but you might want to check how to send a custom message to an application and try to figure out how to post name and serial there. |
redoC 21. Aug 2013 | WM_USER + wParam + lParam + Atom ....but that maze what follows ... i look at it sometime later. |
tamaroth Moderator 21. Aug 2013 | It's really not that complicated once you figure out how the VM works, I'm still following what happens after the VM and should have the keygen by the end of the week, hopefully. |
tomkol Author 22. Aug 2013 | VM is nothing complicated. It's really very simple. And what follows is also quite easy once you figure out what is going on. |
tamaroth Moderator 27. Aug 2013 | One question: after all successful checks my name and serial shows up in a keygenme for a bit and then it's erased and 'Good Boy' message is nowhere to be seen. Is that on purpose or maybe I've missed something? Anyhow, keygen is almost ready (just need to write some xgcd for unsigned int and it all be well) |
tamaroth Moderator 27. Aug 2013 | It's hard to post correct values for you to check, as there's no easy way to input them as well as magic value changing now and then, however, here are some examples: name: tomkol magic: B910AB51-15171F0C-A8E1C64E serial: 8F0627E8#EFA61684#93083B90 name: tamaroth magic: 351FAA8D-D8E2C098-2FB4DF30 serial: 34C114D3#042E892F#03EEA86E name: crackmes.de magic: 737298DE-B5BF3C14-31B71E91 serial: F81E2B4F#FC1DCF71#14DEDF5C |
tomkol Author 28. Aug 2013 | Thats the purpose. I hope you found a place where good boy message is shown. If not you missed something at the end of check procedure. Waiting for your solution. |
tamaroth Moderator 28. Aug 2013 | Yeah, found it ... Silly me ;-) Writing a tut and finishing a kg (you know, non constant name, some sanity checks etc) as I write this. |
tomkol Author 28. Aug 2013 | Can't wait to read it. And yes the serials you provided are correct. It's easy to test if you have source and can compile some test version that simply checks static data. |
tamaroth Moderator 30. Aug 2013 | Solution submitted, hopefully it'll be accepted soon! |
andrewl.us Moderator 03. Sep 2013 | despite finding that this "bosom of code" is cold and hard and uninviting, he bravely enters and exposes the bosom for all to see ... good job! |
tomkol Author 04. Sep 2013 | Good work tamaroth. I see you love to complicate your life. Read pm from me and check what you missed. Especially check how easy it is to reverse mmx function. |
tamaroth Moderator 05. Sep 2013 | Haha, I didn't even know about this! Well, at least I've learned something! :) |
andrewl.us Moderator 05. Sep 2013 | share? |
tomkol Author 06. Sep 2013 | It's all in tamaroth hands. If he wants he can post pass to archive and reveal all secrets. |
tamaroth Moderator 06. Sep 2013 | When you look in my solution, you find that I have neg and add operation in the VM. This is the same as sub ... but for some reason it did not even occur to me when I was reversing. The other thing I did not know about was Gray code algorithm! I won't post the pass to the archive though, maybe someone else wants to solve it still :) |
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.