SunBeam Posted April 1, 2015 Posted April 1, 2015 (edited) [ Solutions so far: JohnWho, What ] (read whole thread) Hello folks. Decided I would post this here as well, as we're lacking some exercise on these kinds of targets. Purpose: open up the test target, click OK on the message box. Use any tool you want to alter a byte in application's active memory (e.g.: "MZ" string at ImageBase) and another message will appear. Goal: make the 'bad' message never pop-up, but not through patching the all-too-clear JUMP. Inline VMProtect's CRC check method so the CALL always returns 1. Again, not through MOV EAX,1|RETN (P.S.: imagine you don't know where this function is in a well-obfuscated target). Link: https://www.mediafire.com/file/sngpjiclmdgu3m2/Lic_MessageBox_2.rar/file Password: sunbeam Kudos, Sun Lic_MessageBox_2.rar Edited January 28, 2022 by Teddy Rogers Updated download link. Also attached same file. 2
portbinder Posted April 2, 2015 Posted April 2, 2015 Hmmmm. Looks Challenging definitely gonna try it.
JohnWho Posted April 2, 2015 Posted April 2, 2015 Not really sure if this is what you are looking for: http://rghost.net/8qKpBRy5x
av999 Posted April 2, 2015 Posted April 2, 2015 .0041A380: 81FA2F014000 cmp edx,00040012F -- 1.0041A386: 7507 jnz .00041A38F -- 2.0041A388: B840800000 mov eax,000008040 .0041A38D: 81FAB0C64000 cmp edx,00040C6B0 -- 3.0041A393: 7507 jnz .00041A39C -- 4.0041A395: B839187C2D mov eax,02D7C1839 .0041A39A: E9D71FFFFF jmp .00040C376 -- 5
JohnWho Posted April 2, 2015 Posted April 2, 2015 I still don't know what you mean by "did you check patch?"
av999 Posted April 2, 2015 Posted April 2, 2015 patch=inline code look at your inline exe more carefully
JohnWho Posted April 2, 2015 Posted April 2, 2015 Wouldn't it be easier if you tell me whats wrong instead of having me guessing? Does it not work for you or what?
SunBeam Posted April 2, 2015 Author Posted April 2, 2015 (edited) Hi guys. @JohnWho: He's talking about the jumps Unless your intention was to put them like that, the correct code would be: 0041A380 81FA 2F014000 CMP EDX,0040012F 0041A386 75 07 JNZ SHORT 0041A38D <-- instead of 41A38F 0041A388 B8 40800000 MOV EAX,8040 0041A38D 81FA B0C64000 CMP EDX,0040C6B0 0041A393 75 07 JNZ SHORT 0041A39A <-- instead of 41A39C 0041A395 B8 39187C2D MOV EAX,2D7C1839 0041A39A - E9 D71FFFFF JMP 0040C376 And from the looks of it, I take it you've changed code in 40012F and 40C6B0 areas. Well, second one is obvious, since you hooked code, so 40C6AA+1 = 40C6B0: 0040C6A9 60 PUSHAD 0040C6AA - E9 D1DC0000 JMP 0041A380 While first one is at 40012E (-1 from 2F): 0x40 <- 0x00. Funny thing about it is if left patched like this, loop never exits. The TEST EAX,EAX after the CALL is never hit again. All in all, awesome work BR, Sun Edited April 2, 2015 by SunBeam
SunBeam Posted April 2, 2015 Author Posted April 2, 2015 (edited) ^ Indeed Would it be possible to get this documented or just pointers on how to approach it? The way I see it: 1. If you plan on patching lots of memory, whatever changes you want make, you will have to fix the CRC in your hooked code. In gamehacking we're using Cheat Engine to hook various portions of code, hence if I hook 8-10 locations, I have to fix CRC as you probably did. 2. Would it be possible to kill the return value (1 to 0)? That is if you figure out where this is calculated. That way, no matter how much code I'd hook, return is always 1 (all OK), thus not having to worry about correct hashes. BR, Sun Edited April 2, 2015 by SunBeam
JohnWho Posted April 2, 2015 Posted April 2, 2015 Yes would probably have to fix crc several times but if you do: example, patch: 461022 -> to something 473100 -> to something 481203 -> to something you might only need to fix CRC after 481203, depending on where code block ends, so often you can get away with 3-5 fixes It has been my plan to reverse the CRC check more deeply to find a clean fix but i haven't had the time for it. Memory crc and file crc is done by same routine btw.
SunBeam Posted April 2, 2015 Author Posted April 2, 2015 (edited) Correct, same code flow, but separate functions: File CRC: 0040C6A9 60 PUSHAD 0040C6AA - E9 D1DC0000 JMP 0041A380 00419DF6 3202 XOR AL,BYTE PTR DS:[EDX] .. 00418617 60 PUSHAD 00418618 E9 47020000 JMP 00418864 .. 00418864 9C PUSHFD 00418865 FF4D 00 DEC DWORD PTR SS:[EBP]Memory CRC (same function, but recompiled for this particular use): 0040CBE3 3202 XOR AL,BYTE PTR DS:[EDX] 0040CBE5 56 PUSH ESI 0040CBE6 42 INC EDX 0040CBE7 E8 BDFAFFFF CALL 0040C6A9 .. 0040C6A9 60 PUSHAD 0040C6AA ^ E9 C7FCFFFF JMP 0040C376 <-- your hook .. 0040C376 9C PUSHFD 0040C377 FF4D 00 DEC DWORD PTR SS:[EBP]Will try and use same memory range, with both the OK and BAD values for the CRC and see where VMProtect's coming up with that 0/1 BOOL. BR,Sun Edited April 2, 2015 by SunBeam
SunBeam Posted April 2, 2015 Author Posted April 2, 2015 (edited) @JohnWho: This is the code behind the example: #define WIN32_LEAN_AND_MEAN #include <windows.h> #include "VMProtectSDK.h" DWORD dwShow = 0; VOID CALLBACK CheckMemory( HWND hWnd, UINT uMsg, UINT timerId, DWORD dwTime ) { if( VMProtectIsValidImageCRC() ) { // nothing here } else { MessageBox( 0, "VMProtectIsValidImageCRC active check failed. You changed code! Exiting. Patch the CRC check (not the JUMP!).", "Info", MB_ICONEXCLAMATION ); ExitProcess( 0 ); } } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) { MSG msg; MessageBox( 0, "VMProtectIsValidImageCRC active check enabled. CRC value is OK now. Try changing code and see what happens.", "Info", MB_OK ); SetTimer( NULL, 0, 2000, (TIMERPROC)&CheckMemory ); while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return TRUE; } It's not perfect, but for the purpose of this exercise, works as supposed. There are games (e.g.: Assassin's Creed - Unity) that use a similar approach to check memory integrity, but their timer is set to 200ms So, the elegant way to disable the check (I think they need a timer or something, thread, to infinitely check on the code via VMProtect's SDK API) is to disable the timer/thread/etc. - whatever they use (figuring out first what's the used method). BR, Sun Edited April 2, 2015 by SunBeam
JohnWho Posted April 2, 2015 Posted April 2, 2015 You are right, not same routine... in every target i checked it was same routine, maybe it was different versions/builds. I didn't even fix the file crc, didn't realize it was enabled
SunBeam Posted April 2, 2015 Author Posted April 2, 2015 (edited) Hehe, it's still there. Same flow: VirtualProtect, GetModuleFileNameW, CreateFileW, GetFileSize(Ex), CreateFileMappingW, MapViewOfFile (might've forgotten something here), UnmapViewOfFile, CloseHandle (on the mapping). I thought the logic was to generate the file CRC (on the sections they indicate they're checking) then compare the computed value(s) with the ones calculated via IsValidImageCRC function That would explain why file CRC is there, even though I've not enabled it in the protector options (I've left everything out, using Maximum Speed). BR, Sun Edited April 2, 2015 by SunBeam
portbinder Posted April 2, 2015 Posted April 2, 2015 Hey sunbeam can you make more complex crc checker on a crackme xD
SunBeam Posted April 2, 2015 Author Posted April 2, 2015 (edited) Hehe Well, I'm not yet satisfied till I find that 1/0 BOOL to patch in VMProtect - OR - the way the function that checks memory is called X times (infinitely). Will try and think of more combos with VMProtect's SDK. BR, Sun Edited April 2, 2015 by SunBeam
simple Posted April 2, 2015 Posted April 2, 2015 (edited) I'm not following all your rules here of what is valid / not valid solution, but changing the interval arg to something very high, then change it back to 2000 before the call (that way it makes 1 check after starting, then waits a 4 days, etc before calling again and u can mod the binary), or block WM_TIMER from arriving, etc work fine for me. Probably many more ways without wasting time reversing the whole crc routine. Edit - Another way it to get the return value of SetTimer() which doesnt involve moding any code then from outside of the application call KillTimer(NULL, ReturnValueOfSetTimer) and it won't get called anymore. Edited April 2, 2015 by simple
SunBeam Posted April 2, 2015 Author Posted April 2, 2015 (edited) @simple: The target here mimics Ubisoft's memory check implemented in Assassin's Creed: Unity. That target is x64 for one, and for two, I don't know (haven't looked into it, but will do so) if they use a timer or a thread (I think it's a thread). I created this to illustrate what happens in some games that have VMProtect used as protection. I was looking into a more-VMProtect-wise approach, rather than patching the timer or similar. As I said, in that game the timer might be obfuscated as well. Last I tried, I set a break on WM_TIMER, nothing came up, so I'm sure they're using something else. BR,Sun Edited April 2, 2015 by SunBeam 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now