Reverse Engineering - Entwickeln gegen eine Blackbox

Reverse Engineering - Entwickeln gegen eine Blackbox

3ba9b3c0301721f8d45d1afca292768f?s=128

Cedric Fröhner

June 06, 2018
Tweet

Transcript

  1. Reverse Engineering Entwickeln gegen eine Blackbox

  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
  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
  4. 06.06.2018 4 Was ist Reverse Engineering?

  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.
  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
  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
  8. 06.06.2018 8 Warum wurde es notwendig?

  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)
  10. 06.06.2018 10 Darf thinkstep das?

  11. Darf thinkstep das? 06.06.2018 11 Decrypten • Verstoß gegen das

    Urheberrecht • Rechtliche Konsequenzen
  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
  13. 06.06.2018 13 Was haben wir vorgefunden?

  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
  15. 06.06.2018 15 Wie sind wir vorgegangen?

  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
  17. 06.06.2018 17 Betrachten wir ein Beispiel

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

  19. Betrachten wir ein Beispiel 06.06.2018 19 Der Inhalt der Stub-Datei

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

    extends OldLibExample { public static function formatTimeString($timestamp) { return parent::formatTimeString($timestamp); } }
  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
  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
  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
  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); } }
  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); } }
  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.
  27. 06.06.2018 27 Welche Probleme sind aufgetreten?

  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
  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?
  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
  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
  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
  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
  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
  35. Warum benutzt man Globals an dieser Stelle? Probleme 06.06.2018 35

  36. 06.06.2018 36 Betrachten wir ein Beispiel

  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
  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‘
  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‘
  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'
  41. 06.06.2018 41 Welche Probleme sind aufgetreten?

  42. Segmentation fault Probleme 06.06.2018 42

  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
  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
  45. 06.06.2018 45 Fallstricke - die uns bekannt sind

  46. Closures Fallstricke 06.06.2018 46

  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
  48. Vererbung class ElementExample { public function doSomething() { // 7

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

  50. Fazit 06.06.2018 50 • Sehr hohe Testabdeckung notwendig • Hoher

    Aufwand durch Regressionstests • Iterativ-Inkrementelles Vorgehen notwendig
  51. Fazit 06.06.2018 51 Bugfixrelease Replacement 2016

  52. Danke! 06.06.2018 52 cedric.froehner@thinkstep.com Cedric_Froehner furiousfoo