|  | 
	
		|  | 
	
		| Reversing Basics - A Practical Approach Using IDA Pro | 
	
		| Author:
		Amit Malik aka DouBle_Zer0 | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		
	
			 |  | 
	
		
	
		|  | 
	
		|  | 
	
		|  | 
	
		|  | 
	
	
		
	
			 |  | 
	
	
		|  | 
	
		|  | 
	
		|  | 
	
		
	
		 |  | 
		| Reverse engineering is a very important skill for information 
			security researchers. In this tutorial I will explore the basic 
			concepts of reverse engineering by reversing a simple crackme. | 
		|  | 
		|  | 
		|  | 
	
		| The crackme used in this tutorial is from binary auditing course. I 
			will use static approach to solve the problem as it clearly 
			demonstrates the power of reverse engineering. A little bit 
			knowledge of Assembly and Disassemblers, Debuggers is required to 
			understand this material. I will use IDA Disassembler 
			[Reference 2] as it is the 
			most powerful disassembler exists in the market, Hexrays provide a 
			demo version of IDA and I think demo version is enough for solving 
			this exercise but I am using version 5.1. | 
	
		|  | 
	
		|  | 
	
		|  | 
	
	
		
	
	 |  | 
	
		| Reverse engineering can be easy and can be difficult, it depends on 
		your target. But the basic steps are | 
	
		| 
			Detect packer/encryptor -> if present, then first unpack/decrypt 
			the file and fix imports etc.Static Analysis -> Understand the application logic without 
			executing it in live environment.Dynamic Analysis -> Execute the binary and monitor the 
			application activities. | 
	
		| Above steps are just basic of reverse engineering, overall process 
		is based on reverser goals. For eg: for AV researchers and crackers 
		basic steps are same but process is different. 
 | 
	
		|  | 
	
		|  | 
	
		
	
	
		|  | 
	
		| API(Application Programming Interface):  In windows world, code 
		sharing is the core of communication and trust. A user application can't 
		directly control hardware or can't directly communicate with windows 
		kernel. So how would application work if application can't talk with the 
		kernel ?. Windows provide various DLLs(Dynamic Link Library) and these 
		DLLs exports various functions to provide services to user applications 
		and we call them API. So the understanding of APIs is necessary. 
 Eg: if you are using printf() function in your code and the linker links 
		the function call to the printf() function in msvcrt.dll, so the 
		printf() function is an API : Read PE file format if you want to know 
		how these things work.
 
 Return Value in EAX: The second important 
		thing is that every function/API mostly returns to EAX register. For eg: 
		lets say we are using strlen() to calculate the length of the string, 
		strlen() will return the value into EAX register..
 | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		
	
	 |  | 
	
		| Now it is time to get in action with reversing and cracking our 
		crackme [Reference 1]. Here are our tasks, | 
	
		| 
			Remove splash screen -> I am leaving this task for you ?Find Hard Coded Password -> we will work on this.Write a keygen -> we will work on this. | 
	
		| Load file into IDA Pro. (if you don't know how to operate with IDA 
		then first read "THE IDA PRO BOOK" [Reference 
		3] excellent guide for IDA usage) 
 Go 
		with default options and you will see IDA is processing the file, you 
		can start the analysis now. One of the most important thing is to look 
		on the Import and Export function tabs to get a compact view that how 
		many and what api is our target application using. Now run the 
		application independently, I mean like a normal application not under 
		debugger and feed some garbage value and note the messages that we get.
 
 | 
	
		|  | 
	
		|   | 
	
		|  | 
	
		| As you can see in the picture that our crackme is popping up a 
		message box on invalid input. The String "Sorry, please try again" is 
		important or you can say that this string will save a lot of work, 
		situation may vary with target to target but for this crackme this 
		string can be the starting point. But as we can see that IDA is showing 
		the starting function and we don't have any string that can match with 
		the error message i.e "Sorry, Please try again". 
 Now we have two 
		approaches one is trace the call from start function to the function 
		that is containing our magic string. For eg. Go into call sub_40102c and 
		do the same within this function and another approach is to go to 
		function tab in IDA and analyse each function independently. Generally 
		we use the combination of both to manage the analysis time.
 | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		| As you can see in the picture that the function name starting with 
		sub_* are user defined functions, we will open each function and look 
		for our magic string i.e "Sorry, Please try again". Continue with this 
		process we can find our magic string in function sub_401178. | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		| As we can see in the picture that we have now clear targets, now we 
		can backtrace and can find out the starting point of string matching. 
 | 
	
		|  | 
	
		|   | 
	
		|  | 
	
		| In the first box we can see that application is calling a API 
		GetWindowTextA. If you don't know the api functionality then in this 
		case you can search on msdn win api reference guide. The guide will 
		provide you the parameter meanings, structure and expected return values 
		etc. | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		| Now compare this format with the format that is displayed by IDA, we 
		can say that PUSH OFFSET String will receive the data entered by user. 
		Now notice the next two statements LEA EAX, aHardcoded and LEA EBX, 
		String, that means the address of a hardcoded string is moved into EAX 
		and the address of the string that is entered by user is moved into EBX. 
		Now we can say that the aHardcoded contain our hardcoded password 
		because application is matching this string with the user entered 
		string. | 
	
		|  | 
	
		| MOV CL,[EAX] ; 
		hardcoded string [one char each time] MOV DL,[EBX ; string entered by 
		user [one char each time]
 CMP CL,DL ; compare
 JN Z SHORT_BAD_BOY ; 
		if no match call bad_boy
 INC EAX ; else increase eax,ebx
 INC EBX
 JMP @Loop ; jump back to loop
 
 | 
	
		|  | 
	
		| The above loop is for string matching, so now we are sure that the 
		aHardcoded contain our harcoded password and that is HardCoded. 
 | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		| Now we have to find out the solution of second challenge. But if we 
		look into the current function we have only solution for hardcoded one 
		so it means we have to jump to another function to find out the solution 
		for second challenge. Continue with the same process [jumping to 
		functions from function tab for our magic string] we can say that the 
		function sub_4015e4 is the next target for analysis. | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		| Now we will backtrace to find out the origin of these message boxes 
		and then figure out that what value will invoke good_boy message box. 
		Starting point of this function is the origin of these message boxes 
		because at the beginning application is calling two GetWindowTextA and 
		we know the purpose of this API from our previous challenge. So 
		application is expecting Name and Serial from user. 
 If you look at the 
		code then we can say that if we don't fill any values into the fields 
		then we get a message box like "Please enter username or please enter a 
		Serial". Now what if we enter a garbage value to the fields? Then we 
		will enter into a simple computation and we have to reverse that logic.
 | 
	
		|  | 
	
		| mov username_len, eax ; 
		move the value of eax (username length – returned by API) into a 
		variable xor ecx, ecx ; clear out ECX register
 xor ebx, ebx ; 
		clear out EBX register
 xor edx, edx ; clear out EDX register
 lea 
		esi, username_stor ; move the address of username (a[] = "amit" then ESI 
		= a[0]) into ESI
 lea edi, user_gene ; destination buffer where we 
		want to store username after computation (like b[] = a[0] ^ 2; it is 
		just a example)
 mov ecx, 0Ah ; move the value 10 (decimal) into ecx
 
 loop:
 movsx eax, byte ptr [esi+ebx] ;ESI=address of username and 
		EBX=0 -> look above
 cdq ;nothing special in this application used to 
		convert dword into quadword
 idiv ecx ; divide the value of EAX with 
		ECX (EAX/10 –> as ECX = 10) -> look above, now idiv instruction store 
		the quotient into EAX and Remainder into EDX so we can say (EAX%10 = 
		EDX)
 xor edx, ebx ; xor the value of EDX with EBX (notice that EBX 
		will play as a counter)(EDX=EDX^EBX)
 add edx, 2 ; ADD two into EDX 
		(EDX = EDX+2)
 cmp dl, 0Ah ; now compare DL (EDX) with 10
 jl short 
		loc_401646 ;if EDX < 10 jump to loc_401646
 sub dl, 0Ah ; else 
		subtract 10 from DL(EDX)
 
 loc_401646:
 mov [edi+ebx], dl ; move the 
		value of DL(EDX) into EDI (EDI is our destination) -> look above
 inc 
		ebx ;increment EBX (notice that EBX work as a pointer or you can say 
		like i in a loop ?)
 cmp ebx, username_len ;compare the value of EBX 
		with length of username
 jnz short loop_username ; jump if EBX != 
		username_length to the (loop) -> look above
 
 
 | 
	
		| so now we can generate a 
		pseudo code of these instructions let say a[] = "amit" is our source 
		string and b[] is our destination then | 
	
		|  | 
	
		| c = 10 ; ECX i = 0 ; 
		EBX
 
 loop:
 b[i] = a[i] % c;
 b[i] = b[i] ^ i;
 b[i] = b[i]+2;
 if (b[i] > 10)
 b[i] = b[i]-10;
 I++;
 If(i != strlen(a))
 Goto 
		loop;
 
 | 
	
		| So this is the logic of username computation and we have our 
		computed value into b[]. Now comes the Serial generation 
		algorithm. | 
	
		|  | 
	
		| xor ecx, ecx ; clear 
		out ECX xor ebx, ebx ; clear out EBX
 xor edx, edx ; clear out EDX
 lea esi, serial_stor ;move address of user entered serial into ESI
 lea edi, serial_gene ; target buffer means store serial after 
		computation (similar to username process)
 mov ecx, 0Ah ; move 10 into 
		ECX
 loc_401669:
 movsx eax, byte ptr [esi+ebx] ; move the value of 
		serial into EAX (one char ?)
 cdq ; nothing special for this 
		application
 idiv ecx ; divide EAX with 10;
 mov [edi+ebx], dl ; 
		move the remainder into EDI (our destination)
 inc ebx ; increment 
		pointer (means i)
 cmp ebx, serial_len ; comare it with the length of 
		serial
 jnz short loc_401669
 | 
	
		|  | 
	
		| Now the result of this computation is stored into another array let 
		say c[]; in the next few instructions we have a loop in the 
		application that will match the value of c[] with b[]. Notice that 
		b[] hold the username where c[] hold the result of 
		serial computation.
 
 As we can see in above code that application is 
		only dividing the serial number entered by user with 10 and comparing 
		the result with the result of username computation, so we can say that 
		if x is the result of username computation then x * 11 is the value of 
		serial.
 
 So now we can develop the keygen:
 | 
	
		|  | 
	
		| /* Author: DouBle_Zer0  
		*/ 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 int main()
 {
 char a[10];
 char b[10];
 int c;
 int i;
 int d;
 
 printf("[-]Coded By DouBle_Zer0\n");
 printf("Plz enter your name: ");
 scanf("%s",a);
 
 d = strlen(a) - 1;
 
 for(i=0;i<=d;i++)
 {
 c = a[i] % 10;
 c = c ^ i;
 c = c + 2;
 if (c > 10)
 {
 c = c - 10;
 }
 b[i] = c * 11;
 }
 
 b[i] = 0;
 
 printf("Corresponding password is: %s\n",b);
 system("pause");
 
 exit(0);
 
 }
 | 
	
		|  | 
	
		| and here is the result in front of you ! | 
	
		|  | 
	
		|   | 
	
		|  | 
	
	
		 |  | 
	
		
			 |  | 
	
		
	
	
		|  | 
	
		| Here is the video demonstration showing the above reversing of crackme in action | 
	
		|  | 
	
		|  | 
		 |  | 
	
	
		 |  | 
	
			 |  | 
		 
			
	
	 |  | 
	
	
		| 
			
			Crackme 
			EXE, keygen source 
			IDA PRO - Popular 
			Disassembler & Debugger 
			
			The IDA Pro Book - Recommended
 | 
	
		|  | 
	
		|  | 
		
		
	
			 |  | 
	
		
	
		|  | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		|  | 
		|  |