Binary Bomb



  • Hallo :). Ich habe die Aufgabe eine binäre Bombe zu entschärfen. Dabei gibt es verschiedene Phasen, ich bin jetzt bei Phase 5. Lieder komme ich jetzt nicht weiter. Hier erstmal der Assembler Code.

    08048efb <phase_5>:
         8048efb:       55                      push   %ebp
         8048efc:       89 e5                   mov    %esp,%ebp
         8048efe:       56                      push   %esi
         8048eff:       53                      push   %ebx
         8048f00:       83 ec 20                sub    $0x20,%esp
         8048f03:       8d 45 f0                lea    -0x10(%ebp),%eax
         8048f06:       89 44 24 0c             mov    %eax,0xc(%esp)
         8048f0a:       8d 45 f4                lea    -0xc(%ebp),%eax
         8048f0d:       89 44 24 08             mov    %eax,0x8(%esp)
         8048f11:       c7 44 24 04 e4 a6 04    movl   $0x804a6e4,0x4(%esp)
         8048f18:       08
         8048f19:       8b 45 08                mov    0x8(%ebp),%eax
         8048f1c:       89 04 24                mov    %eax,(%esp)
         8048f1f:       e8 8c f9 ff ff          call   80488b0 <__isoc99_sscanf@plt>
         8048f24:       83 f8 01                cmp    $0x1,%eax
         8048f27:       7f 05                   jg     8048f2e <phase_5+0x33>
         8048f29:       e8 d3 06 00 00          call   8049601 <explode_bomb>
         8048f2e:       8b 45 f4                mov    -0xc(%ebp),%eax
         8048f31:       83 e0 0f                and    $0xf,%eax
         8048f34:       89 45 f4                mov    %eax,-0xc(%ebp)
         8048f37:       83 f8 0f                cmp    $0xf,%eax
         8048f3a:       74 29                   je     8048f65 <phase_5+0x6a>
         8048f3c:       b9 00 00 00 00          mov    $0x0,%ecx
         8048f41:       ba 00 00 00 00          mov    $0x0,%edx
         8048f46:       bb c0 a5 04 08          mov    $0x804a5c0,%ebx
         8048f4b:       83 c2 01                add    $0x1,%edx
         8048f4e:       8b 04 83                mov    (%ebx,%eax,4),%eax
         8048f51:       01 c1                   add    %eax,%ecx
         8048f53:       83 f8 0f                cmp    $0xf,%eax
         8048f56:       75 f3                   jne    8048f4b <phase_5+0x50>
         8048f58:       89 45 f4                mov    %eax,-0xc(%ebp)
         8048f5b:       83 fa 0f                cmp    $0xf,%edx
         8048f5e:       75 05                   jne    8048f65 <phase_5+0x6a>
         8048f60:       39 4d f0                cmp    %ecx,-0x10(%ebp)
         8048f63:       74 05                   je     8048f6a <phase_5+0x6f>
         8048f65:       e8 97 06 00 00          call   8049601 <explode_bomb>
         8048f6a:       83 c4 20                add    $0x20,%esp
         8048f6d:       5b                      pop    %ebx
         8048f6e:       5e                      pop    %esi
         8048f6f:       5d                      pop    %ebp
         8048f70:       c3                      ret
    

    So, was ich bis jetzt herausgefunden habe ist, dass an Adresse 8048f11 mit "movl $0x804a6e4,0x4(%esp)" das Format der Eingabe an sscanf übergeben wird. Mit "x/s 0x804a6e4" habe ich mir der Format anzeigen lassen "%d %d", das heißt man muss 2 Integers eingeben. Es wird an 8048f24 und 8048f27 überprüft, ob die eingabe > 1 ist.

    Was jetzt glaube ich ziemlich wichtig ist, ist 8048f31. Dort wird eax mit 0xf geundet. 0xf ist in binärer Schreibweise 1111.

    Nach dem and-Befehl wird dann in 8048f37 geschaut, ob eax 15 ist. Wenn ja, springt es zu explode_bomb. edx ist danach der Zähler einer Schleife und wird am Anfang von jedem Durchlauf um 1 erhöht. In 8048f53 wird nochmal überprüft ob eax 15 ist, wenn ja geht es zum Anfang der Schleife. Falls nicht, wird edx mit 15 in 8048f5b verglichen. Solange dies nicht der Fall ist, springt man zum Anfang der Schleife zurück. Dh es wird max 15 Schleifendurchgänge geben.

    Wenn die Schleife erfolgreich durchgelaufen ist, wird in 8048f60 %ecx mit -0x10(%ebp) vergleichen. Wenn ecx gleich ist, hat man das richtige Ergebnis gefunden, falls nicht explodiert die Bombe.

    Das ist glaube ich alles, was ich zur Zeit habe. Danke schonmal für Eure Hilfe !! 🙂



  • Wie wäre es mit einem Syntax, der für Menschen gemacht ist und nicht für eine back end Assembler?



  • Naja ich habe nur die ausführbare Datei der Bombe bekommen und keinen c-Code. Deswegen kann ich nur den Assembler Code posten, den mir objdump ausgespuckt hat. Ich hoffe ich habe dich richtig verstanden :D.



  • einfach die Option -M intel benutzen - dann ist die ganze Sache besser lesbar, macht Sinn und passt auch zur Dokumentation von Intel und AMD.



  • Alles klar. Danke schonmal für den Tipp :). Hier ist die Ausgabe:

    08048efb <phase_5>:
     8048efb:	55                   	push   ebp
     8048efc:	89 e5                	mov    ebp,esp
     8048efe:	56                   	push   esi
     8048eff:	53                   	push   ebx
     8048f00:	83 ec 20             	sub    esp,0x20
     8048f03:	8d 45 f0             	lea    eax,[ebp-16]
     8048f06:	89 44 24 0c          	mov    DWORD PTR [esp+12],eax
     8048f0a:	8d 45 f4             	lea    eax,[ebp-12]
     8048f0d:	89 44 24 08          	mov    DWORD PTR [esp+8],eax
     8048f11:	c7 44 24 04 e4 a6 04 	mov    DWORD PTR [esp+4],0x804a6e4
     8048f18:	08 
     8048f19:	8b 45 08             	mov    eax,DWORD PTR [ebp+8]
     8048f1c:	89 04 24             	mov    DWORD PTR [esp],eax
     8048f1f:	e8 8c f9 ff ff       	call   80488b0 <__isoc99_sscanf@plt>
     8048f24:	83 f8 01             	cmp    eax,0x1
     8048f27:	7f 05                	jg     8048f2e <phase_5+0x33>
     8048f29:	e8 d3 06 00 00       	call   8049601 <explode_bomb>
     8048f2e:	8b 45 f4             	mov    eax,DWORD PTR [ebp-12]
     8048f31:	83 e0 0f             	and    eax,0xf
     8048f34:	89 45 f4             	mov    DWORD PTR [ebp-12],eax
     8048f37:	83 f8 0f             	cmp    eax,0xf
     8048f3a:	74 29                	je     8048f65 <phase_5+0x6a>
     8048f3c:	b9 00 00 00 00       	mov    ecx,0x0
     8048f41:	ba 00 00 00 00       	mov    edx,0x0
     8048f46:	bb c0 a5 04 08       	mov    ebx,0x804a5c0
     8048f4b:	83 c2 01             	add    edx,0x1
     8048f4e:	8b 04 83             	mov    eax,DWORD PTR [ebx+eax*4]
     8048f51:	01 c1                	add    ecx,eax
     8048f53:	83 f8 0f             	cmp    eax,0xf
     8048f56:	75 f3                	jne    8048f4b <phase_5+0x50>
     8048f58:	89 45 f4             	mov    DWORD PTR [ebp-12],eax
     8048f5b:	83 fa 0f             	cmp    edx,0xf
     8048f5e:	75 05                	jne    8048f65 <phase_5+0x6a>
     8048f60:	39 4d f0             	cmp    DWORD PTR [ebp-16],ecx
     8048f63:	74 05                	je     8048f6a <phase_5+0x6f>
     8048f65:	e8 97 06 00 00       	call   8049601 <explode_bomb>
     8048f6a:	83 c4 20             	add    esp,0x20
     8048f6d:	5b                   	pop    ebx
     8048f6e:	5e                   	pop    esi
     8048f6f:	5d                   	pop    ebp
     8048f70:	c3                   	ret
    


  • Warum ist das jetzt besser lesbar? Die AT&T Syntax ist genauso gut lesbar, das ist reine Gewohnheitssache.



  • Mechanics schrieb:

    Warum ist das jetzt besser lesbar? Die AT&T Syntax ist genauso gut lesbar, das ist reine Gewohnheitssache.

    Das vielleicht schon, aber --demangle wird __isoc99_sscanf@plt effektiv besser lesbar 😉
    Nur dem Verständnis hilfts wenig.



  • Falls es helfen würde, könnte ich auch das komplette Programm hochladen...



  • Soweit ich das sehen kann, häng alles von dem Inhalt eines Arrays ab:

    int n = sscanf(func_arg1,"%d %d",&local1,&local2);
    if (n <= 1)
        explode;
    
    local1 = local1 & 15;
    
    int i,k;
    
    for (i=0,k=0; local1 != 15; i++)
    {
       local1 = int_array[local1];
       k = k + local1;
    }
    
    if(i != 15 || k != local2)
        explode;
    
    return local1;
    

    Die erste Zahl muss auf jeden Fall kleiner als 15 sein.



  • Nur wie kann ich auf das Array zugreifen und den Inhalt auslesen?
    Außerdem, sehe ich das richtig, dass bei 8048f11 Informationen über das Eingabeformat für sscanf stehen sollten?



  • Die Adresse ist in EBX: 0x804a5c0



  • Hier ist nochmal eine decompilierte Version:

    int result; // eax@3
    int v2; // edx@4
    int v3; // ecx@4
    int v4; // [sp+18h] [bp-10h]@1
    int v5; // [sp+1Ch] [bp-Ch]@1

    if ( __isoc99_sscanf(a1, "%d %d", &v5, &v4) <= 1 )
    explode_bomb();
    result = v5 & 0xF;
    v5 = result;
    if ( result == 15 )
    goto LABEL_11;
    v3 = 0;
    v2 = 0;
    do
    {
    ++v2;
    result = *(_DWORD *)&array_3459[4 * result];
    v3 += result;
    }
    while ( result != 15 );
    v5 = 15;
    if ( v2 != 15 || v4 != v3 )
    LABEL_11:
    explode_bomb();
    return result;
    }



  • Wenn ich mir mit "x/16c 0x804a5c0" den Inhalt ausgeben lasse, kommt

    0x804a5c0 <array.3459>: 10 '\n' 0 '\000' 0 '\000' 0 '\000'
    2 '\002' 0 '\000' 0 '\000' 0 '\000'
    0x804a5c8 <array.3459+8>: 14 '\016' 0 '\000' 0 '\000'
    0 '\000' 7 '\a' 0 '\000' 0 '\000' 0 '\000'

    raus... Soll das das Array sein? Danke nochmal für deine Zeit und Hilfe 🙂



  • Hier ist die Datei, falls es weiterhilft: http://filebin.ca/jaby5lrl4bo/bomb
    die passwörter bis Phase_5 kann ich dann posten 🙂

    Okay hier sind sie:
    The future will be better tomorrow.
    0 1 3 6 10 15
    1 v 899
    162 3



  • Die Start-Adresse auf das Array liegt bei 0x804a5c0, EBX wird damit belegt:

    mov    ebx,0x804a5c0
    

    EAX enthält den Index des Array Elements. Da dieser mit 4, also sizeof(DWORD), multipliziert wird, handelt es sich um ein DWORD-Array, das DWORD wird ja auch nach EAX kopiert, mittels DWORD PTR[].

    add    edx,0x1 
    mov    eax,DWORD PTR [ebx+eax*4]
    


  • Hallo squay,

    ich weiß zwar nicht, was die Funktion eigentlich bezwecken soll, da ich den gesamten Kontext nicht kenne. Aber dennoch habe ich das Disassembly mal kommentiert und eine mögliche C-Implementation geschrieben. Aufgrund des oben genannten Problems habe ich mich beim C Code sehr nah an das Disassembly Listing gehalten. Ich hoffe, dass es dir weiterhilft.

    Ich gehe mal davon aus, dass du verhindern willst, dass explode_bomb() aufgerufen wird. Wenn du dir die Funktion ansiehst, dann wirst du bemerken, dass es da letzten Endes doch auf den Wert eines spezifischen Array Elements ankommt (wie es mir scheint).

    08048efb <phase_5>:
    
    ; Stack frame of phase_5:
    ; function typedef: DWORD __cdecl phase_5(char* pszStringToScan)
    ; Segment:
    ;	EBP+0x08: pszStringToScan
    ;	EBP+0x04: Return address
    ;	EBP+0x00: Old EBP value
    ;	EBP-0x04: ESI backup
    ;	EBP-0x08: EBX backup 
    ;	...
    ;	EBP-0x12: First sscanf format list argument
    ;	EBP-0x16: Second sscanf format list argument
    
     8048efb:   55                      push   ebp	; Backup old EBP value to use as stack pointer
     8048efc:   89 e5                   mov    ebp,esp	; Copy value from ESP to EBP. EBP stack frame pointer setup done
     8048efe:   56                      push   esi	; Backup ESI to use it
     8048eff:   53                      push   ebx	; Backup EBX to use it
     8048f00:   83 ec 20                sub    esp,0x20 ;Subtract 0x20 bytes from ESP to allocate stack memory
     8048f03:   8d 45 f0                lea    eax,[ebp-16]	; Load expression ebp-0x16 to EAX. It's the pointer to the second format list arg for sscanf
     8048f06:   89 44 24 0c             mov    DWORD PTR [esp+12],eax ; Copy value from EAX to [ESP+0x12]. At ESP+0x12 is the fourth function arg
     8048f0a:   8d 45 f4                lea    eax,[ebp-12]	; Load expression EBP-0x12 to EAX. It's the pointer to the first format list arg for sscanf
     8048f0d:   89 44 24 08             mov    DWORD PTR [esp+8],eax	; Copy value from EAX to [ESP+0x08]. At ESP+0x08 is the third function arg
     8048f11:   c7 44 24 04 e4 a6 04    mov    DWORD PTR [esp+4],0x804a6e4	; Copy constant VA value to [ESP+0x04]. At ESP+0x04 is the second function arg
     8048f19:   8b 45 08                mov    eax,DWORD PTR [ebp+8]	; Copy value at [EBP+0x08] (argument of phase_5()) to EAX. The string which shall be scanned is passed to phase_5() function
     8048f1c:   89 04 24                mov    DWORD PTR [esp],eax	; Copy value from EAX to [ESP]. At ESP is the first function arg
     8048f1f:   e8 8c f9 ff ff          call   80488b0 <__isoc99_sscanf@plt> ; Call sscanf function (cdecl)
     8048f24:   83 f8 01                cmp    eax,0x1	; Perform comparition with EAX and 0x01
     8048f27:   7f 05                   jg     8048f2e <phase_5+0x33>	; If EAX is greater then jump to address
     8048f29:   e8 d3 06 00 00          call   8049601 <explode_bomb>	; Else call explode_bomb(). So we don't want to get to this place
     8048f2e:   8b 45 f4                mov    eax,DWORD PTR [ebp-12]	; Copy DWORD at [EBP-12] (first format list arg) to EAX
     8048f31:   83 e0 0f                and    eax,0xf	; Perform AND operation with EAX and 0x0F
     8048f34:   89 45 f4                mov    DWORD PTR [ebp-12],eax	; Copy new value back to the stack var
     8048f37:   83 f8 0f                cmp    eax,0xf	; Perform comparision with EAX and 0x0F
     8048f3a:   74 29                   je     8048f65 <phase_5+0x6a>	; If both are equal jump to the address. That shall not happen.
     8048f3c:   b9 00 00 00 00          mov    ecx,0x0	; Initialize ECX with 0x00000000 by copying
     8048f41:   ba 00 00 00 00          mov    edx,0x0	; Initialize EDX with 0x00000000 by copying
     8048f46:   bb c0 a5 04 08          mov    ebx,0x804a5c0	; Copy VA constant to EBX. It is the base address of a DWORD array
     ;Begin loop
     8048f4b:   83 c2 01                add    edx,0x1	; Add 0x01 to EDX
     8048f4e:   8b 04 83                mov    eax,DWORD PTR [ebx+eax*4]	; Copy the DWORD at EBX+EAX*4 to EAX. Get index offset by EAX*4
     8048f51:   01 c1                   add    ecx,eax	; Add EAX to ECX
     8048f53:   83 f8 0f                cmp    eax,0xf	; Perform comparison with EAX and 0x0F. To end this loop EAX must have the value 0x0F at its lowest byte
     8048f56:   75 f3                   jne    8048f4b <phase_5+0x50>	; If both are not equal jump to loop begin. 
     ; End loop
     8048f58:   89 45 f4                mov    DWORD PTR [ebp-12],eax	; Copy EAX back to the stack var
     8048f5b:   83 fa 0f                cmp    edx,0xf	; Compare EDX with 0x0F
     8048f5e:   75 05                   jne    8048f65 <phase_5+0x6a> ; If not equal jump to the fail part. So, basically, EDX must have the value 0x0F at its lowest byte to avoid explode_bomb() call
     8048f60:   39 4d f0                cmp    DWORD PTR [ebp-16],ecx	; Compare DWORD at [EBP-0x016] with ECX
     8048f63:   74 05                   je     8048f6a <phase_5+0x6f>	; If both are equal jump to the success part!
     8048f65:   e8 97 06 00 00          call   8049601 <explode_bomb>	; Call explode_bomb() function. So we don't want to get to this place from 8048f3a and 8048f5e
     8048f6a:   83 c4 20                add    esp,0x20	; Remove the allocated stack memory by adding
     8048f6d:   5b                      pop    ebx	; Restore EBX
     8048f6e:   5e                      pop    esi	; Restore ESI
     8048f6f:   5d                      pop    ebp	; Restore old EBP
     8048f70:   c3                      ret	; Restore return address
    
     // Possible C implementation
     DWORD __cdecl phase_5_8048efb(char* pszStringToScan)
     {
    	static unsigned int uia804a5c0[...] = {...};
    
    	DWORD dwEBP12;
    	DWORD dwEBP16;
    
    	if (sscanf(pszStringToScan, "%d %d", &dwEBP12, &dwEBP16) <= 0x01)
    		explode_bomb();
    
    	DWORD dwEAX = dwEBP12 & 0x0F;
    	dwEBP12 = dwEAX;
    
    	if (dwEAX == 0x0F)
    		explode_bomb();
    
    	DWORD dwECX, dwEDX;
    	dwECX = dwEDX = 0;
    
    	while (dwEAX != 0x0F) {
    		dwEAX = *(DWORD*)((DWORD)uia804a5c0 + dwEAX * 4); //uia804a5c0[dwEAX];
    
    		dwECX += dwEAX;
    
    		dwEDX++;
    	}
    
    	dwEBP12 = dwEAX;
    
    	if ((dwEDX != 0x0F) || (dwECX != dwEBP16))
    		explode_bomb();
    
    	return dwEAX;
     }
    
     //Conclusion: If you want the function phase_5() to succeed then the values of the
     //important registers need the following values (context beginning at 8048f3c till the end):
     //EAX==0x0F && EDX!=0x0F && ECX!=dwEBP16
     //Since ECX and EDX get changed inside the loop it all depends on the array element value at a certain position
    

    http://pastebin.com/7BMrsuuP

    Ich kann natürlich auch was falsch interpretiert haben, bin gerade nicht so konzentriert...

    Gruß


Log in to reply