EvOlUtIoN Posted December 21, 2009 Posted December 21, 2009 (edited) Well, I know that execryptor 2.4.1 is actually quite old. But just click on protect is not enough, this itime i used some sdk, and also put a 5 uses trial, after 5 uses some strings are lost. And also i put some custom things that will make the target more hard. Difficulty: 3/10 Goal: unpack it and make it working forever. Good luck execryptor_unpackme_2009.rar Edited December 21, 2009 by EvOlUtIoN 1
SunBeam Posted December 22, 2009 Posted December 22, 2009 (edited) Interesting. This reminds me of an old target I had to inline once (RSI had some issues as well). What puzzles me still is the fact that you've used god damn high memory (BaseOfCode, SizeOfImage) so that the "unpacked" file eats up to ~700MB of memory. This is one thing I gotta solve first, then I'll post my version. Maybe an inline? :-) Edited December 22, 2009 by SunBeam
EvOlUtIoN Posted December 22, 2009 Author Posted December 22, 2009 Well the big memory used is one of thing i have implemented manually, this was for avoid do use automatic unpacker. Maybe it will work anyway, but the operation take more than a while. It should be easy to solve though, not needed much knowledge, and using correct plugins and pe editors you can dump with a more reasonable size. I prefer unpacked instead of inline or loader.
thisistest Posted December 22, 2009 Posted December 22, 2009 0040198C 6A 00 PUSH 00040198E FF15 E0434000 CALL DWORD PTR DS:[4043E0] ; kernel32.GetModuleHandleA
EvOlUtIoN Posted December 22, 2009 Author Posted December 22, 2009 no thisistest, oep is not a masm type.
SunBeam Posted December 22, 2009 Posted December 22, 2009 @thisistest: OEP is at 401900.And Evo set a SEH at OEP, just to make sure nothing wrong happens in between :-)2944EE01 64:FF35 00000000 PUSH DWORD PTR FS:[0]2944EE08 - E9 092BFBD6 JMP execrypt.00401916..00401916 64:8925 00000000 MOV DWORD PTR FS:[0],ESP0040191D 83EC 50 SUB ESP,5000401920 53 PUSH EBX00401921 56 PUSH ESI00401922 57 PUSH EDIWorking on unpacking it :-P
EvOlUtIoN Posted December 22, 2009 Author Posted December 22, 2009 Yes oep is correct of course, but this is not an asm compiled, so sehandlers are from compiler here
SunBeam Posted December 22, 2009 Posted December 22, 2009 I never said it's ASM :-P Just traced till obfu_OEP, then out of wrapper and into stolen bytes. Then landed at that SEH (generated probably with _try _except etc..)..
quosego Posted December 22, 2009 Posted December 22, 2009 (edited) Since we're doing a little contest here.. Let's join the fun. Unpacking Ftw. Btw if sunbeam can't do this in 10 mins it's at least 5/10. EDIT: And yeah that 700mb resource section is rather annoying. Edited December 22, 2009 by quosego
EvOlUtIoN Posted December 22, 2009 Author Posted December 22, 2009 I know it is annoying, and i can tell that the protection can be done also better indeed, i will put it in another target...i don't think this will take so much to be solved. Simply it is better to dump with a method different from other times .
LCF-AT Posted December 22, 2009 Posted December 22, 2009 Hello,here my unpacked file.I hope this is what you want so I canexecryptor_unpackme_2009_Unpacked.rar 1
SunBeam Posted December 23, 2009 Posted December 23, 2009 Good work, LCF-AT.And despite quosego's remark, it still puzzles me how to solve this unpackme. It's not EXECryptor that bugs me, but the god damn resources section.LCF-AT, will you shed some light into this? As in, how you unpacked it - just the "how to cut the freaking 700 MB out of the dumped file" part :-) Or you may share it all..
Why Not Bar Posted December 23, 2009 Posted December 23, 2009 (edited) file dumped ~700MB File Unpacked... execryptor_unpacked.rar Edited December 23, 2009 by Why Not Bar
EvOlUtIoN Posted December 23, 2009 Author Posted December 23, 2009 Really ths 700MB section is so hard to dump?Remember that you can also dump sections one by one...
quosego Posted December 23, 2009 Posted December 23, 2009 Yeah it can be done by dumping partially etc and reconstructing.. But I was just being stubborn and simply wanted to do it like I always do execryptor. Which didn't work in my slow VM which takes ages to process this.. More like a time thing than impossible. Wanted to just move everything low mem and insert a big virtual size in the PE header like the original.
EvOlUtIoN Posted December 23, 2009 Author Posted December 23, 2009 Nothing is impossible of course, but how to distribute a 700MB unpacked file? My aim was to produce an unpackme harder than a simple execryptor old unpackme, and seems that i done it. Congratulations for both solvers.
quosego Posted December 23, 2009 Posted December 23, 2009 (edited) Neah would've done raw size smaller and virtual size 700 mb. Edited December 23, 2009 by quosego
SunBeam Posted December 23, 2009 Posted December 23, 2009 Idea was this -- when you buff up the resources section up to 700 MB, addresses around it get that amount added to them. As in: sec1 - 400000 sec2 - 400000 + 700MB -> 254xxxxx And guess what happens when you put on EXECryptor. Of course, the calculated VM will do this: push 290932009 add eax, 273289371 pop ebx add eax,ebx etc.. So result will be an address like 254xxxxx <- and how would you go through that VM? I've solved a loader once for WinOLS which used same tactics. So I had dumped the VM sections manually. Then loaded a dummy app. Used Cheat Engine to load up the sections in memory at their designated addresses, after which I ran he deVM script to acquire the crypt_constants used to clean the code. Once I got them all (cuz if I ran it through the 700MB VM, at some point Olly got stuck and would run very slow - like 1 instruction every 1 minute) I could see where I'm going :-) So, once more, would be very interested in a "how to do this ****" tutorial Now that the crackme's been solved..
LCF-AT Posted December 23, 2009 Posted December 23, 2009 Hi, so I never would make a dump with a hugh size like 700 MB. Here a short tutorial for SunBeam and also the others of course. --------------------------------- 1. Get OEP / use HeapCreate or GetModuleHandleA to come close on this place. 2. Break on the first OEP command which will used. 3. Make a copy of the UnpackMe 4. Load the copy in LordPE and fix all manually --- Just remove all 29xxxxxx / ALL / Imports, Tls etc... 5. Load the fixed size copy in a second Olly / EP 0054C985 RVA now 6. Dump all sections exept the last one of the first loaded UnpackMe in Olly 1 --- Use Dump Region and enter the address & size manually / look in Olly 2 there you can see the sections correctly now 401000 | 2000 403000 | 1000 etc.... 7. Open a hex editor like winhex.Load on section like 401000-2000 into and select all and copy it with hex value 8. Go to Olly 2 and go to section 401000...select all and paste now you got one sections fixed. 9. Do the same with the rest too. 10. Fix IAT in your first Olly so for this you can use the script by PE_Kill to make it fast. 11. Select fixed IAT and copy it in Olly 2. 12. Set Olly 2 on the right OEP and fix the few stolen bytes. 13. Create a dump in Olly 2 with Olly Dump plugin,disable rebuild imports & enable fix raw size. 14. Load the new dump in Olly 2 15. Load / loadlib "COMCTL32.dll" / 00404458 773116C9 <---- 16. Run 17. Bad message AV at address 294B0E68 so this address does not exist in our dump file. 18. Go to Olly 1 to address 294B0E68 19. Scroll up to find the start / or enter 2941B000 <-- start of code. till $+132FFE <-- End 20. Go again to LordPE and dump 2941B000 | 133000 21. Add section to our dump / make valid rebuild 22. Load dump in Olly /load COMCTL32.dll / insert IAT binary. 23. Open ImpRec enter data etc.. 24. Fix our [section]-dump 25. Make valid rebuild- 26. Load fixed dump in Olly and run.Dump starts now- 27. Check the new added section to see whether this section is really needed or not. 28. Set MemBP on access on it and run.From codesection to new section to codesection / switching memBPs. 29. 3 times breaks on it....Look a bit back to find start of routine or other decision. 00401120 PUSH EBP // RET00401121 MOV EBP,ESP00401123 SUB ESP,400401126 PUSH EBX00401127 PUSH ESI00401128 MOV EBX,DWORD PTR SS:[EBP+8]0040112B JMP 2944CC88004010D0 PUSH EBP // RET004010D1 MOV EBP,ESP004010D3 SUB ESP,1C004010D6 JMP 294B0E68004012D5 CMP EAX,1004012D8 JNZ SHORT 00401304004012DA CALL 29448AA7 // NOP004012DF CALL 2949250C // NOP So make this patches and save and now you have a fast working file.So the code is not really needed so we can just make this patches in this case.Now you can also make some cosmetic changes like removing some sections and the TLS...CallBack [004BB12C] 2954C991 <-- 0 it- greetz
EvOlUtIoN Posted December 24, 2009 Author Posted December 24, 2009 Yes, that's the right way...thank you LCF-AT@sunbeamI solved the same winols loader, but i preferred an inline that time instead of unpacking. Anyway that is where i taken the idea.
SunBeam Posted April 16, 2010 Posted April 16, 2010 @LCF_AT:This still doesn't solve my initial problem. As I said, when EXECryptor unwraps itself, the VM works in such a fashion that the calculated addresses are in high memory. My goal wasn't to unpack the file, but rather make it so VM is moved to low memory, in order for me to clean it up (since Olly stucks at high memory). I followed your tutorial up to the point where you say "check if sections are used with memory breakpoints on access". Then it hit me - I don't want to remove sections from the file, I just want the unpacked code to land in low memory.See this:0054C985 > E8 3BFFFFFF CALL copy.0054C8C50054C98A 05 690A0000 ADD EAX,0A690054C98F FFE0 JMP EAX..0054C8C5 E8 00000000 CALL copy.0054C8CA0054C8CA 58 POP EAX0054C8CB 56 PUSH ESI0054C8CC 57 PUSH EDI0054C8CD 51 PUSH ECX0054C8CE 53 PUSH EBX0054C8CF 50 PUSH EAX0054C8D0 8B1C24 MOV EBX,DWORD PTR SS:[ESP]0054C8D3 81EB CAC85429 SUB EBX,2954C8CA // ------------------- [1]0054C8D9 B8 EE690000 MOV EAX,69EE0054C8DE 50 PUSH EAX0054C8DF 6A 04 PUSH 40054C8E1 68 00100000 PUSH 10000054C8E6 50 PUSH EAX0054C8E7 6A 00 PUSH 00054C8E9 B8 C4B04B29 MOV EAX,294BB0C4 // ------------------- [2]0054C8EE 8B0418 MOV EAX,DWORD PTR DS:[EAX+EBX]0054C8F1 FFD0 CALL EAXWhat I showed above is only the easy part. There are portions in EC that use calculus:PUSH DWORD{ calculus here } // $RESULT is something like 29xxxxxxJMP to $RESULTSo yeah, any ideas? :-)
SunBeam Posted April 16, 2010 Posted April 16, 2010 (edited) I found the solution, yet I gotta fix VolX's script a bit for deVM-ing. Basically, follow your tutorial, remove all 29xxxxxx from everything (SizeOfImage, BaseOfCode, sections, IAT location and APIs, TLS wiped). Save file and rebuild PE. Load file and use this as a script:/*LPVOID WINAPI VirtualAlloc( __in_opt LPVOID lpAddress, __in SIZE_T dwSize, __in DWORD flAllocationType, __in DWORD flProtect // ptr);*/pauseexec pushad push 40 push 3000 push 133000 push 2941B000 call VirtualAlloc mov ecx, 133000 mov esi, 41B000 mov edi, 2941B000 rep movs byte ptr [edi], byte ptr [esi] popadendemov eip, 2954C991retIt allocates the high-memory of the original file, without .rsrc being that BIG. Then copies the code starting from first EC section till end of file to what we earlier allocated. Sets EIP, so we can trace from there :-) Unpacking of code works perfectly, as EC fills the sections correctly. The only thing deVM script fails at is getting correct SizeOfImage. I'll fix it in VolX's script.EDIT: Now that I changed my PC (to a Core2Duo one) Olly doesn't freeze anymore when script traces through high-memory for those 0x40 crypt constants T_T. This is stupid.. Makes me wanna kill myself. Well, it was good to try as proof of concept. Maybe some of you still have old rigs on which Olly will basically run a line of code every 2-3 minutes in a 700MB memory-mapped file :-) Edited April 16, 2010 by SunBeam
antrobs Posted April 17, 2010 Posted April 17, 2010 Great info! and thanks for reminding about old rigs too.... i'm planing to buy i5.
SunBeam Posted April 17, 2010 Posted April 17, 2010 (edited) Here you go, unpacked, VM-included and cleaned. Don't expect it to run, I'll explain :-)/*| PART 1 - TRACING\*00401900 - E9 19530929 JMP 29496C1E29496C1E 50 PUSH EAX // save state of EAX ..29496C27 68 2DA077AA PUSH AA77A02D // from here [1]..29496C34 58 POP EAX..29496C3D 81E8 B8572167 SUB EAX,672157B829496C43 ^ E9 DC71FBFF JMP 2944DE24..2944DE24 81C0 C1E5ECE5 ADD EAX,E5ECE5C1 // to here [2]..2944DE31 870424 XCHG DWORD PTR SS:[ESP],EAX // we get [ESP] == 29432E36..2944DE3A E9 31F30300 JMP 2948D170..2948D170 C3 RETNSo exit point is 29432E36. Moving on:29432E36 56 PUSH ESI // save state of ESI register..29432E3F 68 042F35EB PUSH EB352F04 // from here [3]..29432E4C 5E POP ESI..29432E55 81CE 9AE49A60 OR ESI,609AE49A29432E5B ^\E9 06D5FEFF JMP 29420366..29420366 81C6 EB13823D ADD ESI,3D8213EB // till here [4]..29420373 873424 XCHG DWORD PTR SS:[ESP],ESI // we get [ESP] == 29420389; used later as RET point for function 2949BEE5..2942037C E9 64BB0700 JMP 2949BEE5Now we are inside an EXECryptor_API, which starts here:2949BEE5 55 PUSH EBP2949BEE6 8BEC MOV EBP,ESP <-- we step over this line with F7So, follow ESP (or EBP, since they are equal), follow in dump and set a hardware breakpoint on access (DWORD). Shift+F9 and we're here:00401046 8BE5 MOV ESP,EBP00401048 5D POP EBP00401049 C3 RETN <-- you are hereExit RET with F7 and we are where I said earlier:29420389 50 PUSH EAXThis is another masked API:29420389 50 PUSH EAX..29420392 892C24 MOV DWORD PTR SS:[ESP],EBPThose two basically mean PUSH EBP :-) Then:294B3405 89E5 MOV EBP,ESP <-- F7 to step over this lineIf we repeat the same idea, with following ESP (or EBP) in stack, setting a HWBP on access, DWORD, we observe that API never exits. Application dies. Let's investigate why..2944EE01 64:FF35 00000000 PUSH DWORD PTR FS:[0] // part of the stolen bytes from 4019002944EE08 - E9 092BFBD6 JMP unpacked.00401916/*| PART 2 - NO DYING ON ME\*Well, if you trace down the code, you will end up to here:004019AC 52 PUSH EDX004019AD 50 PUSH EAX004019AE 6A 00 PUSH 0004019B0 53 PUSH EBX004019B1 E8 3AF8FFFF CALL unpacked.004011F0That is WinMain(). Inside it, tracing a bit, we get up to here:00401260 6A 00 PUSH 000401262 68 80124000 PUSH unpacked.0040128000401267 6A 00 PUSH 000401269 68 E9030000 PUSH 3E90040126E 53 PUSH EBX0040126F FF15 48444000 CALL DWORD PTR DS:[<&user32.DialogBoxParamA>] ; user32.DialogBoxParamAThe function at 401280 is the one that crashes us. Let's see why:00401280 53 PUSH EBX <-- set breakpoint here with F2Shift+F9 once. Shift+F9 once more, and trace a bit up to here:004012B2 E8 19FEFFFF CALL unpacked.004010D0This is a call to VM (well, it's clean now so you can see where you're going). So let's trace a bit:29486B87 FF15 C4434000 CALL DWORD PTR DS:[<&kernel32.VirtualQuery>] ; kernel32.VirtualQueryStack is:$ ==> > 2941B000 |Address = 2941B0004 > 0012FB18 |Buffer = 0012FB188 > 0000001C \BufSize = 1C (28.)So it interrogates the current section's characteristics. Moving on:29426381 817D E8 00004000 CMP DWORD PTR SS:[EBP-18],400000 // [EBP-18] would be 2941000029426388 0F84 CE680200 JE 2944CC5CSince this check fails, cuz 29410000 used to be a section inside the original executable, which I've relocated, its base won't be the same as the file's (400000). Check fails, we crash :-) So let's fix it:29426388 /E9 CF680200 JMP 2944CC5C2942638D |90 NOPNow you'll see it runs :-P Chunk is copied from 41B000, so let's find those bytes in there and change them in the file, so when copy ocurrs, JMP is fixed by itself:00426381 817D E8 00004000 CMP DWORD PTR SS:[EBP-18],unpacked.0040000000426388 E9 CF680200 JMP unpacked.0044CC5C0042638D 90 NOPSave changes to the file and see it work now :-)I'll post more about used APIs later on ;-)Cheerios,Sununpacked.zip Edited April 17, 2010 by SunBeam 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now