تبلیغات :
آکوستیک ، فوم شانه تخم مرغی، صداگیر ماینر ، یونولیت
دستگاه جوجه کشی حرفه ای
فروش آنلاین لباس کودک
خرید فالوور ایرانی
خرید فالوور اینستاگرام
خرید ممبر تلگرام

[ + افزودن آگهی متنی جدید ]




صفحه 7 از 17 اولاول ... 34567891011 ... آخرآخر
نمايش نتايج 61 به 70 از 163

نام تاپيک: آموزش کرک و قفل شکنی ( انگلیسی ) از بهترین کرکرهای روس و ...

  1. #61
    پروفشنال Morteza_SOS's Avatar
    تاريخ عضويت
    Apr 2006
    پست ها
    577

    پيش فرض

    Level : intermediate

    ~~~~~~~~~~~~~~~~~
    Unpacking SecuROM 4.xx
    ~~~~~~~~~~~~~~~~~




    My sister's son brought me yesterday one CD with interactive flash stories for kids. He wanted to watch that on my computer. Since loading of CD material in working memory was slow, I burned image with Nero to my hard drive. I thought that it would be much faster than wait while CD finds right files. But image just wouldn't run. I just cursed it and placed original CD back into drive and I left kid to watch those stories. Today after lunch, I was bored and curious so I decided to throw quick look on original CD. I was pleasantly surprised - main executable was packed by SecuROM.



    1. Introduction

    I say pleasantly because I never before had in my hands original CD protected with SecuROM. I know that this is old version, but what can I do? But I'm also surprised that Nero 6 couldn't burn working image. I thought that Nero can do that?!? I have some other tools like Alcohol 120%, Dameon tools, but I don't have experience with burning these kind of software. I just don't play these new games that comes on CD-DVD (I like emulators, you know; MAME, WinUAE, ZNES, etc.). Ok, let's start I'm writing this tutorial while unpacking so it won't go into depth of SecuROM. Hell I even don't know will I finish it! Maybe I will fail to unpack SecuROM I hope not. Let's go!

    The CD name is CROTALES and it contains Croatian tales from known writer (in Croatia) Ivana Brlic-Mazuranic. I doubt that readers of this tutorial will find this CD somewhere, but protector was used allot in games from 2-3 years ago (2003-2004). I think that current version of SecuROM is 7. CD contains .swf files and one executable file START.EXE. That file is nothing more than macromedia flash player protected with SecuROM. Cracking this CD is not hard, we can play .swf files in any browser. But we are interested in SecuROM.

    First information I got from PEID 0.94:

    SecuROM 4.x.x.x - 5.x.x.x -> Sony DADC [Overlay]

    If you are interested in exact version, you can use Yates SecuROM/SafeDisc version detector (for older versions):

    SecuROM - 4.84.00 0001

    Or you could manually search for version information. With some hex editor, search for "AddD" string in file:

    0017A000 41 64 64 44 03 00 00 00 34 2E 38 34 2E 30 30 00 AddD...4.84.00.
    0017A010 30 30 30 31 A2 20 19 27 C8 27 A3 2C F2 2D 1E 3D 0001˘.'Č'Ł,ň-=


    How image looks in memory? Let's see:

    Memory map
    Address Size Owner Section Contains Type Access Initial Mapped as
    00400000 00001000 START PE header Imag R RWE
    00401000 00097000 START .text code Imag R RWE
    00498000 0000B000 START .rdata code Imag R RWE
    004A3000 000D0000 START .data code Imag R RWE
    00573000 00001000 START .data1 data Imag R RWE
    00574000 00001000 START .CRT Imag R RWE
    00575000 00031000 START .cms_t SFX Imag R RWE
    005A6000 0007E000 START .cms_d Imag R RWE
    00624000 00003000 START .idata imports Imag R RWE
    00627000 00016000 START .rsrc resources Imag R RWE

    Obviously protector's sections are .data1, .CRT, .cms_t and .idata. EP of protector code looks like common MSVC++ 6.0 OEP:

    0059C490 > 55 PUSH EBP
    0059C491 8BEC MOV EBP,ESP
    0059C493 6A FF PUSH -1
    0059C495 68 48A26000 PUSH START.0060A248
    0059C49A 68 24C25900 PUSH START.0059C224
    0059C49F 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
    0059C4A5 50 PUSH EAX
    0059C4A6 64:8925 00000000 MOV DWORD PTR FS:[0],ESP
    0059C4AD 83EC 58 SUB ESP,58
    0059C4B0 53 PUSH EBX
    0059C4B1 56 PUSH ESI
    0059C4B2 57 PUSH EDI ; ntdll.7C910738
    0059C4B3 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP
    0059C4B6 FF15 EC476200 CALL DWORD PTR DS:[<&kernel32.GetVersion>; kernel32.GetVersion
    0059C4BC 33D2 XOR EDX,EDX ; ntdll.KiFastSystemCallRet
    0059C4BE 8AD4 MOV DL,AH
    0059C4C0 8915 10766100 MOV DWORD PTR DS:[617610],EDX ; ntdll.KiFastSystemCallRet
    0059C4C6 8BC8 MOV ECX,EAX
    0059C4C8 81E1 FF000000 AND ECX,0FF
    0059C4CE 890D 0C766100 MOV DWORD PTR DS:[61760C],ECX
    0059C4D4 C1E1 08 SHL ECX,8
    0059C4D7 03CA ADD ECX,EDX ; ntdll.KiFastSystemCallRet
    0059C4D9 890D 08766100 MOV DWORD PTR DS:[617608],ECX
    0059C4DF C1E8 10 SHR EAX,10
    0059C4E2 A3 04766100 MOV DWORD PTR DS:[617604],EAX
    0059C4E7 33F6 XOR ESI,ESI
    0059C4E9 56 PUSH ESI
    0059C4EA E8 E5120000 CALL START.0059D7D4
    ...
    ...


    If we take a look in the first section (where it should be original EP) we can see that section is not encrypted. SecuROM protection consist from CD check, OEP code encryption and import protection. It is not hard to fool SecuROM so it thinks that CD is inside, but that is useless. SecuROM needs some information stored on CD that will decrypt OEP code! And that information cannot be read and copied to another CD, or to hard drive (there my Nero 6 failed). To crack SecuROM we need original CD. So I pushed back CD into drive.





    2. Finding OEP and decrypting

    This is very easy thing to do if we have original CD. These versions of SecuROM are CD copy protections. They doesn't have anti-debug tricks so decrypting OEP code and breaking there is a joke. To quick find OEP, I placed bp on GetDriveTypeA. After stopping, it resumed in new loaded DLL (DLL extracted in temp folder). I was here:

    2000110D 66:3D 0500 CMP AX,5
    20001111 75 0F JNZ SHORT sintfnt.20001122
    20001113 8B4C24 28 MOV ECX,DWORD PTR SS:[ESP+28] ; START.0061A520
    20001117 8B4424 24 MOV EAX,DWORD PTR SS:[ESP+24] ; START.006215D0
    2000111B 8919 MOV DWORD PTR DS:[ECX],EBX
    2000111D 8B08 MOV ECX,DWORD PTR DS:[EAX]
    2000111F 41 INC ECX
    20001120 8908 MOV DWORD PTR DS:[EAX],ECX
    20001122 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10]
    20001126 D1E9 SHR ECX,1
    20001128 4B DEC EBX
    20001129 894C24 10 MOV DWORD PTR SS:[ESP+10],ECX
    2000112D ^79 8F JNS SHORT sintfnt.200010BE
    2000112F 8B5424 24 MOV EDX,DWORD PTR SS:[ESP+24] ; START.006215D0
    20001133 33C0 XOR EAX,EAX
    20001135 5F POP EDI ; START.00403000
    20001136 5E POP ESI ; START.00403000
    20001137 8B0A MOV ECX,DWORD PTR DS:[EDX]
    20001139 5D POP EBP ; START.00403000
    2000113A 85C9 TEST ECX,ECX
    2000113C 0F9FC0 SETG AL
    2000113F 5B POP EBX ; START.00403000
    20001140 83C4 10 ADD ESP,10
    20001143 C2 0800 RETN 8

    After RETN 8 I was here, back in START.EXE:

    00582994 85C0 TEST EAX,EAX
    00582996 75 3B JNZ SHORT START.005829D3
    00582998 FF15 F4A76100 CALL DWORD PTR DS:[61A7F4] ; sintfnt.FGDM32
    0058299E 833D C4C35C00 00 CMP DWORD PTR DS:[5CC3C4],0
    005829A5 74 1E JE SHORT START.005829C5
    005829A7 68 94216000 PUSH START.00602194 ; ASCII "70015A56C550882901D183BCD7CDD288E72EC775B8161D9AB F56"
    005829AC 68 C0F26100 PUSH START.0061F2C0
    005829B1 E8 7F800100 CALL START.0059AA35
    005829B6 83C4 08 ADD ESP,8
    005829B9 68 C0F26100 PUSH START.0061F2C0
    005829BE 6A 20 PUSH 20
    005829C0 E8 EB3DFFFF CALL START.005767B0
    005829C5 6A 01 PUSH 1
    005829C7 E8 342DFFFF CALL START.00575700
    005829CC 6A 01 PUSH 1
    005829CE E8 4B7C0100 CALL START.0059A61E
    005829D3 833D C4C35C00 00 CMP DWORD PTR DS:[5CC3C4],0
    005829DA 74 2E JE SHORT START.00582A0A


    This version of SecuROM has easy to spot OEP jump. Scrolling down couple pages I sow it:

    00582EB6 B8 A0704600 MOV EAX,START.004670A0
    00582EBB 90 NOP
    00582EBC 90 NOP
    00582EBD 50 PUSH EAX
    00582EBE EB 08 JMP SHORT START.00582EC8
    00582EC0 58 POP EAX
    00582EC1 A1 38946100 MOV EAX,DWORD PTR DS:[619438]
    00582EC6 -FFE0 JMP EAX ; Can it be more obvious !?!
    00582EC8 A3 38946100 MOV DWORD PTR DS:[619438],EAX
    00582ECD A3 40C96100 MOV DWORD PTR DS:[61C940],EAX
    00582ED2 833D CC746100 00 CMP DWORD PTR DS:[6174CC],0
    00582ED9 74 19 JE SHORT START.00582EF4
    00582EDB A1 6EBE6100 MOV EAX,DWORD PTR DS:[61BE6E]
    00582EE0 83E0 02 AND EAX,2
    00582EE3 85C0 TEST EAX,EAX
    00582EE5 74 0D JE SHORT START.00582EF4

    OEP of this file looks pretty weird:

    004670A0 . 83EC 44 SUB ESP,44
    004670A3 . 56 PUSH ESI ; START.00404120
    004670A4 . FF15 609E5A00 CALL DWORD PTR DS:[5A9E60] ; START.0057D010
    004670AA . 8BF0 MOV ESI,EAX ; START.004670A0
    004670AC . 8A06 MOV AL,BYTE PTR DS:[ESI]
    004670AE . 3C 22 CMP AL,22
    004670B0 . 75 1C JNZ SHORT START.004670CE
    004670B2 . 8A46 01 MOV AL,BYTE PTR DS:[ESI+1]
    004670B5 . 46 INC ESI ; START.00404120
    004670B6 . 3C 22 CMP AL,22
    004670B8 . 74 0C JE SHORT START.004670C6
    004670BA > 84C0 TEST AL,AL
    004670BC . 74 08 JE SHORT START.004670C6
    004670BE . 8A46 01 MOV AL,BYTE PTR DS:[ESI+1]
    004670C1 . 46 INC ESI ; START.00404120
    004670C2 . 3C 22 CMP AL,22
    004670C4 .^75 F4 JNZ SHORT START.004670BA
    004670C6 > 803E 22 CMP BYTE PTR DS:[ESI],22
    004670C9 . 75 0F JNZ SHORT START.004670DA
    004670CB . 46 INC ESI ; START.00404120
    004670CC . EB 0C JMP SHORT START.004670DA
    004670CE > 3C 20 CMP AL,20
    004670D0 . 7E 08 JLE SHORT START.004670DA
    004670D2 > 8A46 01 MOV AL,BYTE PTR DS:[ESI+1]
    004670D5 . 46 INC ESI ; START.00404120
    004670D6 . 3C 20 CMP AL,20
    004670D8 .^7F F8 JG SHORT START.004670D2
    004670DA > 8A06 MOV AL,BYTE PTR DS:[ESI]
    004670DC . 84C0 TEST AL,AL
    004670DE . 74 0C JE SHORT START.004670EC
    004670E0 > 3C 20 CMP AL,20
    004670E2 . 7F 08 JG SHORT START.004670EC
    004670E4 . 8A46 01 MOV AL,BYTE PTR DS:[ESI+1]
    004670E7 . 46 INC ESI ; START.00404120
    004670E8 . 84C0 TEST AL,AL
    004670EA .^75 F4 JNZ SHORT START.004670E0
    004670EC > 8D4424 04 LEA EAX,DWORD PTR SS:[ESP+4]
    004670F0 . C74424 30 0000>MOV DWORD PTR SS:[ESP+30],0
    004670F8 . 50 PUSH EAX ; START.004670A0
    004670F9 . FF15 609E5A00 CALL DWORD PTR DS:[5A9E60] ; START.0057D010
    004670FF . F64424 30 01 TEST BYTE PTR SS:[ESP+30],1
    00467104 . 74 0B JE SHORT START.00467111
    00467106 . 8B4424 34 MOV EAX,DWORD PTR SS:[ESP+34]
    0046710A . 25 FFFF0000 AND EAX,0FFFF
    0046710F . EB 05 JMP SHORT START.00467116
    00467111 > B8 0A000000 MOV EAX,0A




    3. Imports

    More than half of imports in main executable now leads to same address. For example, first import that will be triggered:

    004670A4 . FF15 609E5A00 CALL DWORD PTR DS:[5A9E60] ; START.0057D010

    Protection used is just custom function that calculates what import should be triggered from a specified offset. It seams that it doesn't need original CD to be in drive for this. I didn't go in details. After tracing into that call, I scrolled down couple pages again and found one (of two) JMP EAX that jumps to correct import:

    0057D010 55 PUSH EBP
    0057D011 8BEC MOV EBP,ESP
    0057D013 81EC B4000000 SUB ESP,0B4
    0057D019 53 PUSH EBX
    0057D01A 56 PUSH ESI ; START.00404120
    0057D01B 57 PUSH EDI ; START.00403000
    0057D01C 8945 D4 MOV DWORD PTR SS:[EBP-2C],EAX ; START.004670A0
    0057D01F 895D A4 MOV DWORD PTR SS:[EBP-5C],EBX
    0057D022 894D 8C MOV DWORD PTR SS:[EBP-74],ECX
    0057D025 8955 EC MOV DWORD PTR SS:[EBP-14],EDX ; ntdll.KiFastSystemCallRet
    0057D028 8975 84 MOV DWORD PTR SS:[EBP-7C],ESI ; START.00404120
    0057D02B 897D E8 MOV DWORD PTR SS:[EBP-18],EDI ; START.00403000
    0057D02E 896D F4 MOV DWORD PTR SS:[EBP-C],EBP
    0057D031 8965 C4 MOV DWORD PTR SS:[EBP-3C],ESP
    0057D034 8B45 04 MOV EAX,DWORD PTR SS:[EBP+4] ; START.0059C55E
    0057D037 8945 A8 MOV DWORD PTR SS:[EBP-58],EAX ; START.004670A0
    0057D03A 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] ; START.00400000
    0057D03D 8945 90 MOV DWORD PTR SS:[EBP-70],EAX ; START.004670A0
    0057D040 8B45 0C MOV EAX,DWORD PTR SS:[EBP+C]
    0057D043 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX ; START.004670A0
    0057D046 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
    0057D049 8945 DC MOV DWORD PTR SS:[EBP-24],EAX ; START.004670A0
    0057D04C 8B45 14 MOV EAX,DWORD PTR SS:[EBP+14]
    0057D04F 8945 B4 MOV DWORD PTR SS:[EBP-4C],EAX ; START.004670A0
    0057D052 8B45 18 MOV EAX,DWORD PTR SS:[EBP+18] ; ntdll.7C910738
    0057D055 8945 D0 MOV DWORD PTR SS:[EBP-30],EAX ; START.004670A0
    0057D058 833D 2C736100 00 CMP DWORD PTR DS:[61732C],0
    0057D05F 75 09 JNZ SHORT START.0057D06A
    0057D061 833D 30736100 00 CMP DWORD PTR DS:[617330],0
    0057D068 74 18 JE SHORT START.0057D082
    0057D06A A1 28736100 MOV EAX,DWORD PTR DS:[617328]
    0057D06F 83E8 01 SUB EAX,1
    0057D072 A3 28736100 MOV DWORD PTR DS:[617328],EAX ; START.004670A0
    0057D077 833D 28736100 00 CMP DWORD PTR DS:[617328],0
    0057D07E 7F 02 JG SHORT START.0057D082
    0057D080 -FFE0 JMP EAX ; START.004670A0
    0057D082 8B45 04 MOV EAX,DWORD PTR SS:[EBP+4] ; START.0059C55E
    0057D085 8945 C8 MOV DWORD PTR SS:[EBP-38],EAX ; START.004670A0
    0057D088 60 PUSHAD
    0057D089 68 00AD6100 PUSH START.0061AD00
    0057D08E FF15 D0D66100 CALL DWORD PTR DS:[61D6D0] ; ntdll.RtlEnterCriticalSection
    0057D094 C745 A0 00000000 MOV DWORD PTR SS:[EBP-60],0
    0057D09B EB 09 JMP SHORT START.0057D0A6
    ...
    scroooooooolling down
    ...
    0057DD08 50 PUSH EAX ; START.004670A0
    0057DD09 8B4D D8 MOV ECX,DWORD PTR SS:[EBP-28] ; ntdll.7C910738
    0057DD0C 51 PUSH ECX
    0057DD0D E8 7EF2FFFF CALL START.0057CF90
    0057DD12 61 POPAD
    0057DD13 8B45 CC MOV EAX,DWORD PTR SS:[EBP-34] ; ntdll.7C97E4C0
    0057DD16 8BF0 MOV ESI,EAX ; START.004670A0
    0057DD18 8B06 MOV EAX,DWORD PTR DS:[ESI]
    0057DD1A 5F POP EDI ; 0012FFB0
    0057DD1B 5E POP ESI ; 0012FFB0
    0057DD1C 5B POP EBX ; 0012FFB0
    0057DD1D 8BE5 MOV ESP,EBP
    0057DD1F 5D POP EBP ; 0012FFB0
    0057DD20 -FFE0 JMP EAX ; Jump to import!!!
    0057DD22 6A 00 PUSH 0
    ...


    I'm not sure, but maybe there is some timer check inside. My target crushed on some exception after pausing olly, but if I just run it within Olly (after reaching OEP) it runs fine.

    Imports that are not redirected point to original IAT section:

    00497DB0 $-FF25 10844900 JMP DWORD PTR DS:[498410] ; comdlg32.GetOpenFileNameA

    We can see that IAT is filled with good imports:

    00498000 F0 6B DD 77 83 78 DD 77 1B 76 DD 77 49 6F DE 77 .k.w.x.w.v.wIo.w
    00498010 BB D5 DF 77 E7 EB DD 77 00 00 00 00 B9 45 F4 77 ...w...w.....E.w
    00498020 E4 68 F1 77 D5 5F F1 77 4B 4C F2 77 84 48 F4 77 .h.w._.wKL.w.H.w
    00498030 7C F7 F1 77 F7 47 F4 77 CB 4C F2 77 00 65 F2 77 |..w.G.w.L.w.e.w
    ...
    cut
    ...
    00498410 1E 31 3B 76 D8 7C 3C 76 CD 46 3D 76 00 00 00 00 .1;v.|<v.F=v....
    00498420 D3 85 52 77 C0 41 4F 77 09 60 52 77 E0 D1 52 77 ..Rw.AOw.`Rw..Rw
    00498430 68 20 4F 77 4C 20 4F 77 00 00 00 00 h OwL Ow....

    And that ordinals and names are not destroyed:

    004A0F30 A4 0F 0A 00 00 00 00 00 57 53 4F 43 4B 33 32 2E ........WSOCK32.
    004A0F40 64 6C 6C 00 0F 00 43 6F 43 72 65 61 74 65 49 6E dll...CoCreateIn
    004A0F50 73 74 61 6E 63 65 00 00 31 00 43 6F 49 6E 69 74 stance..1.CoInit
    004A0F60 69 61 6C 69 7A 65 00 00 59 00 43 6F 55 6E 69 6E ialize..Y.CoUnin
    004A0F70 69 74 69 61 6C 69 7A 65 00 00 1B 00 43 6F 46 72 itialize....CoFr
    004A0F80 65 65 55 6E 75 73 65 64 4C 69 62 72 61 72 69 65 eeUnusedLibrarie
    ...
    cut
    ...
    004A2030 00 00 9D 00 77 61 76 65 49 6E 43 6C 6F 73 65 00 ....waveInClose.
    004A2040 AB 00 77 61 76 65 49 6E 55 6E 70 72 65 70 61 72 ..waveInUnprepar
    004A2050 65 48 65 61 64 65 72 00 A8 00 77 61 76 65 49 6E eHeader...waveIn
    004A2060 52 65 73 65 74 00 57 49 4E 4D 4D 2E 64 6C 6C 00 Reset.WINMM.dll.

    Probably IMAGE_IMPORT_DESCRYPTORS are also untouched. That is very sloppy work by SecuROM because it makes easier IAT rebuilding. I wrote script that finds all calls to import algo , places EIP value there, runs, stops on JMP EAX, grabs import , search for that import in IAT, and then it change CALL destination to that import in IAT. But SecuROM maybe has some trick because target was crushing multiple times so I had to rebuild imports part-by-part. But After I have done with restoring calls, I dumped file to disk, then I used ImpREC to create new IAT. We could even repair IAT without ImpREC, but that would take more time. SecuROM uses WriteProcessMemory to write imports in IAT.





    4. Fixing dump

    After dumping and using ImpREC I double clicked on dumped file. Macromedia player window opened, but it just stud there without running stories. That is no wonder since macromedia files have overlay. Overlay is some extra data attached at the end of file. That data is not loaded in memory because that data is not registered in PE header as a part of last section. Overlay is usual thing with macromedia files. Since ImpREC created new last section, macromedia player cannot find overlay data (which is now before last section). To fix this problem we need just to attach overlay back at the end of file. How to do it? You calculate size of that overlay, then you use hex editor to copy and paste it at the end of file. Or you can just attach whole original file back to the end of dumped one. After I fixed overlay problem, I double clicked on dump and it worked just fine And wow, do you know how faster it runs without SecuROM layer ?!? Much faster because SecuROM must unpack temp files, load couple dlls, pass protection layer, pass that import algo, but searching and reading special data on CD is the slowest part.






    5. The End

    Btw, SecuROM has created couple DLL's in temp file. They are packed with PEtite except 16-bit file which is packed with PKLITE:

    CmdLineExt02.dll
    SIntf16.dll
    SIntf32.dll
    SIntfNT.dll

    In some versions this files can be found in windowssystem32 folder. Don't know purpose of these files (I didn't waste time on them).


    And that was my first SecuROM unpacking. It was not hard , I guess that newer versions are harder. The most interesting part of SecuROM should be that "unreadable" data on disc, but I needed to return CD so I just find the quickest way to remove protection.

  2. #62
    پروفشنال Morteza_SOS's Avatar
    تاريخ عضويت
    Apr 2006
    پست ها
    577

    پيش فرض

    Level : intermediate

    ~~~~~~~~~~~~~~~~~~~
    Bustme1 solution by haggar
    ~~~~~~~~~~~~~~~~~~~



    The goal of this crackme is to unpack it and then dig a serial for some name while keygen is optional. Solution consit from two parts - unpacking and reversing serial. Tools that I used are OllyDbg 1.10, ImpREC, LordPE, hex editor.



    [1] UNPACKING

    Crackme is packed with custom protector. Protector is based on two-process protection (self debugging) which makes it more dificult for unpacking with Ring3 debuggers such as Olly. Protected file has some bad values in PE header (Number Of Rva And Sizes, for example) which Olly cannot dygest. We cannot change those values because crackme becomes corupted. But that doesn't prevent debugging in olly. However, if you would like to have nice analysis, try to find OllyAdvanced plugin that fixes these bugs in Olly.

    Protector has few anti-debug tricks. It uses IsDebuggerPresent to detect debugger and BlockInput to block keyboard and mouse. Those are well known tricks (check Yoda Protectors tutorials on BIW reversing for more info about these tricks). But main protection is self-debugging.

    Protector debugs it's own process to prevent debugging from Ring3 debuggers. Detaching processes will not give solution because import accessing requires both processes. Unpacking can be separated in two parts; decrypting and import repairing.



    - Decrypting and dumping -

    Since this is a self-debugging based protection, processes must know which one is debugger and which one is debuggee. When we start process by double-click, that process must check is he a debuggee. There are warious techniques to accomplish this; command line arguments, mutex, etc. But this protector will use very simple solution. It will check does some string exist in it, if it does - that process is debuggee. If not, then it will start a new process and write that string in it. Second process will perform same check. For writing is used WriteProcessMemory that writes next string to 400002 (in PE header) of "son" process:

    ####INVIUS_L0RD_EXECUTABLE

    So to avoid self-debugging, we just have to write this string in our process loaded in Olly. However, altough there will be no double processes, crackme will create debugg loop and try to debug something. Debugging loop is in separate thread while main one enters in infinite jump EB FE. Why it that happening , I didn't tried to find out. All sections of crackme are decrypted except import section at 406000. That is enough for dumping. Dump is OK, it just needs fixing some PE info (sections sizes needs to be rounded on 1000 alignment). OEP is easy to find since we have MingWin compiled executable. OEP is at 401220.



    - Import repairing -

    This is little harder thing to sove. For that I had to examne protector's debug loop. Secondary process, a debuggee, has redirected all import jumps to allocated block. For example, if we detach processes and follow first import call at 40122D:

    0040122D FF15 5C614000 CALL DWORD PTR DS:[40615C]

    at the call destination (I removed junk jumps from pasted code):

    009B0268 50 PUSH EAX
    009B0269 52 PUSH EDX
    009B026A B8 860E9EEC MOV EAX,EC9E0E86 ; IMPORT_ID value.
    009B026F BA 875A3E00 MOV EDX,3E5A87 ; Address of IMPORT_ALGO
    009B0293 C3 RETN

    EAX holds IMPORT_ID value which is maybe some hash. Then it jumps to IMPORT_ALGO where some small calculations are performed and then HLT opcode is triggered that couses exception C0000096 (PRIVILEGED INSTRUCTION):

    003E5AD5 F4 HLT ; Privileged command

    That exception is caugth by debugger, ei. first process which now takes controll. If we examne debug loop of first process, we will see how this exception is handled:

    003E4C5D 813D 494D3E00 96>CMP DWORD PTR DS:[3E4D49],C0000096 ; Our exception code.
    003E4C67 74 31 JE SHORT 003E4C9A
    003E4C69 813D 494D3E00 04>CMP DWORD PTR DS:[3E4D49],80000004
    003E4C73 74 58 JE SHORT 003E4CCD
    003E4C75 813D 494D3E00 03>CMP DWORD PTR DS:[3E4D49],80000003
    003E4C7F 74 05 JE SHORT 003E4C86
    003E4C81 ^E9 DAFDFFFF JMP 003E4A60

    Protector then retrieves resgisters state of debugged process (via GetThreadContext) and reads some data from debuggee (ReadProcessMemory). With that data it decrypts apropriate strings (API ordinals and DLL names) in 406000 section, loads libraries, retrieves API address and uses SetThreadContext as a jump directly to API. Then it continues debug event.

    To retrieve imports, I wrote small script that plays with thread context buffer. After couple minutes and manually work, I placed all pointers in dumped file, then I loaded needed libraries in Olly (kernel32.dll, user32.dll, msvcrt.dll) and used ImpREC to rebuild IAT. Then I noticed that I still has some problems.



    - Runtime decryption-encryption -

    Protector has runtime decryption-encryption. For example, this part will decrypt 185 bytes starting from 00401C2D address:

    00401C08 $ 55 PUSH EBP
    00401C09 . 89E5 MOV EBP,ESP
    00401C0B . 83EC 78 SUB ESP,78
    00401C0E > 50 PUSH EAX
    00401C0F . 68 85010000 PUSH 185 ; Number of bytes to decrypt.
    00401C14 . 68 2D1C4000 PUSH bustme1.00401C2D ; Starting address.
    00401C19 . B8 00009B00 MOV EAX,9B0000 : Block where decryptor loop is placed.
    00401C1E . FFD0 CALL EAX
    00401C20 . 58 POP EAX

    There are about 20~30 this paterns. They doesn't have to be decrypted. We can place those decryptor loops in dump and change MOV EAX,009B0000 to new address , MOV EAX,0040xxxx. And dump will run fine. But it is better to decrypt all those parts and NOP all those opcodes. After decrypting, I removed last two sections and now I have nice and clean dump.





    [2] REVERSING KEYCHECK

    Keycheck is not hard , but I'm totally rusty. Check is performed in separate thread. Also, crackme goes to Sleep for a 500 miliseconds every little. Don't know why, maybe just to annoy us. Keycheck consist from two main parts.



    - First part -

    00401A7C |. 83F8 11 |CMP EAX,11 ; Serial must be 11h bytes long.
    00401A7F |. 75 25 |JNZ SHORT dump.00401AA6
    00401A81 |. C70424 9050400>|MOV DWORD PTR SS:[ESP],dump.00405090
    00401A88 |. E8 71F9FFFF |CALL dump.004013FE
    00401A8D |. 83F8 03 |CMP EAX,3 ; Name must have min 4 chars.
    00401A90 |. 76 14 |JBE SHORT dump.00401AA6
    00401A92 |. 803D 14514000 >|CMP BYTE PTR DS:[405114],2D ; Serial format is XXXX-XXX-XXXXXXXX
    00401A99 |. 75 0B |JNZ SHORT dump.00401AA6
    00401A9B |. 803D 18514000 >|CMP BYTE PTR DS:[405118],2D
    00401AA2 |. 75 02 |JNZ SHORT dump.00401AA6
    00401AA4 |. EB 14 |JMP SHORT dump.00401ABA

    Crackme will then take midlle part of serial (those 3 chars between "-") and INC/DEC them to create new three byte string "S1,S2,S3":

    S1 = 6._char + 2
    S2 = 7._char + 1
    S3 = 8._char - 2

    Then it creates 100h byte array and fills it with values 00,01,02,03,04,....,FD,FE,FF. This array is then changed with our new three byte string values. One string is taken:

    00BCFF8C 62 75 73 74 20 6D 65 20 23 31 20 2D 20 62 70 78 bust me #1 - bpx
    00BCFF9C 20 32 6B 36 FF EE CA 00 2k6....

    And it's hashed:

    00BCFF8C EC B7 72 DD B9 5A E9 90 B9 10 EA 3E D2 AD 60 28 ..r..Z.....>..`(
    00BCFF9C D2 F6 8D 23 D5 B2 CF 00 ...#....

    That hash is compared with hardcoded one:

    0040407F 94 D8 BE 56 20 7F AA 07 74 B3 EC D4 96 11 35 84 ...V ...t.....5.
    0040408F 11 CF 40 25 8F 59 15 00 ..@%.Y..

    If they match - first check is passed. This check depends only on 3 bytes from our serial, and it is actually hardcode part same for every name. I tought that it was too big job to rip all that code, and all in order to find out 3 bytes from serial. So I patched algo to loop untill it finds right 3 bytes that give correct hash. Three bytes that gives correct hash are

    9G7

    which gives new serial shape

    XXXX-9G7-XXXXXXXX




    - Second part -

    Second part of serial is harder to catch and this time I needed some brain usage. I'll start from end. We will see GoodBoy message if this loop gets EAX=3 as incoming parameter. In case of EAX=1, serial is bad, other values are possible bugs in crackme (judging by author comments):

    004012C3 |. 837D FC 01 CMP DWORD PTR SS:[EBP-4],1 ; BAD BOY!
    004012C7 |. 74 08 JE SHORT dump.004012D1
    004012C9 |. 837D FC 03 CMP DWORD PTR SS:[EBP-4],3 ; GOOD BOY!
    004012CD |. 74 2C JE SHORT dump.004012FB
    004012CF |. EB 54 JMP SHORT dump.00401325
    004012D1 |> C74424 0C 1000>MOV DWORD PTR SS:[ESP+C],10 ; |
    004012D9 |. C74424 08 0040>MOV DWORD PTR SS:[ESP+8],dump.00404000 ; |ASCII "Error"
    004012E1 |. C74424 04 0840>MOV DWORD PTR SS:[ESP+4],dump.00404008 ; |ASCII "Bad serial, you better fix this."
    004012E9 |. A1 14504000 MOV EAX,DWORD PTR DS:[405014] ; |
    004012EE |. 890424 MOV DWORD PTR SS:[ESP],EAX ; |
    004012F1 |. E8 7A170000 CALL <JMP.&user32.MessageBoxA> ; MessageBoxA
    004012F6 |. 83EC 10 SUB ESP,10
    004012F9 |. EB 5E JMP SHORT dump.00401359
    004012FB |> C74424 0C 4000>MOV DWORD PTR SS:[ESP+C],40 ; |
    00401303 |. C74424 08 2940>MOV DWORD PTR SS:[ESP+8],dump.00404029 ; |ASCII "Not an Error"
    0040130B |. C74424 04 3840>MOV DWORD PTR SS:[ESP+4],dump.00404038 ; |ASCII "Good serial, pat yourself on the back."
    00401313 |. A1 14504000 MOV EAX,DWORD PTR DS:[405014] ; |
    00401318 |. 890424 MOV DWORD PTR SS:[ESP],EAX ; |
    0040131B |. E8 50170000 CALL <JMP.&user32.MessageBoxA> ; MessageBoxA
    00401320 |. 83EC 10 SUB ESP,10
    00401323 |. EB 34 JMP SHORT dump.00401359
    00401325 |> C74424 0C 1000>MOV DWORD PTR SS:[ESP+C],10 ; |
    0040132D |. C74424 08 5F40>MOV DWORD PTR SS:[ESP+8],dump.0040405F ; |ASCII "Quitting"
    00401335 |. C74424 04 6840>MOV DWORD PTR SS:[ESP+4],dump.00404068 ; |ASCII "Shit, somthin's broken"
    0040133D |. A1 14504000 MOV EAX,DWORD PTR DS:[405014] ; |
    00401342 |. 890424 MOV DWORD PTR SS:[ESP],EAX ; |
    00401345 |. E8 26170000 CALL <JMP.&user32.MessageBoxA> ; MessageBoxA
    0040134A |. 83EC 10 SUB ESP,10
    0040134D |. C70424 0100000>MOV DWORD PTR SS:[ESP],1 ; |
    00401354 |. E8 B7160000 CALL <JMP.&msvcrt.exit> ; exit

    Let's see where EAX=3 is given:

    00401B8B |. E8 18FBFFFF |CALL dump.004016A8
    00401B90 |. 8945 D4 |MOV DWORD PTR SS:[EBP-2C],EAX
    00401B93 |. E8 66FDFFFF |CALL dump.004018FE ; This proc must return EAX=0.
    00401B98 |. 0105 10504000 |ADD DWORD PTR DS:[405010],EAX
    00401B9E |. 833D 10504000 >|CMP DWORD PTR DS:[405010],0 ; [00405010] must be 0 to pass check.
    00401BA5 |. 74 14 |JE SHORT dump.00401BBB ; GoodBoy jump is executed in that case.
    00401BA7 |. C74424 04 0A00>|MOV DWORD PTR SS:[ESP+4],0A
    00401BAF |. C70424 0100000>|MOV DWORD PTR SS:[ESP],1
    00401BB6 |. E8 D5F6FFFF |CALL dump.00401290
    00401BBB |> 833D 10504000 >|CMP DWORD PTR DS:[405010],0
    00401BC2 |. 75 16 |JNZ SHORT dump.00401BDA
    00401BC4 |. C74424 04 0000>|MOV DWORD PTR SS:[ESP+4],0
    00401BCC |. C70424 0300000>|MOV DWORD PTR SS:[ESP],3 ; EAX=3 will be passed here.
    00401BD3 |. E8 B8F6FFFF |CALL dump.00401290

    As it can be seen, EAX=3 if [00405010]=0, and that will be if CALL at 00401B93 returns EAX=0. So we must start from the end of that procedure. I will not paste code, but just reversed pseudo code:


    EAX = 0 <---- LAST CONDITION !
    0 = 69696969 SUB ((reg XOR 37) XOR 37) <-> reg=69696969
    70000390 = reg SUB 06969A27 <-> reg=70000390
    0000A954 = reg IMUL reg <-> reg=0000A954
    0000A955 = reg - 1 <-> reg=0000A955
    0000A955 = _lrotr reg , 1 <-> reg=000152AA
    000152AA = reg XOR 0B33F <-> reg=0001E195
    0001E195 = _lrotl reg , 3 <-> reg=A0003C32

    That was reversing from the end. _lrotl is ROL and reg represent DWORD value in register format (in memory bytes are swapped). Before that _lrotr is used on dword given from name hash and last part of serial. Procedure for name hash is at 004016A8. Procedure for serial hash is at 0040195C and it is not actually a hash. It is just characters formated to hex value (egxample "12345678" -> 12345678h). Those two hashes must give A0003C32 value to _lrorl.

    [78563412] shash1
    [78563412] shash2
    [00003B1F] nhash

    AND shash1,FFFF0000 -> [00003412]
    MOV EDX,shash1 -> 12340000
    XOR nhash,EDX -> [00000F0D]
    AND shash2,0000FFFF -> [78560000]
    mov EDX,shash2 -> 00005678
    ADD nhash,EDX -> [78560F0D]

    [78560F0D] -> 0D0F5678 -> This value must be A0003C32 to pass last check.

    And here is solution: We can take name hash as constant (nhash) and we need to find serial hash that will give needed DWORD. Since serial hash is nothing but last part of serial formated as hex DWORD, we can reverse it easily.

    0D0F(5678) -> Last four serial chars from false serial -> "5678"
    A000(3C32) -> True last four chars -> "3C32"

    XOR 1F3B0000,12340000 = 0D0F0000

    but it must be

    XOR 1F3B0000,xxxxxxxx = A0000000

    which gives

    BF3B0000

    and serial for my name is

    1234-9G7-BF3B3C32



    For the end I need to mention that name hash depends on firs four characters from serial too. I didn't botheredd to reverse that part too because keygen is optional, but it is not hard and generic keygen is easy to code.





    [3] THE END

  3. #63
    پروفشنال Morteza_SOS's Avatar
    تاريخ عضويت
    Apr 2006
    پست ها
    577

    پيش فرض

    حالا به سراغ یکی از پروتکتورهای قدرتمند به اسم SDProtector 1.12 می رویم !

  4. #64
    پروفشنال Morteza_SOS's Avatar
    تاريخ عضويت
    Apr 2006
    پست ها
    577

    پيش فرض

    شما برای کرک این پروتکتور به اسکریپت های زیر احتیاج دارید :

    اولین اسکریپت کاملا مشخصه کارش چیه عنوانش را پر رنگتر کردم :




    /*
    -------------------------------------------------------------
    SDProtector 1.12 - generic script for cleaning imports
    -------------------------------------------------------------
    */





    var x
    var y
    var addr
    var block
    var fixed
    mov fixed,0

    ask "Enter base address of block where IAT is redirected:"
    cmp $RESULT,0
    je done8
    mov block,$RESULT

    log "================================================= ======"
    log " "
    log " SDProtector 1.12 - script for fixing imports (haggar)"
    log " "
    log "================================================= ======"
    log " "
    log "Numbers of fixed patherns:"
    log " "



    mov addr,block
    pattern1:
    find addr,#5850609C680100000050B8????????50B8????????50 E8????????9D61740E750CFF35#
    cmp $RESULT,0
    je done1
    mov addr,$RESULT
    add $RESULT,11
    mov x,[$RESULT]
    sub x,addr
    sub x,5
    fill addr,1,E9
    add addr,1
    mov [addr],x
    add addr,4
    fill addr,2D,90
    inc fixed
    jmp pattern1


    done1:
    log "type 1:"
    log fixed


    mov addr,block
    mov fixed,0
    pattern2:
    find addr,#5850609C680400000050B8????????50B8????????50 E8????????9D61B8#
    cmp $RESULT,0
    je done2
    mov addr,$RESULT
    add $RESULT,1E
    mov x,[$RESULT]
    add $RESULT,6
    mov y,[$RESULT]
    xor x,y
    sub x,addr
    sub x,5
    fill addr,1,E9
    add addr,1
    mov [addr],x
    add addr,4
    fill addr,25,90
    inc fixed
    jmp pattern2


    done2:
    log "type 2:"
    log fixed


    mov addr,block
    mov fixed,0
    pattern3:
    find addr,#5850609C680200000050B8????????50B8????????50 E8????????9D#
    cmp $RESULT,0
    je done3
    mov addr,$RESULT
    add $RESULT,1E
    mov x,[$RESULT]
    add $RESULT,6
    mov y,[$RESULT]
    sub x,y
    sub x,addr
    sub x,5
    fill addr,1,E9
    add addr,1
    mov [addr],x
    add addr,4
    fill addr,25,90
    inc fixed
    jmp pattern3


    done3:
    log "type 3:"
    log fixed


    mov addr,block
    mov fixed,0
    pattern4:
    find addr,#5850609C680300000050B8????????50B8????????50 E8????????9D#
    cmp $RESULT,0
    je done4
    mov addr,$RESULT
    add $RESULT,1E
    mov x,[$RESULT]
    add $RESULT,6
    mov y,[$RESULT]
    add x,y
    sub x,addr
    sub x,5
    fill addr,1,E9
    add addr,1
    mov [addr],x
    add addr,4
    fill addr,25,90
    inc fixed
    jmp pattern4

    done4:
    log "type 4:"
    log fixed

    mov addr,block
    mov fixed,0
    pattern5:
    find addr,#B8????????9C35????????9D50C3#
    cmp $RESULT,0
    je done5
    mov addr,$RESULT
    fill $RESULT,1,0E9
    add $RESULT,1
    mov x,[$RESULT]
    add $RESULT,6
    mov y,[$RESULT]
    xor x,y
    sub $RESULT,6
    sub x,$RESULT
    sub x,4
    mov [$RESULT],x
    inc fixed
    jmp pattern5


    done5:
    log "type 5:"
    log fixed


    mov addr,block
    mov fixed,0
    pattern6:
    find addr,#B8????????9C05????????9DFFE0#
    cmp $RESULT,0
    je done6
    mov addr,$RESULT
    fill $RESULT,1,0E9
    add $RESULT,1
    mov x,[$RESULT]
    add $RESULT,6
    mov y,[$RESULT]
    add x,y
    sub $RESULT,6
    sub x,$RESULT
    sub x,4
    mov [$RESULT],x
    inc fixed
    jmp pattern6

    done6:
    log "type 6:"
    log fixed



    mov addr,block
    mov fixed,0
    pattern7:
    find addr,#740E750CFF35????????FF20F6094100B8????????FF E0#
    cmp $RESULT,0
    je done7
    mov addr,$RESULT
    fill $RESULT,10,90
    add $RESULT,10
    fill $RESULT,1,0E9
    add $RESULT,1
    mov x,[$RESULT]
    sub x,$RESULT
    sub x,4
    mov [$RESULT],x
    inc fixed
    jmp pattern7


    done7:
    log "type 7:"
    log fixed


    mov addr,block
    mov fixed,0
    pattern8:
    find addr,#B8????????9C2D????????9D50C3#
    cmp $RESULT,0
    je done8
    mov addr,$RESULT
    fill $RESULT,1,0E9
    add $RESULT,1
    mov x,[$RESULT]
    add $RESULT,6
    mov y,[$RESULT]
    sub x,y
    sub x,addr
    sub x,5
    add addr,1
    mov [addr],x
    inc fixed
    jmp pattern8


    done8:
    log "type 8:"
    log fixed
    log " "
    log "Now use ImpREC to repair dumped file."
    log " "
    log " - THE END -"
    ret

  5. #65
    پروفشنال Morteza_SOS's Avatar
    تاريخ عضويت
    Apr 2006
    پست ها
    577

    پيش فرض

    دومین اسکریپت :



    //SDPR 1.12 Pro - redirecting decryption calls

    var oep
    var addr
    var pointer
    var type

    mov oep,eip
    mov addr,401000



    LABEL_01:
    find addr,#E8??????FFEB11#
    cmp $RESULT,0
    je END_01
    mov addr,$RESULT

    add addr,1
    mov pointer,addr
    mov pointer,[pointer]
    add pointer,addr
    add pointer,4
    mov type,pointer
    add type,1
    mov type,[type]
    add type,pointer
    add type,5

    cmp type,518738
    je FIX_01
    cmp type,5185E1
    je FIX_01
    cmp type,5188D6
    je FIX_01
    cmp type,5187F4
    je FIX_01
    jmp LABEL_01

    FIX_01:
    sub type,addr
    sub type,4
    mov [addr],type
    jmp LABEL_01
    END_01:






    mov addr,401000

    LABEL_02:
    find addr,#E8??????FFEB11#
    cmp $RESULT,0
    je END_02
    mov addr,$RESULT

    add addr,1
    mov pointer,addr
    mov pointer,[pointer]
    add pointer,addr
    add pointer,4
    mov type,pointer
    add type,1
    mov type,[type]
    add type,pointer
    add type,5

    cmp type,14622E
    je FIX_02
    cmp type,146233
    je FIX_02
    cmp type,146238
    je FIX_02
    cmp type,14623D
    je FIX_02
    cmp type,146242
    je FIX_02
    cmp type,146247
    je FIX_02
    jmp LABEL_02

    FIX_02:

    mov pointer,type
    add pointer,1
    mov pointer,[pointer]
    add pointer,type
    add pointer,5
    sub pointer,addr
    sub pointer,4
    mov [addr],pointer

    jmp LABEL_02
    END_02:















    ret

  6. #66
    پروفشنال Morteza_SOS's Avatar
    تاريخ عضويت
    Apr 2006
    پست ها
    577

    پيش فرض

    سومین اسکریپت :




    //SDP 1.12 - runtime decryption

    var oep
    var addr
    var pointer
    var type

    mov oep,eip
    mov addr,401000



    LABEL_01: //Decrypt.
    find addr,#E8??????FFEB11#
    cmp $RESULT,0
    je END_01
    mov addr,$RESULT

    add addr,1
    mov pointer,addr
    mov pointer,[pointer]
    add pointer,addr
    add pointer,4
    mov type,pointer
    add type,1
    mov type,[type]
    add type,pointer
    add type,5
    cmp type,518738
    jne LABEL_01

    sub addr,1
    mov eip,addr
    add addr,5
    bp addr
    esto
    bc eip
    sub addr,5
    mov [addr],#909090909090909090909090909090909090909090909090 #
    jmp LABEL_01
    END_01:


    mov addr,401000
    LABEL_02: //Patch encryptor.
    find addr,#E8??????FFEB11#
    cmp $RESULT,0
    je END_02
    mov addr,$RESULT

    add addr,1
    mov pointer,addr
    mov pointer,[pointer]
    add pointer,addr
    add pointer,4
    mov type,pointer
    add type,1
    mov type,[type]
    add type,pointer
    add type,5
    cmp type,5185E1
    jne LABEL_02

    sub addr,1
    mov [addr],#909090909090909090909090909090909090909090909090 #
    jmp LABEL_02
    END_02:










    mov eip,oep





    ret

  7. #67
    پروفشنال Morteza_SOS's Avatar
    تاريخ عضويت
    Apr 2006
    پست ها
    577

    پيش فرض

    اسکریپت آخر :





    /*
    ---------------------------------------------------------
    SDProtector Pro 1.12 - OEP script for tutorial (haggar)
    ---------------------------------------------------------
    Script just finds stolen code.
    ---------------------------------------------------------
    */



    var SDP_base
    var GetVersion
    var CreateFile
    var IsDebugger
    var Snapshot
    var SystemInfo
    var Unhandled
    var GetTick
    var ModHandle


    mov SDP_base,eip

    gpa "GetVersion","kernel32.dll"
    mov GetVersion,$RESULT
    findop GetVersion,#c3#
    mov GetVersion,$RESULT

    gpa "CreateFileA","kernel32.dll"
    mov CreateFile,$RESULT
    findop CreateFile,#C21C00#
    mov CreateFile,$RESULT

    gpa "IsDebuggerPresent","kernel32.dll"
    mov IsDebugger,$RESULT
    findop IsDebugger,#c3#
    mov IsDebugger,$RESULT

    gpa "CreateToolhelp32Snapshot","kernel32.dll"
    mov Snapshot,$RESULT
    findop Snapshot,#c20800#
    mov Snapshot,$RESULT

    gpa "GetSystemInfo","kernel32.dll"
    mov SystemInfo,$RESULT
    findop SystemInfo,#C20400#
    mov SystemInfo,$RESULT

    gpa "UnhandledExceptionFilter","kernel32.dll"
    find $RESULT,#50FF15????????85C00f8C#
    mov Unhandled,$RESULT

    gpa "GetTickCount","kernel32.dll"
    mov GetTick,$RESULT
    findop GetTick,#C3#
    mov GetTick,$RESULT

    gpa "GetModuleHandleA","kernel32.dll"
    mov ModHandle,$RESULT
    findop ModHandle,#c20400#
    mov ModHandle,$RESULT




    //-------- To the ZwQueryInformationProcess,custom IsDebuggerPresent -------
    bp GetVersion
    esto
    esto
    esto
    esto
    mov eax,80000001
    bc eip


    //------------------------- Temporary file check --------------------------
    bp CreateFile
    esto
    bc eip
    sti
    find eip,#837C241C0C7376E8#
    bp $RESULT
    esto
    bc eip
    add eip,7d
    mov $RESULT,eip
    add $RESULT,32
    bp $RESULT
    esto
    bc eip
    mov edi,1234


    //--------------------- IsDebuggerPresent check ------------------------
    bp IsDebugger
    esto
    bc eip
    mov eax,0


    //--------------------- CreateToolhelp32Snapshot ------------------------
    bp Snapshot
    esto
    bc eip
    mov eax,0


    //---------------------- Kill Monitoring Threads ------------------------
    bp SystemInfo
    esto
    bc eip
    sti
    mov $RESULT,esp
    add $RESULT,24
    mov [$RESULT],0
    sti
    sti
    mov [$RESULT],1


    //------------------- UnhandledExceptionFilter trick --------------------
    bp Unhandled
    esto
    mov eax,0
    bc eip


    //--------------------- CreateFileA for drivers check -------------------
    bp CreateFile
    esto //First time it opens itself.
    esto
    bc eip
    sti
    add eip,0cc


    //----------------- GetTickCount initialization stuff -------------------
    bp GetTick
    esto
    mov eax,3
    mov edx,2
    mov esi,1
    esto
    mov eax,3
    mov edx,2
    mov esi,1
    sti
    sti
    sti
    sti
    sti
    sti
    sti
    sti
    sti
    sti
    sti
    mov eax,211
    esto
    mov eax,3
    mov edx,2
    mov esi,1
    bc eip


    //----------------- Registration, nag window , reg keys -------------------
    bp GetVersion
    esto
    esto
    bc eip
    rtr
    sti
    rtr


    //----------------------- Find stolen OEP code -----------------------------
    bp GetTick
    esto
    esto
    esto
    esto
    bc eip

    bp ModHandle
    esto
    esto
    bc eip
    sti

    find SDP_base,#58054BFFFFFF8038E90F85????FFFFC600E89D61 FFE0#
    add $RESULT,14
    bp $RESULT
    esto
    bc eip




    ret
    ret



















    بعد از این اسکریپت نحوه استفاده از این اسکریپت ها و آموزش کرک را می گذارم .

  8. #68
    پروفشنال Morteza_SOS's Avatar
    تاريخ عضويت
    Apr 2006
    پست ها
    577

    پيش فرض

    نحوه کرک و آموزش اسکریپت ها :



    SDProtector Pro 1.12 - anti debug reference






    SDProtector is nice protector with tons of anti-debug tricks. It is very hard to run protected target within debugger. This tutorial will try to show most of those tricks. Target is SDProtector Pro 1.12 itself. Tools that are used in this tutorial are usuall unpacking tools (PEiD, olly, ImpREC, LordPE, hex editor) but also, this tutorial requires that you have Windows XP operating system.




    1. EFLAG trick

    Imidiatley after you load target in olly, by scrolling down you will see first anti-debug trick. It is EFLAG trick. Protector pushes all flags into stack. There it tries to change T flag in stack:

    0050A06A 33C0 XOR EAX,EAX
    0050A06C 64:FF30 PUSH DWORD PTR FS:[EAX]
    0050A06F 64:8920 MOV DWORD PTR FS:[EAX],ESP <---- Installs local SEH.
    0050A072 9C PUSHFD <------------------------ Pushes flags to stack.
    0050A073 804C24 01 01 OR BYTE PTR SS:[ESP+1],1 <------ Tries to change flags. That couse exception.
    0050A078 9D POPFD
    0050A079 90 NOP
    0050A07A 90 NOP
    0050A07B C3 RETN


    It will try to change T flag. Now, that generates exception and protector local SEH (Structured Exception Handler) deals with that exception. Check stack and you will see where is local handler:

    0012FFB8 00000246
    0012FFBC /0012FFE0 Pointer to next SEH record
    0012FFC0 |0050A02F SE handler
    0012FFC4 |7C816D4F RETURN to kernel32.7C816D4F
    0012FFC8 |7C910738 ntdll.7C910738
    0012FFCC |FFFFFFFF
    0012FFD0 |7FFD5000
    0012FFD4 |8054B038
    0012FFD8 |0012FFC8
    0012FFDC |82C47BF0
    0012FFE0 \FFFFFFFF End of SEH chain

    Handler is at 0050A02F. Place bp there and run:


    0050A02F E8 01000000 CALL SDProtec.0050A035 <------------ Start of handler.
    0050A034 90 NOP <------------------------------- I NOP-ed this junk byte to see better.
    0050A035 58 POP EAX <--------------------------- CALL-POP is used to get current address.
    0050A036 05 53000000 ADD EAX,53 <------------------------ EAX will point to SEH uninstaller.
    0050A03B 51 PUSH ECX
    0050A03C 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10]
    0050A040 8981 B8000000 MOV DWORD PTR DS:[ECX+B8],EAX
    0050A046 B8 55010000 MOV EAX,155
    0050A04B 8941 20 MOV DWORD PTR DS:[ECX+20],EAX
    0050A04E 33C0 XOR EAX,EAX
    0050A050 8941 04 MOV DWORD PTR DS:[ECX+4],EAX
    0050A053 8941 08 MOV DWORD PTR DS:[ECX+8],EAX
    0050A056 8941 0C MOV DWORD PTR DS:[ECX+C],EAX
    0050A059 8941 10 MOV DWORD PTR DS:[ECX+10],EAX
    0050A05C 59 POP ECX
    0050A05D C3 RETN <------------------------------ Throws us to ntdll.dll.


    SEH will handle exception , then return to ntdll.dll, and ntdll.dll will throw us at return address:

    0050A087 64:8F00 POP DWORD PTR FS:[EAX]
    0050A08A 58 POP EAX



    This trick is to prevent tracing opcode-by-opcode. If somebody don't understand what is happening, he will trace trugh that exception. Since T flag will be changed in stack and then poped back by POPFD, T=1 will couse target to crush. If we change back T=0 after POPFD, it will not help because program flow goes in wrong way and again, target crushes. So we need to let protector local SEH to handle it.






    2. SEH chain

    I don't know is this a trick, but SDP messes little with SEH's:

    0050A5F3 50 PUSH EAX
    0050A5F4 83EC 08 SUB ESP,8
    0050A5F7 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
    0050A5FD 64:FF35 00000000 PUSH DWORD PTR FS:[0]
    0050A604 64:8925 00000000 MOV DWORD PTR FS:[0],ESP
    0050A60B 83C4 08 ADD ESP,8
    0050A60E 50 PUSH EAX
    0050A60F 64:FF35 00000000 PUSH DWORD PTR FS:[0]
    0050A616 64:8925 00000000 MOV DWORD PTR FS:[0],ESP
    0050A61D 64:8F05 00000000 POP DWORD PTR FS:[0]
    0050A624 64:A3 00000000 MOV DWORD PTR FS:[0],EAX
    0050A62A 83C4 08 ADD ESP,8
    0050A62D 58 POP EAX
    0050A62E B8 00000000 MOV EAX,0
    0050A633 50 PUSH EAX
    0050A634 E8 01000000 CALL SDProtec.0050A63A


    I sad that I don't know purpose of this because it does not harm to our debugging. Olly has some problems in case of recursive SEH chains. That means, if application installs more than one local (nested inside other) SEH, olly complains. It can desturb our debugging in some cases , as I noticed in some other protectors.






    3. INT3 and RDTSC trick


    Eventually we will came to next trick. Protector installs local SEH and then couse INT3 exception:

    0050F7E1 64:FF30 PUSH DWORD PTR FS:[EAX]
    0050F7E4 64:8920 MOV DWORD PTR FS:[EAX],ESP <-------- Installs SEH.
    0050F7E7 BD D3F10E30 MOV EBP,300EF1D3
    0050F7EC 81C5 78563412 ADD EBP,12345678
    0050F7F2 66:B8 1700 MOV AX,17
    0050F7F6 66:83E8 13 SUB AX,13
    0050F7FA CC INT3 <------------------------------ Make exception.
    0050F7FB 90 NOP
    0050F7FC 3C 04 CMP AL,4
    0050F7FE 74 32 JE SHORT SDProtec.0050F832
    0050F800 74 03 JE SHORT SDProtec.0050F805
    0050F802 75 01 JNZ SHORT SDProtec.0050F805


    In stack we see where handler is and we go there:

    0050F894 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
    0050F898 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C]
    0050F89C FF81 B8000000 INC DWORD PTR DS:[ECX+B8]
    0050F8A2 8B00 MOV EAX,DWORD PTR DS:[EAX]
    0050F8A4 2D 03000080 SUB EAX,80000003 <------------------ It checks is it INT3 exception.
    0050F8A9 75 0E JNZ SHORT SDProtec.0050F8B9 <------- If not, just crush.
    0050F8AB 33C0 XOR EAX,EAX
    0050F8AD 8941 04 MOV DWORD PTR DS:[ECX+4],EAX
    0050F8B0 8941 08 MOV DWORD PTR DS:[ECX+8],EAX
    0050F8B3 8941 0C MOV DWORD PTR DS:[ECX+C],EAX
    0050F8B6 8941 10 MOV DWORD PTR DS:[ECX+10],EAX
    0050F8B9 C3 RETN <------------------------------ Jump to ntdll.dll.


    Ntdll.dll returns us back to code. Here is whole snippet, junk is NOP-ed. Read comments:

    0050F7FA CC INT3
    0050F7FB 90 NOP <------------------------------- It returns here!
    0050F7FC 3C 04 CMP AL,4 <-------------------------- If EAX=4, then OK (exception was handled).
    0050F7FE 74 32 JE SHORT SDProtec.0050F832 <-------- Good jump.
    0050F800 74 03 JE SHORT SDProtec.0050F805 <-------- If EAX<>4, we are detected.
    0050F802 75 01 JNZ SHORT SDProtec.0050F805
    0050F804 90 NOP
    0050F805 E8 01000000 CALL SDProtec.0050F80B
    0050F80A FF58 05 CALL FAR FWORD PTR DS:[EAX+5]
    0050F80D 27 DAA
    0050F80E 0000 ADD BYTE PTR DS:[EAX],AL
    0050F810 008B D083C232 ADD BYTE PTR DS:[EBX+32C283D0],CL
    0050F816 E8 9D060000 CALL SDProtec.0050FEB8
    0050F81B EB 01 JMP SHORT SDProtec.0050F81E
    0050F81D FFE8 JMP FAR EAX
    0050F81F 0100 ADD DWORD PTR DS:[EAX],EAX
    0050F821 0000 ADD BYTE PTR DS:[EAX],AL
    0050F823 FF58 05 CALL FAR FWORD PTR DS:[EAX+5]
    0050F826 0E PUSH CS
    0050F827 0000 ADD BYTE PTR DS:[EAX],AL
    0050F829 0050 E9 ADD BYTE PTR DS:[EAX-17],DL
    0050F82C 3F AAS
    0050F82D 3F AAS
    0050F82E 0000 ADD BYTE PTR DS:[EAX],AL
    0050F830 FFE8 JMP FAR EAX
    0050F832 64:8F05 00000000 POP DWORD PTR FS:[0] <-------------- Good jump throw us here. Uninstall SEH.
    0050F839 83C4 04 ADD ESP,4
    0050F83C 0F31 RDTSC <----------------------------- Timer value is given to EAX:EDX.
    0050F83E 8BC8 MOV ECX,EAX <----------------------- Then saved to EXC:EBX.
    0050F840 8BDA MOV EBX,EDX
    0050F842 7E 06 JLE SHORT SDProtec.0050F84A
    0050F844 7F 04 JG SHORT SDProtec.0050F84A
    0050F846 0010 ADD BYTE PTR DS:[EAX],DL
    0050F848 40 INC EAX
    0050F849 90 NOP
    0050F84A 50 PUSH EAX
    0050F84B 9C PUSHFD
    0050F84C 51 PUSH ECX
    0050F84D 33C9 XOR ECX,ECX
    0050F84F 67:E3 05 JCXZ SHORT SDProtec.0050F857
    0050F852 0010 ADD BYTE PTR DS:[EAX],DL
    0050F854 40 INC EAX
    0050F855 00E8 ADD AL,CH
    0050F857 59 POP ECX
    0050F858 E8 04000000 CALL SDProtec.0050F861
    0050F85D 90 NOP
    0050F85E 90 NOP
    0050F85F 90 NOP
    0050F860 90 NOP
    0050F861 58 POP EAX
    0050F862 EB 02 JMP SHORT SDProtec.0050F866
    0050F864 90 NOP
    0050F865 90 NOP
    0050F866 83C0 02 ADD EAX,2
    0050F869 EB 01 JMP SHORT SDProtec.0050F86C
    0050F86B 90 NOP
    0050F86C 50 PUSH EAX
    0050F86D C3 RETN
    0050F86E 90 NOP
    0050F86F 9D POPFD
    0050F870 58 POP EAX
    0050F871 0F31 RDTSC <----------------------------- Tracing brings us here! New timer value.
    0050F873 2BC1 SUB EAX,ECX <----------------------- Here it substract old timer value and new.
    0050F875 1BD3 SBB EDX,EBX
    0050F877 83FA 00 CMP EDX,0 <------------------------- Check EDX difference.
    0050F87A ^75 84 JNZ SHORT SDProtec.0050F800 <------- If it exist, we are detected.
    0050F87C 3D 00000060 CMP EAX,60000000 <------------------ Again, check difference in EAX.
    0050F881 ^0F87 79FFFFFF JA SDProtec.0050F800 <-------------- Bad jump again.
    0050F887 74 31 JE SHORT SDProtec.0050F8BA <-------- These are good jumps.
    0050F889 75 2F JNZ SHORT SDProtec.0050F8BA


    And that was first type of INT3-RDTSC check. This check will occure couple times. Comments describe what happens , so we know what to do. Let SEH handles exception and be carefull about RDTSC bad jumps. Here INT3 actually didn't affect RDTSC timing, but there is couple variations of INT3-RDTSC checks.






    4. Checking breakpoints on imports

    It checks breakpoints on imports:

    00519A8C 58 POP EAX
    00519A8D 05 A4040000 ADD EAX,4A4
    00519A92 8B00 MOV EAX,DWORD PTR DS:[EAX]
    00519A94 8038 CC CMP BYTE PTR DS:[EAX],0CC <------- Check first byte on API.
    00519A97 74 0A JE SHORT SDProtec.00519AA3 <------ Bad jump!
    00519A99 50 PUSH EAX ; kernel32.LoadLibraryA
    00519A9A C3 RETN <---------------------------- Jump to import if OK.

    Often used and almost all API's are checked like this.






    5. Custom GetProcAddress function

    SDProtector has custom GetProcAddress function to retrieve API's:

    00513788 53 PUSH EBX
    00513789 55 PUSH EBP
    0051378A 8B6C24 10 MOV EBP,DWORD PTR SS:[ESP+10]
    0051378E 56 PUSH ESI
    0051378F 57 PUSH EDI ; ntdll.7C910738
    00513790 8B7C24 14 MOV EDI,DWORD PTR SS:[ESP+14]
    ...
    ...[cut]...
    ...
    00513829 77 07 JA SHORT SDProtec.00513832
    0051382B 55 PUSH EBP
    0051382C 57 PUSH EDI ; ntdll.7C910738
    0051382D E8 C4610000 CALL SDProtec.005199F6
    00513832 5F POP EDI ; SDProtec.00516D80
    00513833 5E POP ESI ; SDProtec.00516D80
    00513834 5D POP EBP ; SDProtec.00516D80
    00513835 5B POP EBX ; SDProtec.00516D80
    00513836 C2 0800 RETN 8






    6. Integrity checks , detecting breakpoints in code

    SDProtector has couple integrity checks. These check everything and they can detect breakpoints:

    00513AFE > 83EC 68 SUB ESP,68
    00513B01 53 PUSH EBX
    00513B02 56 PUSH ESI
    00513B03 57 PUSH EDI
    00513B04 E8 B5B8FFFF CALL SDProtec.0050F3BE
    00513B09 6A 00 PUSH 0
    00513B0B 8BF8 MOV EDI,EAX
    00513B0D E8 C05E0000 CALL <SDProtec.API_BP_CHECK_2>
    00513B12 50 PUSH EAX
    00513B13 E8 9DC6FFFF CALL SDProtec.005101B5
    00513B18 E8 A1B8FFFF CALL SDProtec.0050F3BE
    00513B1D 8BF0 MOV ESI,EAX
    00513B1F 81EE 00010000 SUB ESI,100
    00513B25 E8 B5C0FFFF CALL SDProtec.0050FBDF
    00513B2A 8BD8 MOV EBX,EAX
    00513B2C 8D4424 1C LEA EAX,DWORD PTR SS:[ESP+1C]
    00513B30 50 PUSH EAX
    00513B31 E8 B6C7FFFF CALL <SDProtec.INIT_CONST_1>
    00513B36 68 00010000 PUSH 100
    00513B3B 8D4C24 24 LEA ECX,DWORD PTR SS:[ESP+24]
    00513B3F 56 PUSH ESI
    00513B40 51 PUSH ECX
    00513B41 E8 CEC7FFFF CALL SDProtec.00510314
    00513B46 81C3 B8FBFFFF ADD EBX,-448
    00513B4C 81C6 48040000 ADD ESI,448
    00513B52 53 PUSH EBX
    00513B53 8D5424 30 LEA EDX,DWORD PTR SS:[ESP+30]
    00513B57 56 PUSH ESI
    00513B58 52 PUSH EDX
    00513B59 E8 B6C7FFFF CALL SDProtec.00510314
    00513B5E 8D4424 38 LEA EAX,DWORD PTR SS:[ESP+38]
    00513B62 8D4C24 28 LEA ECX,DWORD PTR SS:[ESP+28]
    00513B66 50 PUSH EAX
    00513B67 51 PUSH ECX
    00513B68 E8 4BC8FFFF CALL SDProtec.005103B8
    00513B6D 83C4 24 ADD ESP,24
    00513B70 83C7 60 ADD EDI,60
    00513B73 8D5424 0C LEA EDX,DWORD PTR SS:[ESP+C]
    00513B77 6A 10 PUSH 10
    00513B79 57 PUSH EDI
    00513B7A 52 PUSH EDX
    00513B7B E8 62D0FFFF CALL SDProtec.00510BE2
    00513B80 5F POP EDI
    00513B81 5E POP ESI
    00513B82 85C0 TEST EAX,EAX <----------------- EAX must be 0.
    00513B84 5B POP EBX
    00513B85 74 0A JE SHORT SDProtec.00513B91 <--- Good jump.
    00513B87 E8 43B8FFFF CALL SDProtec.0050F3CF
    00513B8C E8 DEFBFFFF CALL SDProtec.0051376F
    00513B91 B8 01000000 MOV EAX,1
    00513B96 83C4 68 ADD ESP,68
    00513B99 C3 RETN


    If we search for all references on first opcode in snippet, we will see that this part is called couple times at least.


    Now, here is very annoying and good trick against Olly. Check what Olly (in Olly help file) says about tracing:


    Use hardware breakpoints to step or trace code
    If you step or trace executable code, OllyDbg attempts to use single-step trap. In some cases, for example, if you asked to step over the call to subroutine, or execute string command at once, or run your program till selection, OllyDbg must set temporary breakpoint. Normally it uses command INT3. When OS supports hardware breakpoints, this option is active and there is at least one free hardware breakpoint, OllyDbg sets temporary hardware breakpoint. As inter-process memory access is very time-consuming, hardware breakpoints may accelerate run trace by as much as 20% (trace over). Notice that hardware breakpoints are non-destructive, i.e. don't change the contents of the memory. This feature was proposed by kab.


    Olly , when tracing over calls, sets temporary breakpoint (INT3=CC) after the call. So SDProtector's checksum algorithm detects our tracing even we tought that we didn't set breakpoint. Simply, that temporary breakpoint will corrupt checksum. Lucky for us, Olly gives good solution for this problem because instead of placing INT3, Olly can use hardware breakpoint.

    You can set this option in:

    Olly menu --> "Options" --> "Debugging options" --> "Debug" --> "Use hardware breakpoints to step or trace code"

    An we will not be detected.

    But maybe now we have side afect. Since SDProtector uses exceptions to detect hardware breakpoint, maybe this will be the problem. Another solution is, that you label checksum procedure, then when you see that you are entering in it, you just place hw breakpoint on good jump. Then you remove that hw bp.








    7. Three interesting API's

    After retrieving couple API's that SDP needs for work, it will then call GetVersion to retrieve some system information. SDP will actually check version of our OS to see if it's supports three API's. If check gives positive result, it will then collect those API's. Those three API's are:

    ZwQueryInformationProcess
    ZwQuerySystemInformation
    ZwSetInformationThread


    Those are very powerfull API's. We will see later how SDP will use them. Below is snippet of that code. Read comments:


    00517670 8B8424 4C040000 MOV EAX,DWORD PTR SS:[ESP+44C] <-------- Interesting check.
    00517677 85C0 TEST EAX,EAX <-------------------------- Some test.
    00517679 0F85 8B000000 JNZ SDProtec.0051770A <----------------- Skip these APIs.
    0051767F E8 7A210000 CALL <SDProtec.IMPORT_GetVersion> <----- GetVersion.
    00517684 3D 00000080 CMP EAX,80000000
    00517689 73 7F JNB SHORT SDProtec.0051770A <----------- Skip these APIs.
    0051768B 85DB TEST EBX,EBX
    0051768D 74 7B JE SHORT SDProtec.0051770A <------------ Skip these APIs.
    0051768F 68 0CDD4000 PUSH SDProtec.0040DD0C
    00517694 E8 0C7DFFFF CALL <SDProtec.API-DLL_STRING>
    00517699 50 PUSH EAX
    0051769A 68 6CB34000 PUSH SDProtec.0040B36C
    0051769F E8 017DFFFF CALL <SDProtec.API-DLL_STRING>
    005176A4 50 PUSH EAX
    005176A5 E8 DC230000 CALL <SDProtec.API_BP_CHECK_1>
    005176AA 50 PUSH EAX
    005176AB E8 D8C0FFFF CALL <SDProtec.GET_PROC_ADDR_1>
    005176B0 85C0 TEST EAX,EAX
    005176B2 74 05 JE SHORT SDProtec.005176B9
    005176B4 8903 MOV DWORD PTR DS:[EBX],EAX
    005176B6 83C3 04 ADD EBX,4
    005176B9 68 26DD4000 PUSH SDProtec.0040DD26
    005176BE E8 E27CFFFF CALL <SDProtec.API-DLL_STRING>
    005176C3 50 PUSH EAX
    005176C4 68 6CB34000 PUSH SDProtec.0040B36C
    005176C9 E8 D77CFFFF CALL <SDProtec.API-DLL_STRING>
    005176CE 50 PUSH EAX
    005176CF E8 B2230000 CALL <SDProtec.API_BP_CHECK_1>
    005176D4 50 PUSH EAX
    005176D5 E8 AEC0FFFF CALL <SDProtec.GET_PROC_ADDR_1>
    005176DA 85C0 TEST EAX,EAX
    005176DC 74 05 JE SHORT SDProtec.005176E3
    005176DE 8903 MOV DWORD PTR DS:[EBX],EAX
    005176E0 83C3 04 ADD EBX,4
    005176E3 68 1BC24000 PUSH SDProtec.0040C21B
    005176E8 E8 B87CFFFF CALL <SDProtec.API-DLL_STRING>
    005176ED 50 PUSH EAX
    005176EE 68 6CB34000 PUSH SDProtec.0040B36C
    005176F3 E8 AD7CFFFF CALL <SDProtec.API-DLL_STRING>
    005176F8 50 PUSH EAX
    005176F9 E8 88230000 CALL <SDProtec.API_BP_CHECK_1>
    005176FE 50 PUSH EAX
    005176FF E8 84C0FFFF CALL <SDProtec.GET_PROC_ADDR_1>
    00517704 85C0 TEST EAX,EAX
    00517706 74 02 JE SHORT SDProtec.0051770A
    00517708 8903 MOV DWORD PTR DS:[EBX],EAX
    0051770A 5F POP EDI ; ntdll.7C910738
    0051770B 5E POP ESI ; ntdll.7C910738
    0051770C 5D POP EBP ; ntdll.7C910738
    0051770D B8 01000000 MOV EAX,1
    00517712 5B POP EBX ; ntdll.7C910738
    00517713 81C4 38040000 ADD ESP,438
    00517719 C2 0400 RETN 4

    As you can see, there are three checks and , in case that one fails, these API's will not be retrieved. This means that we can avoid that part of protection by just skipping this whole procedure.






    8. SMC trick (trick with Self Modifying Code)

    This is very interesting trick against tracing trough code. Check this code:

    0050A807 F3:66:A5 REP MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI] <---- I'm here!
    0050A80A E8 45000000 CALL SDProtec.0050A854
    0050A80F E8 79000000 CALL SDProtec.0050A88D
    0050A814 E8 00104000 CALL 0090B819

    ECX=00000003 (decimal 3.)
    DS:[ESI]=[0050A81D]=01EB
    ES:[EDI]=[0050A807]=66F3


    Check carefull and you will see that this line of code modyfies itself. When you trace with F7 , it changes opcode to:

    0050A807 EB 01 JMP SHORT SDProtec.0050A80A <---------------------- Same line!
    0050A809 A5 MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
    0050A80A E8 45000000 CALL SDProtec.0050A854 <--------------------------- Then you jump here!
    0050A80F E8 79000000 CALL SDProtec.0050A88D
    0050A814 E8 00104000 CALL 0090B819


    It will change itself to jump. And that new jump leads to "Debugger detected" message! But if we place new origin at 50A809 line, it will again change that line to:

    0050A807 EB 01 JMP SHORT SDProtec.0050A80A
    0050A809 90 NOP
    0050A80A EB 03 JMP SHORT SDProtec.0050A80F <------------------ Here! New code.
    0050A80C 90 NOP
    0050A80D 0000 ADD BYTE PTR DS:[EAX],AL
    0050A80F E8 79000000 CALL SDProtec.0050A88D <----------------------- And jumps here then!
    0050A814 E8 00104000 CALL 0090B819


    It will change same line to jump. But this jump jumps at second call , and that call is good one! Conclusion is, that if we trace with F7, we will stuck. But if we place bp on second call and run, we will pass this trick.

    It is very interesting. I'm wonder how guy discovered it.

    This trick will be used couple times more.






    9. RDTSC - INT3 - CALL/JMP check

    Here is similar trick that is described before. This time protector will first trigger RDTSC to get timer value and save it. Then it will trigger INT3 exception. After exception is handled, it will trigger another RDTSC opcode to retrieve new value. Then it compare difference. This time protector placed INT3 inside RDTSC pairs. So if somebody stuck on exception and then tries to pass it , timer check will detect him. It also has CALL-JMP check. Here is code:


    0050A8A0 0F31 RDTSC <---------------------------- 1. Get timer value, then save it in stack.
    0050A8A2 50 PUSH EAX
    0050A8A3 52 PUSH EDX
    ...
    ...
    0050A904 CC INT3 <----------------------------- 2. Generate exception.
    0050A905 90 NOP <------------------------------ 9. Return after ntdll.dll.
    0050A906 3C 04 CMP AL,4
    0050A908 74 3A JE SHORT SDProtec.0050A944 <------- 10. Good jump (exception is handled).
    0050A90A 74 03 JE SHORT SDProtec.0050A90F <------- 11. Bad jumps.
    0050A90C 75 01 JNZ SHORT SDProtec.0050A90F
    0050A90E 90 NOP <------------------------------ I NOP-ed byte to clear junk.
    0050A90F E8 01000000 CALL SDProtec.0050A915
    ...
    ...
    0050A944 64:8F05 00000000 POP DWORD PTR FS:[0] <------------- 12. Uninstall local handler.
    0050A94B 83C4 04 ADD ESP,4
    0050A94E E8 01000000 CALL SDProtec.0050A954
    0050A953 90 NOP <------------------------------ I NOP-ed byte to clear junk.
    0050A954 58 POP EAX
    0050A955 05 C1FEFFFF ADD EAX,-13F
    0050A95A 8038 E9 CMP BYTE PTR DS:[EAX],0E9 <-------- 13. Again this CALL-JMP check.
    0050A95D ^75 AB JNZ SHORT SDProtec.0050A90A <------ 14. Bad jump.
    0050A95F C600 E8 MOV BYTE PTR DS:[EAX],0E8
    0050A962 5B POP EBX
    0050A963 59 POP ECX
    0050A964 0F31 RDTSC <---------------------------- 15. Get timer value.
    0050A966 2BC1 SUB EAX,ECX
    0050A968 1BD3 SBB EDX,EBX
    0050A96A 83FA 00 CMP EDX,0
    0050A96D ^75 9B JNZ SHORT SDProtec.0050A90A
    0050A96F 3D 00000080 CMP EAX,80000000
    0050A974 ^77 94 JA SHORT SDProtec.0050A90A
    0050A976 74 49 JE SHORT SDProtec.0050A9C1
    0050A978 75 47 JNZ SHORT SDProtec.0050A9C1
    0050A97A E8 00104000 CALL 0090B97F
    0050A97F B0 89 MOV AL,89
    0050A981 9C PUSHFD
    0050A982 04 8B ADD AL,8B
    0050A984 44 INC ESP
    0050A985 24 04 AND AL,4
    0050A987 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C]
    0050A98B FF81 B8000000 INC DWORD PTR DS:[ECX+B8]
    0050A991 8B00 MOV EAX,DWORD PTR DS:[EAX]
    0050A993 2D 03000080 SUB EAX,80000003
    0050A998 75 26 JNZ SHORT SDProtec.0050A9C0
    0050A99A E8 01000000 CALL SDProtec.0050A9A0
    0050A99F FF58 05 CALL FAR FWORD PTR DS:[EAX+5] ; Far call
    ...
    ...
    0050A983 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4] <----- 3. Handle it here.
    0050A987 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C]
    0050A98B FF81 B8000000 INC DWORD PTR DS:[ECX+B8]
    0050A991 8B00 MOV EAX,DWORD PTR DS:[EAX]
    0050A993 2D 03000080 SUB EAX,80000003 <----------------- 4. Exception type check.
    0050A998 75 26 JNZ SHORT SDProtec.0050A9C0 <------ 5. Bad jump.
    0050A99A E8 01000000 CALL SDProtec.0050A9A0
    0050A99F 90 NOP <------------------------------ I NOP-ed byte to clear junk.
    0050A9A0 58 POP EAX
    0050A9A1 05 75FEFFFF ADD EAX,-18B
    0050A9A6 8038 E8 CMP BYTE PTR DS:[EAX],0E8 <-------- 6. CALL-JMP check.
    0050A9A9 ^0F85 5BFFFFFF JNZ SDProtec.0050A90A <------------ 7. Bad jump.
    0050A9AF C600 E9 MOV BYTE PTR DS:[EAX],0E9
    0050A9B2 33C0 XOR EAX,EAX
    0050A9B4 8941 04 MOV DWORD PTR DS:[ECX+4],EAX
    0050A9B7 8941 08 MOV DWORD PTR DS:[ECX+8],EAX
    0050A9BA 8941 0C MOV DWORD PTR DS:[ECX+C],EAX
    0050A9BD 8941 10 MOV DWORD PTR DS:[ECX+10],EAX
    0050A9C0 C3 RETN <----------------------------- 8. Return to ntdll.dll.


    That CALL-JMP check is interesting , but I didn't examne it better. It probably crush target if we somehow pass/nop exception.






    10. GetTickCount - INT3 check

    SDProtector also uses GetTickCount API to perform similar time check like with RDTSC. GetTickCount returns to EAX and EDX some timer value.

    It calls GetTickCount first time, then is saves that EAX value o memory:

    0050AB84 8902 MOV DWORD PTR DS:[EDX],EAX ;Let's set EAX=1 and EDX to 2.


    Then it calls second GetTickCount and pushes EAX and EDX values to stack:

    0050AA19 50 PUSH EAX ;Let's set it to EAX=3.
    0050AA1A 8BC2 MOV EAX,EDX ;And EDX=4.
    0050AA1C 50 PUSH EAX


    Then after little tracing trough code, it calls third time GetTickCount. Let's set EAX=5 and EDX=6. Then it pops previous value (3) to EBX and checks difference:

    0050AA4B 5B POP EBX ;EBX=3
    0050AA4C 81C3 F4010000 ADD EBX,1F4
    0050AA52 2BD8 SUB EBX,EAX ;EBX=(3+1F4)-5
    0050AA54 78 42 JS SHORT SDProtec.0050AA98 ;If diffrence is too big, then jump to error message.




    That was second GetTickCount check which is nested in first one. Now, protector will generate INT3 exception:

    0050AB4E CC INT3 <------------------------------------ 1. Exception.
    0050AB4F 90 NOP
    0050AB50 33C0 XOR EAX,EAX
    0050AB52 C700 521C4000 MOV DWORD PTR DS:[EAX],SDProtec.00401C52
    0050AB58 7A 0A JPE SHORT SDProtec.0050AB64
    0050AB5A 7B 08 JPO SHORT SDProtec.0050AB64
    ...
    ...
    0050ABDF 8B6424 08 MOV ESP,DWORD PTR SS:[ESP+8] <------------ 2. SEH.
    0050ABE3 64:8F05 00000000 POP DWORD PTR FS:[0]
    ...
    ...
    0050ABF0 58 POP EAX
    0050ABF1 05 0E000000 ADD EAX,0E
    0050ABF6 50 PUSH EAX
    0050ABF7 E9 42EE0000 JMP <SDProtec.TICK_COUNT_1> <-------------- 3. Then jump to fourth GetTickCount.
    0050ABFC FFE8 JMP FAR EAX
    ...
    ...
    0050AC03 5A POP EDX
    0050AC04 81C2 78FBFFFF ADD EDX,-488
    0050AC0A 8B0A MOV ECX,DWORD PTR DS:[EDX]
    0050AC0C 83F9 00 CMP ECX,0 <---------------------- It checks first EAX=1 is it 0!
    0050AC0F ^74 95 JE SHORT SDProtec.0050ABA6 <----- Bad jump!
    0050AC11 2BC1 SUB EAX,ECX <-------------------- Then checks difference from first EAX=1 and second EAX=7.
    0050AC13 ^78 91 JS SHORT SDProtec.0050ABA6 <----- Bad jump!
    0050AC15 2D D0070000 SUB EAX,7D0 <-------------------- Same range check.
    0050AC1A ^79 8A JNS SHORT SDProtec.0050ABA6 <---- Bad jump!
    0050AC1C B8 7612800E MOV EAX,0E801276
    0050AC21 8902 MOV DWORD PTR DS:[EDX],EAX
    0050AC23 E8 01000000 CALL SDProtec.0050AC29


    So not only that this check will check is difference between first GetTickCount and fourth GetTickCount inside 7D0 range, but it will also check did first GetTickCount returned 0! So if we patch GetTickCount API, or we use some tool or plugin to fool GetTickCount, it will detect that and exit.


    The easiest way to kill this check is to set GetTickCount to return EAX=1 and EDX=0. Simply, we can patch first opcodes of that API, but even that isn't needed. We can just place bp at the end of API and run fast 4 times. And all previous checks will be avoided.






    11. GetProcessTimes - GetSystemTimeAsFileTime check

    This is new time check and it is performed only once. SDProtector first calls GetTickCount. It will nest new check inside GetTickCount one. Then it calls GetVersion to check something. If system doesnt match, this bew check is just skipped. So we can just skip this check by executing one jump. But letc see how it goes:

    00517B79 E8 C01E0000 CALL <SDProtec.TICK_COUNT_1> <---------- GetTickCount.
    00517B7E 8BF8 MOV EDI,EAX <--------------------------- Store EAX to EDI.
    00517B80 E8 791C0000 CALL <SDProtec.IMPORT_GetVersion> <----- GetVersion.
    00517B85 3D 00000080 CMP EAX,80000000
    00517B8A 0F83 8B000000 JNB SDProtec.00517C1B <----------------- Skip everything if OS doesnt match.
    00517B90 81FF 4F5346D2 CMP EDI,D246534F
    00517B96 75 05 JNZ SHORT SDProtec.00517B9D
    00517B98 BF 505346D2 MOV EDI,D2465350
    00517B9D 68 57EB4000 PUSH SDProtec.0040EB57
    00517BA2 E8 FE77FFFF CALL <SDProtec.API-DLL_STRING>
    00517BA7 50 PUSH EAX
    00517BA8 68 67EB4000 PUSH SDProtec.0040EB67
    00517BAD E8 F377FFFF CALL <SDProtec.API-DLL_STRING>
    00517BB2 50 PUSH EAX
    00517BB3 E8 CE1E0000 CALL <SDProtec.API_BP_CHECK_1>
    00517BB8 50 PUSH EAX
    00517BB9 E8 CABBFFFF CALL <SDProtec.GET_PROC_ADDR_1>
    00517BBE 8BF0 MOV ESI,EAX
    00517BC0 85F6 TEST ESI,ESI
    00517BC2 74 57 JE SHORT SDProtec.00517C1B
    00517BC4 8D4424 08 LEA EAX,DWORD PTR SS:[ESP+8]
    00517BC8 8D4C24 08 LEA ECX,DWORD PTR SS:[ESP+8]
    00517BCC 50 PUSH EAX
    00517BCD 8D5424 0C LEA EDX,DWORD PTR SS:[ESP+C]
    00517BD1 51 PUSH ECX
    00517BD2 8D4424 18 LEA EAX,DWORD PTR SS:[ESP+18]
    00517BD6 52 PUSH EDX
    00517BD7 50 PUSH EAX
    00517BD8 E8 D91B0000 CALL SDProtec.005197B6 <----------------- GetCurrentProcess.
    00517BDD 50 PUSH EAX
    00517BDE FFD6 CALL ESI <------------------------------- GetProcessTimes.
    00517BE0 85C0 TEST EAX,EAX
    00517BE2 74 37 JE SHORT SDProtec.00517C1B <------------- If fails, skip check.
    00517BE4 8D4C24 08 LEA ECX,DWORD PTR SS:[ESP+8]
    00517BE8 51 PUSH ECX
    00517BE9 E8 D0190000 CALL SDProtec.005195BE <----------------- GetSystemTimeAsFileTime.
    00517BEE 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C]
    00517BF2 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+14]
    00517BF6 2BC1 SUB EAX,ECX
    00517BF8 74 2C JE SHORT SDProtec.00517C26
    00517BFA 83F8 01 CMP EAX,1
    00517BFD 77 39 JA SHORT SDProtec.00517C38 <------------- Bad jump.
    00517BFF 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8]
    00517C03 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10]
    00517C07 C1E8 04 SHR EAX,4
    00517C0A C1E9 04 SHR ECX,4
    00517C0D 05 00000010 ADD EAX,10000000
    00517C12 2BC1 SUB EAX,ECX
    00517C14 3D 00000001 CMP EAX,1000000
    00517C19 77 1D JA SHORT SDProtec.00517C38 <------------- Bad jump.
    00517C1B 5F POP EDI
    00517C1C B8 4F5346D2 MOV EAX,D246534F
    00517C21 5E POP ESI
    00517C22 83C4 10 ADD ESP,10
    00517C25 C3 RETN
    00517C26 8B5424 08 MOV EDX,DWORD PTR SS:[ESP+8]
    00517C2A 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10]
    00517C2E 2BD1 SUB EDX,ECX
    00517C30 81FA 00000010 CMP EDX,10000000
    00517C36 ^76 E3 JBE SHORT SDProtec.00517C1B <------------ Good jump! Must be executed!
    00517C38 8BC7 MOV EAX,EDI
    00517C3A 5F POP EDI
    00517C3B 5E POP ESI
    00517C3C 83C4 10 ADD ESP,10
    00517C3F C3 RETN


    GetProcessTimes will return some timing information about specified process (it called before GetCurrent process and that means it gives information for it's own process) to some 64-bit buffer (two dwords). GetSystemTimeAsFileTime will retrieve system time and store it in file format to some buffer. SDP will just check differences.

    Continue to trace and we will meet new anti-debug trick soon. Notice that GetTickCount is still opened and waiting for second pair of that check. SDP author nested couple checks one inside another.






    12. ZwQueryInformationProcess , custom IsDebuggerPresent , GetTickCount and RDTSC check

    Tracing further after last check, we will meet one SMC trick, EFLAG trick, and finally, we will get here:

    005182A3 E8 56150000 CALL <SDProtec.IMPORT_GetVersion> <----- It checks does OS matches request.
    005182A8 3D 00000080 CMP EAX,80000000
    005182AD 0F83 96000000 JNB SDProtec.00518349 <----------------- If not, we can skip all these checks.
    005182B3 53 PUSH EBX
    005182B4 55 PUSH EBP
    005182B5 56 PUSH ESI
    005182B6 57 PUSH EDI
    005182B7 E8 82170000 CALL <SDProtec.TICK_COUNT_1> <---------- Second part of GetTickCount check.
    005182BC 8BE8 MOV EBP,EAX
    005182BE E8 D3E0FFFF CALL SDProtec.00516396 <---------------- RDTSC inside.
    005182C3 68 0CDD4000 PUSH SDProtec.0040DD0C
    005182C8 8BF8 MOV EDI,EAX
    005182CA 8BDA MOV EBX,EDX
    005182CC E8 D470FFFF CALL <SDProtec.API-DLL_STRING>
    005182D1 50 PUSH EAX
    005182D2 68 6CB34000 PUSH SDProtec.0040B36C
    005182D7 E8 C970FFFF CALL <SDProtec.API-DLL_STRING>
    005182DC 50 PUSH EAX
    005182DD E8 A4170000 CALL <SDProtec.API_BP_CHECK_1>
    005182E2 50 PUSH EAX
    005182E3 E8 A0B4FFFF CALL <SDProtec.GET_PROC_ADDR_1> <------- Get ZwQueryInformationProcess API.
    005182E8 8BF0 MOV ESI,EAX
    005182EA 85F6 TEST ESI,ESI
    005182EC 74 2D JE SHORT SDProtec.0051831B
    005182EE 33C0 XOR EAX,EAX
    005182F0 803C30 CC CMP BYTE PTR DS:[EAX+ESI],0CC <--------- Check it for breakpoints, first 8 bytes.
    005182F4 74 49 JE SHORT SDProtec.0051833F
    005182F6 40 INC EAX
    005182F7 83F8 08 CMP EAX,8
    005182FA ^7C F4 JL SHORT SDProtec.005182F0
    005182FC 6A 00 PUSH 0
    005182FE 8D4424 14 LEA EAX,DWORD PTR SS:[ESP+14]
    00518302 6A 04 PUSH 4
    00518304 50 PUSH EAX
    00518305 6A 07 PUSH 7 <--------------------------------- Flag for testing debugger.
    00518307 E8 AA140000 CALL SDProtec.005197B6 <----------------- GetCurrentProcess import.
    0051830C 50 PUSH EAX
    0051830D FFD6 CALL ESI <------------------------------- Call ZwQueryInformationProcess.
    0051830F 85C0 TEST EAX,EAX
    00518311 75 08 JNZ SHORT SDProtec.0051831B <------------ If API failed, skip check.
    00518313 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] <---------- Here it checks buffer for debugg info.
    00518317 85C0 TEST EAX,EAX <--------------------------- We are detected if EAX<>0.
    00518319 75 24 JNZ SHORT SDProtec.0051833F <------------ Debugger found, we are detected.
    0051831B E8 41FAFFFF CALL SDProtec.00517D61 <----------------- Custom IsDebuggerPresent check.
    00518320 85C0 TEST EAX,EAX
    00518322 75 1B JNZ SHORT SDProtec.0051833F <------------ We are detected if EAX<>0.
    00518324 E8 6DE0FFFF CALL SDProtec.00516396 <----------------- Second pair of RDTSC check.
    00518329 2BC7 SUB EAX,EDI
    0051832B 1BD3 SBB EDX,EBX
    0051832D 895424 14 MOV DWORD PTR SS:[ESP+14],EDX
    00518331 75 0C JNZ SHORT SDProtec.0051833F <------------- Bad jump.
    00518333 3D 000000FF CMP EAX,FF000000
    00518338 77 05 JA SHORT SDProtec.0051833F <-------------- Bad jump.
    0051833A BD 00000080 MOV EBP,80000000
    0051833F 5F POP EDI
    00518340 8BC5 MOV EAX,EBP
    00518342 5E POP ESI
    00518343 5D POP EBP
    00518344 5B POP EBX
    00518345 83C4 08 ADD ESP,8
    00518348 C3 RETN
    00518349 B8 00000080 MOV EAX,80000000
    0051834E 83C4 08 ADD ESP,8
    00518351 C3 RETN


    ZwQueryInformationProcess API can check is current process is beeing debugged. Stack:

    0012FF90 0051830F /CALL to ZwQueryInformationProcess from SDProtec.0051830D
    0012FF94 FFFFFFFF |hProcess = FFFFFFFF
    0012FF98 00000007 |InfoClass = 7
    0012FF9C 0012FFB8 |Buffer = 0012FFB8
    0012FFA0 00000004 |Bufsize = 4
    0012FFA4 00000000 \pReqsize = NULL

    hProcess = FFFFFFFF points to current process
    InfoClass = 7 is code that this API checks for debugger presence
    Buffer = 0012FFB8 is buffer where it will store process info.

    We check that buffer in dump and execute API:

    0012FFB8 FF FF FF FF 46 02 00 00 36 AE 50 00 DF AB 50 00 ....F...6®P...P.
    0012FFC8 38 07 91 7C FF FF FF FF 00 C0 FD 7F 38 B0 54 80 8..|........8.T.
    0012FFD8 C8 FF 12 00 68 62 C6 82 FF FF FF FF F3 99 83 7C ....hb.........|
    0012FFE8 58 6D 81 7C 00 00 00 00 00 00 00 00 00 00 00 00 Xm.|............
    0012FFF8 00 A0 50 00 00 00 00 00 ..P.....

    First DWORD, FFFFFFFF tells that debugger is found. We must set that to 00000000 and it will think that process is not being debugged.


    Custom IsDebuggerPresent check is also inside this code block:

    00517D61 55 PUSH EBP
    00517D62 8BEC MOV EBP,ESP
    00517D64 51 PUSH ECX
    00517D65 50 PUSH EAX
    00517D66 51 PUSH ECX
    00517D67 64:A1 18000000 MOV EAX,DWORD PTR FS:[18]
    00517D6D 8B40 30 MOV EAX,DWORD PTR DS:[EAX+30]
    00517D70 8B08 MOV ECX,DWORD PTR DS:[EAX]
    00517D72 894D FC MOV DWORD PTR SS:[EBP-4],ECX
    00517D75 59 POP ECX
    00517D76 58 POP EAX
    00517D77 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
    00517D7A C1E8 10 SHR EAX,10
    00517D7D 83E0 01 AND EAX,1
    00517D80 8BE5 MOV ESP,EBP
    00517D82 5D POP EBP
    00517D83 C3 RETN


    We can notice that all checks and tricks before this ZwQueryInformationProcess can be bypassed by just running fast. All previous tricks where anti-trace tricks. This is first reall anti-debugger check. Also, GetTickCount in this check and previous one is not clear to me. It seams that it doesn't serve the purpose, I didn't noticed that values are used.






    13. Temp file and new process

    Next check also seams to be based on time. First, one string is prepared:

    ASCII "~temp0%d.tmp"

    Then with wsprintfA name of temporary file is formated:

    ASCII "~temp0-1790399849.tmp"


    Protector uses GetTempPathA to get temporary folder path. Then is uses CreateFileA to create that temp file. Then is reads 12 bytes (0C hex) from file using ReadFileA API. Then it will check how many bytes it readed:

    00516593 837C24 1C 0C CMP DWORD PTR SS:[ESP+1C],0C
    00516598 73 76 JNB SHORT SDProtec.00516610

    If 0, file is empty and SDP will generate 8 bytes with RDTSC (EAX:EDX) and write it in buffer. Last 4 bytes that are written in buffer are probably from GetTickCount value. Then it will encrypt that 12 bytes and write them in the file. Then it will start new process from target and exit this one. new process will perform all checks as usuall, and then it will come to this part again.


    This time it will see that file has 12 bytes inside, read them, and decrypt them. It will take first DWORD, substract some value in EDI with it and then check is it in given range. If it doesn't fit in that range, it will go wild creating new processes, untill it eventually exits saying "Debugger detected":

    0051663E 2B7C24 18 SUB EDI,DWORD PTR SS:[ESP+18]
    00516642 81FF 803E0000 CMP EDI,3E80
    00516648 897C24 20 MOV DWORD PTR SS:[ESP+20],EDI
    0051664C 76 08 JBE SHORT SDProtec.00516656 <------------ Good jump if EDI=<3E80.
    0051664E 83FB 05 CMP EBX,5
    00516651 74 7E JE SHORT SDProtec.005166D1
    00516653 43 INC EBX
    00516654 EB 57 JMP SHORT SDProtec.005166AD
    00516656 85FF TEST EDI,EDI
    00516658 0F85 B0000000 JNZ SDProtec.0051670E <------------------ But it must not be EDI=0.
    0051665E E8 33FDFFFF CALL SDProtec.00516396

    Avoiding this detection is not hard. By executing three above jumps we avoid new process.






    14. ZwQuerySystemInformation


    This API is one of those which are not documented so I can only guess what it does. I assume that it can retrieve various information about system, but SDP will use it for detecting hostile drivers. SDP will get names of all drivers loaded in memory. All those drivers will be compared with hardcoded names (like softice drivers, etc...). This doesn't detect Olly so you don't have to worry, but we can avoid this check because it is OS dependent:

    0051836E E8 8B140000 CALL <SDProtec.IMPORT_GetVersion>
    00518373 3D 00000080 CMP EAX,80000000
    00518378 0F83 F6000000 JNB SDProtec.00518474 <---------- Execute this jump and problem is solved.
    0051837E 68 26DD4000 PUSH SDProtec.0040DD26
    00518383 E8 1D70FFFF CALL SDProtec.0050F3A5
    00518388 50 PUSH EAX
    ...
    ...

    This check is used at least twice (after threads part it is used one time more).







    15. IsDebuggerPresent

    Well known check:

    0051828C E8 F5170000 CALL <SDProtec.API_BP_CHECK_1>
    00518291 50 PUSH EAX
    00518292 E8 F1B4FFFF CALL <SDProtec.GET_PROC_ADDR_1>
    00518297 85C0 TEST EAX,EAX
    00518299 74 02 JE SHORT SDProtec.0051829D
    0051829B -FFE0 JMP EAX ; kernel32.IsDebuggerPresent







    16. CreateToolhelp32Snapshot, Process32First, Process32Next - detecting hostile processes

    SDP has black list of some hostile processes:

    0012FE74 00517F89 ASCII "OLLYDBG.EXE"
    0012FE78 00517F95 ASCII "SOFTICE.EXE"
    0012FE7C 00517FA1 ASCII "LORDPE.EXE"
    0012FE80 00517FAC ASCII "PEDUMPER.EXE"
    0012FE84 00517FB9 ASCII "FILEMON.EXE"
    0012FE88 00517FC5 ASCII "REGMON.EXE"
    0012FE8C 00517FD0 ASCII "IMPORTREC.EXE"
    0012FE90 00517FDE ASCII "SUPERIMPORTREC.EXE"
    0012FE94 00517FF1 ASCII "DEBUGAPISPY.EXE"

    It uses CreateToolhep32Snapshot to retrieve snapshot. The with Process32First and Process32Next checks does some process is blacklisted. It checks names of processes with blacklisted:

    0050FD78 F3:A6 REPE CMPS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
    0050FD7A B8 01000000 MOV EAX,1 <------------------------------------ EAX=1.
    0050FD7F 75 01 JNZ SHORT SDProtec.0050FD82
    0050FD81 48 DEC EAX <-------------------------------------- If it finds hostile process, EAX=0.
    0050FD82 5F POP EDI
    0050FD83 5E POP ESI
    0050FD84 C9 LEAVE
    0050FD85 C2 0800 RETN 8

    ESI 0012FEBC ASCII "OLLYDBG.EXE"
    EDI 00517F89 ASCII "OLLYDBG.EXE"


    005181A9 E8 B47BFFFF CALL SDProtec.0050FD62 <--------------- Name check.
    005181AE 85C0 TEST EAX,EAX
    005181B0 74 08 JE SHORT SDProtec.005181BA <----------- EAX=0 -> jump, debugger detected.
    005181B2 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10]
    005181B6 85C0 TEST EAX,EAX
    005181B8 74 30 JE SHORT SDProtec.005181EA <----------- EAX=1 -> good jump.
    005181BA 8B5424 50 MOV EDX,DWORD PTR SS:[ESP+50]
    005181BE 52 PUSH EDX
    005181BF 6A 00 PUSH 0
    005181C1 6A 01 PUSH 1
    005181C3 E8 D61B0000 CALL SDProtec.00519D9E
    ...
    ...

    We can prevent detection renaming Olly , or to change it in SDP blacklist buffer, but the easiest way is to just set EAX=0 uppon return from CreateToolhep32Snapshot API. This will produce ERROR_INVALID_HANDLE and SDP will just exit from this check.







    17. Monitoring threads

    SDProtector can create two threads to monitor for file changes and hostile tools. Threads are created suspended:

    0012FF6C 00517973 /CALL to CreateThread from SDProtec.0051796E
    0012FF70 00000000 |pSecurity = NULL
    0012FF74 00010000 |StackSize = 10000 (65536.)
    0012FF78 005179E0 |ThreadFunction = SDProtec.005179E0
    0012FF7C 0050A1BC |pThreadParm = SDProtec.0050A1BC
    0012FF80 00000004 |CreationFlags = CREATE_SUSPENDED
    0012FF84 0012FF94 \pThreadId = 0012FF94

    Then it will resume threads. We can prevent creating threads or resuming, by just patching API's. Or, since threads are optional, we can just skip them:

    00517936 E8 B3220000 CALL SDProtec.00519BEE <--------------- GetSystemInfo
    0051793B 837C24 24 01 CMP DWORD PTR SS:[ESP+24],1 <---------- "Do we need threads?" check.
    00517940 0F85 94000000 JNZ SDProtec.005179DA <---------------- Jump if not.
    00517946 57 PUSH EDI
    00517947 E8 727AFFFF CALL SDProtec.0050F3BE
    0051794C 8BF0 MOV ESI,EAX
    0051794E 8D4C24 0C LEA ECX,DWORD PTR SS:[ESP+C]
    00517952 51 PUSH ECX
    00517953 6A 04 PUSH 4
    00517955 8DBE BC000000 LEA EDI,DWORD PTR DS:[ESI+BC]
    0051795B 57 PUSH EDI
    0051795C 68 E0E94000 PUSH SDProtec.0040E9E0
    00517961 E8 3F7AFFFF CALL SDProtec.0050F3A5
    00517966 50 PUSH EAX
    00517967 68 00000100 PUSH 10000
    0051796C 6A 00 PUSH 0
    0051796E E8 B71C0000 CALL <SDProtec.IMPORT_BC_CHECK_4> <---- Create first thread.
    00517973 8D5424 10 LEA EDX,DWORD PTR SS:[ESP+10]
    00517977 8BD8 MOV EBX,EAX
    00517979 52 PUSH EDX
    0051797A 6A 04 PUSH 4
    0051797C 57 PUSH EDI
    0051797D 68 A8E74000 PUSH SDProtec.0040E7A8
    00517982 E8 1E7AFFFF CALL SDProtec.0050F3A5
    00517987 50 PUSH EAX
    00517988 68 00000100 PUSH 10000
    0051798D 6A 00 PUSH 0
    0051798F E8 961C0000 CALL <SDProtec.IMPORT_BC_CHECK_4> <---- Create second thread.
    00517994 85C0 TEST EAX,EAX
    00517996 5F POP EDI
    00517997 74 41 JE SHORT SDProtec.005179DA
    00517999 85DB TEST EBX,EBX
    0051799B 74 3D JE SHORT SDProtec.005179DA
    0051799D 50 PUSH EAX
    0051799E C786 A8000000 00>MOV DWORD PTR DS:[ESI+A8],0
    005179A8 C786 AC000000 00>MOV DWORD PTR DS:[ESI+AC],0
    005179B2 C786 C0000000 00>MOV DWORD PTR DS:[ESI+C0],0
    005179BC 8986 B0000000 MOV DWORD PTR DS:[ESI+B0],EAX
    005179C2 899E B4000000 MOV DWORD PTR DS:[ESI+B4],EBX
    005179C8 E8 111D0000 CALL <SDProtec.IMPORT_BC_CHECK> <------ ResumeThread.
    005179CD 53 PUSH EBX
    005179CE E8 0B1D0000 CALL <SDProtec.IMPORT_BC_CHECK> <------ ResumeThread.
    005179D3 6A 00 PUSH 0
    005179D5 E8 BC1C0000 CALL SDProtec.00519696
    005179DA 5E POP ESI
    005179DB 5B POP EBX
    005179DC 83C4 2C ADD ESP,2C
    005179DF C3 RETN








    18. Checking installed services in registry for SI

    0012FF9C 00515566 /CALL to RegOpenKeyA from SDProtec.00515561
    0012FFA0 80000002 |hKey = HKEY_LOCAL_MACHINE
    0012FFA4 00515523 |Subkey = "SYSTEM\CurrentControlSet\Services\IceExt"
    0012FFA8 0012FFAC \pHandle = 0012FFAC







    19. SetUnhandledExceptionFilter

    It installs finall SEH and then triggers exception. Within debugger , target crushes. I explained in Obsidium tutorial how to avoid this. Also, you can use some plugin for olly.







    20. CreateFileA drivers check

    List of drivers and monitoring tools:

    0012DBDC 00518E53 ASCII "\\.\SICE"
    0012DBE0 00518E5C ASCII "\\.\NTICE"
    0012DBE4 00518E66 ASCII "\\.\SIWDEBUG"
    0012DBE8 00518E73 ASCII "\\.\SIWVID"
    0012DBEC 00518E7E ASCII "\\.\FILEMON"
    0012DBF0 00518E8A ASCII "\\.\Global\FILEMON"
    0012DBF4 00518E9D ASCII "\\.\REGMON"
    0012DBF8 00518EA8 ASCII "\\.\Global\REGMON"
    0012DBFC 00518EBA ASCII "\\.\FILEVXD.VXD"
    0012DC00 00518ECA ASCII "\\.\REGVXD.VXD"
    0012DC04 00518ED9 ASCII "\\.\TRW"
    0012DC08 00518EE1 ASCII "\\.\TRWDEBUG"
    0012DC0C 00518EEE ASCII "\\.\ICEDUMP"
    0012DC10 00518EFA ASCII "\\.\FROGSICE"
    0012DC14 00518F07 ASCII "\\.\IceExt"
    0012DC18 00518F12 ASCII "\\.\RvtracerDevice0"
    0012DC1C 00518F26 ASCII "\\.\BW2K"
    0012DC20 00518F2F ASCII "\\.\SUPERBPM"
    0012DC24 00518F3C ASCII "\\.\NTICED052"
    0012DC28 00518F4A ASCII "\\.\NTICE7871"
    0012DC2C 00518F58 ASCII "\\.\TRW2000"
    0012DC30 00518F64 ASCII "\\.\VKEYPROD"

    It uses CreateFileA to try open such files and RtlGetLastWin32Error to get error information. If ERROR_SUCCSESS is returned, driver is detected. Inside this check is nested IsDebuggerPresent check which is called in every cycle.







    21. INT1 trick to detect SoftICE

    This is trick for SoftICE, it generates memory access violation or something. I don't have SoftICE so I'm not sure how it works, but I assume that SI handles that exception, return different exception code to program:

    0050DBB0 33C0 XOR EAX,EAX
    0050DBB2 64:FF30 PUSH DWORD PTR FS:[EAX]
    0050DBB5 64:8920 MOV DWORD PTR FS:[EAX],ESP <-------------- 1. Install SEH.
    0050DBB8 CD 01 INT 1 <----------------------------------- 2. Generate exception.
    0050DBBA C3 RETN
    0050DBBB 64:8F05 00000000 POP DWORD PTR FS:[0] <-------------------- 7. Return here.
    0050DBC2 83C4 04 ADD ESP,4
    0050DBC5 EB 63 JMP SHORT SDProtec.0050DC2A
    0050DBC7 74 03 JE SHORT SDProtec.0050DBCC
    0050DBC9 75 01 JNZ SHORT SDProtec.0050DBCC
    0050DBCB E8 E8010000 CALL SDProtec.0050DDB8
    0050DBD0 00FF ADD BH,BH
    0050DBD2 58 POP EAX
    0050DBD3 05 27000000 ADD EAX,27
    0050DBD8 8BD0 MOV EDX,EAX
    0050DBDA 83C2 32 ADD EDX,32
    0050DBDD E8 D6220000 CALL SDProtec.0050FEB8
    0050DBE2 EB 01 JMP SHORT SDProtec.0050DBE5
    0050DBE4 FFE8 JMP FAR EAX
    0050DBE6 0100 ADD DWORD PTR DS:[EAX],EAX
    0050DBE8 0000 ADD BYTE PTR DS:[EAX],AL
    0050DBEA FF58 05 CALL FAR FWORD PTR DS:[EAX+5]
    0050DBED 0E PUSH CS
    0050DBEE 0000 ADD BYTE PTR DS:[EAX],AL
    0050DBF0 0050 E9 ADD BYTE PTR DS:[EAX-17],DL
    0050DBF3 78 5B JS SHORT SDProtec.0050DC50
    0050DBF5 0000 ADD BYTE PTR DS:[EAX],AL
    0050DBF7 FF00 INC DWORD PTR DS:[EAX]
    0050DBF9 1040 00 ADC BYTE PTR DS:[EAX],AL
    0050DBFC 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4] <------------ 3. Handler.
    0050DC00 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C]
    0050DC04 8B00 MOV EAX,DWORD PTR DS:[EAX]
    0050DC06 3D 04000080 CMP EAX,80000004 <------------------------ 4. Check exception code.
    0050DC0B ^74 BA JE SHORT SDProtec.0050DBC7 <-------------- 5. Bad jump.
    0050DC0D 3D 050000C0 CMP EAX,C0000005
    0050DC12 75 15 JNZ SHORT SDProtec.0050DC29 <------------- 6. Bad jump too.
    0050DC14 83A9 B8000000 FD SUB DWORD PTR DS:[ECX+B8],-3
    0050DC1B 33C0 XOR EAX,EAX
    0050DC1D 8941 04 MOV DWORD PTR DS:[ECX+4],EAX
    0050DC20 8941 08 MOV DWORD PTR DS:[ECX+8],EAX
    0050DC23 8941 0C MOV DWORD PTR DS:[ECX+C],EAX
    0050DC26 8941 10 MOV DWORD PTR DS:[ECX+10],EAX
    0050DC29 C3 RETN







    22. Import protection

    After last INT1 check, we will met one SMC and EFLAG , and then it comes time to decrypt IAT. IAT is first encrypted (thunks, hint arrays, IID, names, ordinals). During runtime, SDP decrypts names, load libraries, decrypts thunks, hints and ordinals. Then it finds import, place it in thunk, or it redirect it to stack memory where it obfuscate it. Then it destroys ordinals, hint arrays, etc. IAT protection will not be discussed here in details because IAT can be repaired after reaching OEP. Also, IAT handling procedure is pretty big, and this tutorial has already become too big. If you are experienced with PE format and rebuilding files, you will easily prevent IAT destruction and retrieve virgin untouched IAT. That gives nice and clean dump, also prevents possible errors while rebuilding IAT with tools such as ImpREC.

    Note that IAT algorithm also has couple integrity checks, so it is advisable to patch them.








    23. UnhandledExceptionFilter breakpoint check

    Altough almost all API's are checked for breakpoints, I'm showing this one separatley because this is a SoftICE check. SoftICE sets INT3 at the beggining of UnhandledExceptionFilter API so it can controll exception handling. SDProtector checks is INT3 placed on this API for that reason. It will not use this API at all.

    00518250 85C0 TEST EAX,EAX ; kernel32.UnhandledExceptionFilter
    00518252 74 0F JE SHORT SDProtec.00518263
    00518254 8038 CC CMP BYTE PTR DS:[EAX],0CC
    00518257 75 0A JNZ SHORT SDProtec.00518263
    00518259 E8 7171FFFF CALL SDProtec.0050F3CF
    0051825E ^E9 0CB5FFFF JMP SDProtec.0051376F
    00518263 C3 RETN






    24. Stolen code and OEP

    After UnhandledExceptionFilter check, it happens a lot interesting things. SDProtector searching some files in windows directory, then in C:\, checks time. It also performs some registry operations, particulary interesting is that it writes key with embedded nulls so "normall" tools like regedit cannot get access.

    We can place breakpoint on GetTickCount and run fast 4 times to avoid detection. Then two times we break on GetModuleHandleA, little tracing, and we find jump to stolen OEP code:

    0050E79C 58 POP EAX
    0050E79D 05 4BFFFFFF ADD EAX,-0B5
    0050E7A2 8038 E9 CMP BYTE PTR DS:[EAX],0E9
    0050E7A5 ^0F85 73FFFFFF JNZ SDProtec.0050E71E
    0050E7AB C600 E8 MOV BYTE PTR DS:[EAX],0E8
    0050E7AE 9D POPFD
    0050E7AF 61 POPAD
    0050E7B0 -FFE0 JMP EAX ; SDProtec.004B5A10


    And there we have stolen opcodes:

    004B5A10 55 PUSH EBP
    004B5A11 8BEC MOV EBP,ESP
    004B5A13 6A FF PUSH -1
    004B5A15 68 E0214700 PUSH SDProtec.004721E0
    004B5A1A 68 64E54300 PUSH SDProtec.0043E564
    004B5A1F 60 PUSHAD
    004B5A20 9C PUSHFD
    004B5A21 -FFE2 JMP EDX
    004B5A23 0000 ADD BYTE PTR DS:[EAX],AL
    004B5A25 0000 ADD BYTE PTR DS:[EAX],AL


    PUSHAD and PUSHFD are not stolen ofcourse. They purpose is to save original registers values. But JMP EDX retuns us to SDProtectors code, right below JMP EAX. Again, same checks are performed and then it point us where is OEP. Here is snippet with NOP-ed bytes to get cleaner picture:


    0050ED1B 58 POP EAX
    0050ED1C 05 FEB3FFFF ADD EAX,FFFFB3FE
    0050ED21 2B08 SUB ECX,DWORD PTR DS:[EAX] <--------- ECX is counter how many bytes to check.
    0050ED23 FC CLD
    0050ED24 B0 C3 MOV AL,0C3
    0050ED26 F2:AE REPNE SCAS BYTE PTR ES:[EDI] <------- EDI=439434, it scans for C3 bytes now.
    0050ED28 83F9 00 CMP ECX,0 <-------------------------- Checks if ECX=0, is all code checked.
    0050ED2B 7E 13 JLE SHORT SDProtec.0050ED40
    0050ED2D EB 01 JMP SHORT SDProtec.0050ED30
    0050ED2F 90 NOP
    0050ED30 4F DEC EDI
    0050ED31 FFD7 CALL EDI <--------------------------- When it finds C3 byte, it jumps on it.
    0050ED33 74 03 JE SHORT SDProtec.0050ED38
    0050ED35 75 01 JNZ SHORT SDProtec.0050ED38
    0050ED37 90 NOP
    0050ED38 57 PUSH EDI
    0050ED39 47 INC EDI
    0050ED3A 49 DEC ECX
    0050ED3B ^7F E9 JG SHORT SDProtec.0050ED26
    0050ED3D EB 01 JMP SHORT SDProtec.0050ED40
    0050ED3F 90 NOP
    0050ED40 81EC 00100000 SUB ESP,1000
    0050ED46 70 0E JO SHORT SDProtec.0050ED56
    0050ED48 71 0C JNO SHORT SDProtec.0050ED56

    oep with stolen code:

    00439434 0000 ADD BYTE PTR DS:[EAX],AL <----------- This is OEP. Code is stolen.
    00439436 0000 ADD BYTE PTR DS:[EAX],AL
    00439438 0000 ADD BYTE PTR DS:[EAX],AL
    0043943A E8 13CB0D00 CALL SDProtec.00515F52 <------------- Here it points at start.
    0043943F 8BE0 MOV ESP,EAX
    00439441 9D POPFD
    00439442 61 POPAD
    00439443 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
    00439449 50 PUSH EAX
    0043944A 64:8925 00000000 MOV DWORD PTR FS:[0],ESP
    00439451 83EC 58 SUB ESP,58
    00439454 53 PUSH EBX
    00439455 56 PUSH ESI



    Now we know where is OEP and what are stolen bytes.

    SDProtector pointed us to OEP and it scanned for all 0C3 bytes in code section from our OEP, then it jumped to everyone of them and returned back. Every address of each 0C3 byte is pushed to stack and that it has a reason. Then again, SDP is performing same timer and trace checks, then it decrypt some code couple times. Last decrypted block will erase SDP code:

    0050F250 F3:AA REP STOS BYTE PTR ES:[EDI]
    0050F252 60 PUSHAD
    0050F253 9C PUSHFD
    0050F254 58 POP EAX
    0050F255 8BC8 MOV ECX,EAX


    Then it jumps to OEP:

    0050F388 58 POP EAX ; SDProtec.0046970F
    0050F389 05 4BFFFFFF ADD EAX,-0B5
    0050F38E 8038 E9 CMP BYTE PTR DS:[EAX],0E9
    0050F391 ^0F85 73FFFFFF JNZ SDProtec.0050F30A
    0050F397 C600 E8 MOV BYTE PTR DS:[EAX],0E8
    0050F39A 9D POPFD
    0050F39B 61 POPAD
    0050F39C C3 RETN <-------------------------- Returns to original code section.

    But it will not jump directly to OEP! As I sad before, it pushed addresses of every 0C3 byte in code section after OEP. So it will keep returning, executing all those RETN (0C3) opcodes/bytes untill it reach OEP! To reach OEP, we don't need to execute all these RETN opcodes, we can place breakpoint at it (after stolen code) and just run.

    That all looks nice in theory, but SDP has one big trap. Check next part of tutorial.








    25. Hashes on everything (imports too) and decrypting

    You might fail to reach OEP. SDP performs hashing of everthing ; PE header, Entry Point of it's own layer, sections, memory and... imports! Yep, SDP hashes imports too, so if you placed breakpoint on some import, it is recorded. And those hashes are sometimes checked as checksum, but sometimes they are used as decryption key for decrypting blocks of code. That is case with last decrypted block that throw us at OEP. It is huge task to avoid being detected because it uses hashing many times. But it seams that it uses them sometimes in pairs, for example - for detecting breakpoints on imports.

    Last decrypted block is good example of that: I was using my script to find stolen code. That script used breakpoint on GetVersion import, that was detected. But after I found stolen code, I cleared that breakpoint. SDP has hashed again some imports and GetVersion too, and this time it got diffrent value. Those two (at least) hashes are important for decrypting last block. It decrypted last block , but it was all junk. When I tried again, I left breakpoint on GetVersion and this time it decrypted last block correctly!

    I assume that hashing with imports and decrypting block could go something like this; hash 1. time, hash 2. time, add or substract hashes, add difference (or that some value) to decryption key, then decrypt. Ofcourse, bad key gives junk code, while good key gives correct decrypted code. Problem is that it has too many these hashing, but, maybe we could find where it holds good keys.








    26. Repairing imports

    I already sad that imports can be repaired during runtime. But here we will see how they are protected. If we search for all intermodular calls, we will see many calls to stack area:

    Found intermodular calls
    Address Disassembly Destination
    00401193 CALL DWORD PTR DS:[46A62C] DS:[0046A62C]=00145ABE
    004011A4 CALL DWORD PTR DS:[46A630] DS:[0046A630]=00145AF6
    00401294 CALL DWORD PTR DS:[46A624] DS:[0046A624]=00145A4E
    0040130C CALL DWORD PTR DS:[46A620] DS:[0046A620]=00145A16
    ...
    ...etc...


    If we follow one call , we see how import is protected:

    001457E6 58 POP EAX <----------------------- We jump here.
    001457E7 50 PUSH EAX
    001457E8 60 PUSHAD
    001457E9 9C PUSHFD
    001457EA 68 03000000 PUSH 3
    001457EF 50 PUSH EAX
    001457F0 B8 1FDBA78F MOV EAX,8FA7DB1F
    001457F5 50 PUSH EAX
    001457F6 B8 3B5A2DE8 MOV EAX,E82D5A3B
    001457FB 50 PUSH EAX
    001457FC E8 6F103D00 CALL SDProtec.00516870 <------- It goes in SDP layer.
    00145801 9D POPFD
    00145802 61 POPAD
    00145803 B8 3B5A2DE8 MOV EAX,E82D5A3B <------------- To eax moves this value.
    00145808 9C PUSHFD
    00145809 05 1FDBA78F ADD EAX,8FA7DB1F <------------- Then it adds this one.
    0014580E 9D POPFD
    0014580F -FFE0 JMP EAX <---------------------- And it jumps there.


    As you can see, last two value that are given to EAX are destination of jump, and that jump is import. There are couple patherns similar to this one, and we have some even easier. I wrote script to decrypt those imports. Script just patches this code, decrypts EAX value and sets jump to import. Then ImpREC can be used:

    001457E6 -E9 6FDDC077 JMP user32.GetSubMenu
    001457EB 90 NOP
    001457EC 90 NOP
    001457ED 90 NOP
    001457EE 90 NOP
    001457EF 90 NOP
    001457F0 90 NOP
    001457F1 90 NOP
    001457F2 90 NOP
    001457F3 90 NOP
    001457F4 90 NOP
    001457F5 90 NOP
    001457F6 90 NOP
    001457F7 90 NOP
    001457F8 90 NOP
    001457F9 90 NOP
    001457FA 90 NOP
    001457FB 90 NOP
    001457FC 90 NOP
    001457FD 90 NOP
    001457FE 90 NOP
    001457FF 90 NOP
    00145800 90 NOP
    00145801 90 NOP
    00145802 90 NOP
    00145803 90 NOP
    00145804 90 NOP
    00145805 90 NOP
    00145806 90 NOP
    00145807 90 NOP
    00145808 90 NOP
    00145809 90 NOP
    0014580A 90 NOP
    0014580B 90 NOP
    0014580C 90 NOP
    0014580D 90 NOP
    0014580E 90 NOP
    0014580F 90 NOP
    00145810 E0 00 LOOPDNE SHORT 00145812


    Now all imports will be found with ImpREC if we use "trace level 1" option, but one will still be unresoplved. That one points to SDP layer at 00515AB3. That one is replaced MessageBoxA or MessageBoxW and this one is part of embeded SDP protection. We can cut that invalid thunk. It will not be erased from image, only new IAT will not have that pointer, but target will still be able to jump there. Before dumping, it would be good idea to decrypt runtime decryption.









    27. Runtime decryption-encryption

    SDProtector has runtime decryption-encryption code blocks. These blocks can be decrypted before dumping with some small olly script. There are couple types of runtime decryption. We have this call and below him a jump that jumps 11 bytes further. That is marker for decryptor:

    0040C52E E8 1B73D3FF CALL 0014384E <------------------------ Call to decryptor.
    0040C533 EB 11 JMP SHORT SDProtec.0040C546 <---------- Return here from call.
    0040C535 5B POP EBX
    0040C536 0000 ADD BYTE PTR DS:[EAX],AL
    0040C538 006F 01 ADD BYTE PTR DS:[EDI+1],CH
    0040C53B 034C00 00 ADD ECX,DWORD PTR DS:[EAX+EAX]
    0040C53F 0000 ADD BYTE PTR DS:[EAX],AL
    0040C541 0000 ADD BYTE PTR DS:[EAX],AL
    0040C543 0000 ADD BYTE PTR DS:[EAX],AL
    0040C545 E8 62F9FE67 CALL 683FBEAC <------------------------ Encrypted block.
    0040C54A F71F NEG DWORD PTR DS:[EDI]
    0040C54C D9DE FSTP ESI
    0040C54E 90 NOP
    0040C54F 99 CDQ
    0040C550 8D6CB4 5A LEA EBP,DWORD PTR SS:[ESP+ESI*4+5A]
    0040C554 B0 E1 MOV AL,0E1
    0040C556 4E DEC ESI
    0040C557 B6 A3 MOV DH,0A3
    0040C559 215C3D A0 AND DWORD PTR SS:[EBP+EDI-60],EBX
    0040C55D 4C DEC ESP


    If we follow call, we will see a lot of jumps to SDP layer:

    0014384E -E9 E54E3D00 JMP SDProtec.00518738
    00143853 -E9 894D3D00 JMP SDProtec.005185E1
    00143858 -E9 DB4E3D00 JMP SDProtec.00518738
    0014385D -E9 7F4D3D00 JMP SDProtec.005185E1
    00143862 -E9 D14E3D00 JMP SDProtec.00518738
    00143867 -E9 754D3D00 JMP SDProtec.005185E1
    0014386C -E9 C74E3D00 JMP SDProtec.00518738
    00143871 -E9 6B4D3D00 JMP SDProtec.005185E1
    00143876 -E9 BD4E3D00 JMP SDProtec.00518738
    0014387B -E9 614D3D00 JMP SDProtec.005185E1
    00143880 -E9 B34E3D00 JMP SDProtec.00518738
    ...
    ...

    We can notice that most of them leads to two addresses - decryptor and encryptor. After decrypting we can patch decryptor call and encryptor, which will be at the bottom of decrypted code:

    0040C52C 8BF1 MOV ESI,ECX
    0040C52E 90 NOP <-------------------------------- I patched decryptor call.
    0040C52F 90 NOP
    0040C530 90 NOP
    0040C531 90 NOP
    0040C532 90 NOP
    0040C533 90 NOP
    0040C534 90 NOP
    0040C535 90 NOP
    0040C536 90 NOP
    0040C537 90 NOP
    0040C538 90 NOP
    0040C539 90 NOP
    0040C53A 90 NOP
    0040C53B 90 NOP
    0040C53C 90 NOP
    0040C53D 90 NOP
    0040C53E 90 NOP
    0040C53F 90 NOP
    0040C540 90 NOP
    0040C541 90 NOP
    0040C542 90 NOP
    0040C543 90 NOP
    0040C544 90 NOP
    0040C545 90 NOP
    0040C546 6A 00 PUSH 0
    0040C548 8D8D DCFDFFFF LEA ECX,DWORD PTR SS:[EBP-224]
    0040C54E E8 43910100 CALL SDProtec.00425696
    0040C553 8365 FC 00 AND DWORD PTR SS:[EBP-4],0
    0040C557 8D7E 74 LEA EDI,DWORD PTR DS:[ESI+74]
    0040C55A 57 PUSH EDI
    0040C55B 8D8D 38FEFFFF LEA ECX,DWORD PTR SS:[EBP-1C8]
    0040C561 E8 A50D0400 CALL SDProtec.0044D30B
    0040C566 83C6 78 ADD ESI,78
    0040C569 8D8D 3CFEFFFF LEA ECX,DWORD PTR SS:[EBP-1C4]
    0040C56F 56 PUSH ESI
    0040C570 E8 960D0400 CALL SDProtec.0044D30B
    0040C575 8D8D DCFDFFFF LEA ECX,DWORD PTR SS:[EBP-224]
    0040C57B E8 4D180400 CALL SDProtec.0044DDCD
    0040C580 83F8 01 CMP EAX,1
    0040C583 75 1C JNZ SHORT SDProtec.0040C5A1
    0040C585 8D85 38FEFFFF LEA EAX,DWORD PTR SS:[EBP-1C8]
    0040C58B 8BCF MOV ECX,EDI
    0040C58D 50 PUSH EAX
    0040C58E E8 780D0400 CALL SDProtec.0044D30B
    0040C593 8D85 3CFEFFFF LEA EAX,DWORD PTR SS:[EBP-1C4]
    0040C599 8BCE MOV ECX,ESI
    0040C59B 50 PUSH EAX
    0040C59C E8 6A0D0400 CALL SDProtec.0044D30B
    0040C5A1 90 NOP <--------------------------------- And I patched encryptor one.
    0040C5A2 90 NOP
    0040C5A3 90 NOP
    0040C5A4 90 NOP
    0040C5A5 90 NOP
    0040C5A6 90 NOP
    0040C5A7 90 NOP
    0040C5A8 90 NOP
    0040C5A9 90 NOP
    0040C5AA 90 NOP
    0040C5AB 90 NOP
    0040C5AC 90 NOP
    0040C5AD 90 NOP
    0040C5AE 90 NOP
    0040C5AF 90 NOP
    0040C5B0 90 NOP
    0040C5B1 90 NOP
    0040C5B2 90 NOP
    0040C5B3 90 NOP
    0040C5B4 90 NOP
    0040C5B5 90 NOP
    0040C5B6 90 NOP
    0040C5B7 90 NOP
    0040C5B8 90 NOP


    I used script to decrypt all these calls. After that we will still have some unresolved intermodular calls:

    Found intermodular calls
    Address Disassembly Destination
    0041B3F9 CALL SDProtec.00400040 SDProtec.00514E26 <---- DEMO
    0041523B CALL SDProtec.00400059 SDProtec.00514F47 <---- Encryptor
    0040E715 CALL SDProtec.00400054 SDProtec.005150FD <---- Decryptor
    0041097E CALL SDProtec.00400054 SDProtec.005150FD <---- Decryptor
    00413A5A CALL SDProtec.00400054 SDProtec.005150FD <---- Decryptor
    004151E1 CALL SDProtec.00400054 SDProtec.005150FD <---- Decryptor
    00415F85 CALL SDProtec.00400054 SDProtec.005150FD <---- Decryptor
    00418D8C CALL SDProtec.00400054 SDProtec.005150FD <---- Decryptor
    0041A4B1 CALL SDProtec.00400054 SDProtec.005150FD <---- Decryptor
    00421A77 CALL SDProtec.00400054 SDProtec.005150FD <---- Decryptor
    00424C67 CALL SDProtec.00400054 SDProtec.005150FD <---- Decryptor
    00411542 CALL 0014388A SDProtec.005188D6
    00411E2C CALL 0014389E SDProtec.005188D6
    0041631F CALL 00143966 SDProtec.005188D6


    Probably there are more decryptor calls left, because Olly didn't show every one due to not properly analyzed code section. Plus that junk disturbs finding references. If you find some call, fix it manually. We see that some of rest calls points to PE header.

    The first one, that points to 00400040, is demo call to function which is not available in demo mode. It shows MessageBox "This function is not....blah blah..." and then it just returns to code. Without valid key we cannot decrypt it. But call points to PE header and in PE header are couple jumps:

    00400040 -E9 E961D4FF JMP 0014622E
    00400045 -E9 E961D4FF JMP 00146233
    0040004A -E9 E961D4FF JMP 00146238
    0040004F -E9 E961D4FF JMP 0014623D
    00400054 -E9 E961D4FF JMP 00146242
    00400059 -E9 E961D4FF JMP 00146247

    Those jumps point to stack where are pointers back to SDP layer:

    0014622E -E9 F3EB3C00 JMP SDProtec.00514E26
    00146233 -E9 40ED3C00 JMP SDProtec.00514F78
    00146238 -E9 69EF3C00 JMP SDProtec.005151A6
    0014623D -E9 36ED3C00 JMP SDProtec.00514F78
    00146242 -E9 B6EE3C00 JMP SDProtec.005150FD
    00146247 -E9 FBEC3C00 JMP SDProtec.00514F47

    Ok, to finish with first "demo" call, I just replaced CALL 00400040 to CALL 00514E26.

    Second one 00400059 is call to encryptor. Above that call (in code section, but Olly didn't show that reference due junk) is decryptor and we just decrypt it like rest.

    The rest of them that points to 005150FD are decryptors and we fix them in same way. Please note that this tutorial is not step-by-step guide and you cannot blindly follow it. It just shows and discuss certain types of protections. That mean, you can get defferent results, number of calls (if any) etc.


    The last three , that point to 005188D6, are part of embedded protection. Just change that CALL pointers to point where last JMP points (in SDP layer). Check is there more suspitious calls. If not, we can dump.









    28. Dumping

    SDProtector has protected part of process memory using VirtualProtect API (probably) so some tools cannot dump image. LordPE will complain, OllyDump too, etc... LordPE has option to use Intelli's dump engine which can dump, but it will padd non-accessibile memory with zeros. Maybe that area doesn't have anything important there (maybe it doesn't have anything at all , just zeros), but it is better to dump it properly. It is not some philosophy - in Olly you just set "Full access" on every section and then you can dump it with whatever you like. Then use ImpREC to rebuild new IAT.

    My dumped SDrotector now runs fine. But open Olly, run dump, try protect some file and... "Debugger detected" and Olly is closed He he, all that I can say to author of SDProtector is "---- you man!". I hope that reader will not take this as insult. It is more compliment to SDP developer. But I am angry. I spent two days on this protector and I'm still on a ice. We are not done yet, no.








    29. Embedded protection

    As said, some of those calls that points to SDP layer are part of embedded protection. SDP performs again same timer, trace and debugger checks, but it has couple new ones too. If you would now search for all intermodular calls, you would find couple (10~20) calls that point to same place in SDP layer, to this code:

    00515AB3 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
    00515AB7 85C0 TEST EAX,EAX
    00515AB9 7D 1D JGE SHORT dump.00515AD8
    00515ABB 83F8 F5 CMP EAX,-0B
    00515ABE 7E 18 JLE SHORT dump.00515AD8
    00515AC0 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10]
    00515AC4 8B5424 0C MOV EDX,DWORD PTR SS:[ESP+C]
    00515AC8 51 PUSH ECX
    00515AC9 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C]
    00515ACD 52 PUSH EDX
    00515ACE 51 PUSH ECX
    00515ACF 50 PUSH EAX
    00515AD0 E8 A1F7FFFF CALL dump.00515276
    00515AD5 C2 1000 RETN 10

    This is starting point of embedded code protection. From this place, program flow is directed to diffrent protection modules. We simply place breakpoint on this addres and run. Then we trace and we meet a first trick.








    29.1. ZwSetInformationThread

    After little tracing, we get here (I labeled some calls to know what should I expect):

    00515232 > 56 PUSH ESI
    00515233 E8 C6450000 CALL <SDProtec.IMPORT_GetVersion> <------- OS version.
    00515238 3D 00000080 CMP EAX,80000000
    0051523D 73 35 JNB SHORT SDProtec.00515274 <------------- Skip this if it doesn't match.
    0051523F 68 1BC24000 PUSH SDProtec.0040C21B
    00515244 E8 5CA1FFFF CALL <SDProtec.PREPARE_STRING>
    00515249 50 PUSH EAX
    0051524A 68 6CB34000 PUSH SDProtec.0040B36C
    0051524F E8 51A1FFFF CALL <SDProtec.PREPARE_STRING>
    00515254 50 PUSH EAX
    00515255 E8 2C480000 CALL <SDProtec.API_BP_CHECK_1>
    0051525A 50 PUSH EAX
    0051525B E8 28E5FFFF CALL <SDProtec.GET_PROC_ADDR_1> <-------- Get proc address ZwSetInformationThread.
    00515260 8BF0 MOV ESI,EAX
    00515262 85F6 TEST ESI,ESI
    00515264 74 0E JE SHORT SDProtec.00515274 <------------- If fails, skip.
    00515266 6A 00 PUSH 0
    00515268 6A 00 PUSH 0
    0051526A 6A 11 PUSH 11 <-------------------------------- 11 -> Debugger cannot read memory.
    0051526C E8 9D410000 CALL SDProtec.0051940E <----------------- GetCurrentThread.
    00515271 50 PUSH EAX
    00515272 FFD6 CALL ESI <------------------------------- ZwSetInformationThread.
    00515274 5E POP ESI
    00515275 C3 RETN


    So here SDP checks does our OS supports ZwSetInformationThread API, then it uses it for making process memory unreadable for debugger. Patching some of those jumps that skips everything solves this issue.








    29.2. EnumWindows , GetWindowTextA , FindWindowExA and how to hide Olly

    Let's see what more it has in the embedded part. I labeled some procedures:

    0051530F 83FF FC CMP EDI,-4 <---------------------------- Here picks what protection is triggered.
    00515312 0F84 AE000000 JE SDProtec.005153C6
    00515318 83FF FB CMP EDI,-5
    0051531B 0F84 A5000000 JE SDProtec.005153C6
    00515321 83FF FA CMP EDI,-6
    00515324 0F84 9C000000 JE SDProtec.005153C6
    0051532A 83FF F9 CMP EDI,-7
    0051532D 75 26 JNZ SHORT SDProtec.00515355
    0051532F E8 D1A1FFFF CALL <SDProtec.TIME_TRACE_EXCEPTIONS> <- Here are stanard RDTSC, EFLAGS, etc. tricks.
    00515334 E8 D52C0000 CALL <SDProtec.SNAPSHOT_CHECK> <-------- Snapshot trick.
    00515339 6A 00 PUSH 0
    0051533B 68 E2C64000 PUSH SDProtec.0040C6E2
    00515340 E8 60A0FFFF CALL <SDProtec.PREPARE_STRING>
    00515345 50 PUSH EAX
    00515346 E8 43450000 CALL <SDProtec.ENUM_WINDOWS> <---------- All windows tricks.
    0051534B 5F POP EDI
    0051534C 33C0 XOR EAX,EAX
    0051534E 5E POP ESI
    0051534F 83C4 40 ADD ESP,40
    00515352 C2 1000 RETN 10
    00515355 83FF F8 CMP EDI,-8
    00515358 75 0F JNZ SHORT SDProtec.00515369
    0051535A E8 D3FEFFFF CALL <SDProtec.ZW_SET_THREAD>
    0051535F 5F POP EDI
    00515360 33C0 XOR EAX,EAX
    00515362 5E POP ESI
    00515363 83C4 40 ADD ESP,40
    00515366 C2 1000 RETN 10
    00515369 83FF F7 CMP EDI,-9
    0051536C 75 2E JNZ SHORT SDProtec.0051539C
    0051536E 8D4C24 10 LEA ECX,DWORD PTR SS:[ESP+10]
    00515372 51 PUSH ECX
    00515373 6A 05 PUSH 5
    00515375 E8 3DEAFFFF CALL <SDProtec.REGISTRATION_CHECK> <---- Checks registration info.
    0051537A 85C0 TEST EAX,EAX
    0051537C ^74 CD JE SHORT SDProtec.0051534B

    We can see that it uses same RDTSC, GetTickCount, EFLAG, INT3 tricks again in one procedure, while in the second one it uses CreateToolhelp32Snapshot. There is no need to explain them again. Since those calls doesn't have any paramethers, we can just patch them.



    EnumWindows is new and interesting. When we enter in that part, it will jump to EnumWindows API. This API returns back to some callback function - pice of code that software author coded. We can see where is that function in the stack:

    016ED740 0051534B /CALL to EnumWindows from SDProtec.00515346
    016ED744 005156E2 |Callback = SDProtec.005156E2
    016ED748 00000000 \lParam = 0

    Callback procedure , a code that will search for hostile windows etc., is at 005156E2. Procedure is too big to be pasted here and also, this part is possible to examne on dumped file.

    SDP will simply enumerate all top windows one by one with EnumWindows which will then pass window handle to callback function. That function uses GetClassName to retrieve class of that window. Then class is compared with blacklisted. If blacklisted is spoted, then it calls GetWindowThreadProcessId to get thread ID and proces PID. Then it opens with OpenProcess and terminates it with TerminateProcess. If class is not suspitious, then it gets window title by using GetWindowTextA. It converts all characters of name to uppercase and then it check on blacklist. It also uses FindWindowExA.

    We can see black list above callback routine:

    0051557F ASCII "OLLYDBG",0 <---------------------------- Olly class name.
    00515587 ASCII "UKILLOD",0 <---------------------------- Couple renamed olly's.
    0051558F ASCII "FLYODBG",0
    00515597 ASCII "DEBUG_API_SPY_WND_CLASS",0
    005155AF ASCII "OLLYDBG -",0 <-------------------------- Olly caption when target is loaded.
    005155B9 ASCII "UKILLOD -",0
    005155C3 ASCII "IMPORT RECONSTRUCTOR",0
    005155D8 ASCII "DFCG SUPERVER IMPORT RECONSTRUCTOR",0
    005155FB ASCII "[ LORDPE DELUXE ]",0
    0051560D ASCII "DFCG LORDPE",0
    00515619 ASCII "FILE MONITOR - SYSINTERNALS",0
    00515635 ASCII "REGISTRY MONITOR - SYSINTERNALS",0
    00515655 ASCII "FLYODBG -",0
    0051565F ASCII "AUTO DEBUG FOR WINDOWS",0
    00515676 ASCII "MDIClient",0 <------ This string exist in Olly too , but it doesn't have to be changed(?).
    00515680 ASCII "ACPU",0 <------------------------------- And these below are olly classes too.
    00515685 ASCII "ACPUASM",0
    0051568D ASCII "ACPUDUMP",0
    00515696 ASCII "ACPUSTACK",0
    005156A0 ASCII "ACPUINFO",0
    005156A9 ASCII "ACPUREG",0
    005156B1 ASCII "TCPU",0 <------------------------------- These ones are renamed.
    005156B6 ASCII "TCPUASM",0
    005156BE ASCII "TCPUDUMP",0
    005156C7 ASCII "TCPUSTACK",0
    005156D1 ASCII "TCPUINFO",0
    005156DA ASCII "TCPUREG",0

    To hide Olly (if we wish to do sow) we need to rename olly process name , couple classes and window names. We don't need to rename .ini file, or anything in it. Problem is only that plugins won't be loaded, so we need to change ollydbg.exe string in them too. After this, Olly is not detected anymore by embedded protection, neither with monitoring threads.









    30. The end

    And that would be all.

    I just took a brief look at monitoring threads procedures. They seam to do nothing new that wasn't mentioned in this tutorial.

    Registry keys , some file searches that are performed in C:\ and %WINDOWS% folders are not examned. And probably I will not make any new update to that.

    Btw, here is small trick for passing exceptions checks, because they can be frustrated. When you find SEH handler, you place breakpoint at it. You are now in SEH which returns to ntdll.dll code. Problem could be to track where you should return now back in code. The easiest way is that you place memory breakpoint on access on that section. Then you break there and remove breakpoint. But this can (and probably will) set T flag to 1 , and target will crush. And you might be confused. So always after you handled exception, check T flag. If it's T=1, then set it to 0. And you can continue debugging.

    SDProtector Pro 1.12 was the hardes thing that I have unpacked up to this day. Lot of tricks, but main problem is that it uses them constantly over and over. Avoiding being detected in SDProtector is like trying to run betwen rain drops - impossible. But it is very smart protector and you can learn a lot from it.



    More info about SDProtector:

    SDProtector 1.1 protected WinXP Notepad unpacking - by softworm (chinese tutorial)
    SDProtector 1.12 - parts I,II,III,IV - by +NCR/CRC! [ReVeRsEr] (spanish tutorial)
    SDProtector 1.16 - by +NCR/CRC! [ReVeRsEr] (spanish tutorial)




    (c) haggar 2006

  9. #69
    پروفشنال Morteza_SOS's Avatar
    تاريخ عضويت
    Apr 2006
    پست ها
    577

    پيش فرض

    Level : newbie

    Unwrapping eLicense 4.0





    This small tut will describe removing protection layer from eLicense 4.0 protected programs. Since eLicense is not available for evaluation, I was not able to protect some mine file with it and make a target for tutorial. Because of that, I used shareware application for a target. However, I will not provide target name or downlad link in this tutorial. I want to keep it legal (if cracking tutorial can be that at all) as much as possible.








    1. Intruduction

    After installing protected application, I scanned install folder with PEiD 0.94. PEiD did not give any possible indication that some file is protected with eLicense protector. On the main executable of installed application it returned "Nothing found*". But in the same folder, one file is recognized as ASPack 2.12. That file was elicen40.dll . Name of this file clearly suggest that this dll is part of eLicense protection system.

    Next step was loading main executable in OllyDbg. I got 4 warnings that some modules have entry point outside of code section before evaluation window showed. Why 4 modules when only one (elicen40.dll) is packed? Also , evaluation window showed altough I didn't started target.

    I found that upon starting target or loading it in olly, it creates file in temporary folder. That file s1cc.2xcp , is a DLL packed with ASPack 2.12 too and it is also part of eLicense system. Second file is ofcourse elicen40.dll. Other two files are lcmmfu.cpl and mmfs.dll , both placed in windows folder, also packed with ASPack. I do not know does this two files are part of protection, but right now that is not important.

    After all modules are loaded and evaluation window is showed, I clicked on "Trial" bottun and my main exe file just crushed in Olly at this point:

    00453132 A0 C8BF0068 MOV AL,BYTE PTR DS:[6800BFC8]
    00453137 5C POP ESP
    00453138 25 450064A1 AND EAX,A1640045
    0045313D 0000 ADD BYTE PTR DS:[EAX],AL
    0045313F 0000 ADD BYTE PTR DS:[EAX],AL
    00453141 50 PUSH EAX
    00453142 64:8925 00000000 MOV DWORD PTR FS:[0],ESP
    00453149 83EC 58 SUB ESP,58
    0045314C 53 PUSH EBX
    0045314D 56 PUSH ESI
    0045314E 57 PUSH EDI
    0045314F 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP
    00453152 FF15 74C24500 CALL DWORD PTR DS:[45C274]
    00453158 33D2 XOR EDX,EDX ; WS2_32.71AC4070
    0045315A 8AD4 MOV DL,AH
    0045315C 8915 8C3B4700 MOV DWORD PTR DS:[473B8C],EDX ; WS2_32.71AC4070
    00453162 8BC8 MOV ECX,EAX


    Later I sow that this is OEP of main protected executable. Whole file is decrypted, but couple first OEP bytes are destroyed (?) so file crushed. But OEP is found. Solution lies in elicen40.dll. Main executable is encrypted and this dll performs decryption. Protection is so simple that I didn't even bother to go deeper inside. Let's see how we can unwrapp target.






    2. Unpacking DLL and finding OEP

    To unpack main executable, we need to unpack elicen40.dll. I hope that you know how to unpack ASPack packed DLL. Ok, in case that you don't know, here is how:

    - load elicen40.dll in Olly
    - place bp on GetProcAddress and run 3 times (then remove bp), return to code
    - scroll down and find

    024A53AF 61 POPAD
    024A53B0 75 08 JNZ SHORT elicen40.024A53BA
    024A53B2 B8 01000000 MOV EAX,1
    024A53B7 C2 0C00 RETN 0C
    024A53BA 68 00000000 PUSH 0
    024A53BF C3 RETN

    - place bp on last RETN
    - run to break on that bp
    - press F7 to go on DLL OEP

    02485415 55 PUSH EBP
    02485416 8BEC MOV EBP,ESP
    02485418 53 PUSH EBX ; elicen40.
    02485419 8B5D 08 MOV EBX,DWORD PTR SS:[EBP+8] ; elicen40.
    0248541C 56 PUSH ESI
    0248541D 8B75 0C MOV ESI,DWORD PTR SS:[EBP+C] ; elicen40.02480000
    02485420 57 PUSH EDI
    02485421 8B7D 10 MOV EDI,DWORD PTR SS:[EBP+10]
    02485424 85F6 TEST ESI,ESI
    02485426 75 09 JNZ SHORT elicen40.02485431
    02485428 833D A8F84902 00 CMP DWORD PTR DS:[249F8A8],0
    0248542F EB 26 JMP SHORT elicen40.02485457
    02485431 83FE 01 CMP ESI,1
    02485434 74 05 JE SHORT elicen40.0248543B
    02485436 83FE 02 CMP ESI,2
    02485439 75 22 JNZ SHORT elicen40.0248545D

    - open LordPE, select loaddll.exe process, in lower pane select our elicen40.dll and make full dump
    - open ImpREC, attach to loaddll.exe, click on "Pick DLL" and select our elicen40.dll
    - enter your OEP=OEP-ImageBase, in my case it is 00005415=02485415-02480000
    - press "IAT auto search", then "Get imports", and then "Fix dump" to rebuild IAT
    - our elicen40.dll is now unpacked from ASPack

    Change name of that dumped_.dll to elicen40.dll and start main exe to see did you unpacked dll correctly. Mine works good. Btw, ASPack can be unpacked without use of ImpREC and in that case we would ge clener dump. But that is not important.


    This dll unpacks our target and then it jumps to OEP via one jump. But if we run target within debugger, OEP bytes will be destroyed. There is quick way around that "bug".
    Load unpacked elicen40.dll in Olly. Select first line at the beggining of code section.Right click on code and select "Search for"->"command". Enter JMP DWORD [CONST] and hit "Find" button. First jump that is founded is our OEP jump:

    02483CCF . FF25 5CF84902 JMP DWORD PTR DS:[249F85C]
    02483CD5 > 5E POP ESI ; ntdll.7C9011A7
    02483CD6 . 5D POP EBP ; ntdll.7C9011A7
    02483CD7 . 5B POP EBX ; ntdll.7C9011A7
    02483CD8 . 8BE5 MOV ESP,EBP
    02483CDA . 5D POP EBP ; ntdll.7C9011A7


    We binary change first two bytes to EB FE (infinite jump) and then we save changes:

    02483CCF -EB FE JMP SHORT elicen40.02483CCF
    02483CD1 5C POP ESP ; ntdll.7C9011A7
    02483CD2 F8 CLC
    02483CD3 49 DEC ECX
    02483CD4 025E 5D ADD BL,BYTE PTR DS:[ESI+5D]
    02483CD7 . 5B POP EBX ; ntdll.7C9011A7
    02483CD8 . 8BE5 MOV ESP,EBP
    02483CDA . 5D POP EBP ; ntdll.7C9011A7


    Now , after program is unpacked, it will run in memory forever. Start main execuatble, click on "Trial" button and program will eneter in infinite jump. Now , opene Olly and just attached to target. Shift+F9 to run it, then F12 to pause it, and you are on the right place:

    02483CCF -EB FE JMP SHORT elicen40.02483CCF
    02483CD1 5C POP ESP ; kernel32.7C816D4F
    02483CD2 F8 CLC
    02483CD3 49 DEC ECX
    02483CD4 025E 5D ADD BL,BYTE PTR DS:[ESI+5D]
    02483CD7 5B POP EBX ; kernel32.7C816D4F
    02483CD8 8BE5 MOV ESP,EBP
    02483CDA 5D POP EBP ; kernel32.7C816D4F


    Restore original bytes FF 25:

    02483CCF -FF25 5CF84902 JMP DWORD PTR DS:[249F85C] ; target.
    02483CD5 5E POP ESI ; kernel32.7C816D4F
    02483CD6 5D POP EBP ; kernel32.7C816D4F
    02483CD7 5B POP EBX ; kernel32.7C816D4F
    02483CD8 8BE5 MOV ESP,EBP
    02483CDA 5D POP EBP ; kernel32.7C816D4F


    F7 to get on OEP:

    0045312C > 55 PUSH EBP
    0045312D 8BEC MOV EBP,ESP
    0045312F 6A FF PUSH -1
    00453131 68 A0C84500 PUSH target.0045C8A0
    00453136 68 5C254500 PUSH target.0045255C
    0045313B 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
    00453141 50 PUSH EAX
    00453142 64:8925 00000000 MOV DWORD PTR FS:[0],ESP
    00453149 83EC 58 SUB ESP,58
    0045314C 53 PUSH EBX
    0045314D 56 PUSH ESI ; ntdll.ZwQueryValueKey
    0045314E 57 PUSH EDI
    0045314F 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP
    00453152 FF15 74C24500 CALL DWORD PTR DS:[45C274]
    00453158 33D2 XOR EDX,EDX ; ws2_32.71AC4070
    0045315A 8AD4 MOV DL,AH
    0045315C 8915 8C3B4700 MOV DWORD PTR DS:[473B8C],EDX ; ws2_32.71AC4070
    00453162 8BC8 MOV ECX,EAX
    00453164 81E1 FF000000 AND ECX,0FF
    0045316A 890D 883B4700 MOV DWORD PTR DS:[473B88],ECX


    And that is OEP! With correct bytes. Now we need to dump files and to fix imports.






    3. Dumping and rebuilding IAT

    First we need to dump main executable. Open LordPE and in options, under "Task viever", select "Full dump:Paste header from disk". That is important since eLicense corrupts PE header in memory. Now make a full dump.

    Imports are hidden. If check one call:

    00453152 FF15 74C24500 CALL DWORD PTR DS:[45C274] ; DS:[0045C274]=0015C6DD

    Then we follow it:

    0015C6DD 50 PUSH EAX
    0015C6DE A1 38C71500 MOV EAX,DWORD PTR DS:[15C738]
    0015C6E3 3305 48C71500 XOR EAX,DWORD PTR DS:[15C748]
    0015C6E9 A3 485B1400 MOV DWORD PTR DS:[145B48],EAX
    0015C6EE 58 POP EAX ; kernel32.7C816D4F
    0015C6EF FF25 485B1400 JMP DWORD PTR DS:[145B48]

    We can see that it has encrypted imports. But it is simple:

    Import = Encrypted_import XOR some_constant




    I just wrote one script for olly , that will restore all imports in my target. It does same thing as eLicense code - it just XOR two values. Check script and try to write one that will work for your target:


    //eLicense 4.0 import fixer

    var pointer
    var constant
    var addr
    mov addr,45c000 //Start of import table.

    label_01:
    cmp addr,45c5f4 //End of import table.
    ja end_01
    mov pointer,[addr]
    and pointer,0FFFF0000
    cmp pointer,00160000
    add addr,4
    jne label_01
    sub addr,4
    mov pointer,[addr]
    add pointer,2
    mov pointer,[pointer]
    mov pointer,[pointer]

    mov constant,[addr]
    add constant,8
    mov constant,[constant]
    mov constant,[constant]

    xor pointer,constant

    mov [addr],pointer
    add addr,4

    jmp label_01
    end_01:

    ret


    Script scans import table in file and not code section.
    After fixing imports, we need to use ImpREC. In ImpREC options, select also "Use PE header from disc". Then attach to target, click "IAT auto search", then "Get imports", and then "Fix dump". Find dumped.exe and fix it. Run dumped_.exe and if it's work, you have unpacked eLicense 4.0.

  10. #70
    پروفشنال Morteza_SOS's Avatar
    تاريخ عضويت
    Apr 2006
    پست ها
    577

    پيش فرض

    Level : newbie

    Serial Fishing Tutorial #1 [by: Khaosgott96]


    Hello fellow crackers and newbies. This is my VERY first tutorial I have EVER written so if u have any suggestions on making my future tutorials more informative drop me an email at: [ برای مشاهده لینک ، با نام کاربری خود وارد شوید یا ثبت نام کنید ]



    TOOLS USED

    OllyDbg 1.09d or 1.10


    Target
    ------

    Power Archiver 9.26.01


    ================================================== ================================================== ===========================

    Ok so first things first. Install PowerArchiver (Thats a given) and run it... a message box should pop up saying this is an evaluation version blah blah blah.....
    then u have the options of clicking I agree to use it as an evaluation version or to enter the registeration information ("Enter Registraion Code...") click that and enter any name and serial into it.
    I use khaosgott96 for the name and 12345678 for the registration code. Then click OK and you should get an error saying "Incorrect registration information"
    So bust out a pen and paper (which, while cracking, you should always have by you) and write that error down. it is not neccessary to write the whole thing down just "Incorrect registration information" will be fine.

    Now... Open up Olly and then click file/open and open up POWERARC.EXE

    you should have something like the following...



    next thing your gunna do is right click in the code window (See figure above) and click "Search For-----> All referenced text strings"
    Next scroll up to the top and highlight the first line. then right click anywhere in that window and click "Search For Text"
    now be sure to UNCHECK the case sensitive box. now type in the search "incorrect registration information" and press OK.

    See Figure Below...

    [image6]


    now... click that line to make sure it is highlighted and press enter. you should now be taken back to the code window.
    You now should have landed here... (See figure below)



    Now if you scroll up a bit you'll see:


    006519A9 > 55 PUSH EBP
    006519AA . 8B55 F4 MOV EDX,DWORD PTR SS:[EBP-C]
    006519AD . 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]


    look at the picture below and compare it to the code listed above...



    OK so if we take a look at the following code again we see:


    006519A9 > 55 PUSH EBP
    006519AA . 8B55 F4 MOV EDX,DWORD PTR SS:[EBP-C]
    006519AD . 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]

    so highlight the line:
    006519AD . 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]

    and press F2 to set a breakpoint. now were ready to to catch the program by its tail right before it enters the serial generation routine.

    Now press F9 to run the program. (if u get any execeptions press shift+F9 until the program runs). now keep olly open and go to PowerArchiver and click "Enter Registration Code" and enter any name for the username but remember what name u used because you will need it later.
    Enter 12345678 as the registration code and click OK. Olly should break and pop up. if it didnt then you didnt set your BreakPoint right, so go back and look how to set it correctly.
    Otherwise just continue with the tutorial. Now if you look in the REGISTERS window in olly you will see that EDX contains out user-entered serial "12345678", so what we are going to do is set a breakpoint on it so when the program goes to access it to compare it to the real serial it will break and there in plain text we will see the REAL serial to which it is being compared to.
    So then all we have to do is write that number down close olly and reopen the program normally and enter the same name and then the REAL serial that we just fished out.
    "well how the f*ck do u do that??" u may ask... well i'll tell you.

    First thing you are going to do is higlight the EDX resiter by left clicking it in the REGISTERS window.
    Then Right click what you just highlighted and click "Follow In Dump". Now take a look at the Hex Dump Window.
    You should see you User-entered serial. in our case "12345678" or in hex "31 32 33 34 35 36 37 38". So what you need to do is highlight the first 4 bytes of our user entered serial in our hex dump window.
    These bytes being "31 32 33 34" then right-click the highlighted bytes and click Breakpoint----->Hardware, On Access,------->DWORD. Now what that did was tell Olly to break when it accesses our serial again.
    The next time this serial will be accessesd is then it is compared to the REAL serial generated by PowerArchiver. That being said we will see what the REAL serial for our user-entered name will be. (SEE FIGURE BELOW)



    Okay.... do now you have your breakpoint set. now all you have to do is press F9 and olly should then again break. and what do we have in our register window....well we have our user-entered serial in ESI which is "12345678" and whats that right below it???....it looks like its the REAL serial that the program is checking OUR serial against. it is stored in EDI which contains "BC8097CF".... write this number down. yours will probably be different especially if you used a different name than khaosgott96.



    Have that written down..??? GOOD. now exit Olly and open PowerArchiver by itself..no Olly this time....Sorry olly ur all alone this time.... now click Enter Registration Code and enter the name that you used when u fished out a serial. and use the serial that we fished out for the registration code. and click OK....YES!!! REGISTRATION ACCEPTED....congratulations you now successfully broke through PowerArchiver's protection scheme.

Thread Information

Users Browsing this Thread

هم اکنون 1 کاربر در حال مشاهده این تاپیک میباشد. (0 کاربر عضو شده و 1 مهمان)

User Tag List

قوانين ايجاد تاپيک در انجمن

  • شما نمی توانید تاپیک ایحاد کنید
  • شما نمی توانید پاسخی ارسال کنید
  • شما نمی توانید فایل پیوست کنید
  • شما نمی توانید پاسخ خود را ویرایش کنید
  •