#1
|
|||
|
|||
Securom 7 Rebuild
Hey guys, I was fooling around with securom 7 for the past 2 days, and now I am kind of tired, kind of stumped, and have other Real Life things to attend to, so I thought I might pass this off to someone here and he could continue my work into gaining some insights about this protection.
Keep in mind that I am a self-acknowledged noob. A lot of the stuff I say here may or may not be correct. Please correct me if I am wrong, its always nice to learn something. Before I forget, the target is Grand Theft Auto San Andreas 1.1 Oh, and one last thing before I start: I know that I can dump the heaps at the OEP, and fix the GetProcessId check, but there is no challenge in that, is there? And one last thing. Pirates, fuck off. People who are going to use this to crack the game and distribute it illegally, fuck off. Protection developers, keep reading and pay attention Oh and if you want to learn something, keep reading. Needless to say, this is only for educational purposes, for fun, and for a way to pass time, not for any illegal shit. Ok, so, let me get you up to date on what I have so far. First thing is to find the OEP. Pretty simple task with this protection. Grab your favorite debugger (for the purposes of this post, I used Olly), and start reading. Securom 7 uses some pretty innovative AntiDebug, but nothing as vast as the Safedisc antidebug arsenal. First thing it does is get the tick count with GetTickCount, and then it causes a gazillion exceptions. Since your debugger needs to process all these exceptions, it is naturally slowed down. After it causes all those exceptions, it uses GetTickCount to check if the time elapse was large. If it was -> Debugger detected. To bypass this check you can either put a BP on GetTickCount(Securom doesn't check API's for 0xCC) and change EAX to 0 each time it is called, or just assemble a xor eax, eax; ret; at the beginning of the GetTickCount API The second trick comes into play right after the large amount of exceptions. Its a simple call to NtQueryInformationProcess (also known as ZwQueryInformationProcess). To bypass it, I put a bp on ZwQueryInformationProcess, and kept running and looking at the top of the stack. This API gets called a lot by kernel32 and other standard dll's, but you will once see it getting called from a place with a much return lower address: Code:
00212128 00EDFE7A /CALL to ZwQueryInformationProcess from gta_sa.00EDFE77 0021212C FFFFFFFF |hProcess = FFFFFFFF 00212130 00000007 |InfoClass = 7 00212134 0021217C |Buffer = 0021217C 00212138 00000004 |Bufsize = 4 0021213C 00000000 \pReqsize = NULL Now, before you run the target, put a Memory Breakpoint on the code section. Now run the target, you will break once or twice, and then finally hit the OEP: Code:
00825330 6A 60 PUSH 60 00825332 68 B8908800 PUSH gta_sa.008890B8 00825337 E8 943C0000 CALL gta_sa.00828FD0 Now, I'll go through all the antidumps that I have found so far. The first one that is so blatantly easy to spot is all the JMP DWORD PTR's lying around. What securom does during the protection process is cut and paste some code from the code section, put it into a securom(or another location in the code) section, obfuscate it and do all kinds of other, nasty but cool things to it. After it redirects the code to a new spot, it puts a JMP DWORD PTR to the central securom routine at the place where the the original code was. The central securom routine then redirects it to the correct place. Pretty simple, kind of like IAT redirection, except without the imports, eh? Lets take a look at one of the JMP DWORD PTR's: Code:
0040104A $- FF25 58B04B01 JMP DWORD PTR DS:[14BB058] 00401050 8D604B01 DD gta_sa.014B608D 00401054 D1604B01 DD gta_sa.014B60D1 00401058 15614B01 DD gta_sa.014B6115 0040105C 59614B01 DD gta_sa.014B6159 Code:
0150DEB0 68 CADE5001 PUSH gta_sa.0150DECA 0150DEB5 68 8E624000 PUSH gta_sa.0040628E 0150DEBA 68 200BF000 PUSH gta_sa.00F00B20 0150DEBF 9C PUSHFD 0150DEC0 816C24 04 50540000 SUB DWORD PTR SS:[ESP+4],5450 0150DEC8 9D POPFD 0150DEC9 C3 RETN Code:
00EFB6D0 60 PUSHAD 00EFB6D1 9C PUSHFD 00EFB6D2 E8 00000000 CALL gta_sa.00EFB6D7 00EFB6D7 F0:FE0D 541C3901 LOCK DEC BYTE PTR DS:[1391C54] Code:
00EFE92E 9D POPFD 00EFE92F 61 POPAD 00EFE930 C2 0400 RETN 4 Code:
0040104A $ /FF25 58B04B01 JMP DWORD PTR DS:[14BB058] ; gta_sa.005EE7DA 00401050 |8D604B01 DD gta_sa.014B608D 00401054 |D1604B01 DD gta_sa.014B60D1 00401058 |15614B01 DD gta_sa.014B6115 Another thing to note is that all JMP DWORD PTR's point to mini routines akin to these: Code:
01510540 68 5A055101 PUSH gta_sa.0151055A 01510545 68 6D7B4000 PUSH gta_sa.00407B6D 0151054A 68 D897F100 PUSH gta_sa.00F197D8 0151054F 9C PUSHFD 01510550 816C24 04 08E10100 SUB DWORD PTR SS:[ESP+4],1E108 01510558 9D POPFD 01510559 C3 RETN Code:
0150A360 68 6AA35001 PUSH gta_sa.0150A36A 0150A365 E8 66139FFF CALL gta_sa.00EFB6D0 I coded something on the fly to fix it, no comments since I wasn't expecting anyone to use it at the time. MASM to assemble etc etc... Code:
start: _text equ 00401000h _textSize equ 00457000h _securomData equ 01493000h _securomEnd equ 020DFFF8h _central equ 00EFB6D0h mov eax, _text _find_jmp_dword_loop: cmp word ptr[eax], 025FFh je _jmp_dword_found _find_jmp_dword_loop_ok: inc eax cmp eax, (_text+_textSize) jl _find_jmp_dword_loop int 3 jmp _part_two _jmp_dword_found: mov ebx, dword ptr[eax+2] cmp ebx, _securomData jl _find_jmp_dword_loop_ok cmp ebx, _securomEnd ja _find_jmp_dword_loop_ok mov ebx, dword ptr[ebx] cmp byte ptr[ebx], 068h jne _check_type2 cmp byte ptr[ebx+5], 068h jne _check_type2 cmp byte ptr[ebx+0Ah], 068h jne _check_type2 cmp byte ptr[ebx+0Fh], 09Ch jne _check_type2 jmp _all_clear _check_type2: cmp byte ptr[ebx], 068h jne _uknown cmp byte ptr[ebx+5], 0E8h jne _uknown mov edx, dword ptr[ebx+6] add edx, ebx add edx, 0Ah cmp edx, _central jne _uknown _all_clear: jmp ebx _uknown: int 3 nop nop nop _retPoint: popfd popad add esp, 8 jmp _find_jmp_dword_loop_ok Code:
00EFE92E 9D POPFD 00EFE92F 61 POPAD 00EFE930 C2 0400 RETN 4 The second antidump I noticed in passing. Its your pretty damn standard on-the-fly code decryption. Take a look: Code:
004012E9 .- FF25 2CB14B01 JMP DWORD PTR DS:[14BB12C] Code:
014C4459 E8 D2C8A1FF CALL cracked1.00EE0D30 014C445E 51 PUSH ECX 014C445F 010F ADD DWORD PTR DS:[EDI],ECX Code:
014C4459 55 PUSH EBP 014C445A FF0D 490B5101 DEC DWORD PTR DS:[1510B49] 014C4460 - 0F84 401711FF JE cracked1.005D5BA6 014C4466 8BEC MOV EBP,ESP Code:
_part_two: mov eax, _text mov esi, esp _find_jmp_dword_loop_two: cmp word ptr[eax], 025FFh je _jmp_dword_found_two _find_jmp_dword_loop_ok_two: inc eax cmp eax, (_text+_textSize) jl _find_jmp_dword_loop_two int 3 jmp _part_three _jmp_dword_found_two: mov ebx, dword ptr[eax+2] cmp ebx, _securomData jl _find_jmp_dword_loop_ok_two cmp ebx, _securomEnd ja _find_jmp_dword_loop_ok_two mov ebx, dword ptr[ebx] cmp byte ptr[ebx], 0E8h jne _find_jmp_dword_loop_ok_two push ebx jmp _find_jmp_dword_loop_ok_two Code:
01391D20 58 POP EAX 01391D21 8BBB 20030000 MOV EDI,DWORD PTR DS:[EBX+320] 01391D27 81C7 04000000 ADD EDI,4 01391D2D 8A47 01 MOV AL,BYTE PTR DS:[EDI+1] 01391D30 8607 XCHG BYTE PTR DS:[EDI],AL 01391D32 81C3 24000000 ADD EBX,24 01391D38 C703 00000000 MOV DWORD PTR DS:[EBX],0 01391D3E 9D POPFD 01391D3F 61 POPAD The trick however(there's always a trick) is that it always returns to the above code from this code: Code:
00F00AD5 0FA3FD BT EBP,EDI 00F00AD8 8107 04000000 ADD DWORD PTR DS:[EDI],4 00F00ADE C3 RETN Code:
_part_three: xchg eax, eax _restore_encrypted_loop: pop ebx jmp ebx _ret_point_three: nop nop nop add dword ptr[edi], 4 add esp, 4 pop eax mov edi, dword ptr[ebx+0320h] add edi, 4 mov al, byte ptr[edi+1] xchg byte ptr[edi], al add ebx, 024h mov dword ptr[ebx], 0 popfd popad add esp, 0Ch cmp esp, esi jne _restore_encrypted_loop int 3 Now, replace: Code:
00F00AD8 8107 04000000 ADD DWORD PTR DS:[EDI],4 Ok, with that done, take a look at the next antidump: Code:
014E72F6 68 2F134000 PUSH fixed_1.0040132F 014E72FB E8 D043A1FF CALL fixed_1.00EFB6D0 Code:
mov eax, _securomData _find_mid_jumps_loop: cmp byte ptr[eax], 068h je _mid_jumps_check1 _mid_jumps_ok: inc eax cmp eax, _securomEnd jle _find_mid_jumps_loop int 3 _mid_jumps_check1: cmp byte ptr[eax+5], 0E8h jne _mid_jumps_ok mov ebx, dword ptr[eax+6] add ebx, eax add ebx, 0Ah cmp ebx, _central jne _mid_jumps_ok pushad jmp eax nop nop nop _good_return: mov dword ptr[ebx], 0 popfd popad add esp, 8 popad sub esp, 028h pop edx pop esi add esp, 020h mov dword ptr[eax], 090909090h add eax, 4 mov byte ptr[eax], 090h inc eax mov byte ptr[eax], 0E8h mov ebx, eax sub ebx, edx add ebx, 5 imul ebx, ebx, -1 mov dword ptr[eax+1], ebx jmp _mid_jumps_ok int 3 int 3 int 3 int 3 ;type 2 & type 6 exit _ignore_return: popfd popad add esp, 8 popad jmp _mid_jumps_ok Code:
00EFEC7B C703 00000000 MOV DWORD PTR DS:[EBX],0 00EFEC81 9D POPFD 00EFEC82 61 POPAD 00EFEC83 C3 RETN with a jump to _good_return, and you need to replace the exit point's of the other antidumps (JMP DWORD redirection and instruction emulation) with JMPs to _ignore_return: JMP dword exit point: Code:
00EFE92E 9D POPFD 00EFE92F 61 POPAD 00EFE930 C2 0400 RETN 4 Code:
00F00461 9D POPFD 00F00462 61 POPAD 00F00463 C2 0400 RETN 4 Now, this is the point I have halted at. I don't have the time for the next month or so, so lets see if anyone can continue in my stead. There are two other types of redirections I have noticed. The first (easy) is the import redirection: Code:
006029F4 . 9C PUSHFD 006029F5 . FF0D 20105101 DEC DWORD PTR DS:[1511020] 006029FB .^ 0F84 9197FFFF JE cracked1.005FC192 00602A01 > B8 743F21FE MOV EAX,FE213F74 00602A06 . 35 A489CEFE XOR EAX,FECE89A4 00602A0B . 9D POPFD 00602A0C . FFD0 CALL EAX Code:
014E1ED6 9C PUSHFD 014E1ED7 817424 04 7A2CECD1 XOR DWORD PTR SS:[ESP+4],D1EC2C7A 014E1EDF 9D POPFD 014E1EE0 58 POP EAX 014E1EE1 FFD0 CALL EAX 005D1A0B . 9C PUSHFD 005D1A0C . 817424 08 6996F12C XOR DWORD PTR SS:[ESP+8],2CF19669 005D1A14 . 9D POPFD 005D1A15 . 58 POP EAX 005D1A16 . 870424 XCHG DWORD PTR SS:[ESP],EAX 005D1A19 . EB FF JMP SHORT cracked1.005D1A1A 005D1A1B D0 DB D0 [/code] As you can see, its got a slightly different byte pattern each time, which theoretically makes scanning harder. So, I have decided to blatantly steal Hoodlum's solution to this problem. You will notice that all the import redirections push a pointer to the beginning of the text section right before they go to the Securom routine. These are pointers to the table of DWORDs at the beginning of the code section(you were probably wondering what they are for, now you know): Code:
00401050 8D604B01 DD cracked1.014B608D 00401054 D1604B01 DD cracked1.014B60D1 00401058 15614B01 DD cracked1.014B6115 0040105C 59614B01 DD cracked1.014B6159 00401060 9D614B01 DD cracked1.014B619D 00401064 E1614B01 DD cracked1.014B61E1 00401068 25624B01 DD cracked1.014B6225 0040106C 69624B01 DD cracked1.014B6269 00401070 AD624B01 DD cracked1.014B62AD 00401074 F1624B01 DD cracked1.014B62F1 00401078 35634B01 DD cracked1.014B6335 0040107C 79634B01 DD cracked1.014B6379 00401080 BD634B01 DD cracked1.014B63BD 00401084 01644B01 DD cracked1.014B6401 00401088 45644B01 DD cracked1.014B6445 Now, I'm not going to give you the code for the above, as I have yet to do it, still, its pretty simple, you shouldn't have any troubles. If that doesn't work then you can always scan for CALL EAX's perceded with PUSHFD's and PUSH xxxxxx's that push pointers to the beginning of .text. Do whatever you feel like doing. The last protection has me kind of stumped, and in my opinion is what makes securom so sexy. It replaces single instructions with PUSH/CALLs to the central routine, where they are emulated. I've already figured out that it only emulates certain instructions, and I have a theoretical way of ID'ing each instruction, but its not anything solid enough to warrant me giving you details about. So, this is pretty much what I'm asking you to figure out. Well, thats it for me. I know a lot of you have better things to do, but this post might help some noobies start on this protection, and the way you guys will criticise me will probably help me improve in some way. I'm pretty sure I'll figure out the single instruction emulation eventually, maybe I'll even update this post when I do. Until then, you all take care |
Sponsored Links |
#2
|
||||
|
||||
old old old.. did you actually check the version of the gta : sa 1.1 update?
Quote:
Quote:
and FF 25 to them from another block of code.. which allows them to make all api's used by the code into E8 xx xx xx xx api calls... saving 1 byte per api call.. optimisation sort of... NOT a securom feature
__________________
bleh DO NOT PM me with questions, leave that in the forums...ESPECIALLY if i dont know you... Last edited by TippeX; 14-05-2007 at 00:05. |
#3
|
||||
|
||||
Hmmm, why does the original post smell of 'Sunbeam'!!??
__________________
Can't find a Game Conversion? Check the 'Conversion INDEX'
|
#4
|
||||
|
||||
have to admit, i did actually think the same grumpy...
__________________
bleh DO NOT PM me with questions, leave that in the forums...ESPECIALLY if i dont know you... |
#5
|
|||
|
|||
Hiya guys,
yeah, I bothered to check the version, and I realize that this is fairly old, but hey, you never know. For example, look at Safedisc. A lot of the stuff written about MUPing safedisc 2.7 by Peex still applies to Safedisc 4.6, since they haven't really bothered to update several of their protection features. Also, I've taken a quick peak at the later versions (7.31+), nothing comprehensive mind you, but I think that the structure of securom looks more or less the same, just allocates a lot more memory regions and the exit point is a bit different. But like I said, that was just a cursory glance. Quote:
Quote:
I'm sorry to say, I highly doubt this, because all of the dword's that I have listed are pointers to the Securom section of the game. It is true that they might have originally been VA's pointing to the IAT, but now they have been replaced by securom pointers, and are used for the securom IAT redirection, thus something must be done about them. And finally, about the Sunbeam comment, I was reading this forum when you were having that little chat with him, and I would just like to say I have never spoken to the chap, have never been on the same forum as him, etc etc... If you feel this information is useless, I am sorry to have bothered you and will remove my original post, and be out of your hair. Now, 2 things to learn, FARPROC arrays and how NtQueryInformationProcess is used for debugger detection. I have some reading to do. Please, feel free to continue with the criticism, or tell me to fuck off. I wont be the least bit offended either way. Oh, and in case you are wondering why I am using this nickname, it is because I think this type of information can get me into a sweet bit of legal trouble if I am ever caught. Also, I couldn't think of any fitting nickname while registering, so I just decided to go along with 'anonymous'. Last edited by anonymous1381; 14-05-2007 at 13:27. |
#6
|
||||
|
||||
Quote:
going to the securom section sure.. maybe to the securom iat? Quote:
why not research it fully, spend your time on it, then make a post.. that way its more useful to people later and less full of bullshit and second guessing.. i have to admit though your approach and style, are very similar to sunbeam.. and its clear im not the only one thinking that...
__________________
bleh DO NOT PM me with questions, leave that in the forums...ESPECIALLY if i dont know you... |
#7
|
|||
|
|||
Very well, from now on all posts I make I will try to make as factually correct as possible, and not include any bullshit theories. I can for certain say that all the solutions that I have presented for all the protection options so far aside from the Import redirection and emulated instructions work on my machine.
Also, this post is more in the way of you guys helping me, and maybe even others in the process. Your criticism helps. I admit, I got the idea for writing this post after reading your comments to Sunbeam. You were a lot more critical of him than people would be to me if I posted this information on other cracker forums. All I would get is a 'Thank you'. Thats nice, but what information would I get? Nothing. Also, for all those interested about the NtQueryInformationProcess check: http://msdn2.microsoft.com/en-us/library/ms684280.aspx Quote:
Oh, and please don't assume that I know everything about this subject. Like I said in the original post, I don't, but I would be happy to learn Oh, and about the Sunbeam comment, how can I prove to you that I am not Sunbeam? Last edited by anonymous1381; 14-05-2007 at 14:09. |
#8
|
||||
|
||||
you proved u werent sunbeam by actually going off and researching...
whats the little red text at the top of the page tho?
__________________
bleh DO NOT PM me with questions, leave that in the forums...ESPECIALLY if i dont know you... |
#9
|
|||
|
|||
It says in red letters in the MSDN page that this API may not be used in future versions of windows. Thus, it could possibly lead to some compatibility problems in the future.
__________________
Sanity is for the weak. |
#10
|
|||
|
|||
caki,
maybe you are right, maybe not. Code:
00EDFE4A FF15 30494901 CALL DWORD PTR DS:[<&KERNEL32.GetProcAddress>] ; kernel32.GetProcAddress 00EDFE50 8945 D0 MOV DWORD PTR SS:[EBP-30],EAX 00EDFE53 6A 00 PUSH 0 00EDFE55 6A 04 PUSH 4 00EDFE57 BA D9DDF5FF MOV EDX,FFF5DDD9 00EDFE5C 8D942A F3210A00 LEA EDX,DWORD PTR DS:[EDX+EBP+A21F3] 00EDFE63 83EC 04 SUB ESP,4 00EDFE66 891424 MOV DWORD PTR SS:[ESP],EDX 00EDFE69 6A 07 PUSH 7 00EDFE6B FF15 C84A4901 CALL DWORD PTR DS:[<&KERNEL32.GetCurrentProcess>] ; kernel32.GetCurrentProcess 00EDFE71 83EC 04 SUB ESP,4 00EDFE74 890424 MOV DWORD PTR SS:[ESP],EAX 00EDFE77 FF55 D0 CALL DWORD PTR SS:[EBP-30] Maybe the securom devs do a GetVersion to check if the OS supports ZwQueryInformationProcess? |
#11
|
||||
|
||||
yeh its an 'undocumented' api, but microsoft are usually backwardly compatible with their setups, and some of their code also uses these api's, so if they aren't really going to break their own programs ..
look at the peb / teb blocks from 9x->xp, even on x64 platform, they are backwardly compatible, and only have new stuff added with each os build.. its like their documentation, often its quite wrong on some api's / structs / params... microsoft = do as we say... not as we do
__________________
bleh DO NOT PM me with questions, leave that in the forums...ESPECIALLY if i dont know you... |
#12
|
|||
|
|||
Sorry, I was just curious since I was reading an article the other day in which some Microsoft spokesperson said they were considering to cut it out with the backwards compatibility, since its starting to limit the development of the OS. If that truly does come about, then I think a lot more people aside from the securom folks will have something to worry about.
__________________
Sanity is for the weak. |
Thread Tools | |
Display Modes | |
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
dreamfall tricky securom | Mperor | PC Games | 1 | 02-10-2006 06:57 |
differente version of securom ???? (packer) | bidule | PC Games | 2 | 07-03-2002 02:53 |
[Help! - Removing the Securom protection...] | XICO2KX | CD/DVD Copy Protections & Utilities | 1 | 19-12-2001 19:16 |
Securom protection!! | trax | PC Games | 6 | 15-03-2001 16:15 |
PHILIPS STILL KILLING SD2 AND SONY HANDLING SECUROM 1&2 | Redrum1 | PC Games | 2 | 26-02-2001 14:39 |