Author Archives: Reverse2learn
ZeroAccess new variant (Self Debugging)Unpacker
ZeroAccess new variant (crypter) is in the news from past few days. It is different from traditional crypters which either uses RunPE or overwrite the original image with decrypted Image.It is already covered in avast blog post ,so i will just summarize it in shorter steps.It Basically uses Self debugging concept (it’s not a new thing)
1)Launch its own instance in debug mode (child process)
2)Parents Process Enter into debug loop ,and listen for events from debugee and handle them
3)It decrypts the Embedded PE when it Receives SINGLE_STEP Exception
After Decrypting the Image we have following Function
.text:004013DA ZeroAccess_PE_Load proc near ; CODE XREF: sub_4014A7+42p
.text:004013DA
.text:004013DA Local_SizeofImage= dword ptr -14h
.text:004013DA var_10 = dword ptr -10h
.text:004013DA var_C = dword ptr -0Ch
.text:004013DA Section_Handle = dword ptr -8
.text:004013DA Section_Base_Address= dword ptr -4
.text:004013DA Decompress_Binary= dword ptr 8
.text:004013DA Size = dword ptr 0Ch
.text:004013DA
.text:004013DA push ebp
.text:004013DB mov ebp, esp
.text:004013DD sub esp, 14h
.text:004013E0 push ebx
.text:004013E1 push esi
.text:004013E2 push edi
.text:004013E3 push [ebp+Decompress_Binary]
.text:004013E6 call ds:RtlImageNtHeader
.text:004013EC mov ebx, eax
.text:004013EE xor esi, esi
.text:004013F0 cmp ebx, esi ; Check if Valid NT Header
.text:004013F2 jz Invalid_Nt_Header_Return_0
.text:004013F8 mov eax, [ebx+IMAGE_NT_HEADERS32.OptionalHeader.SizeOfImage]
.text:004013FB push esi
.text:004013FC mov [ebp+Local_SizeofImage], eax
.text:004013FF push SEC_COMMIT
.text:00401404 xor eax, eax
.text:00401406 push PAGE_EXECUTE_READWRITE
.text:00401408 lea edi, [ebp+var_10]
.text:0040140B stosd
.text:0040140C lea eax, [ebp+Local_SizeofImage]
.text:0040140F push eax
.text:00401410 push esi
.text:00401411 push SECTION_ALL_ACCESS
.text:00401416 lea eax, [ebp+Section_Handle]
.text:00401419 push eax
.text:0040141A call ds:ZwCreateSection
.text:00401420 test eax, eax
.text:00401422 jl short Invalid_Nt_Header_Return_0
.text:00401424 push 4
.text:00401426 push esi
.text:00401427 push 2
.text:00401429 lea eax, [ebp+var_C]
.text:0040142C push eax
.text:0040142D push esi
.text:0040142E push esi
.text:0040142F push esi
.text:00401430 lea eax, [ebp+Section_Base_Address]
.text:00401433 push eax
.text:00401434 push 0FFFFFFFFh
.text:00401436 push [ebp+Section_Handle]
.text:00401439 mov [ebp+Section_Base_Address], esi
.text:0040143C mov [ebp+var_C], esi
.text:0040143F call ds:ZwMapViewOfSection
.text:00401445 test eax, eax
.text:00401447 jl short Close_Handle
.text:00401449 mov edi, [ebp+Section_Base_Address]
.text:0040144C mov esi, [ebp+Decompress_Binary]
.text:0040144F mov ecx, [ebx+IMAGE_NT_HEADERS32.OptionalHeader.SizeOfHeaders]
.text:00401452 rep movsb
.text:00401454 movzx edx, [ebx+IMAGE_NT_HEADERS32.FileHeader.NumberOfSections]
.text:00401458 movzx eax, [ebx+IMAGE_NT_HEADERS32.FileHeader.SizeOfOptionalHeader]
.text:0040145C lea eax, [eax+ebx+IMAGE_NT_HEADERS32.OptionalHeader]
.text:00401460 test edx, edx
.text:00401462 jz short If_Zero_Section
.text:00401464 add eax, 14h ; PImage_Section_Header->PointertoRawData
.text:00401467
.text:00401467 Copy_Sections: ; CODE XREF: ZeroAccess_PE_Load+A1j
.text:00401467 mov esi, [eax] ; ESI=Pointer to Raw Data
.text:00401469 mov edi, [eax-8] ; EDI=Virtual_Address
.text:0040146C add esi, [ebp+Decompress_Binary] ; PointerToRawData_Binary_ImageBase
.text:0040146F add edi, [ebp+Section_Base_Address]
.text:00401472 mov ecx, [eax-4] ; SizeOfRawData
.text:00401475 add eax, 28h ;Point to Next Section Headerr
.text:00401478 dec edx ;decrement no_of_section
.text:00401479 rep movsb
.text:0040147B jnz short Copy_Sections ; ESI=Pointer to Raw Data
.text:0040147D
.text:0040147D If_Zero_Section: ; CODE XREF: ZeroAccess_PE_Load+88j
.text:0040147D push [ebp+Section_Base_Address]
.text:00401480 push 0FFFFFFFFh
.text:00401482 call ds:ZwUnmapViewOfSection
.text:00401488 mov eax, [ebp+Section_Handle]
.text:0040148B mov ecx, [ebp+Size]
.text:0040148E mov [ecx], eax
.text:00401490 xor eax, eax
.text:00401492 inc eax
.text:00401493 jmp short Return
.text:00401495 ; ---------------------------------------------------------------------------
.text:00401495
.text:00401495 Close_Handle: ; CODE XREF: ZeroAccess_PE_Load+6Dj
.text:00401495 push [ebp+Section_Handle]
.text:00401498 call ds:ZwClose
.text:0040149E
.text:0040149E Invalid_Nt_Header_Return_0: ; CODE XREF: ZeroAccess_PE_Load+18j
.text:0040149E ; ZeroAccess_PE_Load+48j
.text:0040149E xor eax, eax
.text:004014A0
.text:004014A0 Return: ; CODE XREF: ZeroAccess_PE_Load+B9j
.text:004014A0 pop edi
.text:004014A1 pop esi
.text:004014A2 pop ebx
.text:004014A3 leave
.text:004014A4 retn 8hg
.text:004014A4 ZeroAccess_PE_Load endp
This routine act as a PE Loader ,it reads PE Header and Load PE Decrypted Image Accordingly
So where we can possibly dump it ??
A really good candidate is RtlImageNtHeader !!!
Prototype from ReactOs
PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader(IN PVOID ModuleAddress );
It takes Raw Binary as Input and Give Back Pointer to IMAGE_NT_HEADERS,So idea is to Hook the RtlImageNtHeader and Dump the Memory Block,As we are dumping to binary in raw state so we do not have to realign the binary .
RtlImageNtHeader can be called by other windows dll internally ,so to get the correct call just check if it is called
from main executable (ImageBase to ImageBase+SizeofImage) by checking return address.
ZeroAccess Unpacker Download Link
https://www.dropbox.com/s/iq5eh95fwsks5sy/ZeroAcsessUnpacker.rar
Components
1)Inject.exe =>Start executable in suspended mode and Inject dll(using CreateRemoteThread),after sleeping for 400ms resume
main thread
2)ZeroAcccess_Unpack.dll=> dll that install hooks and dump unpacked file
Note :This did not include any check if sample is ZeroAccess,if you provide non ZeroAccess sample it will produce
unexpected results
Usage :
inject.exe sample.exe
Malware Reversing Part 1
MD5 Hash : 1d8ea40a41988b9c3db9eff5fce3abe5
This is First Part of 2 Part Series .This Malware Drops A File (All malwares do it usually)..So in This Part We will only Analyze Dropper and Next Part We will Analyze Dropped File.
Originally Sample is Downloaded from KernelMode.info ..It is very Good Place for Malware Samples and Reverse Engineering .I Uploaded the Sample to sendspace ..The Password to File is “infected”
Link
http://www.sendspace.com/file/to53wo
Anyway Start With Basic Stuff..Check it with ExeInfo/Protection ID for Packer Detection or Compiler Detection .
NOTE: I Have Dedicated Virtual Machine For Malware Analysis .I recommend You to have same..
Here are Results From ExeInfo/Protection ID
So Sample is Not Packed .:D (Normally Malwares Are packed )
Compiler Detected : Visual C++ 2008
Fine Till Now
Visual C++ Targets are Kind of Ideal For Reversing ..Unlike Delphi Targets That Contain annoying Calls..VC++ Targets are Relatively Easier to Reverse .
Debugger /Disassembler we are going to use are
1)Ollydbg
2)IDA
I have a habit of Running Both IDA and Ollydbg parallely .IDA is very Powerful Due to Its Features Like Renaming the Variables, Functions ,Locations and Cross Reference etc ..Ollydbg is my Personal Favorite Debugger.
Also This Article is mainly to demonstrate Reverse Code Engineering ..I will try to Reverse Engineer Important parts of Malware .
Trace into Ollydbg Till WinMain = 00401648 or Use IDA ..IDA By default Start From WinMain
So lets start Analyzing from WinMain
00401648 /$ 8BFF MOV EDI,EDI //Do Nthing
0040164A |. 55 PUSH EBP //Standard Function Start –Save Frame Pointer
0040164B |. 8BEC MOV EBP,ESP //Move Stack Pointer to EBP
0040164D |. 83EC 1C SUB ESP,1C //Allocate 1C (28) Bytes For Local Variables
00401650 |. 56 PUSH ESI //Save Registers Before Calling
00401651 |. 57 PUSH EDI
00401652 |. E8 120D0000 CALL sample.00402369
Lets Trace Into This Call.. Disassembly Inside Call Looks Like This
Lets Start From Something Interesting.. We have A Call To API “GetModuleHandleW” ,the argument passed is 0 .
We All Know GetModuleHandleW(NULL)..Returns Imagebase of Currently Loaded Executable in EAX ..So This Call returns the Imagebase of sample.exe ..Next few Lines are Interesting
0040237A |. 8BF0 MOV ESI,EAX //Now ESI Contain Imagebase
0040237C |. 8B46 3C MOV EAX,DWORD PTR DS:[ESI+3C] //Get NT HEADER OFFSET
0040237F |. 8B9C30 800000 MOV EBX,DWORD PTR DS:[EAX+ESI+80] //Image_import_Directory
00402386 |. 03DE ADD EBX,ESI //Address Of _IMAGE_IMPORT_DESCRIPTOR Structure
00402388 |. 8B43 0C MOV EAX,DWORD PTR DS:[EBX+C] //Point to Name Field of _IMAGE_IMPORT_DESCRIPTOR
To Understand Above Code ..You Need Some Basic Understanding of PE Format …
First Here We Have = Imagebase+3c
In PE Format First We have IMAGE_DOS_HEADER …..Lets Explore IMAGE_DOS_HEADER in Windbg
Ignore Other Fields.. Here we have e_lfanew at offset 0x3C.
e_lfanew Actually Contains the offset to PE Header
MOV EAX,DWORD PTR DS:[ESI+3C]
So above instruction is to get NT Header Offset
Imagebase is added as we are parsing the File in Memory ..Hope it is Clear Now
MOV EBX,DWORD PTR DS:[EAX+ESI+80]
So What We have is Load value at Imagebase+NT_HEADER+0x80 into EBX ..
Each PE File Contains Array of IMAGE_DATA_ DIRECTORY Structures .Lets Look Into IMAGE_DATA_DIRECTORY Structure
So Each IMAGE_DATA_DIRECTORY Contains Two Fields Virtual Address and Size
NT_HEADER+80 Points to Import_table_address .. The Values of that Directory are
00400170 D4320000 DD 000032D4 ; Import Table address = 32D4
00400174 78000000 DD 00000078 ; Import Table size = 78 (120.)
I Took these values from Memory Window of Ollydbg ..
So what above instruction doing is getting the import table address ..
*Import table is very important concept ..It basically contains the info about imported functions/Dlls
Add Imagebase with Import Table address as we are parsing file in memory
ADD EBX,ESI
Next Instruction is
MOV EAX,DWORD PTR DS:[EBX+C]
This is Interesting .. Import Table is actually a Array of IMAGE_IMPORT_DESCRIPTOR.. Each IMAGE_IMPORT_DESCRIPTOR Structure Contains a Info about Single DLL and Info about Functions imported from this DLL ..SO NO. of IMAGE_IMPORT_DESCRIPTOR= No. of DLLs
Lets Look Into IMAGE_IMPORT_DESCRIPTOR Closely
typedef struct _IMAGE_IMPORT_DESCRIPTOR { _ANONYMOUS_UNION union { DWORD Characteristics; DWORD OriginalFirstThunk; } DUMMYUNIONNAME; DWORD TimeDateStamp; DWORD ForwarderChain; DWORD Name; //offet 0xc DWORD FirstThunk; //offset 0x10 } IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
So in Above Instruction ESI is Pointing to Name From IMAGE_IMPORT_DESCRIPTOR
0040238D |. 8975 F8 MOV [LOCAL.2],ESI //Save ESI Into Local_var
So Next is Loop ..We Can Easily See this in our dear Ollydbg ..Lets Look Into Loop
00402397 |> /03C6 /ADD EAX,ESI //Get Name of DLL In Memory
00402399 |. |68 28134000 |PUSH sample.00401328 ; /s2 = “user32.dll” //Constant String
0040239E |. |50 |PUSH EAX ; |s1 = 000036E4 ??? /
0040239F |. |FF15 48114000 |CALL DWORD PTR DS:[<&msvcrt._stricmp>] ; \_stricmp
004023A5 |. |85C0 |TEST EAX,EAX
004023A7 |. |59 |POP ECX ; sample.00404C78
004023A8 |. |59 |POP ECX ; sample.00404C78
004023A9 |. |0F85 A0000000 |JNZ sample.0040244F
So what above instructions Doing are
1)Get Address of DLL_NAME in Memory
2) Compare the DLL_NAME with “ user32.dll”
3) IF DLL_NAME !=”user32.dll” then Go to NEXT IMAGE_IMPORT_DESCRIPTOR Structure
4)Go to Step 1
So this Loop Continues Untill DLL NAME IS “user32.dll”
So lets Look What Happen When condition is True ..I mean DLL NAME == “user32.dll”
Jump AT 004023A9 is Conditional Jump ..That Not taken If DLL Name ==”user32.dll” .So lets Look Into Code Below the conditional Jump when we Got a Match with DLL Name .
004023AF |. 8B3B MOV EDI,DWORD PTR DS:[EBX] //Get Address OF RVA of IAT in EDI
004023B1 |. 03FE ADD EDI,ESI // Get In Memory Address
004023B3 |. 8B73 10 MOV ESI,DWORD PTR DS:[EBX+10] // RVA of FirstThunk
004023B6 |. 0375 F8 ADD ESI,[LOCAL.2] // IN Memory Address of FirstThunk
So what Above Code Does is Get IN Memory Address(Virtual Address of FirstThunk)..
(Look into PE format to Know More About IAT)
This Whole Procedure is Actually to Parse the Names of APIs Imported By DLL.
004023BE |> /8B4D F8 MOV ECX,[LOCAL.2]
004023C1 |. |8D4408 02 LEA EAX,DWORD PTR DS:[EAX+ECX+2] //Point To Name Of API
So finally Now it Point to Name of APIs Imported By User32.dll
004023BE |> /8B4D F8 MOV ECX,[LOCAL.2] ; sample.00400000
004023C1 |. |8D4408 02 LEA EAX,DWORD PTR DS:[EAX+ECX+2]
004023C5 |. |68 14134000 PUSH sample.00401314 ; /s2 = “RegisterClassExW”
004023CA |. |50 PUSH EAX ; |s1 = “TranslateMessage”
004023CB |. |FF15 48114000 CALL DWORD PTR DS:[<&msvcrt._stricmp>] ; \_stricmp
Check If Current API Name == RegisterClassExW (here it is not equal as First API Imported is Translate Message ).
004023D1 |. |85C0 TEST EAX,EAX ; sample.004037D2
004023D3 |. |59 POP ECX ; sample.004037D2
004023D4 |. |59 POP ECX ; sample.004037D2
004023D5 |. |75 25 JNZ SHORT sample.004023FC
If API Name Matched then DO not JUMP(Execute the Code Below) If Not Matched then JUMP
004023D7 |. |8D45 FC LEA EAX,[LOCAL.1]
004023DA |. |50 PUSH EAX ; /pOldProtect = sample.004037D2
004023DB |. |6A 40 PUSH 40 ; |NewProtect = PAGE_EXECUTE_READWRITE
004023DD |. |6A 04 PUSH 4 ; |Size = 4
004023DF |. |56 PUSH ESI ; |Address = <&USER32.TranslateMessage>
004023E0 |. |FF15 44104000 CALL DWORD PTR DS:[<&KERNEL32.VirtualP>; \VirtualProtect
004023E6 |. |8D45 FC LEA EAX,[LOCAL.1]
IF API NAME MATCHED THEN CHANGE THE PERMISSION FOR THAT ADDRESS (ESI POINT TO ADDRESS OF API) BY USING VirtualProtect
New Protect = PAGE_EXECUTE_READWRITE
MAKE IT WRITABLE
Size= 4
HERE SIZE = 4 Bytes as Probably it Going to Overwrite the API Address ( As we are on 32 bit Arcitecture so Address = 4bytes=32 bits)
Address = ESI ( API ADDRESS) (Address of Target API)
004023E9 |. |50 PUSH EAX ; /pOldProtect = sample.004037D2
004023EA |. |C706 EF194000 MOV DWORD PTR DS:[ESI],sample.004019EF
OverWrite the API Address With 004019EF (Other Function Address)
004023F0 |. |FF75 FC PUSH [LOCAL.1] ; |NewProtect = PAGE_READONLY|PAGE_WRITECOPY
004023F3 |. |6A 04 PUSH 4 ; |Size = 4
004023F5 |. |56 PUSH ESI ; |Address = <&USER32.TranslateMessage>
004023F6 |. |FF15 44104000 CALL DWORD PTR DS:[<&KERNEL32.VirtualP>; \VirtualProtect
Restore the Original Permission Using VirtualProtect
Same Is For Next Part Of LOOP .. it checks API Against “CreateWindowExW”.If Name Matched then Use VirtualProtect to Make that Memory portion Writable .Then Change Address and Again Restore Permission
So let me Write A Pseudo Code To Describe what Just Happened in This LOOP
Parse IMAGE_IMPORT_DESCRIPTOR
If stricmp(Image_Import_descriptor->Name,”user32.dll) //Label2
{
Parse using FirstThunk ..Get API NAMES..
If stricmp(Current_API ,”RegisterClassExW”) //Label1
{
VirtualProtect(Address_of_API,Size(4Bytes), PAGE_EXECUTE_READWRITE,PoldProtec)
// Make it Writable
Address_of_API= 004019EF
VirtualProtect() //Restore original Permissions
}
Else if(Stricmp(Current API,”CreateWIndowExW”)
{
VirtualProtect(Address_of_API,Size(4Bytes), PAGE_EXECUTE_READWRITE,PoldProtec)
// Make it Writable
Address_of_API= 00402228
VirtualProtect() //Restore orginal Permissions
}
Else
{
Get Next API NAME
} //Start From Label 1
Else
{
Get Next IMAGE_IMPORT_DESCRIPTOR TABLE
} //Start From Label 2 ..Once Two Functions are matched Loop Terminates
SO After End OF LOOP We have
Address_RegisterClassExW=004019EF
Address_CreateWindowEx=00402228
Finally Functions Ends and Return …So main Motive is this Function to Make Some Modification in IAT
After Call ..There are some Calls to Resources..More Likely Fake Calls ..As Called Resource does not Exist
00401657 |. 8B7D 08 MOV EDI,[ARG.1] // Move ImageBase Into EDI
0040165A |. 8B35 C8104000 MOV ESI,DWORD PTR DS:[<&USER32.LoadStringW>] ; USER32.LoadStringW
00401660 |. 6A 64 PUSH 64 ; /Count = 64 (100.)
00401662 |. 68 C04A4000 PUSH sample.00404AC0 ; |Buffer = sample.00404AC0
00401667 |. 6A 67 PUSH 67 ; |RsrcID = 67 (103.) //It Actually Never Exist
00401669 |. 57 PUSH EDI ; |hInst = 00400000
0040166A |. FFD6 CALL ESI ; \LoadStringW
This ResourceID does not Exist .Check the GetLastError Field Under the ollydbg ERROR_RESOURCE_TYPE_NOT_FOUND.So Look Like A Fake Call to make Program Look Legitmate(may be)
00401678 |. 57 PUSH EDI ; Arg1 = 00400000 // ImageBase As Parameter
00401679 |. E8 4DFFFFFF CALL sample.004015CB
Trace Into This Call… Again Few Call to Resources ….LoadIcon,LoadResouce ..Nthing Important
After that We See a call
00401637 |. 50 PUSH EAX ; pWndClassEx = 0006FECC
00401638 |. FF15 00114000 CALL DWORD PTR DS:[<&USER32.RegisterClassExW>] ;\RegisterClassExW
Remember the Address of RegisterClassExW is altered in starting ..Now Instead of Going to user32.dll ,it points to another function inside the executable..Trace Into this Function
Here In this Function We can See Some Interesting Calls Such As
GetModuleFileNameA=>Here it is to get the full path of Currently Executing File (As GetModuleHandleW with Argument NULL is used to Get Handle For It)
GetTempPathW=> As Name Suggests Retrieves a Path to Temp Files
Then We can see a Call to Function 00401952 =>
I Checked this Function ..This internally Calls CRT function _vsnwprintf…Which is used For String Manipulation (String Formatting)..
First Call to this Function Returns =TMP1CDFDEBF (It is Directory name..i know it as I analyzed it )
Second Call To This Function Returns a String = C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\\\TMP1CDFDEBF
This LookLike A Location To Drop A File
00401A7D |. 6A 00 PUSH 0 ; /pSecurity = NULL
00401A7F |. 8D85 F4FDFFFF LEA EAX,[LOCAL.131] ; |
00401A85 |. 50 PUSH EAX ; |Path = “C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\\\TMP1CDFDEBF”
00401A86 |. FF15 08104000 CALL DWORD PTR DS:[<&KERNEL32.CreateDirectoryW>]
So Here it Creates A Directory ..Nthing to Explain..
Then Again it Call to 401952(String Formatting) to Generate File Path ..output is
C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\\\TMP1CDFDEBF\\sample.exe
So finally this is Path to Drop File
As Shown in Pic ..then Finally there is call to CopyFileW ..So finally it Drops File to Location Mentioned above..It Actually Copy/Drop the Same File That is being Executed ..
So After Dropping A File Our Function Ends ..
So Till Now We Analyzed the RegisterClassExW_0 Function … Now Trace Into CreateWindowEx_MOD(Modified CreateWindowEx)…I Call this Function CreateWindowEx_MOD as it internally Calles Modified CreateWIndowExW API..
Lets Trace Into This
All Parameters Original/Necessary are passed to CreateWindowEx to make it Look genuine ..Now Step Into CreateWindowExW
So inside CreateWindowExW(that actually is Function 00402228)..We can See some Intersting API Calls
Such As CreateProcessW,GetThreadContext,SetThreadContext, ,WriteProcessMemory…Lets Check what They Exactly Doing ..
Then we have a call to CreateProcessW(W in the end is to indicate a Unicode Version)… CreateProcessW in simple words used to Create a Process …check MSDN For Other info
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx
Lets Check the Paramters Passed to CreateProcessW
Lets Check the Paramters Passed to CreateProcessW
00402266 |. 50 PUSH EAX ; /pProcessInfo = 0006FB90
00402267 |. 8D85 D8FCFFFF LEA EAX,[LOCAL.202] ; |
0040226D |. 50 PUSH EAX ; |pStartupInfo = 0006FB90
0040226E |. 56 PUSH ESI ; |CurrentDir = NULL
0040226F |. 56 PUSH ESI ; |pEnvironment = NULL
00402270 |. 6A 04 PUSH 4 ; |CreationFlags = CREATE_SUSPENDED
00402272 |. 56 PUSH ESI ; |InheritHandles = FALSE
00402273 |. 56 PUSH ESI ; |pThreadSecurity = NULL
00402274 |. 56 PUSH ESI ; |pProcessSecurity = NULL
00402275 |. 56 PUSH ESI ; |CommandLine = NULL
00402276 |. 68 80464000 PUSH sample.00404680 ; |ModuleFileName = “C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\\\TMP1CDFDEBF\\sample.exe”
0040227B |. FF15 40104000 CALL DWORD PTR DS:[<&KERNEL32.CreateProcessW>] ; \CreateProcessW
The Paramters Highlighted in Red Color are Important …Let me explain it
00402270 |. 6A 04 PUSH 4 ; |CreationFlags = CREATE_SUSPENDED
Acc. To MSDN
CREATE_SUSPENDED
0x00000004
The primary thread of the new process is created in a suspended state, and does not run until the ResumeThread function is called.
Hope it is Clear Now….In Case of Malware if Process is created in SUSPENDED mode then it Most probably means it will be modified
Other interesting Paramter is
00402276 |. 68 80464000 PUSH sample.00404680 ; |ModuleFileName = “C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\\\TMP1CDFDEBF\\sample.exe”
So this mean our sample file starts the dropped file into SUSPENDED Mode …
*Also u can think like that …what is meaning of dropping Duplicate/Same File and then Run it ..Does not making sense ..Dropping File and then run it ..then again the file will do same (Off course u can think that file can check its running location and can change its behavior acc. To it but it is not in this case..)…So it will be kind of very Stupid malware that Just Drops itself and do nthing ..:P.. so this Philosophy also provide some hint that there will be some modification in the Dropped File Process..Also We can See Some APIs Like WriteProcessMemory
WriteProcessMemory is basically used for InterProcess Communication …to Write the Given Data in Desired Location in Remote Process.
So All this make Sense that Our malware will make Some Modification in its child Process i.e Dropped File Process .Lets Continue Analyzing
00402287 |. 50 PUSH EAX ; /pContext = 0006FBE8
00402288 |. FFB5 24FDFFFF PUSH [LOCAL.183] ; |hThread = 00000048 (window)
0040228E |. C785 30FDFFFF>MOV [LOCAL.180],10007 ; |
00402298 |. FF15 74104000 CALL DWORD PTR DS:[<&KERNEL32.GetThreadContext>] ; \GetThreadContext
GetThreadContext = Retrieves the context of the specified thread (Simple and smart Defination from MSDN)
pContext = Holds the CONEXT Structre..I.e it Value Of registers obtained ..Here it is 006FBE8
hThread =Handle of thread….Here in this Case it Contains the Handle of main thread of Dropped File Process(I will call it Dropped Process )
Check Context Structre in Windbg ..WIndbg is Pretty Handy Tool to Examine the Data Structres in Windows ..also Shows Offsets …that’s Really Useful…
As You can See EAX is at offset 0xB0 ..
We have Context Structre Starting at 006FBE8
Context.EAX in Memory = 006FBE8+B0=006FC98
Why EAX is So Important … in Case of SUSPENDED Process EAX Always Point To Entry Point
After Executing GetThreadContext
We Have Value of Context.Eax
We have 006Fc98 = 004029B9 ..As Described Earlier it is Entry Point of Dropped Process
Now Examine Next Few Intersting Lines
004022A4 |. 50 PUSH EAX ; /pContext = 0006FBE8
004022A5 |. FFB5 24FDFFFF PUSH [LOCAL.183] ; |hThread = 00000048 (window) //Dropped Process thread
004022AB |. C785 E0FDFFFF>MOV [LOCAL.136],sample.00401E1F //OverWrite EAX
004022B5 |. FF15 70104000 CALL DWORD PTR DS:[<&KERNEL32.SetThreadContext>]
SetThreadContext= Sets the context for the specified thread….
As You Can See it Points to Same Address 0006FBE8
Check the Highlighted… Here LOCAL.136 = 006Fc98 ..So what this instruction doing is Overwriting the value at Location 006Fc98 with 00401E1F..
And Then We have a call to SetThreadContext…
So all this to change the Entry Point of Dropped Process By Overwriting the Eax in Context Structre.
Check the Below Snapshot to get things more Clear way …IDA’s naming feature make this tool ideal for reversing .
So Entry Point is Changed …Lets see what happened Next..Lets Analyze what happen Next
004022C1 |. 56 PUSH ESI ; /pBytesWritten = NULL
004022C2 |. 68 08020000 PUSH 208 ; |BytesToWrite = 208 (520.)
004022C7 |. B8 A0484000 MOV EAX,sample.004048A0 ; |UNICODE “C:\\Documents and Settings\\Administrator\\Desktop\\97c5080399e5df2407d6fdf28faf17f8\\1d8ea40a41988b9c3db“
004022CC |. 50 PUSH EAX ; |Buffer = sample.004048A0
004022CD |. 50 PUSH EAX ; |Address = 4048A0
004022CE |. FFB5 20FDFFFF PUSH [LOCAL.184] |hProcess = 00000044 //Handle of Dropped Process
004022D4 |. FFD3 CALL EBX ; \WriteProcessMemory
As I commented hProcess is Handle of Dropped Process…So what WriteProcessMemory Here Doing is Copying the Orginal Path of Sample To Dropped Process.(4048A0 contains path of Current Executable).You will come to know why this is copied to dropped process
Call to GetCurrentProcessId = This Returns the Process ID of Current Process in Eax
Next , OpenProcess API is called and ProcessID of Current Process is Passed a Parameter..This Means OpenProcess Attempt to Currently Executing Process with PROCESS_ALL_ACCESS (Red mark 1F0FFF=PROCESS_ALL_ACCESS)…If Evrything Fine then OpenProcess Will Return A handle to Local Process Object.
Next We Have a Call to DuplicateHanlde…This is Best Explained in MSDN ..Read it
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724251%28v=vs.85%29.aspx
Then we have a call to WriteProcessMemory…In this call..we are Passing the Real Handle Obtained By Using DuplicateHandle to Dropped Process.. We Write The Handle at =404AA8 (Keep this in Mind)
If u read the MSDN ..then the Purpose of this WriteProcessMemory will be Clear to You ..
Then We have a call to Resume Thread
0040231A |. FFB5 24FDFFFF PUSH [LOCAL.183] ; /hThread = 00000048 //Dropped Process
00402320 |. FF15 1C104000 CALL DWORD PTR DS:[<&KERNEL32.ResumeThread>]
So Finally After making all the Necessary Changes in Dropped Process …It Resumes The Dropped Process and then Dropped Process Start Executing ..
I did not execute ResumeThread Till Now …All I want is to attach Ollydbg to to dropped process..
Here is a way how to do it ..
We have entry point of Dropped Process =401E1F h
So what we are Going to do is to trap the the Dropped Process in Infinite Loop…
I am going to Use PUPE Suite .. And Chaned First Two Bytes at 401E1F to EB FE (Write Down Orginal Bytes Before Changing Orginal Ones)
Check my previous post where i use same method if you are not getting it
https://reverse2learn.wordpress.com/2011/09/01/unprotecting-the-crypter/
So Now Execute ResumeThread.Now Dropped Process is Trapped in Infinite Loop..Attach Ollydbg to it ..Replace EB FE with Orginal Bytes (orginal Bytes : 8B FF)..
*I Recommend to DUMP the Process at this point as I include all the changes made by parent process..we are going to analyze this dumped process in next part of this series
So Finally What we have is Two Instances of Ollydbg one Debugging sample and other Debugging Dropped Process.
This is What We have in Sample Process…After Resuming Main Thread of Dropped Process …it closes Hanldes and Finally Exits
Look at Code From Dropped Process
So What We have Calls To Memset ..After Memset Calls We have Very Intersting API Call
WaitForSingleObject (hObject,TimeOut)
hObject=404AA8 (Remember 2nd WriteProcessMemory Call ,Where we Write the handle obtained from DuplicateHandle at 404AA8 of Dropped Process)
TimeOut = INFINITE // Wait Until Object is Signaled
And After that Handle is Closed by Using CloseHandle
Then We Have a Call to DeleteFileW …The Filename passed is Location of Sample Process
*Remember when we passed the location/path of sample Executable using first WriteProcessMemory Call
So I think Now it is clear how this implement Self Delete(Melt Feature)/Drop File …
Dropped Process Wait for the Event From Sample Process …When it is Signaled it go ahead and delete that file.
So First Part Ends Here …In Next Part We Will Analyze the Dropped Process(I Dumped it when I restore the orginal Bytes after attaching Ollydbg to it).
I Love to get Your Feedback .You can Email me or Comment on my blog
Email Id : reverser90@gmail.com
UNPROTECTING THE CRYPTER
Tools Used
1)OllyDbg
LinK
2)Process Explorer
Link
http://download.sysinternals.com/Files/ProcessExplorer.zip
3)PUPE
Link
http://www.mediafire.com/?bc3ug7jg4gbzcum
4)PE Tools
Link
http://uinc.ru/scripts/load.cgi?files/neox/PE_Tools.zip
5)Hex WorkShop
Link
http://www.bpsoft.com/downloads/
Crypter
So what is a Crypter.If have some experience in malware Field then You must have Heard about tool called “Crypter”or may be used it.The Aim of Crypter to Protect the executables ,making difficult to analyze it or reverse engineer it .But Mostly in Malware Scene the crypters are mainly used to make malwares FUD .Here FUD stands for Fully Undetectable.
Actually the malware are basically distributed as executables ,I mean sources are gernally not available. Public malwares are gernally detected by antivurses ,that’s why crypters are used to make them FUD .
How Crypters Work
Principle for making a crypter is very simple . Crypter Consist of Two parts
1)Builder
2)Stub
How they both parts work
1)You give your file as input to crypter,it encrypts it with any encryption algorithm (most likely RC4,AES)
By encrypting the file it defeat the static analysis done by antivirus.During static analysis the antivirises try to find the the patterns in executable and match with with signatures.Because the file is encrypted
So the antivirus can’t find patterns here.
2)Add the stub before the executable code.
When you run executable then the stub runs and decrypt the encrypted file .
Note :The decrypted file remains in memory .
3)Execute the Decrypted from Memory .
This is actually the heart of crypter.This is also called “Run PE “.There are different methods for Run PE .But Mostly the Crypter used a public method to exectute the File from Memory ,that’s what we are going to target.
Let me Explain the the method .The orginal link of this method is
http://www.security.org.sg/code/loadexe.html
I just copying the steps .i realy suggest you to once read the whole article to understand in more depth.
The steps listed in article are :
1) Use the CreateProcess API with the CREATE_SUSPENDED parameter to create a suspended process from any EXE file. (Call this the first EXE).
2) Call GetThreadContext API to obtain the register values (thread context) of the suspended process. The EBX register of the suspended process points to the process’s PEB. The EAX register contains the entry point of the process (first EXE)
3) Obtain the base-address of the suspended process from its PEB, i.e. at [EBX+8]
4) Load the second EXE into memory (using ReadFile) and perform the neccessary alignment manually. This is required if the file alignment is different from the memory alignment
5) If the second EXE has the same base-address as the suspended process and its image-size is <= to the image-size of the suspended process, simply use the WriteProcessMemory function to write the image of the second EXE into the memory space of the suspended process, starting at the base-address
6) Otherwise, unmap the image of the first EXE using ZwUnmapViewOfSection (exported by ntdll.dll) and use VirtualAllocEx to allocate enough memory for the second EXE within the memory space of the suspended process. The VirtualAllocEx API must be supplied with the base-address of the second EXE to ensure that Windows will give us memory in the required region. Next, copy the image of the second EXE into the memory space of the suspended process starting at the allocated address (using WriteProcessMemory)
7) Patch the base-address of the second EXE into the suspended process’s PEB at [EBX+8]
8) Set EAX of the thread context to the entry point of the second EXE
9) Use the SetThreadContext API to modify the thread context of the suspended process
10) Use the ResumeThread API to resume execute of the suspended process.
When you normally load a packed executable in ollydbg then it shows warning like “the code section is compressed” or “the entrypoint is outside the code section “ whatever means olly give you hint that the executable is packed.But the executable crypted by crypter (which is using above method) never shows any warning when it is loaded into olly it does not show any warning .
Analysis
Here is a target Link
Link
http://www.mediafire.com/?r38tf5d93nt54c4
NOTE : The target is detected as malware by antivirus beaucse it is crypted by using public crypter .Dont worry this is simple and clean application. But i strongly suggest you to using vmware or virtualbox .
Lets start from very basic stuff ,Scan it with PEID
Looks Inocent 😛 ,is it ?
Lets Load it in Olly ..see it shows any warning or not
Everthing Looking normal,Looks Like a normal VB excutable no warning shown by olly
First Verify If our target is realy innocent or malicious.Acc. to method described above it must call Create a new process.So Put a BP on CreateProcessA and CreateProcessW (for both ascii and unicode versions).If it Breaks then see the arguments passed check if it is in SUSPENDED MODE (Also You can Put Breakpoint on ReadProcessMemory and WriteProcessMemory APIs to check it more accurately )
I Put BP on CreateProcessW and CreateProcessA and run it in olly.As you can see this it is Breaked at CreateProcessA..Also You can see it parameters in stack ,also you can see that it is in SUSPENDED_MODE .
It calles the CreateProcess In suspended mode(suspend its main thread) then decrypt the encrypted malware in newly created process address space when everything is on its place then it calls the ResumeThread API and it start running
We are going to attack at the point when It calles the ResumeThread API,because ResumeThread API is last step in executaion and before this everthing will be on its place .
So I Put BP on ResumeThread,Lets See what Happens
Wow Its Breaked on ResumeThread..
Now Step Into ResumeThread by Pressing F7.
As You can see that ResumeThread internally calls window native api NtResumeThread
NOTE: NtResumeThread is Undocumneted native API . Most of windows API works this way .They provide a documented interface for main function then internally called the undocumented native APIs.This Concept is very Important Because Sometime the Crypter authors uses undocumented native APIs instead of Documented APIs.
For example they can directly use NtResumeThread instead of calling ResumeThread.In this way if you put BP on ResumeThread then it will not break .So I strongly suggest you to put breakpoint on native undocumented APIs instead of Documented APIs.
For example always put BP on NtResumeThread instead of ResumeThread ,then you will directly break at 75A0C3D5 instead of 75A0C3C9
Lets Step inside NtResumeThread. By pressing F7.Contnue pressing F7 until you reach it 778764F2
This is point where the ResumeThread actually get executed and our suspended Process will start executing ,but we do not want to execute it to not get infected .So stop Here
Now open the Process Explorer and dump the this process (the child process),select child process ,select full dump
It will be saved as filename .dmp format ,I rename it to dump.exe
I named file as dump.exe ,and I scan it with PEID
Ah, not a Valid PE file..seems scary ..lets Fix this..The PE File start With Letter “MZ “.The File Analyzer like PEID gernally first check if the file contain MZ in starting or not ..if not that mean not a valid PE file(Also they do some extra tests ..but check for ”MZ” is first one.)
Open Up it dump.exe in Hex Workshop,search for “MZ”.Delte Everything above “MZ”. Save It ,Then our file become valid executable .
Now You can scan your modified File with PEID .Just see the results i got
Now Look Like Valid PE 😀
But this is Not runing and giving the C++ Run time Error
If this file is not going to run then why we waste so much time on it ?
The Purpose of making this valid PE is to Find Its OEP by Loading it into Olly or by using other PE utlity tools
Note : You can find directly Calculate OEP from Hex Workshop without Deleting the Bytes If You know PE Header, I want to make it simple so I do it by this simple ad long way.
OEP :Orginal Entry Point .It is the address from which the program start execution.
Why we need OEP ?
WE Dump the program before the ResumeThread execute but it is not working.I am supposing the the crypted program is malware so I do not want to run it,then how I am going to to get it working .The idea is
Change the First Two Bytes at Program Entry point so that it trapped in infinite LOOP ,this way it will not able to get executed and everthing will be placed correctly and we will have a gud chance to dump it .
Lets Find the OEP by of our dumped file by opening it in olly.Also Note Down the starting bytes at entry point
0048847F <ModuleEntryPoint> 6A 60 PUSH 60
EntryPoint 0048847F
The First Two Bytes are 6A 60
Show Time
Lets Finally Fix this
Run the Crypted.exe in olly ,Continue Untill the last instruction inside ResumeThread Executes Like we did before.
That is
countinue Stepping into ResumeThread API until this instruction
7C90EB8D 0F34 SYSENTER
That’s point where the actually execuation takes place
Now We Have to change first two bytes at EntryPoint to trap the program in infinite Loop,we olly use the little program PUPE for this
We can see our child process Crypted.exe in process Explorer. Its process id is 544 in decimal
Process id in Hex =220
Select the Target Process and click Patch . Then You will see the patch window Like this
Change the Number of bytes to 2
Put the OEP in the Direction option and click search we get 6A 60 as bytes (these are ogrinal bytes .note it )
Put EB FE in change by .
EB FE will instruction will make the jump to to same instruction again and again and hence trap it in infinite loop
Now click on patching
After that the orginal bytes are replaced by EB FE .
Now Go to our ollly again and click and Run the Program
After Clicking on Run button you will see that that your process is terminated in olly .
Don’t Worry it does not matter to us .Only child process matter to us that is still running (trapped in infinite loop) . Now you just have to Dump it with Your Favourate Dumping tool. I Will dump it with my favourate that is PE tools
Click on Dump Full and save it with any name you want .i saved it with final_dump.exe
After Dumping Also Kill the process.
Now open the final_dump.exe in olly
As You can see the first two bytes are EB FE ,they will always trp the program in infinite loop to fix it replace these two bytes with orginal two bytes that are 6A 60
Right click on instruction then go to binary -> edit options and replace it with orginal bytes as shown in pic
Now click on the copy to executable option and save this file .Now You have Your orginal file back .
Congrats You just Unpck the crypted file successfully.
You can verify it by running .
Important :
As I already mention the crypter coders now days use the windows undcoumneted native APIs instead of documented API
FOR example Use of NtResumeThread instead of ResumeThread.
So I suggest to Put BP on NtResmeThread instead of Resume Thread.
Apply same to all other API that you want to break on .
These crypters gernally add junk code to make them undtectbale but don’t worry if they are using the same RUN PE method they will get unpacked by using this method because adding junk code did not matter at the end they have to to call ResumeThread 😛
NOTE :This Method works on the crypter who are using the above method written .I found that more than 60 % crypters use the method.
If You like My tute then leave comments or you can mail me .
Solving Crackme 1
Hello Friends,this is the first tutorial of series.I find about a series of serial fishing on cin1team.biz along with solutions.It is just great for beginers.There are Multiple ways to crack a program.I will share the solution to some selected crackme’s given in series .i also recmend you first to try crackme yourself …check the solutions only if u are not able to solve it.i also recmend you to also check the solutions given on cin1team.biz,more the ways you learn more you understand(also they are videos)
Cin1team.biz thread Link
http://www.cin1team.biz/showthread.php?t=1771
So lets start .This is first crackme… You can get it from here
Link
http://www.mediafire.com/?ji1vcq9vj2vm8ix
I assume You are Familier with Ollydbg and basic asm syntax.Also with some basic APIs
So not wasting much of our precious time.Lets start
What crackme need
Lets see what the crackme is asking for ,see the image
It is asking for password ..i just put 123456 and press check.and it is showing the MessageBox titled “wrong”.I realy hate this thing lets fix this shit.
It is always useful to check wheather the program is packed or not(we will discuss about packing and unpacking later),also to check for language in which the program is compiled.
How this can help.By Knowing the language we can use the tools which are made for specific languages.Like VB decompiler,SmartCheck For Visual Basic,DeDe For Delphi.So knowing the languages in which the program is compiled matters.Also Every Languages have different patterns also there are some language specific tricks.so it is good practice to know about the compiler of target .
I am using a famous toold peid for this purpose. So lets start
Nothing Found !!.This can Happen sometimes.Peid actually stroes the patterns generated by different compilers at compile time and try to match it with target executable and depending on the match show the results.But it is easy to play with signatures and modify and change them…we will discuss it later.Lets check in another similar tool like peid.Lets see if it works.Scan the crackme with ExeInfo.
MicroSoft Visual C++ or Masm 5.12 .Looks Confused.Any way we can also guess the language by looking at disasmblly inside ollydbg.
Lets Load it in olly.
It is look like written in Masm.How can we say this.The high Level Languages Like Visual C++,Delphi include different methods for initializing the program for example c run time library functions.Masm gernally do not add extra code .The program will shown in disasmbly as it is actually written .
So we have classic MASM crackme.so lets start .Our main goal is to locate the part of program in which the serial is checked and this badboy is showed up.
Analysis
1)Run the program in olly .it will ask for password .enter any wrong password and press check button.
2)it will show badboy then Just pause the olly ,and press ALT+F9.
3)Then Press “ok” button on badboy messagebox.The olly will leads you to the place from which the messagebox is originating.
See the Pic
Here we are,olly leads me to 004010D8 location ,this is the next instructions after “MessageBox” API.
Here We can see Two MessageBoxes ,You can see Clearly one is having the “Right” title and another one is titled “wrong”.We want goodboy i.e MessageBox with “right”.See Carefully at location 004010AE ,there is conditional jump.Put a BreakPoint on it just by Double Clicking the Opcode Window and Restart the Program.Agin Put any fake serial number and Press Check button .y0,we hit at the breakpoint.Our program breaked at location 004010AE at conditional Jump(JNZ).
JNZ basically checks Zero Flag to Jump .(Jump if not Zero,Jump if zero Flag is not set)
You can clearly see that that JNZ is deciding wheather we get goodboy or badboy.At this time zero flag is not set so surely we will get jump and get badboy.To get Goodboy just set the zero flag and you done.Click on the “0” infront of “Z” as highlighted in Pic and it will become 1 and zero flag is now set.
Also See the Pane window to check wheather the jump is taken or not. So jump is not taken and we will get our goodboy.Just run the program and see.
Yep we got our goodboy.Is this tute is only about to get a goodboy message by patching a conditional jump .The answer is No .we Will go deep,we will analyze why jump is taken before reaching at our breakpoint.Why our serial is rejected(so sad).
Scroll up and you will see a CMP (comparion) instrtion at 004010AB.It is used To Compare two values and set the zero flag as the result.The instruction is
Cmp eax,1
It is comparing eax with 1.
Output of the the above written instruction will be
If eax is greater than or smaller than 1 then unset the zero flag.
If eax is equal to 1 then set the zero flag.
So we need eax to be 1 to get o our goodboy.But from where the eax is getting value.
Just see the above instruction at 004010A6. It’s a call instruction means it is for calling a function
Also You an see a PUSH at 004010A1.Olly is Intelligent Enough to show us what it is being pushed .When it ask for password I enter “123456”.So my enterted serial number is begin pushed into stack.
This PUSH actually acts as parmeter to function which we are calling in next instruction.
How we call function in C.
Myfunction(parameter 1,parameter 2)
How we call function in asm.
PUSH parameter 2
PUSH parameter 1
Call Myfunction
I Hope Now you understand what is meaning of instructions at 004010A1, 004010A6.The function called at 004010A6 is getting serial entered by me as parameter.So this function is looking like serial verifier function ..isn’t.Let see.
Put Breakpoint at 004010A6 and rerun the program.Enter your fake serial ,I entered “123456” and press “check” button. SO we Breaked at 004010A6.Press F7 to step into the function code.
Execute instructions pressing F8 untill 00401101.
At 00401101 PUSH ESI (Saving the orginal value of ESI in stack)
00401102 MOV ESI ,[ARG.1] (Moving the argument passed into ESI(remember the argument was our fake serial, you can see this in pane window. Sorry I miss that in screen shot)
00401105 Call g1.0040110F (call to function)
0040110A POP ESI (Get orginal value back from stack)
So our fake serial is moved into ESI and function is called.Lets see what is happening inside the function by stepping into function by pressing F7.
Wow ,can you see a dark line from 0040111E to 0040112E.This Indicates a Loop.Loop is simply to repeat the process until a condition is met(use google for more detailed information).Mostly serial Comparisons are Done Inside Loops.So pay special attention to loops.
Also we can see xor instructions.
Xor eax,eax (Xoring with same register will make that register zero)
So all 3 xor instruction are to make ecx,eax,ebx zero.
Note
Now people can ask why we just can’t move zero to register Like
Mov eax,0
This is so simple and also producing same result.But this instruction is 5 byte instruction.where xor eax,eax is 2 byte instruction.
There is something called compiler optimizations due to which compiler choose the short instructions to get work done more efficiently.
Ques:>How can we know how much bytes each instruction is having…
Ans=> Just look at opcode window or just yo can subtract the address of your instruction from address of next instruction.
See at 00401117 mov edi,g1.00401138 (a constant string is moved into EDI.ollydbg show the string moved is “Ndg6kP”)
Execute this instruction. Now we got jmp to 0040112b .Instruction at 0040112b is
0040112b Cmp ecx,6
0040112e jb short g1.0040111E
JB check carry flag to decide jump or not.
You remember 0040111E is starting of loop. so these instruction means
Jump to starting to loop until Cmp ecx,6 results carry.
(Cmp instruction actually subtractes the operands then set appropriate flag here it will be ecx-6 it will set carry flag until ecx is 5 or less than 5 )
Now AnaLyze the Loop
Here we can see the value of ESI,EDI ,ECX in olly Registers Window.
ESI contains our fake serial that is “123456”
EDI contains a text “Ndg6kP”
ECX ,EAX,EBX are 0.
0040111E MOV AL,BYTE PTR DS:[ECX+ESI]
00401121 MOV BL,BYTE PTR DS:[ECX+EDI]
These instructions means moving a single byte(a char is of single byte(ascii) ) into al,bl from [ECX+ESI ] and [ECX+ESI] ,Ecx is zero so the first char that is “1” ( ascii value of 1 ) is moved into al.
Similarly “N” (ascii value of “N”) is moved into bl.
00401124 INC BL (increment BL ,in this case ascii value of “N”+1)
00401126 CMP AL,BL (comare al and bl)
00401128 JNZ SHORT g1.00401138 ( conditional jump,if al,bl are not equal then jump to 00401138n else not jump)
What if jmps then
00401138 MOV EAX,0
0040113D POP EDI
0040113E POP ESI
0040113F RETN
Move 0 into eax ,restore values of esi and edi and loop function returns.U remember we did all analysis to find where eax is getting zero.so this place where eax is getting zero .
What if not jumps
0040112A INC ECX (increment Ecx)
0040112B CMP ECX,6 (compare ecx with 6)
0040112E JB SHORT g1.0040111E (jmp until carry)
Ecx increments,and will used to get next char of string in ESI and EDI. Ecx keep incrementing till 5.
If loops terminates then we have these instructions
00401130 MOV EAX,1
00401135 POP EDI
00401136 POP ESI
00401137 RETN
Everthing is almost same as 00401138 ,just instead of 0 ,1 is moved into eax.that will lead to goodboy.You can see this snapshot for more understanding
How serial is Genrated
So Now we understand how things work .Lets write it in more clearer manner ,and how serial is generated
1) first “Ndg6kP” is loaded
2) char is moved and 1 is added
3) points to next char
repeat step 2,3 5 times
(because loop starts with ecx having value 0 and runs until ecx is having 5 ,and ecx is incremented once in each iteration .so 0 to 5 = 6 times)
What is serial
We just having to shift each char of “Ndg6kP” by 1.
“N”+1=”O”
“d”+1=”e”
“g”+1 =”h”
“6”+1=”7”
“k”+1=”l”
“P”+1=”Q”
So final serial is “Oeh7lQ”.Check it in our crackme.
Patching Solution:-
Multiple Patching solution Exists ..i discuss 2 of them
1) AT 00401138
00401138 MOV EAX,0
Here move 1 instead of 0
Mov EAX ,1
2)AT
00401128 JNZ SHORT g1.00401138
Replace this with NOP.
This way loop ends correctly whatever serial you insert.
Hope You Enjoy my tutorial.I love to have your feedback .If you like or dislike this post then comment and let me know .