Souhail's Climb Crackme Tutorial

July 15, 2015 - Reading time: 15 minutes

Target: Souhail's Climb

URL: http://www.crackmes.de/users/souhail/climb/

Protection: N/A

Description: Find the flag inside the crackme.

Tools: IDA

First of all we load the crackme into IDA and then find the main method.

.text:004019DD ; int main()
.text:004019DD public _main
.text:004019DD _main proc near ; CODE XREF: ___mingw_CRTStartup+F8p
.text:004019DD push ebp
.text:004019DE mov ebp, esp
.text:004019E0 and esp, 0FFFFFFF0h
.text:004019E3 sub esp, 20h
.text:004019E6 call ___main
.text:004019EB mov dword ptr [esp+1Ch], offset aFindTheFlagIns ; "Find the flag inside !! Hint : The crac"...
.text:004019F3 mov eax, [esp+1Ch]
.text:004019F7 mov [esp], eax ; char *
.text:004019FA call _puts
.text:004019FF call _create_tree
.text:00401A04 mov eax, 0
.text:00401A09 leave
.text:00401A0A retn
.text:00401A0A _main endp

Here we see a call to the method _create_tree. Lets take take a closer look at that routine.

.text:004016CA ; pTREE create_tree()
.text:004016CA public _create_tree
.text:004016CA _create_tree proc near ; CODE XREF: _main+22p
.text:004016CA
.text:004016CA ptr = dword ptr -6Ch
.text:004016CA i = dword ptr -0Ch
.text:004016CA
.text:004016CA push ebp
.text:004016CB mov ebp, esp
.text:004016CD push edi
.text:004016CE push ebx
.text:004016CF add esp, 0FFFFFF80h
.text:004016D2 lea ebx, [ebp+ptr]
.text:004016D5 mov al, 0
.text:004016D7 mov edx, 60h
.text:004016DC mov edi, ebx
.text:004016DE mov ecx, edx
.text:004016E0 rep stosb
.text:004016E2 mov dword ptr [esp], 0 ; time_t *
.text:004016E9 call _time
.text:004016EE mov [esp], eax ; unsigned int
.text:004016F1 call _srand
.text:004016F6 mov [ebp+i], 0
.text:004016FD jmp short loc_401766
.text:004016FF ; ---------------------------------------------------------------------------

Ok, the first important part starts here.
We have a lot of unnecessary code like the calls to _troll which checks if a debugger is present and displays an annoying message box if it detects one.
The important parts of this loop are the call to _malloc and the compare operation at the end of the loop. From this we see that 23 tree nodes are created and allocated.

.text:004016FF
.text:004016FF loc_4016FF: ; CODE XREF: _create_tree+A0j
.text:004016FF mov dword ptr [esp], 18h ; size_t
.text:00401706 call _malloc
.text:0040170B mov edx, eax
.text:0040170D mov eax, [ebp+i]
.text:00401710 mov [ebp+eax*4+ptr], edx
.text:00401714 mov eax, [ebp+i]
.text:00401717 mov ebx, [ebp+eax*4+ptr]
.text:0040171B call _rand
.text:00401720 mov edx, eax
.text:00401722 mov ecx, [ebp+i]
.text:00401725 mov eax, ecx
.text:00401727 shl eax, 3
.text:0040172A add eax, ecx
.text:0040172C shl eax, 1
.text:0040172E mov [esp+4], edx ; b
.text:00401732 mov [esp], eax ; a
.text:00401735 call _troll
.text:0040173A mov [ebx], eax
.text:0040173C mov eax, [ebp+i]
.text:0040173F mov ebx, [ebp+eax*4+ptr]
.text:00401743 call _rand
.text:00401748 mov edx, eax
.text:0040174A mov ecx, [ebp+i]
.text:0040174D mov eax, ecx
.text:0040174F shl eax, 3
.text:00401752 add eax, ecx
.text:00401754 mov [esp+4], edx ; b
.text:00401758 mov [esp], eax ; a
.text:0040175B call _troll
.text:00401760 mov [ebx+14h], eax
.text:00401763 inc [ebp+i]
.text:00401766
.text:00401766 loc_401766: ; CODE XREF: _create_tree+33j
.text:00401766 cmp [ebp+i], 17h
.text:0040176A jle short loc_4016FF

After all the nodes are allocated, values for each node is assigned.

.text:0040176C mov eax, [ebp+ptr]
.text:0040176F mov byte ptr [eax+8], 65h ; tree[0].value = 'e'
.text:00401773 mov eax, [ebp+ptr+4]
.text:00401776 mov byte ptr [eax+8], 72h ; tree[1].value = 'r'
.text:0040177A mov eax, [ebp+ptr+8]
.text:0040177D mov byte ptr [eax+8], 54h ; tree[2].value = 'T'
.text:00401781 mov eax, [ebp+ptr+0Ch]
.text:00401784 mov byte ptr [eax+8], 6Ch ; tree[3].value = 'l'
.text:00401788 mov eax, [ebp+ptr+10h]
.text:0040178B mov byte ptr [eax+8], 53h ; tree[4].value = 'S'
.text:0040178F mov eax, [ebp+ptr+14h]
.text:00401792 mov byte ptr [eax+8], 76h ; tree[5].value = 'v'
.text:00401796 mov eax, [ebp+ptr+18h]
.text:00401799 mov byte ptr [eax+8], 6Eh ; tree[6].value = 'n'
.text:0040179D mov eax, [ebp+ptr+1Ch]
.text:004017A0 mov byte ptr [eax+8], 69h ; tree[7].value = 'i'
.text:004017A4 mov eax, [ebp+ptr+20h]
.text:004017A7 mov byte ptr [eax+8], 4Eh ; tree[8].value = 'N'
.text:004017AB mov eax, [ebp+ptr+24h]
.text:004017AE mov byte ptr [eax+8], 46h ; tree[9].value = 'F'
.text:004017B2 mov eax, [ebp+ptr+28h]
.text:004017B5 mov byte ptr [eax+8], 6Eh ; tree[10].value = 'n'
.text:004017B9 mov eax, [ebp+ptr+2Ch]
.text:004017BC mov byte ptr [eax+8], 6Ch ; tree[11].value = 'l'
.text:004017C0 mov eax, [ebp+ptr+30h]
.text:004017C3 mov byte ptr [eax+8], 72h ; tree[12].value = 'r'
.text:004017C7 mov eax, [ebp+ptr+34h]
.text:004017CA mov byte ptr [eax+8], 6Ch ; tree[13].value = 'l'
.text:004017CE mov eax, [ebp+ptr+38h]
.text:004017D1 mov byte ptr [eax+8], 65h ; tree[14].value = 'e'
.text:004017D5 mov eax, [ebp+ptr+3Ch]
.text:004017D8 mov byte ptr [eax+8], 65h ; tree[15].value = 'e'
.text:004017DC mov eax, [ebp+ptr+40h]
.text:004017DF mov byte ptr [eax+8], 63h ; tree[16].value = 'c'
.text:004017E3 mov eax, [ebp+ptr+44h]
.text:004017E6 mov byte ptr [eax+8], 69h ; tree[17].value = 'i'
.text:004017EA mov eax, [ebp+ptr+48h]
.text:004017ED mov byte ptr [eax+8], 73h ; tree[18].value = 's'
.text:004017F1 mov eax, [ebp+ptr+4Ch]
.text:004017F4 mov byte ptr [eax+8], 6Fh ; tree[19].value = 'o'
.text:004017F8 mov eax, [ebp+ptr+50h]
.text:004017FB mov byte ptr [eax+8], 69h ; tree[20].value = 'i'
.text:004017FF mov eax, [ebp+ptr+54h]
.text:00401802 mov byte ptr [eax+8], 67h ; tree[21].value = 'g'
.text:00401806 mov eax, [ebp+ptr+58h]
.text:00401809 mov byte ptr [eax+8], 61h ; tree[22].value = 'a'
.text:0040180D mov eax, [ebp+ptr+5Ch]
.text:00401810 mov byte ptr [eax+8], 67h ; tree[23].value = 'g'

And since we are dealing with a tree structure here are the assignments of the child nodes.

.text:00401814 mov eax, [ebp+ptr]
.text:00401817 mov edx, [ebp+ptr+4]
.text:0040181A mov [eax+4], edx           ; tree[0].right = tree[1]
.text:0040181D mov eax, [ebp+ptr+4]
.text:00401820 mov dword ptr [eax+4], 0   ; tree[1].right = 0
.text:00401827 mov eax, [ebp+ptr+4]
.text:0040182A mov edx, [ebp+ptr+14h]
.text:0040182D mov [eax+10h], edx         ; tree[1].left = tree[5]
.text:00401830 mov eax, [ebp+ptr+14h]
.text:00401833 mov edx, [ebp+ptr+3Ch]
.text:00401836 mov [eax+4], edx           ; tree[5].right = tree[15]
.text:00401839 mov eax, [ebp+ptr+3Ch]
.text:0040183C mov dword ptr [eax+4], 0   ; tree[15].right = 0
.text:00401843 mov eax, [ebp+ptr+14h]
.text:00401846 mov edx, [ebp+ptr+20h]
.text:00401849 mov [eax+10h], edx         ; tree[5].left = tree[8]
.text:0040184C mov eax, [ebp+ptr+20h]
.text:0040184F mov edx, [ebp+ptr+38h]
.text:00401852 mov [eax+4], edx           ; tree[8].right = tree[14]
.text:00401855 mov eax, [ebp+ptr+20h]
.text:00401858 mov dword ptr [eax+10h], 0 ; tree[8].left = 0
.text:0040185F mov eax, [ebp+ptr+38h]
.text:00401862 mov dword ptr [eax+4], 0   ; tree[14].right = 0
.text:00401869 mov eax, [ebp+ptr+38h]
.text:0040186C mov dword ptr [eax+10h], 0 ; tree[14].left = 0
.text:00401873 mov eax, [ebp+ptr]
.text:00401876 mov edx, [ebp+ptr+8]
.text:00401879 mov [eax+10h], edx         ; tree[0].left = tree[2]
.text:0040187C mov eax, [ebp+ptr+8]
.text:0040187F mov edx, [ebp+ptr+0Ch]
.text:00401882 mov [eax+4], edx           ; tree[2].right = tree[3]
.text:00401885 mov eax, [ebp+ptr+0Ch]
.text:00401888 mov edx, [ebp+ptr+10h]
.text:0040188B mov [eax+4], edx           ; tree[3].right = tree[4]
.text:0040188E mov eax, [ebp+ptr+10h]
.text:00401891 mov edx, [ebp+ptr+18h]
.text:00401894 mov [eax+4], edx           ; tree[4].right = tree[6]
.text:00401897 mov eax, [ebp+ptr+18h]
.text:0040189A mov edx, [ebp+ptr+40h]
.text:0040189D mov [eax+4], edx           ; tree[6].right = tree[16]
.text:004018A0 mov eax, [ebp+ptr+40h]
.text:004018A3 mov dword ptr [eax+4], 0   ; tree[16].right = 0
.text:004018AA mov eax, [ebp+ptr+40h]
.text:004018AD mov dword ptr [eax+10h], 0 ; tree[16].left = 0
.text:004018B4 mov eax, [ebp+ptr+18h]
.text:004018B7 mov edx, [ebp+ptr+44h]
.text:004018BA mov [eax+10h], edx         ; tree[6].left = tree[17]
.text:004018BD mov eax, [ebp+ptr+44h]
.text:004018C0 mov dword ptr [eax+10h], 0 ; tree[17].left = 0
.text:004018C7 mov eax, [ebp+ptr+44h]
.text:004018CA mov dword ptr [eax+4], 0   ; tree[17].right = 0
.text:004018D1 mov eax, [ebp+ptr+10h]
.text:004018D4 mov edx, [ebp+ptr+1Ch]
.text:004018D7 mov [eax+10h], edx         ; tree[4].left = tree[7]
.text:004018DA mov eax, [ebp+ptr+1Ch]
.text:004018DD mov dword ptr [eax+10h], 0 ; tree[7].left = 0
.text:004018E4 mov eax, [ebp+ptr+1Ch]
.text:004018E7 mov edx, [ebp+ptr+28h]
.text:004018EA mov [eax+4], edx           ; tree[7].right = tree[10]
.text:004018ED mov eax, [ebp+ptr+28h]
.text:004018F0 mov dword ptr [eax+10h], 0 ; tree[10].left = 0
.text:004018F7 mov eax, [ebp+ptr+28h]
.text:004018FA mov edx, [ebp+ptr+54h]
.text:004018FD mov [eax+4], edx           ; tree[10].right = tree[21]
.text:00401900 mov eax, [ebp+ptr+54h]
.text:00401903 mov dword ptr [eax+4], 0   ; tree[21].right = 0
.text:0040190A mov eax, [ebp+ptr+54h]
.text:0040190D mov dword ptr [eax+10h], 0 ; tree[21].left = 0
.text:00401914 mov eax, [ebp+ptr+0Ch]
.text:00401917 mov edx, [ebp+ptr+2Ch]
.text:0040191A mov [eax+10h], edx         ; tree[3].left = tree[11]
.text:0040191D mov eax, [ebp+ptr+2Ch]
.text:00401920 mov dword ptr [eax+4], 0   ; tree[11].right = 0
.text:00401927 mov eax, [ebp+ptr+2Ch]
.text:0040192A mov edx, [ebp+ptr+30h]
.text:0040192D mov [eax+10h], edx         ; tree[11].left = tree[12]
.text:00401930 mov eax, [ebp+ptr+30h]
.text:00401933 mov dword ptr [eax+10h], 0 ; tree[12].left = 0
.text:0040193A mov eax, [ebp+ptr+30h]
.text:0040193D mov edx, [ebp+ptr+4Ch]
.text:00401940 mov [eax+4], edx           ; tree[12].right = tree[19]
.text:00401943 mov eax, [ebp+ptr+4Ch]
.text:00401946 mov dword ptr [eax+4], 0   ; tree[19].right = 0
.text:0040194D mov eax, [ebp+ptr+4Ch]
.text:00401950 mov dword ptr [eax+10h], 0 ; tree[19].left = 0
.text:00401957 mov eax, [ebp+ptr+8]
.text:0040195A mov edx, [ebp+ptr+24h]
.text:0040195D mov [eax+10h], edx         ; tree[2].left = tree[9]
.text:00401960 mov eax, [ebp+ptr+24h]
.text:00401963 mov dword ptr [eax+10h], 0 ; tree[9].left = 0
.text:0040196A mov eax, [ebp+ptr+24h]
.text:0040196D mov edx, [ebp+ptr+34h]
.text:00401970 mov [eax+4], edx           ; tree[9].right = tree[13]
.text:00401973 mov eax, [ebp+ptr+34h]
.text:00401976 mov dword ptr [eax+10h], 0 ; tree[13].left = 0
.text:0040197D mov eax, [ebp+ptr+34h]
.text:00401980 mov edx, [ebp+ptr+48h]
.text:00401983 mov [eax+4], edx           ; tree[13].right = tree[18]
.text:00401986 mov eax, [ebp+ptr+48h]
.text:00401989 mov dword ptr [eax+4], 0   ; tree[18].right = 0
.text:00401990 mov eax, [ebp+ptr+48h]
.text:00401993 mov edx, [ebp+ptr+50h]
.text:00401996 mov [eax+10h], edx         ; tree[18].left = tree[20]
.text:00401999 mov eax, [ebp+ptr+50h]
.text:0040199C mov dword ptr [eax+4], 0   ; tree[20].right = 0
.text:004019A3 mov eax, [ebp+ptr+50h]
.text:004019A6 mov edx, [ebp+ptr+58h]
.text:004019A9 mov [eax+10h], edx         ; tree[20].left = tree[22]
.text:004019AC mov eax, [ebp+ptr+58h]
.text:004019AF mov dword ptr [eax+10h], 0 ; tree[22].left = 0
.text:004019B6 mov eax, [ebp+ptr+58h]
.text:004019B9 mov edx, [ebp+ptr+5Ch]
.text:004019BC mov [eax+4], edx           ; tree[22].right = tree[23]
.text:004019BF mov eax, [ebp+ptr+5Ch]
.text:004019C2 mov dword ptr [eax+4], 0   ; tree[23].right = 0
.text:004019C9 mov eax, [ebp+ptr+5Ch]
.text:004019CC mov dword ptr [eax+10h], 0 ; tree[23].left = 0
.text:004019D3 mov eax, [ebp+ptr]         ; eax = tree[0]
.text:004019D6 sub esp, 0FFFFFF80h
.text:004019D9 pop ebx
.text:004019DA pop edi
.text:004019DB pop ebp
.text:004019DC retn
.text:004019DC _create_tree endp

So now we have to do a depth-first traversal on the tree to get the flag.

Here's some example C# code to print the flag.

using System;

namespace Souhails_Climb
{
    class Node
    {
        public Node Left { get; set; }
        public Node Right { get; set; }
        public char Value { get; set; }
    }

    class Keygen
    {
        static void Main(string[] args)
        {
            PrintTreeValues(CreateTree());
            Console.ReadKey();
        }

        private static void PrintTreeValues(Node tree)
        {
            if (tree == null) return;
            PrintTreeValues(tree.Left);
            Console.Write(tree.Value);
            PrintTreeValues(tree.Right);
        }

        private static Node CreateTree()
        {
            var tree = new Node[24];

            for (var i = 0; i < tree.Length; i++)
            {
                tree[i] = new Node();
            }

            tree[0].Value = 'e';
            tree[1].Value = 'r';
            tree[2].Value = 'T';
            tree[3].Value = 'l';
            tree[4].Value = 'S';
            tree[5].Value = 'v';
            tree[6].Value = 'n';
            tree[7].Value = 'i';
            tree[8].Value = 'N';
            tree[9].Value = 'F';
            tree[10].Value = 'n';
            tree[11].Value = 'l';
            tree[12].Value = 'r';
            tree[13].Value = 'l';
            tree[14].Value = 'e';
            tree[15].Value = 'e';
            tree[16].Value = 'c';
            tree[17].Value = 'i';
            tree[18].Value = 's';
            tree[19].Value = 'o';
            tree[20].Value = 'i';
            tree[21].Value = 'g';
            tree[22].Value = 'a';
            tree[23].Value = 'g';

            tree[0].Right = tree[1];
            tree[0].Left = tree[2];
            tree[1].Right = null;
            tree[1].Left = tree[5];
            tree[2].Right = tree[3];
            tree[2].Left = tree[9];
            tree[3].Right = tree[4];
            tree[3].Left = tree[11];
            tree[4].Right = tree[6];
            tree[4].Left = tree[7];
            tree[5].Right = tree[15];
            tree[5].Left = tree[8];
            tree[6].Right = tree[16];
            tree[6].Left = tree[17];
            tree[7].Right = tree[10];
            tree[7].Left = null;
            tree[8].Right = tree[14];
            tree[8].Left = null;
            tree[9].Right = tree[13];
            tree[9].Left = null;
            tree[10].Right = tree[21];
            tree[10].Left = null;
            tree[11].Right = null;
            tree[11].Left = tree[12];
            tree[12].Right = tree[19];
            tree[12].Left = null;
            tree[13].Right = tree[18];
            tree[13].Left = null;
            tree[14].Right = null;
            tree[14].Left = null;
            tree[15].Right = null;
            tree[15].Left = null;
            tree[16].Right = null;
            tree[16].Left = null;
            tree[17].Right = null;
            tree[17].Left = null;
            tree[18].Right = null;
            tree[18].Left = tree[20];
            tree[19].Right = null;
            tree[19].Left = null;
            tree[20].Right = null;
            tree[20].Left = tree[22];
            tree[21].Right = null;
            tree[21].Left = null;
            tree[22].Right = tree[23];
            tree[22].Left = null;
            tree[23].Right = null;
            tree[23].Left = null;

            return tree[0];
        }
    }
}