Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Reverse Engineering - Entwickeln gegen eine Blackbox

Reverse Engineering - Entwickeln gegen eine Blackbox

Cedric Fröhner

June 06, 2018
Tweet

Other Decks in Programming

Transcript

  1. Reverse Engineering
    Entwickeln gegen eine Blackbox

    View Slide

  2. Speaker
    06.06.2018 2
    - gelernter Softwareentwickler
    - Projekt- & Teamleiter
    - Scrum Master
    - Product Owner
    - Agile Coach
    - Atlassian Fanboy
    Position: Engineering Operations Lead
    Cedric Fröhner

    View Slide

  3. Agenda
    06.06.2018 3

    Was ist Reverse Engineering?

    Warum wurde es notwendig?

    Darf thinkstep das?

    Was haben wir vorgefunden und wie sind wir vorgegangen?

    Beispiele, Probleme und Fallstricke

    View Slide

  4. 06.06.2018 4
    Was ist
    Reverse Engineering?

    View Slide

  5. Was ist Reverse Engineering?
    06.06.2018 5
    Unter Reverse Engineering versteht man die Analyse von Software mit dem Ziel, ihren
    inneren Aufbau / ihre Struktur zu erkennen und zu verstehen.

    View Slide

  6. Was ist Reverse Engineering?
    06.06.2018 6
    Unter Reverse Engineering versteht man die Analyse von Software mit dem Ziel, ihren
    inneren Aufbau / ihre Struktur zu erkennen und zu verstehen.

    Die Analyse von Kommunikationsprotokollen
    Wireshark

    View Slide

  7. Was ist Reverse Engineering?
    06.06.2018 7
    Unter Reverse Engineering versteht man die Analyse von Software mit dem Ziel, ihren
    inneren Aufbau / ihre Struktur zu erkennen und zu verstehen.

    Die Rekonstruktion des Quellcodes von Programmen

    View Slide

  8. 06.06.2018 8
    Warum
    wurde es notwendig?

    View Slide

  9. Warum wurde es notwendig?
    06.06.2018 9

    Kein Support durch das externe Unternehmen

    Die Software ist nur unter PHP 5.5 lauffähig

    Performance Probleme

    Bestehende Bugs konnten nicht behoben werden

    Erschwerte Implementierung von Features (Seiteneffekte)

    View Slide

  10. 06.06.2018 10
    Darf
    thinkstep das?

    View Slide

  11. Darf thinkstep das?
    06.06.2018 11
    Decrypten

    Verstoß gegen das Urheberrecht

    Rechtliche Konsequenzen

    View Slide

  12. Darf thinkstep das?
    06.06.2018 12
    Replacement

    Mit Hilfe der Rechtsabteilung das Vorgehen besprochen

    Das Verhalten der vorhandenen Software analysiert und nachgebaut

    Bibliothek Schritt für Schritt ersetzt

    View Slide

  13. 06.06.2018 13
    Was haben
    wir vorgefunden?

    View Slide

  14. Was haben wir vorgefunden?
    06.06.2018 14

    Eine grobe Gliederung der einzelnen Bestandteile der Software

    Einen vorgegebenen Workflow

    Stub-Dateien pro Klasse
    – Funktionsnamen
    – Geschätzte Anzahl an Codezeilen pro Funktion

    View Slide

  15. 06.06.2018 15
    Wie sind
    wir vorgegangen?

    View Slide

  16. Wie sind wir vorgegangen?
    06.06.2018 16

    Klassenweises Vorgehen

    Test gegen alte Funktion geschrieben

    Funktionsverhalten mit Hilfe von xdebug_trace analysiert

    Neuschreiben der Funktion

    Ersetzen der alten Klassen

    View Slide

  17. 06.06.2018 17
    Betrachten
    wir ein Beispiel

    View Slide

  18. Betrachten wir ein Beispiel
    06.06.2018 18
    OldLibExample::formatTimeStamp(time());
    Blackbox
    2018-05-28 09:48:06

    View Slide

  19. Betrachten wir ein Beispiel
    06.06.2018 19
    Der Inhalt der Stub-Datei
    class StubExample
    {
    public static function formatTimeString($timestamp)
    {
    // 7 lines
    }
    }

    View Slide

  20. Betrachten wir ein Beispiel
    06.06.2018 20
    Die Vorbereitung
    class ReplacedExample extends OldLibExample
    {
    public static function formatTimeString($timestamp)
    {
    return parent::formatTimeString($timestamp);
    }
    }

    View Slide

  21. Der Test
    class ReplacedExampleTest extends \PHPUnit_Framework_TestCase
    {
    public function testFormatTimeString()
    {
    $timestamp = strtotime('28.05.2018 09:48:06');
    $formattedTimestamp = ReplacedExample::formatTimeString($timestamp);
    $this->assertEquals('2018-05-14 09:48:06', $formattedTimestamp);
    }
    }
    Betrachten wir ein Beispiel
    06.06.2018 21

    View Slide

  22. Erzeugen des Traces
    class ReplacedExampleTest extends \PHPUnit_Framework_TestCase
    {
    public function testFormatTimeString()
    {
    $timestamp = strtotime('28.05.2018 09:48:06');
    xdebug_start_trace(__DIR__.'/example_trace');
    $formattedTimestamp = ReplacedExample::formatTimeString($timestamp);
    xdebug_stop_trace();
    $this->assertEquals('2018-05-14 09:48:06', $formattedTimestamp);
    }
    }
    Betrachten wir ein Beispiel
    06.06.2018 22

    View Slide

  23. Analyse des Traces
    TRACE START [2018-05-28 11:24:10]
    0.0003 227270 -> ReplacedExample::formatTimeStamp($timestamp = ‘28.05.2018 09:48:06‘)
    0.0003 227280 -> OldLibExample::formatTimeStamp($timestamp = ‘28.05.2018 09:48:06‘)
    /var/www/examples/hidden_behaviour.php:28
    => $format = 'Y-m-d h:i:s' /var/www/examples/hidden_behaviour.php:17
    0.0004 227376 -> date(...) /var/www/examples/hidden_behaviour.php:22
    => $formattedTimestamp = '2018-05-28 09:48:06'
    => $formattedTimestamp = '2018-05-28 09:48:06'
    0.0004 227512 -> xdebug_stop_trace() /var/www/examples/hidden_behaviour.php:29
    0.0004 227576
    TRACE END [2018-05-28 11:24:10]
    Betrachten wir ein Beispiel
    06.06.2018 23

    View Slide

  24. Betrachten wir ein Beispiel
    06.06.2018 24
    Das Replacement
    class ReplacedExample extends OldLibExample
    {
    public static function formatTimeString($timestamp)
    {
    $format = ‘Y-m-d H:i:s’;
    return date($format‚ $timestamp);
    }
    }

    View Slide

  25. Betrachten wir ein Beispiel
    06.06.2018 25
    Das Refactoring
    class ReplacedExample extends OldLibExample
    {
    public static function formatTimeString($timestamp)
    {
    return date(‘Y-m-d H:i:s‘‚ $timestamp);
    }
    }

    View Slide

  26. Betrachten wir ein Beispiel
    06.06.2018 26
    Das Replacement
    class ReplacedExample
    {
    public static function formatTimeString($timestamp)
    {
    return date(‘Y-m-d H:i:s‘‚ $timestamp);
    }
    }
    Alle Aufrufe der OldLibExample-Klasse werden ausgetauscht.

    View Slide

  27. 06.06.2018 27
    Welche
    Probleme sind aufgetreten?

    View Slide

  28. Probleme
    06.06.2018 28
    Use Case 1
    OldLibExample::formatTimeStamp(time());
    Regression Testing
    Use Case 2 28/05/2028 09:48:06
    Use Case 1
    ReplacedExample::formatTimeStamp(time());
    2018-05-28 09:48:06
    Use Case 2 2018-05-28 09:48:06
    2018-05-28 09:48:06

    View Slide

  29. Probleme
    06.06.2018 29
    Unser Beispiel ist nicht vollständig
    class ReplacedExample
    {
    public static function formatTimeString($timestamp)
    {
    $format = ‘Y-m-d H:i:s’;
    return date($format‚ $timestamp);
    }
    }
    Hatte diese Zuweisung einen Sinn?

    View Slide

  30. Alles nochmal...
    class ReplacedExampleTest extends \PHPUnit_Framework_TestCase
    {
    public function testFormatTimeString()
    {
    $timestamp = strtotime('28.05.2018 09:48:06');
    xdebug_start_trace(__DIR__.'/example_trace');
    $formattedTimestamp = ReplacedExample::formatTimeString($timestamp);
    xdebug_stop_trace();
    $this->assertEquals('2018-05-14 09:48:06', $formattedTimestamp);
    }
    }
    Probleme
    06.06.2018 30

    View Slide

  31. Analyse des Traces
    TRACE START [2018-05-28 11:30:10]
    0.0003 227270 -> ReplacedExample::formatTimeStamp($timestamp = ‘28.05.2018 09:48:06‘)
    0.0003 227280 -> OldLibExample::formatTimeStamp($timestamp = ‘28.05.2018 09:48:06‘)
    /var/www/examples/hidden_behaviour.php:28
    => $format = 'Y-m-d h:i:s' /var/www/examples/hidden_behaviour.php:17
    0.0004 227376 -> date(...) /var/www/examples/hidden_behaviour.php:22
    => $formattedTimestamp = '2018-05-28 09:48:06'
    => $formattedTimestamp = '2018-05-28 09:48:06'
    0.0004 227512 -> xdebug_stop_trace() /var/www/examples/hidden_behaviour.php:29
    0.0004 227576
    TRACE END [2018-05-28 11:30:10]
    Probleme
    06.06.2018 31

    View Slide

  32. Try and error
    class ReplacedExampleTest extends \PHPUnit_Framework_TestCase
    {
    public function testFormatTimeString()
    {
    $timestamp = strtotime('28.05.2018 09:48:06');
    $GLOBALS[‘dateFormat’] = 'd/m/Y h:i:s';
    xdebug_start_trace(__DIR__.'/example_trace');
    $formattedTimestamp = ReplacedExample::formatTimeString($timestamp);
    xdebug_stop_trace();
    $this->assertEquals('2018-05-14 09:48:06', $formattedTimestamp);
    }
    }
    Probleme
    06.06.2018 32

    View Slide

  33. Try and error
    TRACE START [2018-05-28 11:40:10]
    0.0003 227270 -> ReplacedExample::formatTimeStamp($timestamp = ‘28.05.2018 09:48:06‘)
    0.0003 227280 -> OldLibExample::formatTimeStamp($timestamp = ‘28.05.2018 09:48:06‘)
    /var/www/examples/hidden_behaviour.php:28
    => $format = 'Y-m-d h:i:s' /var/www/examples/hidden_behaviour.php:17
    => $format = 'd/m/Y h:i:s' /var/www/examples/hidden_behaviour.php:19
    0.0004 227376 -> date() /var/www/examples/hidden_behaviour.php:22
    => $formattedTimestamp = '2018-05-28 09:48:06'
    => $formattedTimestamp = '2018-05-28 09:48:06'
    0.0004 227512 -> xdebug_stop_trace() /var/www/examples/hidden_behaviour.php:29
    0.0004 227576
    TRACE END [2018-05-28 11:40:10]
    Probleme
    06.06.2018 33

    View Slide

  34. Try and error
    class ReplacedExample
    {
    public static function formatTimeString($timestamp)
    {
    $format = ‘Y-m-d H:i:s’;
    if (!empty($GLOBALS['dateFormat'])) {
    $format = $GLOBALS['dateFormat'];
    }
    return date($format‚ $timestamp);
    }
    }
    Probleme
    06.06.2018 34

    View Slide

  35. Warum benutzt man Globals an dieser Stelle?
    Probleme
    06.06.2018 35

    View Slide

  36. 06.06.2018 36
    Betrachten
    wir ein Beispiel

    View Slide

  37. Andere Funktion – anderes Problem
    public function someTestFunction()
    {
    $timestamp = strtotime('2018-05-15 07:14:03');
    xdebug_start_trace(PATH_FS_TMP.'/../trace-docs/example_trace_');
    $return = \OLD\LIB::localDateTime($timestamp);
    xdebug_stop_trace();
    return $return;
    }
    Betrachten wir ein Beispiel
    06.06.2018 37

    View Slide

  38. Was ist an diesem Trace anders?
    TRACE START [2018-05-28 07:14:03]
    0.0948 6837864 -> \OLD\LIB::localDateTime($dateTime = ‘2018-05-15 07:14:03‘,
    $format = 'd.m.Y H:i:s', $timezone = NULL)
    /var/www/sofi/app/src/ThinkStep/Util/Time.php:328
    0.0948 6837992 -> date(...)
    /var/www/sofi/app/vendor/old/lib/src/Util/Time.php:1050
    0.0949 6838088 >=> '2018-05-15 07:14:03'
    => $dateTime = '2018-05-15 07:14:03'
    /var/www/sofi/app/vendor/old/lib/src/Util/Time.php:1050
    0.0949 6838136 -> defined('LIB_TIME_ZONE')
    /var/www/sofi/app/vendor/old/lib/src/Util/Time.php:1057
    0.0949 6838136 >=> FALSE
    Betrachten wir ein Beispiel
    06.06.2018 38
    Kein ‘TRACE END‘

    View Slide

  39. Wo ist das Ende?
    public function someTestFunction()
    {
    ini_set('xdebug.collect_assignments', 'off');
    $timestamp = strtotime('2018-05-15 07:14:03');
    xdebug_start_trace(PATH_FS_TMP.'/../trace-docs/example_trace_');
    $return = \OLD\LIB\Time::localDateTime($timestamp);
    xdebug_stop_trace();
    return $return;
    }
    Betrachten wir ein Beispiel
    06.06.2018 39
    Bei uns Standard ‘on‘

    View Slide

  40. Ende gut, alles gut?
    TRACE START [2018-05-15 09:27:18]
    0.0794 6837056 -> OLD\LIB\Util\Time::localDateTime($dateTime = ‘2018-05-15 07:14:03‘,
    $format = 'd.m.Y H:i:s', $timezone = NULL)
    /var/www/sofi/app/src/ThinkStep/Util/Time.php:328
    0.0795 6837184 -> date('Y-m-d H:i:s')
    /var/www/sofi/app/vendor/old/lib/src/Util/Time.php:1050
    0.0795 6837280 >=> '2018-05-15 09:27:18'
    0.0795 6837328 -> defined('LIB_TIME_ZONE')
    /var/www/sofi/app/vendor/old/lib/src/Util/Time.php:1057
    0.0795 6837328 >=> FALSE
    ...
    0.0798 6837248 -> xdebug_stop_trace()
    /var/www/sofi/app/src/ThinkStep/Util/Time.php:329
    0.0798 6837320
    TRACE END [2018-05-15 09:27:18]
    Betrachten wir ein Beispiel
    06.06.2018 40
    $dateTime = '2018-05-15 07:14:03'

    View Slide

  41. 06.06.2018 41
    Welche
    Probleme sind aufgetreten?

    View Slide

  42. Segmentation fault
    Probleme
    06.06.2018 42

    View Slide

  43. Segmentation fault

    Kein ‘Trace End’ vorhanden

    Variablenzuweisungen ersichtlich

    Option ‘xdebug.collect_assignments’ auf OFF

    Keine Variablenzuweisung ersichtlich

    ‘Trace End’ vorhanden
    => Mergen der verschiedenen Traces notwendig
    Probleme
    06.06.2018 43

    View Slide

  44. Probleme
    06.06.2018 44
    Xdebug config
    xdebug.collect_includes = 1
    xdebug.collect_vars = 1
    xdebug.collect_params = 4
    xdebug.collect_return = 1
    xdebug.collect_assignments = 1
    xdebug.var_display_max_depth = 5

    View Slide

  45. 06.06.2018 45
    Fallstricke -
    die uns bekannt sind

    View Slide

  46. Closures
    Fallstricke
    06.06.2018 46

    View Slide

  47. Iteration
    “Versteckte“ Abhängigkeiten
    Fallstricke
    06.06.2018 47
    Klasse A
    Klasse B
    Tracing + Replacement
    Klasse A
    function f() {
    var a = Klasse C::function();
    }
    Iteration
    Klasse A
    Klasse B
    Klasse C
    Umfang

    View Slide

  48. Vererbung
    class ElementExample
    {
    public function doSomething()
    {
    // 7 lines
    }
    }
    Fallstricke
    06.06.2018 48
    class TextExample extends ElementExample
    {
    public function doSomething()
    {
    // 10 lines
    }
    }

    View Slide

  49. 06.06.2018 49
    Fazit

    View Slide

  50. Fazit
    06.06.2018 50

    Sehr hohe Testabdeckung notwendig

    Hoher Aufwand durch Regressionstests

    Iterativ-Inkrementelles Vorgehen notwendig

    View Slide

  51. Fazit
    06.06.2018 51
    Bugfixrelease
    Replacement 2016

    View Slide

  52. Danke!
    06.06.2018 52
    [email protected] Cedric_Froehner furiousfoo

    View Slide