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

Reverse Engineering - Entwickeln gegen eine Bla...

Reverse Engineering - Entwickeln gegen eine Blackbox

Cedric Fröhner

June 06, 2018
Tweet

Other Decks in Programming

Transcript

  1. Speaker 06.06.2018 2 - gelernter Softwareentwickler - Projekt- & Teamleiter

    - Scrum Master - Product Owner - Agile Coach - Atlassian Fanboy Position: Engineering Operations Lead Cedric Fröhner
  2. 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
  3. 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.
  4. 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
  5. 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
  6. 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)
  7. 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
  8. 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
  9. 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
  10. Betrachten wir ein Beispiel 06.06.2018 19 Der Inhalt der Stub-Datei

    class StubExample { public static function formatTimeString($timestamp) { // 7 lines } }
  11. Betrachten wir ein Beispiel 06.06.2018 20 Die Vorbereitung class ReplacedExample

    extends OldLibExample { public static function formatTimeString($timestamp) { return parent::formatTimeString($timestamp); } }
  12. 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
  13. 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
  14. 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
  15. 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); } }
  16. 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); } }
  17. 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.
  18. 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
  19. 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?
  20. 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
  21. 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
  22. 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
  23. 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
  24. 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
  25. 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
  26. 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‘
  27. 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‘
  28. 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'
  29. 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
  30. 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
  31. 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
  32. Vererbung class ElementExample { public function doSomething() { // 7

    lines } } Fallstricke 06.06.2018 48 class TextExample extends ElementExample { public function doSomething() { // 10 lines } }
  33. Fazit 06.06.2018 50 • Sehr hohe Testabdeckung notwendig • Hoher

    Aufwand durch Regressionstests • Iterativ-Inkrementelles Vorgehen notwendig