Ok an update i juz got my hotmail id so you guys can add me @ obnoxious_coder@hotmail.com
Thursday, August 21, 2008
Time to make some friends....
V!ctor's OneXor Dissected...:P
00401106 /$ 33C0 XOR EAX,EAX
00401108 . 6A 00 PUSH 0
0040110A . 83F8 01 CMP EAX,1
0040110D 74 0C JE SHORT OneXor.0040111B
0040110F . 68 6E304000 PUSH OneXor.0040306E ; ASCII "OneXor by V!ctor "
00401114 . 68 B7304000 PUSH OneXor.004030B7 ; ASCII "Sorry, wrong password." //BadBoy!!!!
00401119 . EB 0A JMP SHORT OneXor.00401125
0040111B 68 6E304000 PUSH OneXor.0040306E ; ASCII "OneXor by V!ctor "
00401120 . 68 9B304000 PUSH OneXor.0040309B ; ASCII "This is right password!!!!!" //GoodBoy!!!!
00401125 > FF35 00314000 PUSH DWORD PTR DS:[403100] ; hOwner = 00070154 ('OneXor by V!ctor ',class='#32770')
0040112B . E8 3A000000 CALL
00401130 \. C3 RETN
As you can see the only way to get to the good boy wd be to somehow reach the code at VA 40111b but wait still theres some thing missing ahh! yes the PUSH 0 of msg box style. Now the thing to think is that the author does not want a patched solution that means that he must have put that push 0 and jmp 40111b some where. But where!!!!!! Only one easy way to find it.... Binary search of the memory. Press Alt+M right click in the MEMORY Map window hit search n place 6A 00 E9 to search n no sooner you find what you are looking for @ VA 4000B0.
So its clear that one Gud way of solving crackmes is to think in the same line as the author.....:P
Jim~ SpaghettiMe Dissected...:P
Ah! finally the wait is over my tut for Jim~'s SpaghettiMe is finally published; one of the trickiest crackmes i ever faced. A brief over view of the recursion that is used to calculate the serial and how to reverse it.
private int[] overloaded(int[] chr)
{
if (chr.Length <= 1) { return chr;
}
int num = chr[chr.Length - 1];
int[] numArray = new int[chr.Length - 1];
for (int i = 0; i < (chr.Length - 1); i++)
{
numArray[i] = (num + chr[i]) % 0xff;
}
return this.overloaded(numArray);
}
Ok what this function does is that it compresses the int array that it recieves by one element and finally returns a value when the array length becomes == 1. This can be better explained with an example:
suppose that an array of 4 elements is passed onto the function then
array[4]{103,8,6,8} //array[4] refers to an array of 4 elements similarly array[3] an array with 3 elements
array[3] after recursion will be
array[3]{(103+8),(8+8),(6+8)) ==== {111,16,14}
array[2]{(111+14),(16+14)} ==== {125,30}
and finally
array[1]{125+30} ==== {155}
Thus this value that is returned sd be equal to that generated from name.
To reverse it we can simply create an array of 2 elements and keep on expanding it till it becomes 30 elements long. Now one might ask why 30 elements :P this is simply bcoz the seiral is 40 chars long and a base 64 string 40 chars long has a byte array of 30 elements. Now the first element of the array is the one that is calculated from the name and the other is 255. why 255 bcoz the compression is carried out this way suppose if 155 is calculated from name then our initialised array will be array[2]{155,255} which when compressed according to the code numArray[i] = (num + chr[i]) % 0xff; will be (155+255)%255 = 155 simple aint it. So the code that serves our purpose is
private int[] overload(int[] chr)
{
int num;
Random random = new Random();
if (chr.Length >= 30)
{
return chr;
}
int maxValue = chr[chr.Length - 1];
maxValue = random.Next(1, maxValue);
int[] numArray = new int[chr.Length + 1];
numArray[chr.Length] = maxValue;
for (num = 0; num < chr.Length; num++)
{
numArray[num] = ((0xff + chr[num]) - maxValue) % 0xff;
}
return this.overload(numArray);
}
the random number is used to subtarct it from the existing elements of the array and to include it as the incremented element of the new array. 0xff is added so as to avoid -ve numbers.
Now to look at the recursion that is used to calculate the necessary number from name
private int overloaded(int num)
{
if (num > 0)
{
if ((num % 2) == 0)
{
return (3 + this.overloaded((int) (num - 1)));
}
return (this.overloaded((int) (num - 1)) - 2);
}
if (num >= 0)
{
return 0x539;
}
if ((num % 2) == 0)
{
return (3 + this.overloaded((int) (num + 1)));
}
return (this.overloaded((int) (num + 1)) - 2);
}
Of course its not easy to understand what goes on inside this recursion. An easy way to understand it wd be to rip this code and try to see the result by passing different numbers to it.
A table to show what happens when i passed some numbers to it:
0 == 1337
1 == 1335
2 == 1338
3 == 1336
4 == 1339
5 == 1337
this much was enough for me to understand what was happening. For even numbers it was returning (num/2)+1337 and for odd numbers it was returning ((num-1)/2)+1335. The same was also true for -ve numbers. So this can easily be done with the following code:
private int overloadedint(int num)
{
if (num > 0)
{
if (num == 0)
{
return 0x539;
}
if ((num % 2) == 0)
{
return ((num / 2) + 0x539);
}
return (((num - 1) / 2) + 0x537);
}
num *= -1;
if (num == 0)
{
return 0x539;
}
if ((num % 2) == 0)
{
return ((num / 2) + 0x539);
}
return (((num - 1) / 2) + 0x537);
}
Hu? So i guess over all it was a very interesrting crackme. I look forward to seeing some more such crackmes from Jim~ n also that i will be writing some crackmes in the same line.....
Wednesday, August 20, 2008
br0ken's crackme3
Some FreeWares
Ok my second post.
Let me just tell you bout some gr8 freewares that i use:
IDAFicator a gr8 plugin for our beloved OllyDbg. Adds Some xtra Buttons for quick access to many functions of olly. You can get it from: http://www.woodmann.com/collaborative/tools/index.php/IDAFicator
CFF Explorer http://www.ntcore.com/exsuite.php